Audio VTS: do not test duplicate policy configuration file am: ff7dcd7e4d
am: ecf7848f67

Change-Id: I79f97fb002e036c17b7ab42f1af00ed2b17e60fd
diff --git a/Android.bp b/Android.bp
index 79e8609..7ae00b6 100644
--- a/Android.bp
+++ b/Android.bp
@@ -9,3 +9,32 @@
         "-Werror",
     ],
 }
+
+// VTS tests must link to HAL definition libraries statically.
+cc_defaults {
+    name: "VtsHalTargetTestDefaults",
+    defaults: ["hidl_defaults"],
+
+    // Lists all dependencies that can *not* be expected on the device.
+    static_libs: [
+        "VtsHalHidlTargetTestBase",
+    ],
+    group_static_libs: true,
+
+    // Lists all system dependencies that can be expected on the device.
+    shared_libs: [
+        "libbase",
+        // All the following are dependencies of any HAL definition library.
+        "libcutils",
+        "liblog",
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+    ],
+    cflags: [
+        "-O0",
+        "-g",
+    ],
+
+}
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 14616e4..dd4cee0 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -56,4 +56,10 @@
 $(call add-clean-step, rm -rf $(OUT_DIR)/soong/.intermediates/hardware/interfaces/)
 $(call add-clean-step, rm -rf $(OUT_DIR)/soong/.intermediates/hardware/interfaces/)
 $(call add-clean-step, find $(PRODUCT_OUT)/system $(PRODUCT_OUT)/vendor -type f -name "android\.hardware\.configstore*" -print0 | xargs -0 rm -f)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/bin/hw/android.hardware.automotive*)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/hw/android.hardware.automotive*)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib64/hw/android.hardware.automotive*)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/etc/init/android.hardware.automotive*)
 $(call add-clean-step, find $(PRODUCT_OUT)/system $(PRODUCT_OUT)/vendor -type f -name "android\.hardware\.configstore\@1\.1*" -print0 | xargs -0 rm -f)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/android.hardware.tests*)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/vndk/android.hardware.tests*)
diff --git a/OWNERS b/OWNERS
new file mode 100644
index 0000000..9fbcb47
--- /dev/null
+++ b/OWNERS
@@ -0,0 +1,5 @@
+elsk@google.com
+maco@google.com
+malchev@google.com
+smoreland@google.com
+yim@google.com  # vts tests
diff --git a/audio/2.0/Android.bp b/audio/2.0/Android.bp
index b193c8f..cdaaa15 100644
--- a/audio/2.0/Android.bp
+++ b/audio/2.0/Android.bp
@@ -81,13 +81,16 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.audio@2.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.audio@2.0_genc++"],
     generated_headers: ["android.hardware.audio@2.0_genc++_headers"],
     export_generated_headers: ["android.hardware.audio@2.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/audio/2.0/default/Android.mk b/audio/2.0/default/Android.mk
index 621853c..8dec482 100644
--- a/audio/2.0/default/Android.mk
+++ b/audio/2.0/default/Android.mk
@@ -84,8 +84,4 @@
 LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)
 endif
 
-ifeq ($(TARGET_USES_BCRADIO_FUTURE_FEATURES),true)
-LOCAL_CFLAGS += -DTARGET_USES_BCRADIO_FUTURE_FEATURES
-endif
-
 include $(BUILD_EXECUTABLE)
diff --git a/audio/2.0/default/OWNERS b/audio/2.0/default/OWNERS
new file mode 100644
index 0000000..6fdc97c
--- /dev/null
+++ b/audio/2.0/default/OWNERS
@@ -0,0 +1,3 @@
+elaurent@google.com
+krocard@google.com
+mnaganov@google.com
diff --git a/audio/2.0/default/service.cpp b/audio/2.0/default/service.cpp
index 7f28d7d..a215108 100644
--- a/audio/2.0/default/service.cpp
+++ b/audio/2.0/default/service.cpp
@@ -21,8 +21,6 @@
 #include <android/hardware/audio/2.0/IDevicesFactory.h>
 #include <android/hardware/audio/effect/2.0/IEffectsFactory.h>
 #include <android/hardware/soundtrigger/2.0/ISoundTriggerHw.h>
-#include <android/hardware/broadcastradio/1.0/IBroadcastRadioFactory.h>
-#include <android/hardware/broadcastradio/1.1/IBroadcastRadioFactory.h>
 
 using android::hardware::configureRpcThreadpool;
 using android::hardware::joinRpcThreadpool;
@@ -32,13 +30,6 @@
 using android::hardware::audio::V2_0::IDevicesFactory;
 using android::hardware::soundtrigger::V2_0::ISoundTriggerHw;
 using android::hardware::registerPassthroughServiceImplementation;
-namespace broadcastradio = android::hardware::broadcastradio;
-
-#ifdef TARGET_USES_BCRADIO_FUTURE_FEATURES
-static const bool useBroadcastRadioFutureFeatures = true;
-#else
-static const bool useBroadcastRadioFutureFeatures = false;
-#endif
 
 using android::OK;
 
@@ -49,17 +40,9 @@
     LOG_ALWAYS_FATAL_IF(status != OK, "Error while registering audio service: %d", status);
     status = registerPassthroughServiceImplementation<IEffectsFactory>();
     LOG_ALWAYS_FATAL_IF(status != OK, "Error while registering audio effects service: %d", status);
-    // Soundtrigger and FM radio might be not present.
+    // Soundtrigger might be not present.
     status = registerPassthroughServiceImplementation<ISoundTriggerHw>();
     ALOGE_IF(status != OK, "Error while registering soundtrigger service: %d", status);
-    if (useBroadcastRadioFutureFeatures) {
-        status = registerPassthroughServiceImplementation<
-            broadcastradio::V1_1::IBroadcastRadioFactory>();
-    } else {
-        status = registerPassthroughServiceImplementation<
-            broadcastradio::V1_0::IBroadcastRadioFactory>();
-    }
-    ALOGE_IF(status != OK, "Error while registering fm radio service: %d", status);
     joinRpcThreadpool();
     return status;
 }
diff --git a/audio/2.0/vts/functional/Android.bp b/audio/2.0/vts/functional/Android.bp
index b289709..f3b2ca7 100644
--- a/audio/2.0/vts/functional/Android.bp
+++ b/audio/2.0/vts/functional/Android.bp
@@ -16,29 +16,18 @@
 
 cc_test {
     name: "VtsHalAudioV2_0TargetTest",
-    defaults: ["hidl_defaults"],
-    srcs: ["AudioPrimaryHidlHalTest.cpp",
-           "ValidateAudioConfiguration.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libhidlbase",
-        "libhidltransport",
-        "libutils",
-        "libcutils",
-        "libxml2",
-        "android.hardware.audio@2.0",
-        "android.hardware.audio.common@2.0",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: [
+        "AudioPrimaryHidlHalTest.cpp",
+        "ValidateAudioConfiguration.cpp"
     ],
     static_libs: [
-        "VtsHalHidlTargetTestBase",
         "android.hardware.audio.common.test.utility",
+        "android.hardware.audio@2.0",
+        "android.hardware.audio.common@2.0",
+        "libxml2",
     ],
-    cflags: [
-        "-O0",
-        "-g",
-        "-Wall",
-        "-Wextra",
-        "-Werror",
+    shared_libs: [
+        "libicuuc",
     ],
 }
diff --git a/audio/common/2.0/Android.bp b/audio/common/2.0/Android.bp
index 39db15a..0007f44 100644
--- a/audio/common/2.0/Android.bp
+++ b/audio/common/2.0/Android.bp
@@ -32,13 +32,16 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.audio.common@2.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.audio.common@2.0_genc++"],
     generated_headers: ["android.hardware.audio.common@2.0_genc++_headers"],
     export_generated_headers: ["android.hardware.audio.common@2.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/audio/common/2.0/default/Android.bp b/audio/common/2.0/default/Android.bp
index 0486a5c..104bbac 100644
--- a/audio/common/2.0/default/Android.bp
+++ b/audio/common/2.0/default/Android.bp
@@ -16,6 +16,9 @@
 cc_library_shared {
     name: "android.hardware.audio.common@2.0-util",
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     srcs: [
         "EffectMap.cpp",
         "HidlUtils.cpp",
diff --git a/audio/common/2.0/default/OWNERS b/audio/common/2.0/default/OWNERS
new file mode 100644
index 0000000..6fdc97c
--- /dev/null
+++ b/audio/common/2.0/default/OWNERS
@@ -0,0 +1,3 @@
+elaurent@google.com
+krocard@google.com
+mnaganov@google.com
diff --git a/audio/common/test/utility/OWNERS b/audio/common/test/utility/OWNERS
new file mode 100644
index 0000000..6fdc97c
--- /dev/null
+++ b/audio/common/test/utility/OWNERS
@@ -0,0 +1,3 @@
+elaurent@google.com
+krocard@google.com
+mnaganov@google.com
diff --git a/audio/effect/2.0/Android.bp b/audio/effect/2.0/Android.bp
index a004263..fd667f0 100644
--- a/audio/effect/2.0/Android.bp
+++ b/audio/effect/2.0/Android.bp
@@ -130,13 +130,16 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.audio.effect@2.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.audio.effect@2.0_genc++"],
     generated_headers: ["android.hardware.audio.effect@2.0_genc++_headers"],
     export_generated_headers: ["android.hardware.audio.effect@2.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/audio/effect/2.0/default/OWNERS b/audio/effect/2.0/default/OWNERS
new file mode 100644
index 0000000..6fdc97c
--- /dev/null
+++ b/audio/effect/2.0/default/OWNERS
@@ -0,0 +1,3 @@
+elaurent@google.com
+krocard@google.com
+mnaganov@google.com
diff --git a/audio/effect/2.0/vts/functional/Android.bp b/audio/effect/2.0/vts/functional/Android.bp
index 8a370cd..7b421cb 100644
--- a/audio/effect/2.0/vts/functional/Android.bp
+++ b/audio/effect/2.0/vts/functional/Android.bp
@@ -16,24 +16,20 @@
 
 cc_test {
     name: "VtsHalAudioEffectV2_0TargetTest",
-    defaults: ["hidl_defaults"],
-    srcs: ["VtsHalAudioEffectV2_0TargetTest.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libnativehelper",
-        "libutils",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: [
+        "VtsHalAudioEffectV2_0TargetTest.cpp",
+        "ValidateAudioEffectsConfiguration.cpp"
+    ],
+    static_libs: [
+        "android.hardware.audio.common.test.utility",
         "android.hardware.audio.common@2.0",
         "android.hardware.audio.effect@2.0",
         "android.hidl.allocator@1.0",
         "android.hidl.memory@1.0",
+        "libxml2",
     ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
+    shared_libs: [
+        "libicuuc",
     ],
 }
diff --git a/audio/effect/2.0/vts/functional/ValidateAudioEffectsConfiguration.cpp b/audio/effect/2.0/vts/functional/ValidateAudioEffectsConfiguration.cpp
new file mode 100644
index 0000000..fdc1347
--- /dev/null
+++ b/audio/effect/2.0/vts/functional/ValidateAudioEffectsConfiguration.cpp
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+
+#include <unistd.h>
+
+#include "utility/ValidateXml.h"
+
+TEST(CheckConfig, audioEffectsConfigurationValidation) {
+    RecordProperty("description",
+                   "Verify that the effects configuration file is valid according to the schema");
+    const char* xmlConfigFile = "/vendor/etc/audio_effects.xml";
+    // Not every device uses XML configuration, so only validate
+    // if the XML configuration actually exists.
+    if (access(xmlConfigFile, F_OK) == 0) {
+        ASSERT_VALID_XML(xmlConfigFile, "/data/local/tmp/audio_effects_conf_V2_0.xsd");
+    }
+}
diff --git a/audio/effect/2.0/xml/audio_effects_conf_V2_0.xsd b/audio/effect/2.0/xml/audio_effects_conf_V2_0.xsd
new file mode 100644
index 0000000..ca6a7dc
--- /dev/null
+++ b/audio/effect/2.0/xml/audio_effects_conf_V2_0.xsd
@@ -0,0 +1,249 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
+           targetNamespace="http://schemas.android.com/audio/audio_effects_conf/v2_0"
+           xmlns:aec="http://schemas.android.com/audio/audio_effects_conf/v2_0"
+           elementFormDefault="qualified">
+
+  <!-- Simple types -->
+  <xs:simpleType name="versionType">
+    <xs:restriction base="xs:decimal">
+      <xs:enumeration value="2.0"/>
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="uuidType">
+    <xs:restriction base="xs:string">
+      <xs:pattern value="[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}"/>
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="streamInputType">
+    <xs:restriction base="xs:string">
+      <xs:enumeration value="mic"/>
+      <xs:enumeration value="voice_uplink"/>
+      <xs:enumeration value="voice_downlink"/>
+      <xs:enumeration value="voice_call"/>
+      <xs:enumeration value="camcorder"/>
+      <xs:enumeration value="voice_recognition"/>
+      <xs:enumeration value="voice_communication"/>
+      <xs:enumeration value="unprocessed"/>
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="streamOutputType">
+    <xs:restriction base="xs:string">
+      <xs:enumeration value="voice_call"/>
+      <xs:enumeration value="system"/>
+      <xs:enumeration value="ring"/>
+      <xs:enumeration value="music"/>
+      <xs:enumeration value="alarm"/>
+      <xs:enumeration value="notification"/>
+      <xs:enumeration value="bluetooth_sco"/>
+      <xs:enumeration value="enforced_audible"/>
+      <xs:enumeration value="dtmf"/>
+      <xs:enumeration value="tts"/>
+    </xs:restriction>
+  </xs:simpleType>
+  <xs:simpleType name="relativePathType">
+    <xs:restriction base="xs:string">
+      <xs:pattern value="[^/].*"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <!-- Complex types -->
+  <xs:complexType name="librariesType">
+    <xs:annotation>
+      <xs:documentation xml:lang="en">
+        List of effect libraries to load. Each library element must have "name" and
+        "path" attributes. The latter is giving the path of the library .so file
+        relative to the standard effect folders: /(vendor|odm|system)/lib(64)?/soundfx/
+
+        Example for a library in "/vendor/lib/soundfx/lib.so":
+        <library name="name" path="lib.so"/>
+
+      </xs:documentation>
+    </xs:annotation>
+    <xs:sequence>
+      <xs:element name="library" minOccurs="0" maxOccurs="unbounded">
+        <xs:complexType>
+          <xs:attribute name="name" type="xs:string" use="required"/>
+          <xs:attribute name="path" type="aec:relativePathType" use="required"/>
+        </xs:complexType>
+      </xs:element>
+    </xs:sequence>
+  </xs:complexType>
+  <xs:complexType name="effectImplType">
+    <xs:attribute name="library" type="xs:string" use="required"/>
+    <xs:attribute name="uuid" type="aec:uuidType" use="required"/>
+  </xs:complexType>
+  <xs:complexType name="effectType">
+    <xs:complexContent>
+      <xs:extension base="aec:effectImplType">
+        <xs:attribute name="name" type="xs:string" use="required"/>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:complexType name="effectProxyType">
+    <xs:complexContent>
+      <xs:extension base="aec:effectType">
+        <xs:sequence>
+          <xs:element name="libsw" type="aec:effectImplType"/>
+          <xs:element name="libhw" type="aec:effectImplType"/>
+        </xs:sequence>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:complexType name="effectsType">
+    <xs:annotation>
+      <xs:documentation xml:lang="en">
+        List of effects to load. Each effect element must contain "name",
+        "library", and "uuid" attrs. The value of the "library" attr must
+        correspond to the name of a "library" element. The name of the effect
+        element is indicative, only the value of the "uuid" element designates
+        the effect for the audio framework.  The uuid is the implementation
+        specific UUID as specified by the effect vendor. This is not the generic
+        effect type UUID.
+
+        For effect proxy implementations, SW and HW implemetations of the effect
+        can be specified.
+
+        Example:
+
+        <effect name="name" library="lib" uuid="uuuu"/>
+        <effectProxy name="proxied" library="proxy" uuid="xxxx">
+            <libsw library="sw_bundle" uuid="yyyy"/>
+            <libhw library="offload_bundle" uuid="zzzz"/>
+        </effectProxy>
+
+      </xs:documentation>
+    </xs:annotation>
+    <xs:choice maxOccurs="unbounded">
+      <xs:element name="effect" type="aec:effectType" minOccurs="0" maxOccurs="unbounded"/>
+      <xs:element name="effectProxy" type="aec:effectProxyType" minOccurs="0" maxOccurs="unbounded"/>
+    </xs:choice>
+  </xs:complexType>
+  <xs:complexType name="streamProcessingType">
+    <xs:sequence>
+      <xs:element name="apply" minOccurs="0" maxOccurs="unbounded">
+        <xs:complexType>
+          <xs:attribute name="effect" type="xs:string" use="required"/>
+        </xs:complexType>
+      </xs:element>
+    </xs:sequence>
+  </xs:complexType>
+  <xs:complexType name="streamPreprocessType">
+    <xs:annotation>
+      <xs:documentation xml:lang="en">
+        Audio preprocessing configuration. The processing configuration consists
+        of a list of elements each describing processing settings for a given
+        input stream. Valid input stream types are listed in "streamInputType".
+
+        Each stream element contains a list of "apply" elements. The value of the
+        "effect" attr must correspond to the name of an "effect" element.
+
+        Example:
+
+        <stream type="voice_communication">
+            <apply effect="effect1"/>
+            <apply effect="effect2"/>
+        </stream>
+
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexContent>
+      <xs:extension base="aec:streamProcessingType">
+        <xs:attribute name="type" type="aec:streamInputType" use="required"/>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+  <xs:complexType name="streamPostprocessType">
+    <xs:annotation>
+      <xs:documentation xml:lang="en">
+        Audio postprocessing configuration. The processing configuration consists
+        of a list of elements each describing processing settings for a given
+        output stream. Valid output stream types are listed in "streamOutputType".
+
+        Each stream element contains a list of "apply" elements. The value of the
+        "effect" attr must correspond to the name of an "effect" element.
+
+        Example:
+
+        <stream type="music">
+            <apply effect="effect1"/>
+        </stream>
+
+      </xs:documentation>
+    </xs:annotation>
+    <xs:complexContent>
+      <xs:extension base="aec:streamProcessingType">
+        <xs:attribute name="type" type="aec:streamOutputType" use="required"/>
+      </xs:extension>
+    </xs:complexContent>
+  </xs:complexType>
+
+  <!-- Root element -->
+  <xs:element name="audio_effects_conf">
+    <xs:complexType>
+      <xs:sequence>
+        <xs:element name="libraries" type="aec:librariesType"/>
+        <xs:element name="effects" type="aec:effectsType"/>
+        <xs:element name="postprocess" minOccurs="0" maxOccurs="1">
+          <xs:complexType>
+            <xs:sequence>
+              <xs:element name="stream" type="aec:streamPostprocessType" minOccurs="0" maxOccurs="unbounded"/>
+            </xs:sequence>
+          </xs:complexType>
+        </xs:element>
+        <xs:element name="preprocess" minOccurs="0" maxOccurs="1">
+          <xs:complexType>
+            <xs:sequence>
+              <xs:element name="stream" type="aec:streamPreprocessType" minOccurs="0" maxOccurs="unbounded"/>
+            </xs:sequence>
+          </xs:complexType>
+        </xs:element>
+      </xs:sequence>
+      <xs:attribute name="version" type="aec:versionType" use="required"/>
+    </xs:complexType>
+
+    <!-- Keys and references -->
+    <xs:key name="libraryName">
+      <xs:selector xpath="aec:libraries/aec:library"/>
+      <xs:field xpath="@name"/>
+    </xs:key>
+    <xs:keyref name="libraryNameRef1" refer="aec:libraryName">
+      <xs:selector xpath="aec:effects/aec:effect"/>
+      <xs:field xpath="@library"/>
+    </xs:keyref>
+    <xs:keyref name="libraryNameRef2" refer="aec:libraryName">
+      <xs:selector xpath="aec:effects/aec:effect/aec:libsw"/>
+      <xs:field xpath="@library"/>
+    </xs:keyref>
+    <xs:keyref name="libraryNameRef3" refer="aec:libraryName">
+      <xs:selector xpath="aec:effects/aec:effect/aec:libhw"/>
+      <xs:field xpath="@library"/>
+    </xs:keyref>
+    <xs:key name="effectName">
+      <xs:selector xpath="aec:effects/aec:effect"/>
+      <xs:field xpath="@name"/>
+    </xs:key>
+    <xs:keyref name="effectNamePreRef" refer="aec:effectName">
+      <xs:selector xpath="aec:preprocess/aec:stream/aec:apply"/>
+      <xs:field xpath="@effect"/>
+    </xs:keyref>
+    <xs:keyref name="effectNamePostRef" refer="aec:effectName">
+      <xs:selector xpath="aec:postprocess/aec:stream/aec:apply"/>
+      <xs:field xpath="@effect"/>
+    </xs:keyref>
+  </xs:element>
+</xs:schema>
diff --git a/automotive/Android.bp b/automotive/Android.bp
index be58829..8cde817 100644
--- a/automotive/Android.bp
+++ b/automotive/Android.bp
@@ -1,7 +1,9 @@
 // This is an autogenerated file, do not edit.
 subdirs = [
     "evs/1.0",
+    "evs/1.0/default",
     "evs/1.0/vts/functional",
     "vehicle/2.0",
-    "vehicle/2.1",
+    "vehicle/2.0/default",
+    "vehicle/2.0/default/impl/vhal_v2_0/proto",
 ]
diff --git a/automotive/evs/1.0/Android.bp b/automotive/evs/1.0/Android.bp
index 9ca97a7..7ae2231 100644
--- a/automotive/evs/1.0/Android.bp
+++ b/automotive/evs/1.0/Android.bp
@@ -60,13 +60,16 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.automotive.evs@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.automotive.evs@1.0_genc++"],
     generated_headers: ["android.hardware.automotive.evs@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.automotive.evs@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/automotive/evs/1.0/default/Android.bp b/automotive/evs/1.0/default/Android.bp
new file mode 100644
index 0000000..2574e86
--- /dev/null
+++ b/automotive/evs/1.0/default/Android.bp
@@ -0,0 +1,31 @@
+cc_binary {
+    name: "android.hardware.automotive.evs@1.0-service",
+    defaults: ["hidl_defaults"],
+    proprietary: true,
+    relative_install_path: "hw",
+    srcs: [
+        "service.cpp",
+        "EvsCamera.cpp",
+        "EvsEnumerator.cpp",
+        "EvsDisplay.cpp"
+    ],
+    init_rc: ["android.hardware.automotive.evs@1.0-service.rc"],
+
+    shared_libs: [
+        "android.hardware.automotive.evs@1.0",
+        "libui",
+        "libbase",
+        "libbinder",
+        "libcutils",
+        "libhardware",
+        "libhidlbase",
+        "libhidltransport",
+        "liblog",
+        "libutils",
+    ],
+
+    cflags: [
+        "-O0",
+        "-g",
+    ],
+}
diff --git a/automotive/evs/1.0/default/Android.mk b/automotive/evs/1.0/default/Android.mk
deleted file mode 100644
index 0ee7071..0000000
--- a/automotive/evs/1.0/default/Android.mk
+++ /dev/null
@@ -1,29 +0,0 @@
-LOCAL_PATH:=$(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := android.hardware.automotive.evs@1.0-service
-LOCAL_INIT_RC := android.hardware.automotive.evs@1.0-service.rc
-LOCAL_MODULE_RELATIVE_PATH := hw
-LOCAL_VENDOR_MODULE := true
-
-LOCAL_SRC_FILES := \
-    service.cpp \
-    EvsCamera.cpp \
-    EvsEnumerator.cpp \
-    EvsDisplay.cpp \
-
-LOCAL_SHARED_LIBRARIES := \
-    android.hardware.automotive.evs@1.0 \
-    libui \
-    libbase \
-    libbinder \
-    libcutils \
-    libhardware \
-    libhidlbase \
-    libhidltransport \
-    liblog \
-    libutils \
-
-LOCAL_CFLAGS := -O0 -g
-
-include $(BUILD_EXECUTABLE)
diff --git a/automotive/evs/1.0/vts/functional/Android.bp b/automotive/evs/1.0/vts/functional/Android.bp
index e86e9bc..555ff5b 100644
--- a/automotive/evs/1.0/vts/functional/Android.bp
+++ b/automotive/evs/1.0/vts/functional/Android.bp
@@ -15,10 +15,10 @@
 //
 
 cc_test {
-    name: "VtsEvsV1_0Target",
+    name: "VtsHalEvsV1_0Target",
 
     srcs: [
-        "VtsEvsV1_0TargetTest.cpp",
+        "VtsHalEvsV1_0TargetTest.cpp",
         "FrameHandler.cpp",
         "FormatConvert.cpp"
     ],
@@ -43,4 +43,3 @@
         "-g",
     ],
 }
-
diff --git a/automotive/evs/1.0/vts/functional/VtsEvsV1_0TargetTest.cpp b/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp
similarity index 97%
rename from automotive/evs/1.0/vts/functional/VtsEvsV1_0TargetTest.cpp
rename to automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp
index 2e80afe..57050d7 100644
--- a/automotive/evs/1.0/vts/functional/VtsEvsV1_0TargetTest.cpp
+++ b/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp
@@ -17,8 +17,13 @@
 #define LOG_TAG "VtsHalEvsTest"
 
 
-// TODO:  How should we configure these values to target appropriate hardware?
-const static char kEnumeratorName[]  = "EvsEnumeratorHw-Mock";
+// Note:  We have't got a great way to indicate which target
+// should be tested, so we'll leave the interface served by the
+// default (mock) EVS driver here for easy reference.  All
+// actual EVS drivers should serve on the EvsEnumeratorHw name,
+// however, so the code is checked in that way.
+//const static char kEnumeratorName[]  = "EvsEnumeratorHw-Mock";
+const static char kEnumeratorName[]  = "EvsEnumeratorHw";
 
 
 // These values are called out in the EVS design doc (as of Mar 8, 2017)
@@ -474,4 +479,4 @@
 
     // Explicitly release the display
     pEnumerator->closeDisplay(pDisplay);
-}
\ No newline at end of file
+}
diff --git a/automotive/vehicle/2.0/Android.bp b/automotive/vehicle/2.0/Android.bp
index e21bef0..879fe0d 100644
--- a/automotive/vehicle/2.0/Android.bp
+++ b/automotive/vehicle/2.0/Android.bp
@@ -46,13 +46,16 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.automotive.vehicle@2.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.automotive.vehicle@2.0_genc++"],
     generated_headers: ["android.hardware.automotive.vehicle@2.0_genc++_headers"],
     export_generated_headers: ["android.hardware.automotive.vehicle@2.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/automotive/vehicle/2.0/Android.mk b/automotive/vehicle/2.0/Android.mk
index eb05f35..5919487 100644
--- a/automotive/vehicle/2.0/Android.mk
+++ b/automotive/vehicle/2.0/Android.mk
@@ -17,6 +17,177 @@
 
 
 #
+# Build types.hal (DiagnosticFloatSensorIndex)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/DiagnosticFloatSensorIndex.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.DiagnosticFloatSensorIndex
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (DiagnosticIntegerSensorIndex)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/DiagnosticIntegerSensorIndex.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.DiagnosticIntegerSensorIndex
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Obd2CommonIgnitionMonitors)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/Obd2CommonIgnitionMonitors.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.Obd2CommonIgnitionMonitors
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Obd2CompressionIgnitionMonitors)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/Obd2CompressionIgnitionMonitors.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.Obd2CompressionIgnitionMonitors
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Obd2FuelSystemStatus)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/Obd2FuelSystemStatus.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.Obd2FuelSystemStatus
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Obd2FuelType)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/Obd2FuelType.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.Obd2FuelType
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Obd2IgnitionMonitorKind)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/Obd2IgnitionMonitorKind.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.Obd2IgnitionMonitorKind
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Obd2SecondaryAirStatus)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/Obd2SecondaryAirStatus.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.Obd2SecondaryAirStatus
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Obd2SparkIgnitionMonitors)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/Obd2SparkIgnitionMonitors.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.Obd2SparkIgnitionMonitors
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
 # Build types.hal (StatusCode)
 #
 GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/StatusCode.java
@@ -910,6 +1081,139 @@
 LOCAL_GENERATED_SOURCES += $(GEN)
 
 #
+# Build types.hal (VmsAvailabilityStateIntegerValuesIndex)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VmsAvailabilityStateIntegerValuesIndex.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.VmsAvailabilityStateIntegerValuesIndex
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VmsBaseMessageIntegerValuesIndex)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VmsBaseMessageIntegerValuesIndex.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.VmsBaseMessageIntegerValuesIndex
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VmsMessageType)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VmsMessageType.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.VmsMessageType
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VmsMessageWithLayerAndPublisherIdIntegerValuesIndex)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VmsMessageWithLayerAndPublisherIdIntegerValuesIndex.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.VmsMessageWithLayerAndPublisherIdIntegerValuesIndex
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VmsMessageWithLayerIntegerValuesIndex)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VmsMessageWithLayerIntegerValuesIndex.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.VmsMessageWithLayerIntegerValuesIndex
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VmsOfferingMessageIntegerValuesIndex)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VmsOfferingMessageIntegerValuesIndex.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.VmsOfferingMessageIntegerValuesIndex
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VmsSubscriptionsStateIntegerValuesIndex)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VmsSubscriptionsStateIntegerValuesIndex.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.VmsSubscriptionsStateIntegerValuesIndex
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
 # Build types.hal (Wheel)
 #
 GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/Wheel.java
@@ -989,6 +1293,177 @@
 
 
 #
+# Build types.hal (DiagnosticFloatSensorIndex)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/DiagnosticFloatSensorIndex.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.DiagnosticFloatSensorIndex
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (DiagnosticIntegerSensorIndex)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/DiagnosticIntegerSensorIndex.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.DiagnosticIntegerSensorIndex
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Obd2CommonIgnitionMonitors)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/Obd2CommonIgnitionMonitors.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.Obd2CommonIgnitionMonitors
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Obd2CompressionIgnitionMonitors)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/Obd2CompressionIgnitionMonitors.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.Obd2CompressionIgnitionMonitors
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Obd2FuelSystemStatus)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/Obd2FuelSystemStatus.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.Obd2FuelSystemStatus
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Obd2FuelType)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/Obd2FuelType.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.Obd2FuelType
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Obd2IgnitionMonitorKind)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/Obd2IgnitionMonitorKind.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.Obd2IgnitionMonitorKind
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Obd2SecondaryAirStatus)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/Obd2SecondaryAirStatus.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.Obd2SecondaryAirStatus
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Obd2SparkIgnitionMonitors)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/Obd2SparkIgnitionMonitors.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.Obd2SparkIgnitionMonitors
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
 # Build types.hal (StatusCode)
 #
 GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/StatusCode.java
@@ -1882,6 +2357,139 @@
 LOCAL_GENERATED_SOURCES += $(GEN)
 
 #
+# Build types.hal (VmsAvailabilityStateIntegerValuesIndex)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VmsAvailabilityStateIntegerValuesIndex.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.VmsAvailabilityStateIntegerValuesIndex
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VmsBaseMessageIntegerValuesIndex)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VmsBaseMessageIntegerValuesIndex.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.VmsBaseMessageIntegerValuesIndex
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VmsMessageType)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VmsMessageType.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.VmsMessageType
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VmsMessageWithLayerAndPublisherIdIntegerValuesIndex)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VmsMessageWithLayerAndPublisherIdIntegerValuesIndex.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.VmsMessageWithLayerAndPublisherIdIntegerValuesIndex
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VmsMessageWithLayerIntegerValuesIndex)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VmsMessageWithLayerIntegerValuesIndex.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.VmsMessageWithLayerIntegerValuesIndex
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VmsOfferingMessageIntegerValuesIndex)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VmsOfferingMessageIntegerValuesIndex.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.VmsOfferingMessageIntegerValuesIndex
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (VmsSubscriptionsStateIntegerValuesIndex)
+#
+GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VmsSubscriptionsStateIntegerValuesIndex.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.automotive.vehicle@2.0::types.VmsSubscriptionsStateIntegerValuesIndex
+
+$(GEN): $(LOCAL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
 # Build types.hal (Wheel)
 #
 GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/Wheel.java
diff --git a/automotive/vehicle/2.0/default/Android.bp b/automotive/vehicle/2.0/default/Android.bp
new file mode 100644
index 0000000..1690163
--- /dev/null
+++ b/automotive/vehicle/2.0/default/Android.bp
@@ -0,0 +1,117 @@
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//       http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+cc_defaults {
+    name: "vhal_v2_0_defaults",
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "liblog",
+        "libutils",
+        "android.hardware.automotive.vehicle@2.0",
+    ],
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+    ],
+}
+
+cc_library_headers {
+    name: "vhal_v2_0_common_headers",
+    vendor: true,
+    export_include_dirs: ["common/include/vhal_v2_0"],
+}
+
+// Vehicle reference implementation lib
+cc_library_static {
+    name: "android.hardware.automotive.vehicle@2.0-manager-lib",
+    vendor: true,
+    defaults: ["vhal_v2_0_defaults"],
+    srcs: [
+        "common/src/Obd2SensorStore.cpp",
+        "common/src/SubscriptionManager.cpp",
+        "common/src/VehicleHalManager.cpp",
+        "common/src/VehicleObjectPool.cpp",
+        "common/src/VehiclePropertyStore.cpp",
+        "common/src/VehicleUtils.cpp",
+    ],
+    local_include_dirs: ["common/include/vhal_v2_0"],
+    export_include_dirs: ["common/include"],
+}
+
+cc_library_shared {
+    name: "android.hardware.automotive.vehicle@2.0-manager-lib-shared",
+    vendor: true,
+    static_libs: ["android.hardware.automotive.vehicle@2.0-manager-lib"],
+    export_static_lib_headers: ["android.hardware.automotive.vehicle@2.0-manager-lib"],
+}
+
+// Vehicle default VehicleHAL implementation
+cc_library_static {
+    name: "android.hardware.automotive.vehicle@2.0-default-impl-lib",
+    vendor: true,
+    defaults: ["vhal_v2_0_defaults"],
+    srcs: [
+        "impl/vhal_v2_0/EmulatedVehicleHal.cpp",
+        "impl/vhal_v2_0/VehicleEmulator.cpp",
+        "impl/vhal_v2_0/PipeComm.cpp",
+        "impl/vhal_v2_0/SocketComm.cpp",
+    ],
+    local_include_dirs: ["common/include/vhal_v2_0"],
+    export_include_dirs: ["impl"],
+    whole_static_libs: ["android.hardware.automotive.vehicle@2.0-manager-lib"],
+    shared_libs: [
+        "libbase",
+        "libprotobuf-cpp-lite",
+    ],
+    static_libs: [
+        "libqemu_pipe",
+        "android.hardware.automotive.vehicle@2.0-libproto-native",
+    ],
+}
+
+cc_test {
+    name: "android.hardware.automotive.vehicle@2.0-manager-unit-tests",
+    vendor: true,
+    defaults: ["vhal_v2_0_defaults"],
+    whole_static_libs: ["android.hardware.automotive.vehicle@2.0-manager-lib"],
+    srcs: [
+        "tests/RecurrentTimer_test.cpp",
+        "tests/SubscriptionManager_test.cpp",
+        "tests/VehicleHalManager_test.cpp",
+        "tests/VehicleObjectPool_test.cpp",
+        "tests/VehiclePropConfigIndex_test.cpp",
+    ],
+    header_libs: ["libbase_headers"],
+}
+
+cc_binary {
+    name: "android.hardware.automotive.vehicle@2.0-service",
+    defaults: ["vhal_v2_0_defaults"],
+    init_rc: ["android.hardware.automotive.vehicle@2.0-service.rc"],
+    vendor: true,
+    relative_install_path: "hw",
+    srcs: ["VehicleService.cpp"],
+    shared_libs: [
+        "libbase",
+        "libprotobuf-cpp-lite",
+    ],
+    static_libs: [
+        "android.hardware.automotive.vehicle@2.0-manager-lib",
+        "android.hardware.automotive.vehicle@2.0-default-impl-lib",
+        "android.hardware.automotive.vehicle@2.0-libproto-native",
+        "libqemu_pipe",
+    ],
+}
diff --git a/automotive/vehicle/2.0/default/Android.mk b/automotive/vehicle/2.0/default/Android.mk
deleted file mode 100644
index 72e1364..0000000
--- a/automotive/vehicle/2.0/default/Android.mk
+++ /dev/null
@@ -1,194 +0,0 @@
-# Copyright (C) 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-
-vhal_v2_0 = android.hardware.automotive.vehicle@2.0
-
-###############################################################################
-# Vehicle reference implementation lib
-###############################################################################
-include $(CLEAR_VARS)
-LOCAL_MODULE := $(vhal_v2_0)-manager-lib
-LOCAL_SRC_FILES := \
-    common/src/SubscriptionManager.cpp \
-    common/src/VehicleHalManager.cpp \
-    common/src/VehicleObjectPool.cpp \
-    common/src/VehiclePropertyStore.cpp \
-    common/src/VehicleUtils.cpp \
-
-LOCAL_C_INCLUDES := \
-    $(LOCAL_PATH)/common/include/vhal_v2_0
-
-LOCAL_EXPORT_C_INCLUDE_DIRS := \
-    $(LOCAL_PATH)/common/include
-
-LOCAL_SHARED_LIBRARIES := \
-    libhidlbase \
-    libhidltransport \
-    liblog \
-    libutils \
-    $(vhal_v2_0) \
-
-include $(BUILD_STATIC_LIBRARY)
-
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := $(vhal_v2_0)-manager-lib-shared
-LOCAL_SRC_FILES := \
-    common/src/SubscriptionManager.cpp \
-    common/src/VehicleHalManager.cpp \
-    common/src/VehicleObjectPool.cpp \
-    common/src/VehiclePropertyStore.cpp \
-    common/src/VehicleUtils.cpp \
-
-LOCAL_C_INCLUDES := \
-    $(LOCAL_PATH)/common/include/vhal_v2_0
-
-LOCAL_EXPORT_C_INCLUDE_DIRS := \
-    $(LOCAL_PATH)/common/include
-
-LOCAL_SHARED_LIBRARIES := \
-    libhidlbase \
-    libhidltransport \
-    liblog \
-    libutils \
-    $(vhal_v2_0) \
-
-include $(BUILD_SHARED_LIBRARY)
-
-###############################################################################
-# Vehicle HAL Protobuf library
-###############################################################################
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := $(call all-proto-files-under, impl/vhal_v2_0/proto)
-
-LOCAL_PROTOC_OPTIMIZE_TYPE := nano
-
-LOCAL_MODULE := $(vhal_v2_0)-libproto-native
-LOCAL_MODULE_CLASS := STATIC_LIBRARIES
-
-LOCAL_MODULE_TAGS := optional
-
-LOCAL_STRIP_MODULE := keep_symbols
-
-generated_sources_dir := $(call local-generated-sources-dir)
-LOCAL_EXPORT_C_INCLUDE_DIRS := \
-    $(generated_sources_dir)/proto/$(LOCAL_PATH)/impl/vhal_v2_0/proto
-
-include $(BUILD_STATIC_LIBRARY)
-
-
-###############################################################################
-# Vehicle default VehicleHAL implementation
-###############################################################################
-include $(CLEAR_VARS)
-
-LOCAL_MODULE:= $(vhal_v2_0)-default-impl-lib
-LOCAL_SRC_FILES:= \
-    impl/vhal_v2_0/EmulatedVehicleHal.cpp \
-    impl/vhal_v2_0/VehicleEmulator.cpp \
-    impl/vhal_v2_0/PipeComm.cpp \
-    impl/vhal_v2_0/SocketComm.cpp \
-
-LOCAL_C_INCLUDES := \
-    $(LOCAL_PATH)/impl/vhal_v2_0
-
-LOCAL_EXPORT_C_INCLUDE_DIRS := \
-    $(LOCAL_PATH)/impl
-
-LOCAL_WHOLE_STATIC_LIBRARIES := \
-    $(vhal_v2_0)-manager-lib \
-
-LOCAL_SHARED_LIBRARIES := \
-    libbase \
-    libhidlbase \
-    libhidltransport \
-    liblog \
-    libprotobuf-cpp-lite \
-    libutils \
-    $(vhal_v2_0) \
-
-LOCAL_STATIC_LIBRARIES := \
-    libqemu_pipe \
-    $(vhal_v2_0)-libproto-native \
-
-LOCAL_CFLAGS += -Wall -Wextra -Werror
-
-include $(BUILD_STATIC_LIBRARY)
-
-
-###############################################################################
-# Vehicle reference implementation unit tests
-###############################################################################
-include $(CLEAR_VARS)
-
-LOCAL_MODULE:= $(vhal_v2_0)-manager-unit-tests
-
-LOCAL_WHOLE_STATIC_LIBRARIES := \
-    $(vhal_v2_0)-manager-lib \
-
-LOCAL_SRC_FILES:= \
-    tests/RecurrentTimer_test.cpp \
-    tests/SubscriptionManager_test.cpp \
-    tests/VehicleHalManager_test.cpp \
-    tests/VehicleObjectPool_test.cpp \
-    tests/VehiclePropConfigIndex_test.cpp \
-
-LOCAL_HEADER_LIBRARIES := \
-    libbase_headers
-
-LOCAL_SHARED_LIBRARIES := \
-    libhidlbase \
-    libhidltransport \
-    liblog \
-    libutils \
-    $(vhal_v2_0) \
-
-LOCAL_CFLAGS += -Wall -Wextra -Werror
-LOCAL_MODULE_TAGS := tests
-
-include $(BUILD_NATIVE_TEST)
-
-
-###############################################################################
-# Vehicle HAL service
-###############################################################################
-include $(CLEAR_VARS)
-LOCAL_MODULE := $(vhal_v2_0)-service
-LOCAL_INIT_RC := $(vhal_v2_0)-service.rc
-LOCAL_PROPRIETARY_MODULE := true
-LOCAL_MODULE_RELATIVE_PATH := hw
-
-LOCAL_SRC_FILES := \
-    VehicleService.cpp
-
-LOCAL_SHARED_LIBRARIES := \
-    libbase \
-    libhidlbase \
-    libhidltransport \
-    liblog \
-    libprotobuf-cpp-lite \
-    libutils \
-    $(vhal_v2_0) \
-
-LOCAL_STATIC_LIBRARIES := \
-    $(vhal_v2_0)-manager-lib \
-    $(vhal_v2_0)-default-impl-lib \
-    $(vhal_v2_0)-libproto-native \
-    libqemu_pipe \
-
-LOCAL_CFLAGS += -Wall -Wextra -Werror
-
-include $(BUILD_EXECUTABLE)
diff --git a/automotive/vehicle/2.1/default/common/include/vhal_v2_1/Obd2SensorStore.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/Obd2SensorStore.h
similarity index 76%
rename from automotive/vehicle/2.1/default/common/include/vhal_v2_1/Obd2SensorStore.h
rename to automotive/vehicle/2.0/default/common/include/vhal_v2_0/Obd2SensorStore.h
index 6c44626..191a565 100644
--- a/automotive/vehicle/2.1/default/common/include/vhal_v2_1/Obd2SensorStore.h
+++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/Obd2SensorStore.h
@@ -14,38 +14,37 @@
  * limitations under the License.
  */
 
-#ifndef android_hardware_automotive_vehicle_V2_1_Obd2SensorStore_H_
-#define android_hardware_automotive_vehicle_V2_1_Obd2SensorStore_H_
+#ifndef android_hardware_automotive_vehicle_V2_0_Obd2SensorStore_H_
+#define android_hardware_automotive_vehicle_V2_0_Obd2SensorStore_H_
 
 #include <vector>
 
-#include <android/hardware/automotive/vehicle/2.1/types.h>
+#include <android/hardware/automotive/vehicle/2.0/types.h>
 
 namespace android {
 namespace hardware {
 namespace automotive {
 namespace vehicle {
-namespace V2_1 {
+namespace V2_0 {
 
 // This class wraps all the logic required to create an OBD2 frame.
 // It allows storing sensor values, setting appropriate bitmasks as needed,
 // and returning appropriately laid out storage of sensor values suitable
 // for being returned via a VehicleHal implementation.
 class Obd2SensorStore {
-public:
+   public:
     // Creates a sensor storage with a given number of vendor-specific sensors.
-    Obd2SensorStore(size_t numVendorIntegerSensors,
-                    size_t numVendorFloatSensors);
+    Obd2SensorStore(size_t numVendorIntegerSensors, size_t numVendorFloatSensors);
 
     // Stores an integer-valued sensor.
-    V2_0::StatusCode setIntegerSensor(Obd2IntegerSensorIndex index, int32_t value);
+    StatusCode setIntegerSensor(DiagnosticIntegerSensorIndex index, int32_t value);
     // Stores an integer-valued sensor.
-    V2_0::StatusCode setIntegerSensor(size_t index, int32_t value);
+    StatusCode setIntegerSensor(size_t index, int32_t value);
 
     // Stores a float-valued sensor.
-    V2_0::StatusCode setFloatSensor(Obd2FloatSensorIndex index, float value);
+    StatusCode setFloatSensor(DiagnosticFloatSensorIndex index, float value);
     // Stores a float-valued sensor.
-    V2_0::StatusCode setFloatSensor(size_t index, float value);
+    StatusCode setFloatSensor(size_t index, float value);
 
     // Returns a vector that contains all integer sensors stored.
     const std::vector<int32_t>& getIntegerSensors() const;
@@ -55,11 +54,11 @@
     const std::vector<uint8_t>& getSensorsBitmask() const;
 
     // Given a stringValue, fill in a VehiclePropValue
-    void fillPropValue(const std::string& dtc, V2_0::VehiclePropValue *propValue) const;
+    void fillPropValue(const std::string& dtc, VehiclePropValue* propValue) const;
 
-private:
+   private:
     class BitmaskInVector {
-    public:
+       public:
         BitmaskInVector(size_t numBits = 0);
         void resize(size_t numBits);
         bool get(size_t index) const;
@@ -67,7 +66,7 @@
 
         const std::vector<uint8_t>& getBitmask() const;
 
-    private:
+       private:
         std::vector<uint8_t> mStorage;
     };
 
@@ -76,7 +75,7 @@
     BitmaskInVector mSensorsBitmask;
 };
 
-}  // namespace V2_1
+}  // namespace V2_0
 }  // namespace vehicle
 }  // namespace automotive
 }  // namespace hardware
diff --git a/automotive/vehicle/2.1/default/common/src/Obd2SensorStore.cpp b/automotive/vehicle/2.0/default/common/src/Obd2SensorStore.cpp
similarity index 62%
rename from automotive/vehicle/2.1/default/common/src/Obd2SensorStore.cpp
rename to automotive/vehicle/2.0/default/common/src/Obd2SensorStore.cpp
index f4c63a9..65174f7 100644
--- a/automotive/vehicle/2.1/default/common/src/Obd2SensorStore.cpp
+++ b/automotive/vehicle/2.0/default/common/src/Obd2SensorStore.cpp
@@ -23,23 +23,21 @@
 namespace hardware {
 namespace automotive {
 namespace vehicle {
-namespace V2_1 {
+namespace V2_0 {
 
-Obd2SensorStore::BitmaskInVector::BitmaskInVector(size_t numBits)
-{
+Obd2SensorStore::BitmaskInVector::BitmaskInVector(size_t numBits) {
     resize(numBits);
 }
 
 void Obd2SensorStore::BitmaskInVector::resize(size_t numBits) {
-    mStorage = std::vector<uint8_t>((numBits+7)/8, 0);
+    mStorage = std::vector<uint8_t>((numBits + 7) / 8, 0);
 }
 
 void Obd2SensorStore::BitmaskInVector::set(size_t index, bool value) {
     const size_t byteIndex = index / 8;
     const size_t bitIndex = index % 8;
     const uint8_t byte = mStorage[byteIndex];
-    uint8_t newValue = value ? (byte | (1 << bitIndex)) :
-                               (byte & ~(1 << bitIndex));
+    uint8_t newValue = value ? (byte | (1 << bitIndex)) : (byte & ~(1 << bitIndex));
     mStorage[byteIndex] = newValue;
 }
 
@@ -54,37 +52,33 @@
     return mStorage;
 }
 
-Obd2SensorStore::Obd2SensorStore(size_t numVendorIntegerSensors,
-                                 size_t numVendorFloatSensors) {
-        // because the last index is valid *inclusive*
-        const size_t numSystemIntegerSensors = V2_0::toInt(Obd2IntegerSensorIndex::LAST_SYSTEM_INDEX)+1;
-        const size_t numSystemFloatSensors = V2_0::toInt(Obd2FloatSensorIndex::LAST_SYSTEM_INDEX)+1;
-        mIntegerSensors = std::vector<int32_t>(
-            numSystemIntegerSensors+numVendorIntegerSensors, 0);
-        mFloatSensors = std::vector<float>(
-            numSystemFloatSensors+numVendorFloatSensors, 0);
-        mSensorsBitmask.resize(mIntegerSensors.size()+mFloatSensors.size());
+Obd2SensorStore::Obd2SensorStore(size_t numVendorIntegerSensors, size_t numVendorFloatSensors) {
+    // because the last index is valid *inclusive*
+    const size_t numSystemIntegerSensors =
+        toInt(DiagnosticIntegerSensorIndex::LAST_SYSTEM_INDEX) + 1;
+    const size_t numSystemFloatSensors = toInt(DiagnosticFloatSensorIndex::LAST_SYSTEM_INDEX) + 1;
+    mIntegerSensors = std::vector<int32_t>(numSystemIntegerSensors + numVendorIntegerSensors, 0);
+    mFloatSensors = std::vector<float>(numSystemFloatSensors + numVendorFloatSensors, 0);
+    mSensorsBitmask.resize(mIntegerSensors.size() + mFloatSensors.size());
 }
 
-V2_0::StatusCode Obd2SensorStore::setIntegerSensor(Obd2IntegerSensorIndex index,
-    int32_t value) {
-    return setIntegerSensor(V2_0::toInt(index), value);
+StatusCode Obd2SensorStore::setIntegerSensor(DiagnosticIntegerSensorIndex index, int32_t value) {
+    return setIntegerSensor(toInt(index), value);
 }
-V2_0::StatusCode Obd2SensorStore::setFloatSensor(Obd2FloatSensorIndex index,
-    float value) {
-    return setFloatSensor(V2_0::toInt(index), value);
+StatusCode Obd2SensorStore::setFloatSensor(DiagnosticFloatSensorIndex index, float value) {
+    return setFloatSensor(toInt(index), value);
 }
 
-V2_0::StatusCode Obd2SensorStore::setIntegerSensor(size_t index, int32_t value) {
+StatusCode Obd2SensorStore::setIntegerSensor(size_t index, int32_t value) {
     mIntegerSensors[index] = value;
     mSensorsBitmask.set(index, true);
-    return V2_0::StatusCode::OK;
+    return StatusCode::OK;
 }
 
-V2_0::StatusCode Obd2SensorStore::setFloatSensor(size_t index, float value) {
+StatusCode Obd2SensorStore::setFloatSensor(size_t index, float value) {
     mFloatSensors[index] = value;
     mSensorsBitmask.set(index + mIntegerSensors.size(), true);
-    return V2_0::StatusCode::OK;
+    return StatusCode::OK;
 }
 
 const std::vector<int32_t>& Obd2SensorStore::getIntegerSensors() const {
@@ -99,8 +93,7 @@
     return mSensorsBitmask.getBitmask();
 }
 
-void Obd2SensorStore::fillPropValue(const std::string& dtc,
-                                    V2_0::VehiclePropValue *propValue) const {
+void Obd2SensorStore::fillPropValue(const std::string& dtc, VehiclePropValue* propValue) const {
     propValue->timestamp = elapsedRealtimeNano();
     propValue->value.int32Values = getIntegerSensors();
     propValue->value.floatValues = getFloatSensors();
@@ -108,8 +101,6 @@
     propValue->value.stringValue = dtc;
 }
 
-
-
 }  // namespace V2_0
 }  // namespace vehicle
 }  // namespace automotive
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
index fb63e36..08d3d79 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
@@ -27,6 +27,18 @@
 namespace V2_0 {
 
 namespace impl {
+//
+// Some handy constants to avoid conversions from enum to int.
+constexpr int ABS_ACTIVE = (int)VehicleProperty::ABS_ACTIVE;
+constexpr int OBD2_LIVE_FRAME = (int)VehicleProperty::OBD2_LIVE_FRAME;
+constexpr int OBD2_FREEZE_FRAME = (int)VehicleProperty::OBD2_FREEZE_FRAME;
+constexpr int OBD2_FREEZE_FRAME_INFO = (int)VehicleProperty::OBD2_FREEZE_FRAME_INFO;
+constexpr int OBD2_FREEZE_FRAME_CLEAR = (int)VehicleProperty::OBD2_FREEZE_FRAME_CLEAR;
+constexpr int TRACTION_CONTROL_ACTIVE = (int)VehicleProperty::TRACTION_CONTROL_ACTIVE;
+constexpr int VEHICLE_MAP_SERVICE = (int)VehicleProperty::VEHICLE_MAP_SERVICE;
+constexpr int WHEEL_TICK = (int)VehicleProperty::WHEEL_TICK;
+constexpr int ALL_WHEELS =
+    (int)(Wheel::LEFT_FRONT | Wheel::RIGHT_FRONT | Wheel::LEFT_REAR | Wheel::RIGHT_REAR);
 
 /*
  * This property is used for test purpose to generate fake events.
@@ -283,8 +295,68 @@
              .access = VehiclePropertyAccess::READ,
              .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
          },
-     .initialValue = {.int32Values = {1}}}
+     .initialValue = {.int32Values = {1}}},
 
+    {
+        .config =
+            {
+                .prop = WHEEL_TICK,
+                .access = VehiclePropertyAccess::READ,
+                .changeMode = VehiclePropertyChangeMode::CONTINUOUS,
+                .configArray = {ALL_WHEELS, 50000, 50000, 50000, 50000},
+                .minSampleRate = 1.0f,
+                .maxSampleRate = 100.0f,
+            },
+    },
+
+    {
+        .config =
+            {
+                .prop = ABS_ACTIVE,
+                .access = VehiclePropertyAccess::READ,
+                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+            },
+    },
+
+    {
+        .config =
+            {
+                .prop = TRACTION_CONTROL_ACTIVE,
+                .access = VehiclePropertyAccess::READ,
+                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+            },
+    },
+
+    {
+        .config = {.prop = OBD2_LIVE_FRAME,
+                   .access = VehiclePropertyAccess::READ,
+                   .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                   .configArray = {0, 0}},
+    },
+
+    {
+        .config = {.prop = OBD2_FREEZE_FRAME,
+                   .access = VehiclePropertyAccess::READ,
+                   .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                   .configArray = {0, 0}},
+    },
+
+    {
+        .config = {.prop = OBD2_FREEZE_FRAME_INFO,
+                   .access = VehiclePropertyAccess::READ,
+                   .changeMode = VehiclePropertyChangeMode::ON_CHANGE},
+    },
+
+    {
+        .config = {.prop = OBD2_FREEZE_FRAME_CLEAR,
+                   .access = VehiclePropertyAccess::WRITE,
+                   .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                   .configArray = {1}},
+    },
+
+    {.config = {.prop = VEHICLE_MAP_SERVICE,
+                .access = VehiclePropertyAccess::READ_WRITE,
+                .changeMode = VehiclePropertyChangeMode::ON_CHANGE}},
 };
 
 }  // impl
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
index fe34a3f..6bc0522 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
@@ -19,6 +19,7 @@
 #include <android-base/macros.h>
 
 #include "EmulatedVehicleHal.h"
+#include "Obd2SensorStore.h"
 
 namespace android {
 namespace hardware {
@@ -28,6 +29,62 @@
 
 namespace impl {
 
+static std::unique_ptr<Obd2SensorStore> fillDefaultObd2Frame(size_t numVendorIntegerSensors,
+                                                             size_t numVendorFloatSensors) {
+    std::unique_ptr<Obd2SensorStore> sensorStore(
+        new Obd2SensorStore(numVendorIntegerSensors, numVendorFloatSensors));
+
+    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::FUEL_SYSTEM_STATUS,
+                                  toInt(Obd2FuelSystemStatus::CLOSED_LOOP));
+    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::MALFUNCTION_INDICATOR_LIGHT_ON, 0);
+    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::IGNITION_MONITORS_SUPPORTED,
+                                  toInt(Obd2IgnitionMonitorKind::SPARK));
+    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::IGNITION_SPECIFIC_MONITORS,
+                                  Obd2CommonIgnitionMonitors::COMPONENTS_AVAILABLE |
+                                      Obd2CommonIgnitionMonitors::MISFIRE_AVAILABLE |
+                                      Obd2SparkIgnitionMonitors::AC_REFRIGERANT_AVAILABLE |
+                                      Obd2SparkIgnitionMonitors::EVAPORATIVE_SYSTEM_AVAILABLE);
+    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::INTAKE_AIR_TEMPERATURE, 35);
+    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::COMMANDED_SECONDARY_AIR_STATUS,
+                                  toInt(Obd2SecondaryAirStatus::FROM_OUTSIDE_OR_OFF));
+    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::NUM_OXYGEN_SENSORS_PRESENT, 1);
+    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::RUNTIME_SINCE_ENGINE_START, 500);
+    sensorStore->setIntegerSensor(
+        DiagnosticIntegerSensorIndex::DISTANCE_TRAVELED_WITH_MALFUNCTION_INDICATOR_LIGHT_ON, 0);
+    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::WARMUPS_SINCE_CODES_CLEARED, 51);
+    sensorStore->setIntegerSensor(
+        DiagnosticIntegerSensorIndex::DISTANCE_TRAVELED_SINCE_CODES_CLEARED, 365);
+    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::ABSOLUTE_BAROMETRIC_PRESSURE, 30);
+    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::CONTROL_MODULE_VOLTAGE, 12);
+    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::AMBIENT_AIR_TEMPERATURE, 18);
+    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::MAX_FUEL_AIR_EQUIVALENCE_RATIO, 1);
+    sensorStore->setIntegerSensor(DiagnosticIntegerSensorIndex::FUEL_TYPE,
+                                  toInt(Obd2FuelType::GASOLINE));
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::CALCULATED_ENGINE_LOAD, 0.153);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::SHORT_TERM_FUEL_TRIM_BANK1, -0.16);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::LONG_TERM_FUEL_TRIM_BANK1, -0.16);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::SHORT_TERM_FUEL_TRIM_BANK2, -0.16);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::LONG_TERM_FUEL_TRIM_BANK2, -0.16);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::INTAKE_MANIFOLD_ABSOLUTE_PRESSURE, 7.5);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::ENGINE_RPM, 1250.);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::VEHICLE_SPEED, 40.);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::TIMING_ADVANCE, 2.5);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::THROTTLE_POSITION, 19.75);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::OXYGEN_SENSOR1_VOLTAGE, 0.265);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::FUEL_TANK_LEVEL_INPUT, 0.824);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::EVAPORATION_SYSTEM_VAPOR_PRESSURE,
+                                -0.373);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::CATALYST_TEMPERATURE_BANK1_SENSOR1,
+                                190.);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::RELATIVE_THROTTLE_POSITION, 3.);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::ABSOLUTE_THROTTLE_POSITION_B, 0.306);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::ACCELERATOR_PEDAL_POSITION_D, 0.188);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::ACCELERATOR_PEDAL_POSITION_E, 0.094);
+    sensorStore->setFloatSensor(DiagnosticFloatSensorIndex::COMMANDED_THROTTLE_ACTUATOR, 0.024);
+
+    return sensorStore;
+}
+
 enum class FakeDataCommand : int32_t {
     Stop = 0,
     Start = 1,
@@ -40,7 +97,7 @@
                                   this, std::placeholders::_1)),
       mFakeValueGenerator(std::bind(&EmulatedVehicleHal::onFakeValueGenerated,
                                     this, std::placeholders::_1, std::placeholders::_2)) {
-
+    initStaticConfig();
     for (size_t i = 0; i < arraysize(kVehicleProperties); i++) {
         mPropStore->registerProperty(kVehicleProperties[i].config);
     }
@@ -48,23 +105,39 @@
 
 VehicleHal::VehiclePropValuePtr EmulatedVehicleHal::get(
         const VehiclePropValue& requestedPropValue, StatusCode* outStatus) {
+    auto propId = requestedPropValue.prop;
+    auto& pool = *getValuePool();
     VehiclePropValuePtr v = nullptr;
 
-    auto internalPropValue = mPropStore->readValueOrNull(requestedPropValue);
-    if (internalPropValue != nullptr) {
-        v = getValuePool()->obtain(*internalPropValue);
+    switch (propId) {
+        case OBD2_FREEZE_FRAME:
+            v = pool.obtainComplex();
+            *outStatus = fillObd2FreezeFrame(requestedPropValue, v.get());
+            break;
+        case OBD2_FREEZE_FRAME_INFO:
+            v = pool.obtainComplex();
+            *outStatus = fillObd2DtcInfo(v.get());
+            break;
+        default:
+            auto internalPropValue = mPropStore->readValueOrNull(requestedPropValue);
+            if (internalPropValue != nullptr) {
+                v = getValuePool()->obtain(*internalPropValue);
+            }
+
+            *outStatus = v != nullptr ? StatusCode::OK : StatusCode::INVALID_ARG;
+            break;
     }
 
-    *outStatus = v != nullptr ? StatusCode::OK : StatusCode::INVALID_ARG;
     return v;
 }
 
 StatusCode EmulatedVehicleHal::set(const VehiclePropValue& propValue) {
     if (propValue.prop == kGenerateFakeDataControllingProperty) {
-        return handleGenerateFakeDataRequest(propValue);
-    };
-
-    if (mHvacPowerProps.count(propValue.prop)) {
+        StatusCode status = handleGenerateFakeDataRequest(propValue);
+        if (status != StatusCode::OK) {
+            return status;
+        }
+    } else if (mHvacPowerProps.count(propValue.prop)) {
         auto hvacPowerOn = mPropStore->readValueOrNull(toInt(VehicleProperty::HVAC_POWER_ON),
                                                       toInt(VehicleAreaZone::ROW_1));
 
@@ -72,6 +145,12 @@
                 && hvacPowerOn->value.int32Values[0] == 0) {
             return StatusCode::NOT_AVAILABLE;
         }
+    } else if (propValue.prop == OBD2_FREEZE_FRAME_CLEAR) {
+        return clearObd2FreezeFrames(propValue);
+    } else if (propValue.prop == VEHICLE_MAP_SERVICE) {
+        // Placeholder for future implementation of VMS property in the default hal. For now, just
+        // returns OK; otherwise, hal clients crash with property not supported.
+        return StatusCode::OK;
     }
 
     if (!mPropStore->writeValue(propValue)) {
@@ -83,12 +162,29 @@
     return StatusCode::OK;
 }
 
+static bool isDiagnosticProperty(VehiclePropConfig propConfig) {
+    switch (propConfig.prop) {
+        case OBD2_LIVE_FRAME:
+        case OBD2_FREEZE_FRAME:
+        case OBD2_FREEZE_FRAME_CLEAR:
+        case OBD2_FREEZE_FRAME_INFO:
+            return true;
+    }
+    return false;
+}
+
 // Parse supported properties list and generate vector of property values to hold current values.
 void EmulatedVehicleHal::onCreate() {
     for (auto& it : kVehicleProperties) {
         VehiclePropConfig cfg = it.config;
         int32_t supportedAreas = cfg.supportedAreas;
 
+        if (isDiagnosticProperty(cfg)) {
+            // do not write an initial empty value for the diagnostic properties
+            // as we will initialize those separately.
+            continue;
+        }
+
         //  A global property will have supportedAreas = 0
         if (isGlobalProp(cfg.prop)) {
             supportedAreas = 0;
@@ -120,6 +216,8 @@
 
         } while (supportedAreas != 0);
     }
+    initObd2LiveFrame(*mPropStore->getConfigOrDie(OBD2_LIVE_FRAME));
+    initObd2FreezeFrame(*mPropStore->getConfigOrDie(OBD2_FREEZE_FRAME));
 }
 
 std::vector<VehiclePropConfig> EmulatedVehicleHal::listProperties()  {
@@ -176,6 +274,13 @@
 }
 
 bool EmulatedVehicleHal::setPropertyFromVehicle(const VehiclePropValue& propValue) {
+    if (propValue.prop == kGenerateFakeDataControllingProperty) {
+        StatusCode status = handleGenerateFakeDataRequest(propValue);
+        if (status != StatusCode::OK) {
+            return false;
+        }
+    }
+
     if (mPropStore->writeValue(propValue)) {
         doHalEvent(getValuePool()->obtain(propValue));
         return true;
@@ -263,6 +368,100 @@
     }
 }
 
+void EmulatedVehicleHal::initStaticConfig() {
+    for (auto&& it = std::begin(kVehicleProperties); it != std::end(kVehicleProperties); ++it) {
+        const auto& cfg = it->config;
+        VehiclePropertyStore::TokenFunction tokenFunction = nullptr;
+
+        switch (cfg.prop) {
+            case OBD2_FREEZE_FRAME: {
+                tokenFunction = [](const VehiclePropValue& propValue) {
+                    return propValue.timestamp;
+                };
+                break;
+            }
+            default:
+                break;
+        }
+
+        mPropStore->registerProperty(cfg, tokenFunction);
+    }
+}
+
+void EmulatedVehicleHal::initObd2LiveFrame(const VehiclePropConfig& propConfig) {
+    auto liveObd2Frame = createVehiclePropValue(VehiclePropertyType::COMPLEX, 0);
+    auto sensorStore = fillDefaultObd2Frame(static_cast<size_t>(propConfig.configArray[0]),
+                                            static_cast<size_t>(propConfig.configArray[1]));
+    sensorStore->fillPropValue("", liveObd2Frame.get());
+    liveObd2Frame->prop = OBD2_LIVE_FRAME;
+
+    mPropStore->writeValue(*liveObd2Frame);
+}
+
+void EmulatedVehicleHal::initObd2FreezeFrame(const VehiclePropConfig& propConfig) {
+    auto sensorStore = fillDefaultObd2Frame(static_cast<size_t>(propConfig.configArray[0]),
+                                            static_cast<size_t>(propConfig.configArray[1]));
+
+    static std::vector<std::string> sampleDtcs = {"P0070",
+                                                  "P0102"
+                                                  "P0123"};
+    for (auto&& dtc : sampleDtcs) {
+        auto freezeFrame = createVehiclePropValue(VehiclePropertyType::COMPLEX, 0);
+        sensorStore->fillPropValue(dtc, freezeFrame.get());
+        freezeFrame->prop = OBD2_FREEZE_FRAME;
+
+        mPropStore->writeValue(*freezeFrame);
+    }
+}
+
+StatusCode EmulatedVehicleHal::fillObd2FreezeFrame(const VehiclePropValue& requestedPropValue,
+                                                   VehiclePropValue* outValue) {
+    if (requestedPropValue.value.int64Values.size() != 1) {
+        ALOGE("asked for OBD2_FREEZE_FRAME without valid timestamp");
+        return StatusCode::INVALID_ARG;
+    }
+    auto timestamp = requestedPropValue.value.int64Values[0];
+    auto freezeFrame = mPropStore->readValueOrNull(OBD2_FREEZE_FRAME, 0, timestamp);
+    if (freezeFrame == nullptr) {
+        ALOGE("asked for OBD2_FREEZE_FRAME at invalid timestamp");
+        return StatusCode::INVALID_ARG;
+    }
+    outValue->prop = OBD2_FREEZE_FRAME;
+    outValue->value.int32Values = freezeFrame->value.int32Values;
+    outValue->value.floatValues = freezeFrame->value.floatValues;
+    outValue->value.bytes = freezeFrame->value.bytes;
+    outValue->value.stringValue = freezeFrame->value.stringValue;
+    outValue->timestamp = freezeFrame->timestamp;
+    return StatusCode::OK;
+}
+
+StatusCode EmulatedVehicleHal::clearObd2FreezeFrames(const VehiclePropValue& propValue) {
+    if (propValue.value.int64Values.size() == 0) {
+        mPropStore->removeValuesForProperty(OBD2_FREEZE_FRAME);
+        return StatusCode::OK;
+    } else {
+        for (int64_t timestamp : propValue.value.int64Values) {
+            auto freezeFrame = mPropStore->readValueOrNull(OBD2_FREEZE_FRAME, 0, timestamp);
+            if (freezeFrame == nullptr) {
+                ALOGE("asked for OBD2_FREEZE_FRAME at invalid timestamp");
+                return StatusCode::INVALID_ARG;
+            }
+            mPropStore->removeValue(*freezeFrame);
+        }
+    }
+    return StatusCode::OK;
+}
+
+StatusCode EmulatedVehicleHal::fillObd2DtcInfo(VehiclePropValue* outValue) {
+    std::vector<int64_t> timestamps;
+    for (const auto& freezeFrame : mPropStore->readValuesForProperty(OBD2_FREEZE_FRAME)) {
+        timestamps.push_back(freezeFrame.timestamp);
+    }
+    outValue->value.int64Values = timestamps;
+    outValue->prop = OBD2_FREEZE_FRAME_INFO;
+    return StatusCode::OK;
+}
+
 }  // impl
 
 }  // namespace V2_0
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
index c25e083..99d7edb 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
@@ -70,8 +70,15 @@
 
     void onContinuousPropertyTimer(const std::vector<int32_t>& properties);
     bool isContinuousProperty(int32_t propId) const;
+    void initStaticConfig();
+    void initObd2LiveFrame(const VehiclePropConfig& propConfig);
+    void initObd2FreezeFrame(const VehiclePropConfig& propConfig);
+    StatusCode fillObd2FreezeFrame(const VehiclePropValue& requestedPropValue,
+                                   VehiclePropValue* outValue);
+    StatusCode fillObd2DtcInfo(VehiclePropValue* outValue);
+    StatusCode clearObd2FreezeFrames(const VehiclePropValue& propValue);
 
-private:
+    /* Private members */
     VehiclePropertyStore* mPropStore;
     std::unordered_set<int32_t> mHvacPowerProps;
     RecurrentTimer mRecurrentTimer;
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/Android.bp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/Android.bp
new file mode 100644
index 0000000..ec35200
--- /dev/null
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/proto/Android.bp
@@ -0,0 +1,27 @@
+// 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.
+
+// Vehicle HAL Protobuf library
+cc_library_static {
+    name: "android.hardware.automotive.vehicle@2.0-libproto-native",
+    vendor: true,
+    proto: {
+        export_proto_headers: true,
+        type: "lite",
+    },
+    strip: {
+        keep_symbols: true,
+    },
+    srcs: ["VehicleHalProto.proto"]
+}
diff --git a/automotive/vehicle/2.0/default/tests/VehicleHalTestUtils.h b/automotive/vehicle/2.0/default/tests/VehicleHalTestUtils.h
index 28e1a5a..2a06417 100644
--- a/automotive/vehicle/2.0/default/tests/VehicleHalTestUtils.h
+++ b/automotive/vehicle/2.0/default/tests/VehicleHalTestUtils.h
@@ -222,54 +222,6 @@
     return ss.str();
 }
 
-inline std::string toString(const VehiclePropValue &v) {
-    std::stringstream ss;
-    ss << "VehiclePropValue {n"
-       << "  prop: " << hexString(v.prop) << ",\n"
-       << "  areaId: " << hexString(v.areaId) << ",\n"
-       << "  timestamp: " << v.timestamp << ",\n"
-       << "  value {\n"
-       << "    int32Values: " << vecToString(v.value.int32Values) << ",\n"
-       << "    floatValues: " << vecToString(v.value.floatValues) << ",\n"
-       << "    int64Values: " << vecToString(v.value.int64Values) << ",\n"
-       << "    bytes: " << vecToString(v.value.bytes) << ",\n"
-       << "    string: " << v.value.stringValue.c_str() << ",\n"
-       << "  }\n"
-       << "}\n";
-
-    return ss.str();
-}
-
-inline std::string toString(const VehiclePropConfig &config) {
-    std::stringstream ss;
-    ss << "VehiclePropConfig {\n"
-       << "  prop: " << hexString(config.prop) << ",\n"
-       << "  supportedAreas: " << hexString(config.supportedAreas) << ",\n"
-       << "  access: " << enumToHexString(config.access) << ",\n"
-       << "  changeMode: " << enumToHexString(config.changeMode) << ",\n"
-       << "  configFlags: " << hexString(config.configFlags) << ",\n"
-       << "  minSampleRate: " << config.minSampleRate << ",\n"
-       << "  maxSampleRate: " << config.maxSampleRate << ",\n"
-       << "  configString: " << config.configString.c_str() << ",\n";
-
-    ss << "  areaConfigs {\n";
-    for (size_t i = 0; i < config.areaConfigs.size(); i++) {
-        const auto &area = config.areaConfigs[i];
-        ss << "    areaId: " << hexString(area.areaId) << ",\n"
-           << "    minFloatValue: " << area.minFloatValue << ",\n"
-           << "    minFloatValue: " << area.maxFloatValue << ",\n"
-           << "    minInt32Value: " << area.minInt32Value << ",\n"
-           << "    minInt32Value: " << area.maxInt32Value << ",\n"
-           << "    minInt64Value: " << area.minInt64Value << ",\n"
-           << "    minInt64Value: " << area.maxInt64Value << ",\n";
-    }
-    ss << "  }\n"
-       << "}\n";
-
-    return ss.str();
-}
-
-
 }  // namespace V2_0
 }  // namespace vehicle
 }  // namespace automotive
diff --git a/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal
index f1fb6bf..7c08b4a 100644
--- a/automotive/vehicle/2.0/types.hal
+++ b/automotive/vehicle/2.0/types.hal
@@ -226,6 +226,50 @@
         | VehicleArea:GLOBAL),
 
     /**
+     * Reports wheel ticks
+     *
+     * The first four elements represent ticks for individual wheels in the
+     * following order: front left, front right, rear right, rear left.  All
+     * tick counts are cumulative.  Tick counts increment when the vehicle
+     * moves forward, and decrement when vehicles moves in reverse.  The ticks
+     * should be reset to 0 when the vehicle is started by the user.
+     *
+     * The next element in the vector is a reset count.  A reset indicates
+     * previous tick counts are not comparable with this and future ones.  Some
+     * sort of discontinuity in tick counting has occurred.
+     *
+     *  int64Values[0] = reset count
+     *  int64Values[1] = front left ticks
+     *  int64Values[2] = front right ticks
+     *  int64Values[3] = rear right ticks
+     *  int64Values[4] = rear left ticks
+     *
+     * configArray is used to indicate the micrometers-per-wheel-tick value as well as
+     * which wheels are supported.  configArray is set as follows:
+     *
+     *  configArray[0], bits [0:3] = supported wheels.  Uses enum Wheel.
+     *  configArray[1] = micrometers per front left wheel tick
+     *  configArray[2] = micrometers per front right wheel tick
+     *  configArray[3] = micrometers per rear right wheel tick
+     *  configArray[4] = micrometers per rear left wheel tick
+     *
+     * NOTE:  If a wheel is not supported, its value shall always be set to 0.
+     *
+     * VehiclePropValue.timestamp must be correctly filled in.
+     *
+     * @change_mode VehiclePropertyChangeMode:CONTINUOUS
+     * @access VehiclePropertyAccess:READ
+     *
+     * @since o.mr1
+     */
+    WHEEL_TICK = (
+      0x0306
+      | VehiclePropertyGroup:SYSTEM
+      | VehiclePropertyType:COMPLEX
+      | VehicleArea:GLOBAL),
+
+
+    /**
      * Currently selected gear
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
@@ -328,6 +372,34 @@
             | VehicleArea:GLOBAL),
 
     /**
+     * ABS is active.  Set to true whenever ABS is activated.  Reset to false when ABS is off.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     *
+     * @since o.mr1
+     */
+    ABS_ACTIVE = (
+        0x040A
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:BOOLEAN
+        | VehicleArea:GLOBAL),
+
+    /**
+     * Traction Control is active.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     *
+     * @since o.mr1
+     */
+    TRACTION_CONTROL_ACTIVE = (
+        0x040B
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:BOOLEAN
+        | VehicleArea:GLOBAL),
+
+    /**
      * Fan speed setting
      *
      * IVehicle#set may return StatusCode::NOT_AVAILABLE and IVehicle#get is not
@@ -604,6 +676,24 @@
         | VehicleArea:ZONE),
 
     /**
+     * Represents power state for HVAC. Some HVAC properties must require
+     * matching power to be turned on to get out of OFF state. For non-zoned
+     * HVAC properties, VEHICLE_ALL_ZONE corresponds to global power state.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     * @config_string list of HVAC properties whose power is controlled by this
+     *                property. Format is hexa-decimal number (0x...) separated
+     *                by comma like "0x500,0x503". All zones defined in these
+     *                affected properties must be available in the property.
+     */
+    HVAC_POWER_ON = (
+        0x0510
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:BOOLEAN
+        | VehicleArea:ZONE),
+
+    /**
      * Fan Positions Available
      *
      * This is a bit mask of fan positions available for the zone.  Each entry in
@@ -623,19 +713,18 @@
         | VehicleArea:ZONE),
 
     /**
-     * Represents power state for HVAC. Some HVAC properties must require
-     * matching power to be turned on to get out of OFF state. For non-zoned
-     * HVAC properties, VEHICLE_ALL_ZONE corresponds to global power state.
+     * Automatic re-circulation on/off
+     *
+     * IVehicle#set and IVehicle#get must return StatusCode::NOT_AVAILABLE when HVAC unit is off.
+     * See HVAC_POWER_ON property for details.
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ_WRITE
-     * @config_string list of HVAC properties whose power is controlled by this
-     *                property. Format is hexa-decimal number (0x...) separated
-     *                by comma like "0x500,0x503". All zones defined in these
-     *                affected properties must be available in the property.
+     *
+     * @since o.mr1
      */
-    HVAC_POWER_ON = (
-        0x0510
+    HVAC_AUTO_RECIRC_ON = (
+        0x0512
         | VehiclePropertyGroup:SYSTEM
         | VehiclePropertyType:BOOLEAN
         | VehicleArea:ZONE),
@@ -696,7 +785,8 @@
      * requested by Android side. The focus has both per stream characteristics
      * and global characteristics.
      *
-     * Focus request (get of this property) must take the following form:
+     * Focus request (get of this property) must take the following form with indices defined
+     * by VehicleAudioFocusIndex:
      *   int32Values[0]: VehicleAudioFocusRequest type
      *   int32Values[1]: bit flags of streams requested by this focus request.
      *                   There can be up to 32 streams.
@@ -714,7 +804,7 @@
      *                   REQUEST_RELEASE). In that case, audio module must
      *                   maintain mute state until user's explicit action to
      *                   play some media.
-     *   int32Values[3]: Currently active audio contexts. Use combination of
+     *   int32Values[3]: Audio contexts wishing to be active. Use combination of
      *                   flags from VehicleAudioContextFlag.
      *                   This can be used as a hint to adjust audio policy or
      *                   other policy decision.
@@ -729,7 +819,7 @@
      * request.
      *
      * Focus response (set and subscription callback for this property) must
-     * take the following form:
+     * take the following form with indices defined by VehicleAudioFocusIndex:
      *   int32Values[0]: VehicleAudioFocusState type
      *   int32Values[1]: bit flags of streams allowed.
      *   int32Values[2]: External focus state: bit flags of currently active
@@ -742,22 +832,26 @@
      *                   0 means no active audio focus holder outside Android.
      *                   The state must have following values for each
      *                   VehicleAudioFocusState:
-     *                   GAIN: 0 or VehicleAudioExtFocusFlag#PLAY_ONLY_FLAG
-     *                       when radio is active in Android side.
-     *                   GAIN_TRANSIENT: 0. Can be
+     *                   GAIN: VehicleAudioExtFocusFlag#PLAY_ONLY_FLAG
+     *                       when radio is active in Android side. Otherwise,
+     *                       VehicleAudioExtFocusFlag#NONE_FLAG.
+     *                   GAIN_TRANSIENT: Can be
      *                       VehicleAudioExtFocusFlag#PERMANENT_FLAG or
      *                       VehicleAudioExtFocusFlag#TRANSIENT_FLAG if android
      *                       side has requested
      *                       REQUEST_GAIN_TRANSIENT_MAY_DUCK and car side is
-     *                       ducking.
-     *                   LOSS: 0 when no focus is audio is active in car side.
+     *                       ducking. Otherwise
+     *                       VehicleAudioExtFocusFlag#NONE_FLAG.
+     *                   LOSS: VehicleAudioExtFocusFlag#NONE_FLAG when no focus
+     *                       is active in car side.
      *                       VehicleAudioExtFocusFlag#PERMANENT_FLAG when car
      *                       side is playing something permanent.
-     *                   LOSS_TRANSIENT: always must be
+     *                   LOSS_TRANSIENT: must always be
      *                       VehicleAudioExtFocusFlag#PERMANENT_FLAG
-     *   int32Values[3]: context requested by android side when responding to
-     *                   focus request. When car side is taking focus away,
-     *                   this must be zero.
+     *   int32Values[3]: Audio context(s) allowed to be active. When responding positively to a
+     *                   focus request from Android, the request's original context must be
+     *                   repeated here. When taking focus away, or denying a request, the
+     *                   rejected or stopped context would have its corresponding bit cleared.
      *
      * A focus response must be sent per each focus request even if there is
      * no change in focus state. This can happen in case like focus request
@@ -798,8 +892,8 @@
      *
      * VehiclePropConfig
      *   configArray[0] : bit flags of all supported audio contexts from
-     *                    VehicleAudioContextFlag. If this is 0, audio volume is
-     *                    controlled per physical stream.
+     *                    VehicleAudioContextFlag. If this is 0, audio volume
+     *                    is controlled per physical stream.
      *   configArray[1] : flags defined in VehicleAudioVolumeCapabilityFlag to
      *                    represent audio module's capability.
      *   configArray[2..3] : reserved
@@ -809,7 +903,7 @@
      *                         indicates mute state.
      *
      * Data type looks like:
-     *   int32Values[0] : stream context as defined in VehicleAudioContextFlag.
+     *   int32Values[0] : audio context as defined in VehicleAudioContextFlag.
      *                    If only physical stream is supported
      *                    (configArray[0] == 0), this must represent physical
      *                    stream number.
@@ -817,8 +911,8 @@
      *                    defined in the config.
      *   int32Values[2] : One of VehicleAudioVolumeState.
      *
-     * This property requires per stream based get. HAL implementation must
-     * check stream number in get call to return the right volume.
+     * HAL implementations must check the incoming value of audio context
+     * field in get call to return the right volume.
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ_WRITE
@@ -857,18 +951,18 @@
      *                    to represent audio module's capability.
      *
      * Data type looks like:
-     *   int32Values[0] : stream context as defined in VehicleAudioFocusFlag.
+     *   int32Values[0] : audio context as defined in VehicleAudioContextFlag.
      *                    If only physical stream is supported
      *                    (configArray[0] == 0), this must represent physical
      *                    stream number.
      *   int32Values[1] : maximum volume set to the stream. If there is no
-     *                    restriction, this value must be  bigger than
+     *                    restriction, this value must be equal to
      *                    AUDIO_VOLUME's max value.
      *
      * If car does not support this feature, this property must not be
      * populated by HAL.
-     * This property requires per stream based get. HAL implementation must
-     * check stream number in get call to return the right volume.
+     * HAL implementations must check the incoming value of audio context
+     * field in get call to return the right volume.
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ_WRITE
@@ -882,10 +976,8 @@
 
     /**
      * Property to share audio routing policy of android side. This property is
-     * set at the beginning to pass audio policy in android side down to
+     * set at startup to pass audio policy in android side down to
      * vehicle HAL and car audio module.
-     * This can be used as a hint to adjust audio policy or other policy
-     * decision.
      *
      *   int32Values[0] : audio stream where the audio for the application
      *                    context must be routed by default. Note that this is
@@ -893,7 +985,7 @@
      *                    still use different audio stream for whatever reason.
      *   int32Values[1] : All audio contexts that must be sent through the
      *                     physical stream. Flag is defined in
-     *                     VehicleAudioFocusFlag.
+     *                     VehicleAudioContextFlag.
 
      * Setting of this property must be done for all available physical streams
      * based on audio H/W variant information acquired from AUDIO_HW_VARIANT
@@ -909,11 +1001,11 @@
         | VehicleArea:GLOBAL),
 
     /**
-     * Property to return audio H/W variant type used in this car. This allows
-     * android side to support different audio policy based on H/W variant used.
-     * Note that other components like CarService may need overlay update to
-     * support additional variants. If this property does not
-     * exist, default audio policy must be used.
+     * Property to return audio H/W variant type used in this car. This is a
+     * zero based index into the set of audio routing policies defined in
+     * R.array.audioRoutingPolicy on CarService, which  may be overlaid to
+     * support multiple variants. If this property does not exist, the default
+     * audio policy must be used.
      *
      * @change_mode VehiclePropertyChangeMode:STATIC
      * @access VehiclePropertyAccess:READ
@@ -942,14 +1034,13 @@
      * for the routing.
      * This property can support up to 128 external routings.
      * To give full flexibility, there is no standard definition for each bit
-     * flag and assigning each big flag to specific routing type is decided by
+     * flag and assigning each bit flag to specific routing type is decided by
      * VehiclePropConfig#configString.  VehiclePropConfig#configString has
      * format of each entry separated by ',' and each entry has format of
      * bitFlagPositon:typeString[:physicalStreamNumber].
-     *  bitFlagPosition: represents which big flag will be set to enable this
-     *  routing. 0 means
-     *    LSB in int32Values[0]. 31 will be MSB in int32Values[0]. 127 will MSB
-     *    in int32Values[3].
+     *  bitFlagPosition: represents which bit flag will be set to enable this
+     *    routing. 0 means LSB in int32Values[0]. 31 will be MSB in
+     *    int32Values[0]. 127 will MSB in int32Values[3].
      *  typeString: string representation of external routing. Some types are
      *    already defined in AUDIO_EXT_ROUTING_SOURCE_* and use them first
      *    before adding something custom. Applications will find each routing
@@ -1126,10 +1217,11 @@
      *                    change. Instrument cluster still needs to send
      *                    event with new mode to trigger actual mode change.
      *   int32Values[1] : The current app context relevant for instrument
-     *                    cluster. Use the same flag with VehicleAudioFocusFlag
-     *                    but this context represents active apps, not
-     *                    active audio. Instrument cluster side may change mode
-     *                    depending on the currently active contexts.
+     *                    cluster. Use the same flag with
+     *                    VehicleAudioContextFlag but this context represents
+     *                    active apps, not active audio. Instrument cluster
+     *                    side may change mode depending on the currently
+     *                    active contexts.
      *  When system boots up, Android side will write {0, 0, 0, 0} when it is
      *  ready to render to instrument cluster. Before this message, rendering
      *  from android must not be visible in the cluster.
@@ -1790,85 +1882,240 @@
         | VehiclePropertyGroup:SYSTEM
         | VehiclePropertyType:BOOLEAN
         | VehicleArea:GLOBAL),
+
+
+    /**
+     * Vehicle Maps Service (VMS) message
+     *
+     * This property uses COMPLEX data to communicate vms messages.
+     *
+     * Its contents are to be interpreted as follows:
+     * the indices defined in VmsMessageIntegerValuesIndex are to be used to
+     * read from int32Values;
+     * bytes is a serialized VMS message as defined in the vms protocol
+     * which is opaque to the framework;
+     *
+     * IVehicle#get must always return StatusCode::NOT_AVAILABLE.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ_WRITE
+     *
+     * @since o.mr1
+     */
+    VEHICLE_MAP_SERVICE = (
+        0x0C00
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:COMPLEX
+        | VehicleArea:GLOBAL),
+
+    /**
+     * OBD2 Live Sensor Data
+     *
+     * Reports a snapshot of the current (live) values of the OBD2 sensors available.
+     *
+     * The configArray is set as follows:
+     *   configArray[0] = number of vendor-specific integer-valued sensors
+     *   configArray[1] = number of vendor-specific float-valued sensors
+     *
+     * The values of this property are to be interpreted as in the following example.
+     * Considering a configArray = {2,3}
+     * int32Values must be a vector containing Obd2IntegerSensorIndex.LAST_SYSTEM_INDEX + 2
+     * elements (that is, 33 elements);
+     * floatValues must be a vector containing Obd2FloatSensorIndex.LAST_SYSTEM_INDEX + 3
+     * elements (that is, 73 elements);
+     *
+     * It is possible for each frame to contain a different subset of sensor values, both system
+     * provided sensors, and vendor-specific ones. In order to support that, the bytes element
+     * of the property value is used as a bitmask,.
+     *
+     * bytes must have a sufficient number of bytes to represent the total number of possible
+     * sensors (in this case, 14 bytes to represent 106 possible values); it is to be read as
+     * a contiguous bitmask such that each bit indicates the presence or absence of a sensor
+     * from the frame, starting with as many bits as the size of int32Values, immediately
+     * followed by as many bits as the size of floatValues.
+     *
+     * For example, should bytes[0] = 0x4C (0b01001100) it would mean that:
+     *   int32Values[0 and 1] are not valid sensor values
+     *   int32Values[2 and 3] are valid sensor values
+     *   int32Values[4 and 5] are not valid sensor values
+     *   int32Values[6] is a valid sensor value
+     *   int32Values[7] is not a valid sensor value
+     * Should bytes[5] = 0x61 (0b01100001) it would mean that:
+     *   int32Values[32] is a valid sensor value
+     *   floatValues[0 thru 3] are not valid sensor values
+     *   floatValues[4 and 5] are valid sensor values
+     *   floatValues[6] is not a valid sensor value
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     *
+     * @since o.mr1
+     */
+    OBD2_LIVE_FRAME = (
+      0x0D00
+      | VehiclePropertyGroup:SYSTEM
+      | VehiclePropertyType:COMPLEX
+      | VehicleArea:GLOBAL),
+
+    /**
+     * OBD2 Freeze Frame Sensor Data
+     *
+     * Reports a snapshot of the value of the OBD2 sensors available at the time that a fault
+     * occurred and was detected.
+     *
+     * A configArray must be provided with the same meaning as defined for OBD2_LIVE_FRAME.
+     *
+     * The values of this property are to be interpreted in a similar fashion as those for
+     * OBD2_LIVE_FRAME, with the exception that the stringValue field may contain a non-empty
+     * diagnostic troubleshooting code (DTC).
+     *
+     * A IVehicle#get request of this property must provide a value for int64Values[0].
+     * This will be interpreted as the timestamp of the freeze frame to retrieve. A list of
+     * timestamps can be obtained by a IVehicle#get of OBD2_FREEZE_FRAME_INFO.
+     *
+     * Should no freeze frame be available at the given timestamp, a response of NOT_AVAILABLE
+     * must be returned by the implementation. Because vehicles may have limited storage for
+     * freeze frames, it is possible for a frame request to respond with NOT_AVAILABLE even if
+     * the associated timestamp has been recently obtained via OBD2_FREEZE_FRAME_INFO.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     *
+     * @since o.mr1
+     */
+    OBD2_FREEZE_FRAME = (
+      0x0D01
+      | VehiclePropertyGroup:SYSTEM
+      | VehiclePropertyType:COMPLEX
+      | VehicleArea:GLOBAL),
+
+    /**
+     * OBD2 Freeze Frame Information
+     *
+     * This property describes the current freeze frames stored in vehicle
+     * memory and available for retrieval via OBD2_FREEZE_FRAME.
+     *
+     * The values are to be interpreted as follows:
+     * each element of int64Values must be the timestamp at which a a fault code
+     * has been detected and the corresponding freeze frame stored, and each
+     * such element can be used as the key to OBD2_FREEZE_FRAME to retrieve
+     * the corresponding freeze frame.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     *
+     * @since o.mr1
+     */
+    OBD2_FREEZE_FRAME_INFO = (
+      0x0D02
+      | VehiclePropertyGroup:SYSTEM
+      | VehiclePropertyType:COMPLEX
+      | VehicleArea:GLOBAL),
+
+    /**
+     * OBD2 Freeze Frame Clear
+     *
+     * This property allows deletion of any of the freeze frames stored in
+     * vehicle memory, as described by OBD2_FREEZE_FRAME_INFO.
+     *
+     * The configArray is set as follows:
+     *  configArray[0] = 1 if the implementation is able to clear individual freeze frames
+     *                   by timestamp, 0 otherwise
+     *
+     * IVehicle#set of this property is to be interpreted as follows:
+     *   if int64Values contains no elements, then all frames stored must be cleared;
+     *   if int64Values contains one or more elements, then frames at the timestamps
+     *   stored in int64Values must be cleared, and the others not cleared. Should the
+     *   vehicle not support selective clearing of freeze frames, this latter mode must
+     *   return NOT_AVAILABLE.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:WRITE
+     *
+     * @since o.mr1
+     */
+    OBD2_FREEZE_FRAME_CLEAR = (
+      0x0D03
+      | VehiclePropertyGroup:SYSTEM
+      | VehiclePropertyType:COMPLEX
+      | VehicleArea:GLOBAL),
 };
 
 /**
  * Bit flags for fan direction
  */
 enum VehicleHvacFanDirection : int32_t {
-  FACE = 0x1,
-  FLOOR = 0x2,
-  FACE_AND_FLOOR = 0x3,
-  DEFROST = 0x4,
-  DEFROST_AND_FLOOR = 0x5,
+    FACE = 0x1,
+    FLOOR = 0x2,
+    FACE_AND_FLOOR = 0x3,
+    DEFROST = 0x4,
+    DEFROST_AND_FLOOR = 0x5,
 };
 
 /**
  * Constants relevant to radio.
  */
 enum VehicleRadioConstants : int32_t {
-  /** Minimum value for the radio preset */
-  VEHICLE_RADIO_PRESET_MIN_VALUE = 1,
+    /** Minimum value for the radio preset */
+    VEHICLE_RADIO_PRESET_MIN_VALUE = 1,
 };
 
 enum VehicleAudioFocusRequest : int32_t {
-  REQUEST_GAIN = 0x1,
-  REQUEST_GAIN_TRANSIENT = 0x2,
-  REQUEST_GAIN_TRANSIENT_MAY_DUCK = 0x3,
-  /**
-   * This is for the case where android side plays sound like UI feedback
-   * and car side does not need to duck existing playback as long as
-   * requested stream is available.
-   */
-  REQUEST_GAIN_TRANSIENT_NO_DUCK = 0x4,
-  REQUEST_RELEASE = 0x5,
-
+    REQUEST_GAIN = 0x1,
+    REQUEST_GAIN_TRANSIENT = 0x2,
+    REQUEST_GAIN_TRANSIENT_MAY_DUCK = 0x3,
+    /**
+     * This is for the case where android side plays sound like UI feedback
+     * and car side does not need to duck existing playback as long as
+     * requested stream is available.
+     */
+    REQUEST_GAIN_TRANSIENT_NO_DUCK = 0x4,
+    REQUEST_RELEASE = 0x5,
 };
 
 enum VehicleAudioFocusState : int32_t {
-  /**
-   * Android side has permanent focus and can play allowed streams.
-   */
-  STATE_GAIN = 0x1,
+    /**
+     * Android side has permanent focus and can play allowed streams.
+     */
+    STATE_GAIN = 0x1,
 
-  /**
-   * Android side has transient focus and can play allowed streams.
-   */
-  STATE_GAIN_TRANSIENT = 0x2,
+    /**
+     * Android side has transient focus and can play allowed streams.
+     */
+    STATE_GAIN_TRANSIENT = 0x2,
 
-  /**
-   * Car audio module is playing guidance kind of sound outside Android.
-   * Android side can still play through allowed streams with ducking.
-   */
-  STATE_LOSS_TRANSIENT_CAN_DUCK = 0x3,
+    /**
+     * Car audio module is playing guidance kind of sound outside Android.
+     * Android side can still play through allowed streams with ducking.
+     */
+    STATE_LOSS_TRANSIENT_CAN_DUCK = 0x3,
 
-  /**
-   * Car audio module is playing transient sound outside Android. Android side
-   * must stop playing any sounds.
-   */
-  STATE_LOSS_TRANSIENT = 0x4,
+    /**
+     * Car audio module is playing transient sound outside Android. Android side
+     * must stop playing any sounds.
+     */
+    STATE_LOSS_TRANSIENT = 0x4,
 
-  /**
-   * Android side has lost focus and cannot play any sound.
-   */
-  STATE_LOSS = 0x5,
+    /**
+     * Android side has lost focus and cannot play any sound.
+     */
+    STATE_LOSS = 0x5,
 
-  /**
-   * car audio module is playing safety critical sound, and Android side cannot
-   * request focus until the current state is finished. car audio module
-   * restore it to the previous state when it can allow Android to play.
-   */
-  STATE_LOSS_TRANSIENT_EXLCUSIVE = 0x6,
-
+    /**
+     * car audio module is playing safety critical sound, and Android side cannot
+     * request focus until the current state is finished. car audio module
+     * restore it to the previous state when it can allow Android to play.
+     */
+    STATE_LOSS_TRANSIENT_EXLCUSIVE = 0x6,
 };
 
 /**
  * Flags to represent multiple streams by combining these.
  */
 enum VehicleAudioStreamFlag : int32_t {
-  STREAM0_FLAG = (0x1 << 0),
-  STREAM1_FLAG = (0x1 << 1),
-  STREAM2_FLAG = (0x1 << 2),
+    STREAM0_FLAG = (0x1 << 0),
+    STREAM1_FLAG = (0x1 << 1),
+    STREAM2_FLAG = (0x1 << 2),
 };
 
 /**
@@ -1876,107 +2123,110 @@
  * Can be used for audio related property expecting one stream.
  */
 enum VehicleAudioStream : int32_t {
-  STREAM0 = 0,
-  STREAM1 = 1,
+    STREAM0 = 0,
+    STREAM1 = 1,
 };
 
 /**
  * Flag to represent external focus state (outside Android).
  */
 enum VehicleAudioExtFocusFlag : int32_t {
-  /**
-   * No external focus holder.
-   */
-  NONE_FLAG = 0x0,
+    /**
+     * No external focus holder.
+     */
+    NONE_FLAG = 0x0,
 
-  /**
-   * Car side (outside Android) has component holding GAIN kind of focus state.
-   */
-  PERMANENT_FLAG = 0x1,
+    /**
+     * Car side (outside Android) has component holding GAIN kind of focus state.
+     */
+    PERMANENT_FLAG = 0x1,
 
-  /**
-   * Car side (outside Android) has component holding GAIN_TRANSIENT kind of
-   * focus state.
-   */
-  TRANSIENT_FLAG = 0x2,
+    /**
+     * Car side (outside Android) has component holding GAIN_TRANSIENT kind of
+     * focus state.
+     */
+    TRANSIENT_FLAG = 0x2,
 
-  /**
-   * Car side is expected to play something while focus is held by Android side.
-   * One example can be radio attached in car side. But Android's radio app
-   * still must have focus, and Android side must be in GAIN state, but
-   * media stream will not be allocated to Android side and car side can play
-   * radio any time while this flag is active.
-   */
-  PLAY_ONLY_FLAG = 0x4,
+    /**
+     * Car side is expected to play something while focus is held by Android side.
+     * One example can be radio attached in car side. But Android's radio app
+     * still must have focus, and Android side must be in GAIN state, but
+     * media stream will not be allocated to Android side and car side can play
+     * radio any time while this flag is active.
+     */
+    PLAY_ONLY_FLAG = 0x4,
 
-  /**
-   * Car side must mute any media including radio. This can be used with any
-   * focus request including GAIN* and RELEASE.
-   */
-  MUTE_MEDIA_FLAG = 0x8,
+    /**
+     * Car side must mute any media including radio. This can be used with any
+     * focus request including GAIN* and RELEASE.
+     */
+    MUTE_MEDIA_FLAG = 0x8,
 };
 
 /**
  * Index in int32Values for VehicleProperty#AUDIO_FOCUS property.
  */
 enum VehicleAudioFocusIndex : int32_t {
-  FOCUS = 0,
-  STREAMS = 1,
-  EXTERNAL_FOCUS_STATE = 2,
-  AUDIO_CONTEXTS = 3,
+    FOCUS = 0,
+    STREAMS = 1,
+    EXTERNAL_FOCUS_STATE = 2,
+    AUDIO_CONTEXTS = 3,
 };
 
 /**
  * Flags to tell the current audio context.
  */
 enum VehicleAudioContextFlag : int32_t {
-  /** Music playback is currently active. */
-  MUSIC_FLAG = 0x1,
+    /** Music playback is currently active. */
+    MUSIC_FLAG = 0x1,
 
-  /** Navigation is currently running. */
-  NAVIGATION_FLAG = 0x2,
+    /** Navigation is currently running. */
+    NAVIGATION_FLAG = 0x2,
 
-  /** Voice command session is currently running. */
-  VOICE_COMMAND_FLAG = 0x4,
+    /** Voice command session is currently running. */
+    VOICE_COMMAND_FLAG = 0x4,
 
-  /** Voice call is currently active. */
-  CALL_FLAG = 0x8,
+    /** Voice call is currently active. */
+    CALL_FLAG = 0x8,
 
-  /**
-   * Alarm is active.
-   * This must be only used in VehicleProperty#AUDIO_ROUTING_POLICY.
-   */
-  ALARM_FLAG = 0x10,
+    /**
+     * Alarm is active.
+     * This must be only used in VehicleProperty#AUDIO_ROUTING_POLICY.
+     */
+    ALARM_FLAG = 0x10,
 
-  /**
-   * Notification sound is active.
-   * This must be only used in VehicleProperty#AUDIO_ROUTING_POLICY.
-   */
-  NOTIFICATION_FLAG = 0x20,
+    /**
+     * Notification sound is active.
+     * This must be only used in VehicleProperty#AUDIO_ROUTING_POLICY.
+     */
+    NOTIFICATION_FLAG = 0x20,
 
-  /**
-   * Context unknown. Only used for VehicleProperty#AUDIO_ROUTING_POLICY to
-   * represent default stream for unknown contents.
-   */
-  UNKNOWN_FLAG = 0x40,
+    /**
+     * Context unknown. Only used for VehicleProperty#AUDIO_ROUTING_POLICY to
+     * represent default stream for unknown contents.
+     */
+    UNKNOWN_FLAG = 0x40,
 
-  /** Safety alert / warning is played. */
-  SAFETY_ALERT_FLAG = 0x80,
+    /** Safety alert / warning is played. */
+    SAFETY_ALERT_FLAG = 0x80,
 
-  /** CD / DVD kind of audio is played */
-  CD_ROM_FLAG = 0x100,
+    /** CD / DVD kind of audio is played */
+    CD_ROM_FLAG = 0x100,
 
-  /** Aux audio input is played */
-  AUX_AUDIO_FLAG = 0x200,
+    /** Aux audio input is played */
+    AUX_AUDIO_FLAG = 0x200,
 
-  /** system sound like UI feedback */
-  SYSTEM_SOUND_FLAG = 0x400,
+    /** system sound like UI feedback */
+    SYSTEM_SOUND_FLAG = 0x400,
 
-  /** Radio is played */
-  RADIO_FLAG = 0x800,
+    /** Radio is played */
+    RADIO_FLAG = 0x800,
 
-  /** Ext source is played. This is for tagging generic ext sources. */
-  EXT_SOURCE_FLAG = 0x1000,
+    /** Ext source is played. This is for tagging generic ext sources. */
+    EXT_SOURCE_FLAG = 0x1000,
+
+    /** The phone ring tone is played */
+    RINGTONE_FLAG = 0x2000
 };
 
 /**
@@ -1984,65 +2234,65 @@
  * used in configArray[1] of VehiclePropConfig.
  */
 enum VehicleAudioVolumeCapabilityFlag : int32_t {
-  /**
-   * External audio module or vehicle hal has persistent storage
-   * to keep the volume level. This must be set only when per context
-   * volume level is supported. When this is set, audio volume level per
-   * each context will be retrieved from the property when system starts up.
-   * And external audio module is also expected to adjust volume automatically
-   * whenever there is an audio context change.
-   * When this flag is not set, android side will assume that there is no
-   * persistent storage and stored value in android side will be used to
-   * initialize the volume level. And android side will set volume level
-   * of each physical streams whenever there is an audio context change.
-   */
-  PERSISTENT_STORAGE = 0x1,
+    /**
+     * External audio module or vehicle hal has persistent storage to keep the
+     * volume level. When this is set, the audio volume level for each context
+     * will be retrieved from the property when the system starts up.
+     * And external audio module is also expected to adjust volume automatically
+     * whenever there is an audio context change.
+     * When this flag is not set, android side will assume that there is no
+     * persistent storage and the value stored in the android side will be used to
+     * initialize the volume level, and android side will set volume level
+     * of each physical stream whenever there is an audio context change.
+     */
+    PERSISTENT_STORAGE = 0x1,
 
-  /**
-   * When this flag is set, the H/W can support only single master volume for
-   * all streams.
-   * There is no way to set volume level differently per each stream or context.
-   */
-  MASTER_VOLUME_ONLY = 0x2,
+    /**
+     * [DEPRECATED]
+     * When this flag is set, the H/W can support only single master volume for
+     * all streams. There is no way to set volume level differently for each stream
+     * or context.
+     */
+    MASTER_VOLUME_ONLY = 0x2,
 };
 
 /**
  * enum to represent audio volume state.
  */
 enum VehicleAudioVolumeState : int32_t {
-  STATE_OK = 0,
+    STATE_OK = 0,
 
-  /**
-   * Audio volume has reached volume limit set in
-   * VehicleProperty#AUDIO_VOLUME_LIMIT and user's request to increase volume
-   * further is not allowed.
-   */
-  LIMIT_REACHED = 1,
+    /**
+     * Audio volume has reached volume limit set in
+     * VehicleProperty#AUDIO_VOLUME_LIMIT and user's request to increase volume
+     * further is not allowed.
+     */
+    STATE_LIMIT_REACHED = 1,
 };
 
 /**
  * Index in int32Values for VehicleProperty#AUDIO_VOLUME property.
  */
 enum VehicleAudioVolumeIndex : int32_t {
-  INDEX_STREAM = 0,
-  INDEX_VOLUME = 1,
-  INDEX_STATE = 2,
+    STREAM = 0,
+    VOLUME = 1,
+    STATE = 2,
 };
 
 /**
  * Index in int32Values for VehicleProperty#AUDIO_VOLUME_LIMIT property.
  */
 enum VehicleAudioVolumeLimitIndex : int32_t {
-  STREAM = 0,
-  MAX_VOLUME = 1,
+    STREAM = 0,
+    MAX_VOLUME = 1,
 };
 
 /**
  * Index in int32Values for VehicleProperty#AUDIO_ROUTING_POLICY property.
  */
 enum VehicleAudioRoutingPolicyIndex : int32_t {
-  STREAM = 0,
-  CONTEXTS = 1,
+    STREAM = 0,
+    CONTEXTS = 1,
 };
 
 /**
@@ -2054,172 +2304,172 @@
    * Flag to tell that radio is internal to android and radio must
    * be treated like other android stream like media.
    * When this flag is not set or AUDIO_HW_VARIANT does not exist,
-   * radio is treated as external module. This brins some delta in audio focus
+   * radio is treated as external module. This may affect audio focus
    * handling as well.
    */
   INTERNAL_RADIO_FLAG = 0x1,
 };
 
 enum VehicleApPowerStateConfigFlag : int32_t /* NOTE: type is guessed */ {
-  /**
-   * AP can enter deep sleep state. If not set, AP will always shutdown from
-   * VehicleApPowerState#SHUTDOWN_PREPARE power state.
-   */
-  ENABLE_DEEP_SLEEP_FLAG = 0x1,
+    /**
+     * AP can enter deep sleep state. If not set, AP will always shutdown from
+     * VehicleApPowerState#SHUTDOWN_PREPARE power state.
+     */
+    ENABLE_DEEP_SLEEP_FLAG = 0x1,
 
-  /**
-   * The power controller can power on AP from off state after timeout
-   * specified in VehicleApPowerSet VEHICLE_AP_POWER_SET_SHUTDOWN_READY message.
-   */
-  CONFIG_SUPPORT_TIMER_POWER_ON_FLAG = 0x2,
+    /**
+     * The power controller can power on AP from off state after timeout
+     * specified in VehicleApPowerSet VEHICLE_AP_POWER_SET_SHUTDOWN_READY message.
+     */
+    CONFIG_SUPPORT_TIMER_POWER_ON_FLAG = 0x2,
 };
 
 enum VehicleApPowerState : int32_t /* NOTE: type is guessed */ {
-  /** vehicle HAL will never publish this state to AP */
-  OFF = 0,
+    /** vehicle HAL will never publish this state to AP */
+    OFF = 0,
 
-  /** vehicle HAL will never publish this state to AP */
-  DEEP_SLEEP = 1,
+    /** vehicle HAL will never publish this state to AP */
+    DEEP_SLEEP = 1,
 
-  /** AP is on but display must be off. */
-  ON_DISP_OFF = 2,
+    /** AP is on but display must be off. */
+    ON_DISP_OFF = 2,
 
-  /** AP is on with display on. This state allows full user interaction. */
-  ON_FULL = 3,
+    /** AP is on with display on. This state allows full user interaction. */
+    ON_FULL = 3,
 
-  /**
-   * The power controller has requested AP to shutdown. AP can either enter
-   * sleep state or start full shutdown. AP can also request postponing
-   * shutdown by sending VehicleApPowerSetState#SHUTDOWN_POSTPONE message. The
-   * power controller must change power state to this state to shutdown
-   * system.
-   *
-   * int32Values[1] : one of enum_vehicle_ap_power_state_shutdown_param_type
-   */
-  SHUTDOWN_PREPARE = 4,
+    /**
+     * The power controller has requested AP to shutdown. AP can either enter
+     * sleep state or start full shutdown. AP can also request postponing
+     * shutdown by sending VehicleApPowerSetState#SHUTDOWN_POSTPONE message. The
+     * power controller must change power state to this state to shutdown
+     * system.
+     *
+     * int32Values[1] : one of enum_vehicle_ap_power_state_shutdown_param_type
+     */
+    SHUTDOWN_PREPARE = 4,
 };
 
 enum VehicleApPowerStateShutdownParam : int32_t {
-  /** AP must shutdown immediately. Postponing is not allowed. */
-  SHUTDOWN_IMMEDIATELY = 1,
+    /** AP must shutdown immediately. Postponing is not allowed. */
+    SHUTDOWN_IMMEDIATELY = 1,
 
-  /** AP can enter deep sleep instead of shutting down completely. */
-  CAN_SLEEP = 2,
+    /** AP can enter deep sleep instead of shutting down completely. */
+    CAN_SLEEP = 2,
 
-  /** AP can only shutdown with postponing allowed. */
-  SHUTDOWN_ONLY = 3,
+    /** AP can only shutdown with postponing allowed. */
+    SHUTDOWN_ONLY = 3,
 };
 
 enum VehicleApPowerSetState : int32_t /* NOTE: type is guessed */ {
-  /**
-   * AP has finished boot up, and can start shutdown if requested by power
-   * controller.
-   */
-  BOOT_COMPLETE = 0x1,
+    /**
+     * AP has finished boot up, and can start shutdown if requested by power
+     * controller.
+     */
+    BOOT_COMPLETE = 0x1,
 
-  /**
-   * AP is entering deep sleep state. How this state is implemented may vary
-   * depending on each H/W, but AP's power must be kept in this state.
-   */
-  DEEP_SLEEP_ENTRY = 0x2,
+    /**
+     * AP is entering deep sleep state. How this state is implemented may vary
+     * depending on each H/W, but AP's power must be kept in this state.
+     */
+    DEEP_SLEEP_ENTRY = 0x2,
 
-  /**
-   * AP is exiting from deep sleep state, and is in
-   * VehicleApPowerState#SHUTDOWN_PREPARE state.
-   * The power controller may change state to other ON states based on the
-   * current state.
-   */
-  DEEP_SLEEP_EXIT = 0x3,
+    /**
+     * AP is exiting from deep sleep state, and is in
+     * VehicleApPowerState#SHUTDOWN_PREPARE state.
+     * The power controller may change state to other ON states based on the
+     * current state.
+     */
+    DEEP_SLEEP_EXIT = 0x3,
 
-  /**
-   * int32Values[1]: Time to postpone shutdown in ms. Maximum value can be
-   *                 5000 ms.
-   *                 If AP needs more time, it will send another POSTPONE
-   *                 message before the previous one expires.
-   */
-  SHUTDOWN_POSTPONE = 0x4,
+    /**
+     * int32Values[1]: Time to postpone shutdown in ms. Maximum value can be
+     *                 5000 ms.
+     *                 If AP needs more time, it will send another POSTPONE
+     *                 message before the previous one expires.
+     */
+    SHUTDOWN_POSTPONE = 0x4,
 
-  /**
-   * AP is starting shutting down. When system completes shutdown, everything
-   * will stop in AP as kernel will stop all other contexts. It is
-   * responsibility of vehicle HAL or lower level to synchronize that state
-   * with external power controller. As an example, some kind of ping
-   * with timeout in power controller can be a solution.
-   *
-   * int32Values[1]: Time to turn on AP in secs. Power controller may turn on
-   *                 AP after specified time so that AP can run tasks like
-   *                 update. If it is set to 0, there is no wake up, and power
-   *                 controller may not necessarily support wake-up. If power
-   *                 controller turns on AP due to timer, it must start with
-   *                 VehicleApPowerState#ON_DISP_OFF state, and after
-   *                 receiving VehicleApPowerSetState#BOOT_COMPLETE, it shall
-   *                 do state transition to
-   *                 VehicleApPowerState#SHUTDOWN_PREPARE.
-   */
-  SHUTDOWN_START = 0x5,
+    /**
+     * AP is starting shutting down. When system completes shutdown, everything
+     * will stop in AP as kernel will stop all other contexts. It is
+     * responsibility of vehicle HAL or lower level to synchronize that state
+     * with external power controller. As an example, some kind of ping
+     * with timeout in power controller can be a solution.
+     *
+     * int32Values[1]: Time to turn on AP in secs. Power controller may turn on
+     *                 AP after specified time so that AP can run tasks like
+     *                 update. If it is set to 0, there is no wake up, and power
+     *                 controller may not necessarily support wake-up. If power
+     *                 controller turns on AP due to timer, it must start with
+     *                 VehicleApPowerState#ON_DISP_OFF state, and after
+     *                 receiving VehicleApPowerSetState#BOOT_COMPLETE, it shall
+     *                 do state transition to
+     *                 VehicleApPowerState#SHUTDOWN_PREPARE.
+     */
+    SHUTDOWN_START = 0x5,
 
-  /**
-   * User has requested to turn off headunit's display, which is detected in
-   * android side.
-   * The power controller may change the power state to
-   * VehicleApPowerState#ON_DISP_OFF.
-   */
-  DISPLAY_OFF = 0x6,
+    /**
+     * User has requested to turn off headunit's display, which is detected in
+     * android side.
+     * The power controller may change the power state to
+     * VehicleApPowerState#ON_DISP_OFF.
+     */
+    DISPLAY_OFF = 0x6,
 
-  /**
-   * User has requested to turn on headunit's display, most probably from power
-   * key input which is attached to headunit. The power controller may change
-   * the power state to VehicleApPowerState#ON_FULL.
-   */
-  DISPLAY_ON = 0x7,
+    /**
+     * User has requested to turn on headunit's display, most probably from power
+     * key input which is attached to headunit. The power controller may change
+     * the power state to VehicleApPowerState#ON_FULL.
+     */
+    DISPLAY_ON = 0x7,
 };
 
 /**
  * Index in int32Values for VehicleProperty#AP_POWER_STATE property.
  */
 enum VehicleApPowerStateIndex : int32_t {
-  STATE = 0,
-  ADDITIONAL = 1,
+    STATE = 0,
+    ADDITIONAL = 1,
 };
 
 /**
  * Enum to represent bootup reason.
  */
 enum VehicleApPowerBootupReason : int32_t {
-  /**
-   * Power on due to user's pressing of power key or rotating of ignition
-   * switch.
-   */
-  USER_POWER_ON = 0,
+    /**
+     * Power on due to user's pressing of power key or rotating of ignition
+     * switch.
+     */
+    USER_POWER_ON = 0,
 
-  /**
-   * Automatic power on triggered by door unlock or any other kind of automatic
-   * user detection.
-   */
-  USER_UNLOCK = 1,
+    /**
+     * Automatic power on triggered by door unlock or any other kind of automatic
+     * user detection.
+     */
+    USER_UNLOCK = 1,
 
-  /**
-   * Automatic power on triggered by timer. This only happens when AP has asked
-   * wake-up after
-   * certain time through time specified in
-   * VehicleApPowerSetState#SHUTDOWN_START.
-   */
-  TIMER = 2,
+    /**
+     * Automatic power on triggered by timer. This only happens when AP has asked
+     * wake-up after
+     * certain time through time specified in
+     * VehicleApPowerSetState#SHUTDOWN_START.
+     */
+    TIMER = 2,
 };
 
 enum VehicleHwKeyInputAction : int32_t {
-  /** Key down */
-  ACTION_DOWN = 0,
+    /** Key down */
+    ACTION_DOWN = 0,
 
-  /** Key up */
-  ACTION_UP = 1,
+    /** Key up */
+    ACTION_UP = 1,
 };
 
 enum VehicleDisplay : int32_t {
-  /** center console */
-  MAIN = 0,
+    /** center console */
+    MAIN = 0,
 
-  INSTRUMENT_CLUSTER = 1,
+    INSTRUMENT_CLUSTER = 1,
 };
 
 /**
@@ -2312,11 +2562,11 @@
  * the expected output.
  */
 enum VehiclePropertyAccess : int32_t {
-  NONE = 0x00,
+    NONE = 0x00,
 
-  READ = 0x01,
-  WRITE = 0x02,
-  READ_WRITE = 0x03,
+    READ = 0x01,
+    WRITE = 0x02,
+    READ_WRITE = 0x03,
 };
 
 /**
@@ -2325,32 +2575,32 @@
  * The driving states determine what features of the UI will be accessible.
  */
 enum VehicleDrivingStatus : int32_t {
-  UNRESTRICTED = 0x00,
-  NO_VIDEO = 0x01,
-  NO_KEYBOARD_INPUT = 0x02,
-  NO_VOICE_INPUT = 0x04,
-  NO_CONFIG = 0x08,
-  LIMIT_MESSAGE_LEN = 0x10,
+    UNRESTRICTED = 0x00,
+    NO_VIDEO = 0x01,
+    NO_KEYBOARD_INPUT = 0x02,
+    NO_VOICE_INPUT = 0x04,
+    NO_CONFIG = 0x08,
+    LIMIT_MESSAGE_LEN = 0x10,
 };
 
 /**
  * Various gears which can be selected by user and chosen in system.
  */
 enum VehicleGear: int32_t {
-  GEAR_NEUTRAL = 0x0001,
-  GEAR_REVERSE = 0x0002,
-  GEAR_PARK = 0x0004,
-  GEAR_DRIVE = 0x0008,
-  GEAR_LOW = 0x0010,
-  GEAR_1 = 0x0010,
-  GEAR_2 = 0x0020,
-  GEAR_3 = 0x0040,
-  GEAR_4 = 0x0080,
-  GEAR_5 = 0x0100,
-  GEAR_6 = 0x0200,
-  GEAR_7 = 0x0400,
-  GEAR_8 = 0x0800,
-  GEAR_9 = 0x1000,
+    GEAR_NEUTRAL = 0x0001,
+    GEAR_REVERSE = 0x0002,
+    GEAR_PARK = 0x0004,
+    GEAR_DRIVE = 0x0008,
+    GEAR_LOW = 0x0010,
+    GEAR_1 = 0x0010,
+    GEAR_2 = 0x0020,
+    GEAR_3 = 0x0040,
+    GEAR_4 = 0x0080,
+    GEAR_5 = 0x0100,
+    GEAR_6 = 0x0200,
+    GEAR_7 = 0x0400,
+    GEAR_8 = 0x0800,
+    GEAR_9 = 0x1000,
 };
 
 /**
@@ -2610,73 +2860,73 @@
 
 
 enum SubscribeFlags : int32_t {
-  UNDEFINED = 0x0,
+    UNDEFINED = 0x0,
 
-  /**
-   * Subscribe to event that was originated in vehicle HAL
-   * (most likely this event came from the vehicle itself).
-   */
-  HAL_EVENT = 0x1,
+    /**
+     * Subscribe to event that was originated in vehicle HAL
+     * (most likely this event came from the vehicle itself).
+     */
+    HAL_EVENT = 0x1,
 
-  /**
-   * Use this flag to subscribe on events when IVehicle#set(...) was called by
-   * vehicle HAL's client (e.g. Car Service).
-   */
-  SET_CALL = 0x2,
+    /**
+     * Use this flag to subscribe on events when IVehicle#set(...) was called by
+     * vehicle HAL's client (e.g. Car Service).
+     */
+    SET_CALL = 0x2,
 
-  DEFAULT = HAL_EVENT,
+    DEFAULT = HAL_EVENT,
 };
 
 /**
  * Encapsulates information about subscription to vehicle property events.
  */
 struct SubscribeOptions {
-  /** Property to subscribe */
-  int32_t propId;
+    /** Property to subscribe */
+    int32_t propId;
 
-  /**
-   * Area ids - this must be a bit mask of areas to subscribe or 0 to subscribe
-   * to all areas.
-   */
-  int32_t vehicleAreas;
+    /**
+     * Area ids - this must be a bit mask of areas to subscribe or 0 to subscribe
+     * to all areas.
+     */
+    int32_t vehicleAreas;
 
-  /**
-   * Sample rate in Hz.
-   *
-   * Must be provided for properties with
-   * VehiclePropertyChangeMode::CONTINUOUS. The value must be within
-   * VehiclePropConfig#minSamplingRate .. VehiclePropConfig#maxSamplingRate
-   * for a given property.
-   * This value indicates how many updates per second client wants to receive.
-   */
-  float sampleRate;
+    /**
+     * Sample rate in Hz.
+     *
+     * Must be provided for properties with
+     * VehiclePropertyChangeMode::CONTINUOUS. The value must be within
+     * VehiclePropConfig#minSamplingRate .. VehiclePropConfig#maxSamplingRate
+     * for a given property.
+     * This value indicates how many updates per second client wants to receive.
+     */
+    float sampleRate;
 
-  /** Flags that indicate what kind of events listen to. */
-  SubscribeFlags flags;
+    /** Flags that indicate what kind of events listen to. */
+    SubscribeFlags flags;
 };
 
 /** Error codes used in vehicle HAL interface. */
 enum StatusCode : int32_t {
-  OK = 0,
+    OK = 0,
 
-  /** Try again. */
-  TRY_AGAIN = 1,
+    /** Try again. */
+    TRY_AGAIN = 1,
 
-  /** Invalid argument provided. */
-  INVALID_ARG = 2,
+    /** Invalid argument provided. */
+    INVALID_ARG = 2,
 
-  /**
-   * This code must be returned when device that associated with the vehicle
-   * property is not available. For example, when client tries to set HVAC
-   * temperature when the whole HVAC unit is turned OFF.
-   */
-  NOT_AVAILABLE = 3,
+    /**
+     * This code must be returned when device that associated with the vehicle
+     * property is not available. For example, when client tries to set HVAC
+     * temperature when the whole HVAC unit is turned OFF.
+     */
+    NOT_AVAILABLE = 3,
 
-  /** Access denied */
-  ACCESS_DENIED = 4,
+    /** Access denied */
+    ACCESS_DENIED = 4,
 
-  /** Something unexpected has happened in Vehicle HAL */
-  INTERNAL_ERROR = 5,
+    /** Something unexpected has happened in Vehicle HAL */
+    INTERNAL_ERROR = 5,
 };
 
 enum Wheel : int32_t {
@@ -2687,3 +2937,460 @@
     LEFT_REAR = 0x4,
     RIGHT_REAR = 0x8,
 };
+
+/**
+ * The status of the vehicle's fuel system.
+ * These values come from the SAE J1979 standard.
+ */
+enum Obd2FuelSystemStatus : int32_t {
+    OPEN_INSUFFICIENT_ENGINE_TEMPERATURE = 1,
+    CLOSED_LOOP = 2,
+    OPEN_ENGINE_LOAD_OR_DECELERATION = 4,
+    OPEN_SYSTEM_FAILURE = 8,
+    CLOSED_LOOP_BUT_FEEDBACK_FAULT = 16,
+};
+
+/** Defines which ignition monitors are available to be read. */
+enum Obd2IgnitionMonitorKind : int32_t {
+    SPARK = 0,
+    COMPRESSION = 1,
+};
+
+/**
+ * Ignition monitors common to both SPARK and COMPRESSION.
+ * These values come from the SAE J1979 standard.
+ */
+enum Obd2CommonIgnitionMonitors : int32_t {
+    COMPONENTS_AVAILABLE = 0x1 << 0,
+    COMPONENTS_INCOMPLETE = 0x1 << 1,
+
+    FUEL_SYSTEM_AVAILABLE = 0x1 << 2,
+    FUEL_SYSTEM_INCOMPLETE = 0x1 << 3,
+
+    MISFIRE_AVAILABLE = 0x1 << 4,
+    MISFIRE_INCOMPLETE = 0x1 << 5,
+};
+
+/**
+ * Ignition monitors available for SPARK vehicles.
+ * These values come from the SAE J1979 standard.
+ */
+enum Obd2SparkIgnitionMonitors : Obd2CommonIgnitionMonitors {
+    EGR_AVAILABLE = 0x1 << 6,
+    EGR_INCOMPLETE = 0x1 << 7,
+
+    OXYGEN_SENSOR_HEATER_AVAILABLE = 0x1 << 8,
+    OXYGEN_SENSOR_HEATER_INCOMPLETE = 0x1 << 9,
+
+    OXYGEN_SENSOR_AVAILABLE = 0x1 << 10,
+    OXYGEN_SENSOR_INCOMPLETE = 0x1 << 11,
+
+    AC_REFRIGERANT_AVAILABLE = 0x1 << 12,
+    AC_REFRIGERANT_INCOMPLETE = 0x1 << 13,
+
+    SECONDARY_AIR_SYSTEM_AVAILABLE = 0x1 << 14,
+    SECONDARY_AIR_SYSTEM_INCOMPLETE = 0x1 << 15,
+
+    EVAPORATIVE_SYSTEM_AVAILABLE = 0x1 << 16,
+    EVAPORATIVE_SYSTEM_INCOMPLETE = 0x1 << 17,
+
+    HEATED_CATALYST_AVAILABLE = 0x1 << 18,
+    HEATED_CATALYST_INCOMPLETE = 0x1 << 19,
+
+    CATALYST_AVAILABLE = 0x1 << 20,
+    CATALYST_INCOMPLETE = 0x1 << 21,
+};
+
+/**
+ * Ignition monitors only available for COMPRESSION vehicles.
+ * These values come from the SAE J1979 standard.
+ */
+enum Obd2CompressionIgnitionMonitors : Obd2CommonIgnitionMonitors {
+    EGR_OR_VVT_AVAILABLE = 0x1 << 6,
+    EGR_OR_VVT_INCOMPLETE = 0x1 << 7,
+
+    PM_FILTER_AVAILABLE = 0x1 << 8,
+    PM_FILTER_INCOMPLETE = 0x1 << 9,
+
+    EXHAUST_GAS_SENSOR_AVAILABLE = 0x1 << 10,
+    EXHAUST_GAS_SENSOR_INCOMPLETE = 0x1 << 11,
+
+    BOOST_PRESSURE_AVAILABLE = 0x1 << 12,
+    BOOST_PRESSURE_INCOMPLETE = 0x1 << 13,
+
+    NOx_SCR_AVAILABLE = 0x1 << 14,
+    NOx_SCR_INCOMPLETE = 0x1 << 15,
+
+    NMHC_CATALYST_AVAILABLE = 0x1 << 16,
+    NMHC_CATALYST_INCOMPLETE = 0x1 << 17,
+};
+
+/**
+ * The status of the vehicle's secondary air system.
+ * These values come from the SAE J1979 standard.
+ */
+enum Obd2SecondaryAirStatus : int32_t {
+    UPSTREAM = 1,
+    DOWNSTREAM_OF_CATALYCIC_CONVERTER = 2,
+    FROM_OUTSIDE_OR_OFF = 4,
+    PUMP_ON_FOR_DIAGNOSTICS = 8,
+};
+
+/**
+ * The fuel type(s) supported by a vehicle.
+ * These values come from the SAE J1979 standard.
+ */
+enum Obd2FuelType : int32_t {
+    NOT_AVAILABLE = 0,
+    GASOLINE = 1,
+    METHANOL = 2,
+    ETHANOL = 3,
+    DIESEL = 4,
+    LPG = 5,
+    CNG = 6,
+    PROPANE = 7,
+    ELECTRIC = 8,
+    BIFUEL_RUNNING_GASOLINE = 9,
+    BIFUEL_RUNNING_METHANOL = 10,
+    BIFUEL_RUNNING_ETHANOL = 11,
+    BIFUEL_RUNNING_LPG = 12,
+    BIFUEL_RUNNING_CNG = 13,
+    BIFUEL_RUNNING_PROPANE = 14,
+    BIFUEL_RUNNING_ELECTRIC = 15,
+    BIFUEL_RUNNING_ELECTRIC_AND_COMBUSTION = 16,
+    HYBRID_GASOLINE = 17,
+    HYBRID_ETHANOL = 18,
+    HYBRID_DIESEL = 19,
+    HYBRID_ELECTRIC = 20,
+    HYBRID_RUNNING_ELECTRIC_AND_COMBUSTION = 21,
+    HYBRID_REGENERATIVE = 22,
+    BIFUEL_RUNNING_DIESEL = 23,
+};
+
+/**
+ * This enum provides the canonical mapping for sensor properties that have an integer value.
+ * The ordering of the values is taken from the OBD2 specification.
+ * Some of the properties are represented as an integer mapping to another enum. In those cases
+ * expect a comment by the property definition describing the enum to look at for the mapping.
+ * Any value greater than the last reserved index is available to vendors to map their extensions.
+ * While these values do not directly map to SAE J1979 PIDs, an equivalence is listed next
+ * to each one to aid implementors.
+ */
+enum DiagnosticIntegerSensorIndex : int32_t {
+    /** refer to FuelSystemStatus for a description of this value. */
+    FUEL_SYSTEM_STATUS = 0, /* PID 0x03 */
+    MALFUNCTION_INDICATOR_LIGHT_ON = 1, /* PID 0x01 */
+
+    /** refer to IgnitionMonitorKind for a description of this value. */
+    IGNITION_MONITORS_SUPPORTED = 2, /* PID 0x01 */
+
+    /**
+     * The value of this sensor is a bitmask that specifies whether ignition-specific
+     * tests are available and whether they are complete. The semantics of the individual
+     * bits in this value are given by, respectively, SparkIgnitionMonitors and
+     * CompressionIgnitionMonitors depending on the value of IGNITION_MONITORS_SUPPORTED.
+     */
+    IGNITION_SPECIFIC_MONITORS = 3, /* PID 0x01 */
+    INTAKE_AIR_TEMPERATURE = 4, /* PID 0x0F */
+
+    /** refer to SecondaryAirStatus for a description of this value. */
+    COMMANDED_SECONDARY_AIR_STATUS = 5, /* PID 0x12 */
+    NUM_OXYGEN_SENSORS_PRESENT = 6, /* PID 0x13 */
+    RUNTIME_SINCE_ENGINE_START = 7, /* PID 0x1F */
+    DISTANCE_TRAVELED_WITH_MALFUNCTION_INDICATOR_LIGHT_ON = 8, /* PID 0x21 */
+    WARMUPS_SINCE_CODES_CLEARED = 9, /* PID 0x30 */
+    DISTANCE_TRAVELED_SINCE_CODES_CLEARED = 10, /* PID 0x31 */
+    ABSOLUTE_BAROMETRIC_PRESSURE = 11, /* PID 0x33 */
+    CONTROL_MODULE_VOLTAGE = 12, /* PID 0x42 */
+    AMBIENT_AIR_TEMPERATURE = 13, /* PID 0x46 */
+    TIME_WITH_MALFUNCTION_LIGHT_ON = 14, /* PID 0x4D */
+    TIME_SINCE_TROUBLE_CODES_CLEARED = 15, /* PID 0x4E */
+    MAX_FUEL_AIR_EQUIVALENCE_RATIO = 16, /* PID 0x4F */
+    MAX_OXYGEN_SENSOR_VOLTAGE = 17, /* PID 0x4F */
+    MAX_OXYGEN_SENSOR_CURRENT = 18, /* PID 0x4F */
+    MAX_INTAKE_MANIFOLD_ABSOLUTE_PRESSURE = 19, /* PID 0x4F */
+    MAX_AIR_FLOW_RATE_FROM_MASS_AIR_FLOW_SENSOR = 20, /* PID 0x50 */
+
+    /** refer to FuelType for a description of this value. */
+    FUEL_TYPE = 21, /* PID 0x51 */
+    FUEL_RAIL_ABSOLUTE_PRESSURE = 22, /* PID 0x59 */
+    ENGINE_OIL_TEMPERATURE = 23, /* PID 0x5C */
+    DRIVER_DEMAND_PERCENT_TORQUE = 24, /* PID 0x61 */
+    ENGINE_ACTUAL_PERCENT_TORQUE = 25, /* PID 0x62 */
+    ENGINE_REFERENCE_PERCENT_TORQUE = 26, /* PID 0x63 */
+    ENGINE_PERCENT_TORQUE_DATA_IDLE = 27, /* PID 0x64 */
+    ENGINE_PERCENT_TORQUE_DATA_POINT1 = 28, /* PID 0x64 */
+    ENGINE_PERCENT_TORQUE_DATA_POINT2 = 29, /* PID 0x64 */
+    ENGINE_PERCENT_TORQUE_DATA_POINT3 = 30, /* PID 0x64 */
+    ENGINE_PERCENT_TORQUE_DATA_POINT4 = 31, /* PID 0x64 */
+    LAST_SYSTEM_INDEX = ENGINE_PERCENT_TORQUE_DATA_POINT4,
+};
+
+/**
+ * This enum provides the canonical mapping for sensor properties that have a floating-point value.
+ * The ordering of the values is taken from the OBD2 specification.
+ * Any value greater than the last reserved index is available to vendors to map their extensions.
+ * While these values do not directly map to SAE J1979 PIDs, an equivalence is listed next
+ * to each one to aid implementors.
+ */
+enum DiagnosticFloatSensorIndex : int32_t {
+    CALCULATED_ENGINE_LOAD = 0, /* PID 0x04 */
+    ENGINE_COOLANT_TEMPERATURE = 1, /* PID 0x05 */
+    SHORT_TERM_FUEL_TRIM_BANK1 = 2, /* PID 0x06 */
+    LONG_TERM_FUEL_TRIM_BANK1 = 3, /* PID 0x07 */
+    SHORT_TERM_FUEL_TRIM_BANK2 = 4, /* PID 0x08 */
+    LONG_TERM_FUEL_TRIM_BANK2 = 5, /* PID 0x09 */
+    FUEL_PRESSURE = 6, /* PID 0x0A */
+    INTAKE_MANIFOLD_ABSOLUTE_PRESSURE = 7, /* PID 0x0B */
+    ENGINE_RPM = 8, /* PID 0x0C */
+    VEHICLE_SPEED = 9, /* PID 0x0D */
+    TIMING_ADVANCE = 10, /* PID 0x0E */
+    MAF_AIR_FLOW_RATE = 11, /* PID 0x10 */
+    THROTTLE_POSITION = 12, /* PID 0x11 */
+    OXYGEN_SENSOR1_VOLTAGE = 13, /* PID 0x14 */
+    OXYGEN_SENSOR1_SHORT_TERM_FUEL_TRIM = 14, /* PID 0x14 */
+    OXYGEN_SENSOR1_FUEL_AIR_EQUIVALENCE_RATIO = 15, /* PID 0x24 */
+    OXYGEN_SENSOR2_VOLTAGE = 16, /* PID 0x15 */
+    OXYGEN_SENSOR2_SHORT_TERM_FUEL_TRIM = 17, /* PID 0x15 */
+    OXYGEN_SENSOR2_FUEL_AIR_EQUIVALENCE_RATIO = 18, /* PID 0x25 */
+    OXYGEN_SENSOR3_VOLTAGE = 19, /* PID 0x16 */
+    OXYGEN_SENSOR3_SHORT_TERM_FUEL_TRIM = 20, /* PID 0x16 */
+    OXYGEN_SENSOR3_FUEL_AIR_EQUIVALENCE_RATIO = 21, /* PID 0x26 */
+    OXYGEN_SENSOR4_VOLTAGE = 22, /* PID 0x17 */
+    OXYGEN_SENSOR4_SHORT_TERM_FUEL_TRIM = 23, /* PID 0x17 */
+    OXYGEN_SENSOR4_FUEL_AIR_EQUIVALENCE_RATIO = 24, /* PID 0x27 */
+    OXYGEN_SENSOR5_VOLTAGE = 25, /* PID 0x18 */
+    OXYGEN_SENSOR5_SHORT_TERM_FUEL_TRIM = 26, /* PID 0x18 */
+    OXYGEN_SENSOR5_FUEL_AIR_EQUIVALENCE_RATIO = 27, /* PID 0x28 */
+    OXYGEN_SENSOR6_VOLTAGE = 28, /* PID 0x19 */
+    OXYGEN_SENSOR6_SHORT_TERM_FUEL_TRIM = 29, /* PID 0x19 */
+    OXYGEN_SENSOR6_FUEL_AIR_EQUIVALENCE_RATIO = 30, /* PID 0x29 */
+    OXYGEN_SENSOR7_VOLTAGE = 31, /* PID 0x1A */
+    OXYGEN_SENSOR7_SHORT_TERM_FUEL_TRIM = 32, /* PID 0x1A */
+    OXYGEN_SENSOR7_FUEL_AIR_EQUIVALENCE_RATIO = 33, /* PID 0x2A */
+    OXYGEN_SENSOR8_VOLTAGE = 34, /* PID 0x1B */
+    OXYGEN_SENSOR8_SHORT_TERM_FUEL_TRIM = 35, /* PID 0x1B */
+    OXYGEN_SENSOR8_FUEL_AIR_EQUIVALENCE_RATIO = 36, /* PID 0x2B */
+    FUEL_RAIL_PRESSURE = 37, /* PID 0x22 */
+    FUEL_RAIL_GAUGE_PRESSURE = 38, /* PID 0x23 */
+    COMMANDED_EXHAUST_GAS_RECIRCULATION = 39, /* PID 0x2C */
+    EXHAUST_GAS_RECIRCULATION_ERROR = 40, /* PID 0x2D */
+    COMMANDED_EVAPORATIVE_PURGE = 41, /* PID 0x2E */
+    FUEL_TANK_LEVEL_INPUT = 42, /* PID 0x2F */
+    EVAPORATION_SYSTEM_VAPOR_PRESSURE = 43, /* PID 0x32 */
+    CATALYST_TEMPERATURE_BANK1_SENSOR1 = 44, /* PID 0x3C */
+    CATALYST_TEMPERATURE_BANK2_SENSOR1 = 45, /* PID 0x3D */
+    CATALYST_TEMPERATURE_BANK1_SENSOR2 = 46, /* PID 0x3E */
+    CATALYST_TEMPERATURE_BANK2_SENSOR2 = 47, /* PID 0x3F */
+    ABSOLUTE_LOAD_VALUE = 48, /* PID 0x43 */
+    FUEL_AIR_COMMANDED_EQUIVALENCE_RATIO = 49, /* PID 0x44 */
+    RELATIVE_THROTTLE_POSITION = 50, /* PID 0x45 */
+    ABSOLUTE_THROTTLE_POSITION_B = 51, /* PID 0x47 */
+    ABSOLUTE_THROTTLE_POSITION_C = 52, /* PID 0x48 */
+    ACCELERATOR_PEDAL_POSITION_D = 53, /* PID 0x49 */
+    ACCELERATOR_PEDAL_POSITION_E = 54, /* PID 0x4A */
+    ACCELERATOR_PEDAL_POSITION_F = 55, /* PID 0x4B */
+    COMMANDED_THROTTLE_ACTUATOR = 56, /* PID 0x4C */
+    ETHANOL_FUEL_PERCENTAGE = 57,/* PID 0x52 */
+    ABSOLUTE_EVAPORATION_SYSTEM_VAPOR_PRESSURE = 58, /* PID 0x53 */
+    SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK1 = 59, /* PID 0x55 */
+    SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK2 = 60, /* PID 0x57 */
+    SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK3 = 61,/* PID 0x55 */
+    SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK4 = 62, /* PID 0x57 */
+    LONG_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK1 = 63, /* PID 0x56 */
+    LONG_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK2 = 64, /* PID 0x58 */
+    LONG_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK3 = 65, /* PID 0x56 */
+    LONG_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK4 = 66, /* PID 0x58 */
+    RELATIVE_ACCELERATOR_PEDAL_POSITION = 67, /* PID 0x5A */
+    HYBRID_BATTERY_PACK_REMAINING_LIFE = 68, /* PID 0x5B */
+    FUEL_INJECTION_TIMING = 69, /* PID 0x5D */
+    ENGINE_FUEL_RATE = 70, /* PID 0x5E */
+    LAST_SYSTEM_INDEX = ENGINE_FUEL_RATE,
+};
+
+/**
+ * This enum lists the types of supported VMS messages. It is used as the first
+ * integer in the vehicle property integers array and determines how the rest of
+ * the message is decoded.
+ */
+enum VmsMessageType : int32_t {
+    /**
+     * A request from the subscribers to the VMS service to subscribe to a layer.
+     *
+     * This message type uses enum VmsMessageWithLayerIntegerValuesIndex.
+     */
+    SUBSCRIBE = 1,
+
+    /**
+     * A request from the subscribers to the VMS service to subscribe to a layer from a specific publisher.
+     *
+     * This message type uses enum VmsMessageWithLayerAndPublisherIdIntegerValuesIndex.
+     */
+    SUBSCRIBE_TO_PUBLISHER = 2,
+
+    /**
+     * A request from the subscribers to the VMS service to unsubscribes from a layer.
+     *
+     * This message type uses enum VmsMessageWithLayerIntegerValuesIndex.
+     */
+    UNSUBSCRIBE = 3,
+
+    /**
+     * A request from the subscribers to the VMS service to unsubscribes from a layer from a specific publisher.
+     *
+     * This message type uses enum VmsMessageWithLayerAndPublisherIdIntegerValuesIndex.
+     */
+    UNSUBSCRIBE_TO_PUBLISHER = 4,
+
+    /**
+     * Information from the publishers to the VMS service about the layers which the client can publish.
+     *
+     * This message type uses enum VmsOfferingMessageIntegerValuesIndex.
+     */
+    OFFERING = 5,
+
+    /**
+     * A request from the subscribers to the VMS service to get the available layers.
+     *
+     * This message type uses enum VmsBaseMessageIntegerValuesIndex.
+     */
+    AVAILABILITY_REQUEST = 6,
+
+    /**
+     * A request from the publishers to the VMS service to get the layers with subscribers.
+     *
+     * This message type uses enum VmsBaseMessageIntegerValuesIndex.
+     */
+    SUBSCRIPTIONS_REQUEST = 7,
+
+    /**
+     * A response from the VMS service to the subscribers to a VmsMessageType.AVAILABILITY_REQUEST
+     *
+     * This message type uses enum VmsAvailabilityStateIntegerValuesIndex.
+     */
+    AVAILABILITY_RESPONSE = 8,
+
+    /**
+     * A notification from the VMS service to the subscribers on a change in the available layers.
+     *
+     * This message type uses enum VmsAvailabilityStateIntegerValuesIndex.
+     */
+    AVAILABILITY_CHANGE = 9,
+
+    /**
+     * A response from the VMS service to the publishers to a VmsMessageType.SUBSCRIPTIONS_REQUEST
+     *
+     * This message type uses enum VmsSubscriptionsStateIntegerValuesIndex.
+     */
+    SUBSCRIPTIONS_RESPONSE = 10,
+
+    /**
+     * A notification from the VMS service to the publishers on a change in the layers with subscribers.
+     *
+     * This message type uses enum VmsSubscriptionsStateIntegerValuesIndex.
+     */
+    SUBSCRIPTIONS_CHANGE = 11,
+
+    /**
+     * A message from the VMS service to the subscribers or from the publishers to the VMS service
+     * with a serialized VMS data packet as defined in the VMS protocol.
+     *
+     * This message type uses enum VmsBaseMessageIntegerValuesIndex.
+     */
+    DATA = 12,
+};
+
+/**
+ * Every VMS message starts with the type of the message from the VmsMessageType enum.
+ * Messages with no parameters such as VmsMessageType.AVAILABILITY_REQUEST,
+ * VmsMessageType.SUBSCRIPTIONS_REQUEST and VmsMessageType.DATA are also based on this enum.
+ */
+enum VmsBaseMessageIntegerValuesIndex : int32_t {
+    /* The message type as enumerated by VmsMessageType enum. */
+    MESSAGE_TYPE = 0,
+};
+
+/*
+ * A VMS message with a layer is sent as part of a VmsMessageType.SUBSCRIBE or
+ * VmsMessageType.UNSUBSCRIBE messages.
+ *
+ * The layer type is defined in the VMS protocol, and the subtype and version are
+ * controlled by the implementer of the publisher.
+ */
+enum VmsMessageWithLayerIntegerValuesIndex : VmsBaseMessageIntegerValuesIndex {
+    LAYER_TYPE = 1,
+    LAYER_SUBTYPE = 2,
+    LAYER_VERSION = 3,
+};
+
+/*
+ * A VMS message with a layer and publisher ID is sent as part of a
+ * VmsMessageType.SUBSCRIBE_TO_PUBLISHER and VmsMessageType.UNSUBSCRIBE_TO_PUBLISHER messages.
+ */
+enum VmsMessageWithLayerAndPublisherIdIntegerValuesIndex : VmsMessageWithLayerIntegerValuesIndex {
+    PUBLISHER_ID = 4,
+};
+
+/*
+ * An offering can be sent by publishers as part of VmsMessageType.OFFERING in order to
+ * advertise which layers they can publish and under which constraints: e.g., I can publish Layer X
+ * if someone else will publish Layer Y.
+ * The offering contains the publisher ID which was assigned to the publisher by the VMS service.
+ * A single offering is represented as:
+ * - Layer type
+ * - Layer subtype
+ * - Layer version
+ * - Number of dependencies (N)
+ * - N x (Layer type, Layer subtype, Layer version)
+ */
+enum VmsOfferingMessageIntegerValuesIndex : VmsBaseMessageIntegerValuesIndex {
+    PUBLISHER_ID = 1,
+    NUMBER_OF_OFFERS = 2,
+    OFFERING_START = 3,
+};
+
+/**
+ * A subscriptions state is sent to the publishers in response to a change in the subscriptions
+ * as part of a VmsMessageType.SUBSCRIPTIONS_CHANGE, or in response to a
+ * VmsMessageType.SUBSCRIPTIONS_REQUEST message as part of VmsMessageType.SUBSCRIPTIONS_RESPONSE.
+ * The VMS service issues monotonically increasing sequence numbers, and in case a subscriber receives
+ * a smaller sequnce number it should ignore the message.
+ * The subscriptions are sent as a list of layers followed by a list of associated layers:
+ * {Sequence number, N, M, N x layer, M x associated layer}
+ * A subscribed layer is represented as three integers:
+ * - Layer type
+ * - Layer subtype
+ * - Layer version
+ * A subscribed associated layer is a layer with a list of publisher IDs. It is represented as:
+ * - Layer type
+ * - Layer subtype
+ * - Layer version
+ * - Number of publisher IDs (N)
+ * - N x publisher ID
+ */
+enum VmsSubscriptionsStateIntegerValuesIndex : VmsBaseMessageIntegerValuesIndex {
+    SEQUENCE_NUMBER = 1,
+    NUMBER_OF_LAYERS = 2,
+    NUMBER_OF_ASSOCIATED_LAYERS = 3,
+    SUBSCRIPTIONS_START = 4,
+};
+
+/**
+ * An availability state is sent to the subscribers in response to a change in the available
+ * layers as part of a VmsMessageType.AVAILABILITY_CHANGE message, or in response to a
+ * VmsMessageType.AVAILABILITY_REQUEST message as part of a VmsMessageType.AVAILABILITY_RESPONSE.
+ * The VMS service issues monotonically increasing sequence numbers, and in case a subscriber receives
+ * a smaller sequnce number, it should ignore the message.
+ * An available associated layer is a layer with a list of publisher IDs:
+ * - Layer type
+ * - Layer subtype
+ * - Layer version
+ * - Number of publisher IDs (N)
+ * - N x publisher ID
+*/
+enum VmsAvailabilityStateIntegerValuesIndex : VmsBaseMessageIntegerValuesIndex {
+    SEQUENCE_NUMBER = 1,
+    NUMBER_OF_ASSOCIATED_LAYERS = 2,
+    LAYERS_START = 3,
+};
+
diff --git a/automotive/vehicle/2.1/Android.bp b/automotive/vehicle/2.1/Android.bp
deleted file mode 100644
index 9e45fb5..0000000
--- a/automotive/vehicle/2.1/Android.bp
+++ /dev/null
@@ -1,65 +0,0 @@
-// This file is autogenerated by hidl-gen. Do not edit manually.
-
-filegroup {
-    name: "android.hardware.automotive.vehicle@2.1_hal",
-    srcs: [
-        "types.hal",
-        "IVehicle.hal",
-    ],
-}
-
-genrule {
-    name: "android.hardware.automotive.vehicle@2.1_genc++",
-    tools: ["hidl-gen"],
-    cmd: "$(location hidl-gen) -o $(genDir) -Lc++-sources -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.automotive.vehicle@2.1",
-    srcs: [
-        ":android.hardware.automotive.vehicle@2.1_hal",
-    ],
-    out: [
-        "android/hardware/automotive/vehicle/2.1/types.cpp",
-        "android/hardware/automotive/vehicle/2.1/VehicleAll.cpp",
-    ],
-}
-
-genrule {
-    name: "android.hardware.automotive.vehicle@2.1_genc++_headers",
-    tools: ["hidl-gen"],
-    cmd: "$(location hidl-gen) -o $(genDir) -Lc++-headers -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.automotive.vehicle@2.1",
-    srcs: [
-        ":android.hardware.automotive.vehicle@2.1_hal",
-    ],
-    out: [
-        "android/hardware/automotive/vehicle/2.1/types.h",
-        "android/hardware/automotive/vehicle/2.1/hwtypes.h",
-        "android/hardware/automotive/vehicle/2.1/IVehicle.h",
-        "android/hardware/automotive/vehicle/2.1/IHwVehicle.h",
-        "android/hardware/automotive/vehicle/2.1/BnHwVehicle.h",
-        "android/hardware/automotive/vehicle/2.1/BpHwVehicle.h",
-        "android/hardware/automotive/vehicle/2.1/BsVehicle.h",
-    ],
-}
-
-cc_library_shared {
-    name: "android.hardware.automotive.vehicle@2.1",
-    defaults: ["hidl-module-defaults"],
-    generated_sources: ["android.hardware.automotive.vehicle@2.1_genc++"],
-    generated_headers: ["android.hardware.automotive.vehicle@2.1_genc++_headers"],
-    export_generated_headers: ["android.hardware.automotive.vehicle@2.1_genc++_headers"],
-    vendor_available: true,
-    shared_libs: [
-        "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
-        "liblog",
-        "libutils",
-        "libcutils",
-        "android.hardware.automotive.vehicle@2.0",
-    ],
-    export_shared_lib_headers: [
-        "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
-        "libutils",
-        "android.hardware.automotive.vehicle@2.0",
-    ],
-}
diff --git a/automotive/vehicle/2.1/Android.mk b/automotive/vehicle/2.1/Android.mk
deleted file mode 100644
index 8e1c0dd..0000000
--- a/automotive/vehicle/2.1/Android.mk
+++ /dev/null
@@ -1,648 +0,0 @@
-# This file is autogenerated by hidl-gen. Do not edit manually.
-
-LOCAL_PATH := $(call my-dir)
-
-################################################################################
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := android.hardware.automotive.vehicle-V2.1-java
-LOCAL_MODULE_CLASS := JAVA_LIBRARIES
-
-intermediates := $(call local-generated-sources-dir, COMMON)
-
-HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
-
-LOCAL_JAVA_LIBRARIES := \
-    android.hardware.automotive.vehicle-V2.0-java \
-    android.hidl.base-V1.0-java \
-
-
-#
-# Build types.hal (CommonIgnitionMonitors)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/CommonIgnitionMonitors.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.CommonIgnitionMonitors
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (CompressionIgnitionMonitors)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/CompressionIgnitionMonitors.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.CompressionIgnitionMonitors
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (FuelSystemStatus)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/FuelSystemStatus.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.FuelSystemStatus
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (FuelType)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/FuelType.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.FuelType
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (IgnitionMonitorKind)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/IgnitionMonitorKind.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.IgnitionMonitorKind
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (Obd2FloatSensorIndex)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/Obd2FloatSensorIndex.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.Obd2FloatSensorIndex
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (Obd2IntegerSensorIndex)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/Obd2IntegerSensorIndex.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.Obd2IntegerSensorIndex
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (SecondaryAirStatus)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/SecondaryAirStatus.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.SecondaryAirStatus
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (SparkIgnitionMonitors)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/SparkIgnitionMonitors.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.SparkIgnitionMonitors
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VehicleProperty)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/VehicleProperty.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.VehicleProperty
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VmsBaseMessageIntegerValuesIndex)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/VmsBaseMessageIntegerValuesIndex.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.VmsBaseMessageIntegerValuesIndex
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VmsMessageType)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/VmsMessageType.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.VmsMessageType
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VmsOfferingMessageIntegerValuesIndex)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/VmsOfferingMessageIntegerValuesIndex.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.VmsOfferingMessageIntegerValuesIndex
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VmsSimpleMessageIntegerValuesIndex)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/VmsSimpleMessageIntegerValuesIndex.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.VmsSimpleMessageIntegerValuesIndex
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VmsSubscriptionResponseFormat)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/VmsSubscriptionResponseFormat.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.VmsSubscriptionResponseFormat
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build IVehicle.hal
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/IVehicle.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IVehicle.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::IVehicle
-
-$(GEN): $(LOCAL_PATH)/IVehicle.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-include $(BUILD_JAVA_LIBRARY)
-
-
-################################################################################
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := android.hardware.automotive.vehicle-V2.1-java-static
-LOCAL_MODULE_CLASS := JAVA_LIBRARIES
-
-intermediates := $(call local-generated-sources-dir, COMMON)
-
-HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
-    android.hardware.automotive.vehicle-V2.0-java-static \
-    android.hidl.base-V1.0-java-static \
-
-
-#
-# Build types.hal (CommonIgnitionMonitors)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/CommonIgnitionMonitors.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.CommonIgnitionMonitors
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (CompressionIgnitionMonitors)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/CompressionIgnitionMonitors.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.CompressionIgnitionMonitors
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (FuelSystemStatus)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/FuelSystemStatus.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.FuelSystemStatus
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (FuelType)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/FuelType.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.FuelType
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (IgnitionMonitorKind)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/IgnitionMonitorKind.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.IgnitionMonitorKind
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (Obd2FloatSensorIndex)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/Obd2FloatSensorIndex.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.Obd2FloatSensorIndex
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (Obd2IntegerSensorIndex)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/Obd2IntegerSensorIndex.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.Obd2IntegerSensorIndex
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (SecondaryAirStatus)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/SecondaryAirStatus.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.SecondaryAirStatus
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (SparkIgnitionMonitors)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/SparkIgnitionMonitors.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.SparkIgnitionMonitors
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VehicleProperty)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/VehicleProperty.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.VehicleProperty
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VmsBaseMessageIntegerValuesIndex)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/VmsBaseMessageIntegerValuesIndex.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.VmsBaseMessageIntegerValuesIndex
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VmsMessageType)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/VmsMessageType.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.VmsMessageType
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VmsOfferingMessageIntegerValuesIndex)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/VmsOfferingMessageIntegerValuesIndex.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.VmsOfferingMessageIntegerValuesIndex
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VmsSimpleMessageIntegerValuesIndex)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/VmsSimpleMessageIntegerValuesIndex.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.VmsSimpleMessageIntegerValuesIndex
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VmsSubscriptionResponseFormat)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/VmsSubscriptionResponseFormat.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::types.VmsSubscriptionResponseFormat
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build IVehicle.hal
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_1/IVehicle.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IVehicle.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.1::IVehicle
-
-$(GEN): $(LOCAL_PATH)/IVehicle.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/automotive/vehicle/2.1/IVehicle.hal b/automotive/vehicle/2.1/IVehicle.hal
deleted file mode 100644
index a22d1e6..0000000
--- a/automotive/vehicle/2.1/IVehicle.hal
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.1 (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.1
- *
- * 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.automotive.vehicle@2.1;
-
-import android.hardware.automotive.vehicle@2.0;
-
-/**
- * New revision of IVehicle interface that supports properties defined in
- * VehicleProperty enum version 2.1.
- *
- * NOTE: this HAL interface is under development and shouldn't be used in
- *       production.
- *
- * TODO(pavelm): update comment when this interface is ready for prod.
- */
-interface IVehicle extends @2.0::IVehicle {
-};
diff --git a/automotive/vehicle/2.1/default/Android.mk b/automotive/vehicle/2.1/default/Android.mk
deleted file mode 100644
index f19263c..0000000
--- a/automotive/vehicle/2.1/default/Android.mk
+++ /dev/null
@@ -1,121 +0,0 @@
-# Copyright (C) 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-
-vhal_v2_0 = android.hardware.automotive.vehicle@2.0
-vhal_v2_1 = android.hardware.automotive.vehicle@2.1
-
-###############################################################################
-# Vehicle reference implementation lib
-###############################################################################
-include $(CLEAR_VARS)
-LOCAL_MODULE := $(vhal_v2_1)-manager-lib
-LOCAL_SRC_FILES := \
-    common/src/Obd2SensorStore.cpp
-
-LOCAL_C_INCLUDES := \
-    $(LOCAL_PATH)/common/include/vhal_v2_1 \
-    $(LOCAL_PATH)/../../2.0/default/common/include/vhal_v2_0 \
-
-LOCAL_EXPORT_C_INCLUDE_DIRS := \
-    $(LOCAL_PATH)/common/include
-
-LOCAL_SHARED_LIBRARIES := \
-    libhidlbase \
-    libhidltransport \
-    libhwbinder \
-    liblog \
-    libutils \
-    $(vhal_v2_1) \
-
-include $(BUILD_STATIC_LIBRARY)
-
-###############################################################################
-# Vehicle default VehicleHAL implementation
-###############################################################################
-include $(CLEAR_VARS)
-
-LOCAL_MODULE:= $(vhal_v2_1)-default-impl-lib
-LOCAL_SRC_FILES:= \
-    impl/vhal_v2_1/EmulatedVehicleHal.cpp \
-
-LOCAL_C_INCLUDES := \
-    $(LOCAL_PATH)/impl/vhal_v2_1 \
-    $(LOCAL_PATH)/common/include
-
-LOCAL_EXPORT_C_INCLUDE_DIRS := \
-    $(LOCAL_PATH)/impl \
-    $(LOCAL_PATH)/common/include
-
-
-# LOCAL_WHOLE_STATIC_LIBRARIES := \
-
-LOCAL_STATIC_LIBRARIES := \
-    $(vhal_v2_0)-default-impl-lib \
-    $(vhal_v2_0)-manager-lib \
-    libqemu_pipe \
-    $(vhal_v2_1)-manager-lib \
-    $(vhal_v2_0)-libproto-native
-
-LOCAL_SHARED_LIBRARIES := \
-    libbase \
-    libhidlbase \
-    libhidltransport \
-    libhwbinder \
-    liblog \
-    libutils \
-    libprotobuf-cpp-lite \
-    $(vhal_v2_0) \
-    $(vhal_v2_1) \
-
-LOCAL_CFLAGS += -Wall -Wextra -Werror
-
-include $(BUILD_STATIC_LIBRARY)
-
-###############################################################################
-# Vehicle HAL service
-###############################################################################
-include $(CLEAR_VARS)
-LOCAL_MODULE := $(vhal_v2_1)-service
-LOCAL_INIT_RC := $(vhal_v2_1)-service.rc
-LOCAL_MODULE_RELATIVE_PATH := hw
-LOCAL_PROPRIETARY_MODULE := true
-LOCAL_SRC_FILES := \
-    service.cpp
-
-LOCAL_WHOLE_STATIC_LIBRARIES := \
-    $(vhal_v2_0)-libproto-native \
-
-LOCAL_STATIC_LIBRARIES := \
-    $(vhal_v2_0)-manager-lib \
-    $(vhal_v2_0)-default-impl-lib \
-    $(vhal_v2_1)-default-impl-lib \
-    libqemu_pipe \
-    $(vhal_v2_1)-manager-lib \
-
-LOCAL_SHARED_LIBRARIES := \
-    libbase \
-    libhidlbase \
-    libhidltransport \
-    libhwbinder \
-    liblog \
-    libutils \
-    libprotobuf-cpp-lite \
-    $(vhal_v2_0) \
-    $(vhal_v2_1) \
-
-LOCAL_CFLAGS += -Wall -Wextra -Werror
-
-include $(BUILD_EXECUTABLE)
diff --git a/automotive/vehicle/2.1/default/android.hardware.automotive.vehicle@2.1-service.rc b/automotive/vehicle/2.1/default/android.hardware.automotive.vehicle@2.1-service.rc
deleted file mode 100644
index 8929d25..0000000
--- a/automotive/vehicle/2.1/default/android.hardware.automotive.vehicle@2.1-service.rc
+++ /dev/null
@@ -1,4 +0,0 @@
-service vehicle-hal-2.1 /vendor/bin/hw/android.hardware.automotive.vehicle@2.1-service
-    class hal
-    user vehicle_network
-    group system inet
diff --git a/automotive/vehicle/2.1/default/impl/vhal_v2_1/DefaultConfig.h b/automotive/vehicle/2.1/default/impl/vhal_v2_1/DefaultConfig.h
deleted file mode 100644
index 0f10086..0000000
--- a/automotive/vehicle/2.1/default/impl/vhal_v2_1/DefaultConfig.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef android_hardware_automotive_vehicle_V2_1_impl_DefaultConfig_H_
-#define android_hardware_automotive_vehicle_V2_1_impl_DefaultConfig_H_
-
-#include <android/hardware/automotive/vehicle/2.1/types.h>
-#include <vhal_v2_0/VehicleUtils.h>
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace vehicle {
-namespace V2_1 {
-
-namespace impl {
-
-// Some handy constants to avoid conversions from enum to int.
-constexpr int OBD2_LIVE_FRAME = (int) V2_1::VehicleProperty::OBD2_LIVE_FRAME;
-constexpr int OBD2_FREEZE_FRAME = (int) V2_1::VehicleProperty::OBD2_FREEZE_FRAME;
-constexpr int OBD2_FREEZE_FRAME_INFO = (int) V2_1::VehicleProperty::OBD2_FREEZE_FRAME_INFO;
-constexpr int OBD2_FREEZE_FRAME_CLEAR = (int) V2_1::VehicleProperty::OBD2_FREEZE_FRAME_CLEAR;
-constexpr int VEHICLE_MAP_SERVICE = (int) V2_1::VehicleProperty::VEHICLE_MAP_SERVICE;
-constexpr int WHEEL_TICK = (int) V2_1::VehicleProperty::WHEEL_TICK;
-
-
-const V2_0::VehiclePropConfig kVehicleProperties[] = {
-    {
-        .prop = WHEEL_TICK,
-        .access = V2_0::VehiclePropertyAccess::READ,
-        .changeMode = V2_0::VehiclePropertyChangeMode::CONTINUOUS,
-        .minSampleRate = 1.0f,
-        .maxSampleRate = 100.0f,
-    },
-
-    {
-        .prop = OBD2_LIVE_FRAME,
-        .access = V2_0::VehiclePropertyAccess::READ,
-        .changeMode = V2_0::VehiclePropertyChangeMode::ON_CHANGE,
-        .configArray = {0,0}
-    },
-
-    {
-        .prop = OBD2_FREEZE_FRAME,
-        .access = V2_0::VehiclePropertyAccess::READ,
-        .changeMode = V2_0::VehiclePropertyChangeMode::ON_CHANGE,
-        .configArray = {0,0}
-    },
-
-    {
-        .prop = OBD2_FREEZE_FRAME_INFO,
-        .access = V2_0::VehiclePropertyAccess::READ,
-        .changeMode = V2_0::VehiclePropertyChangeMode::ON_CHANGE
-    },
-
-    {
-        .prop = OBD2_FREEZE_FRAME_CLEAR,
-        .access = V2_0::VehiclePropertyAccess::WRITE,
-        .changeMode = V2_0::VehiclePropertyChangeMode::ON_CHANGE
-    },
-
-    {
-        .prop = VEHICLE_MAP_SERVICE,
-        .access = V2_0::VehiclePropertyAccess::READ_WRITE,
-        .changeMode = V2_0::VehiclePropertyChangeMode::ON_CHANGE
-    }
-};
-
-}  // impl
-
-}  // namespace V2_1
-}  // namespace vehicle
-}  // namespace automotive
-}  // namespace hardware
-}  // namespace android
-
-#endif // android_hardware_automotive_vehicle_V2_1_impl_DefaultConfig_H_
diff --git a/automotive/vehicle/2.1/default/impl/vhal_v2_1/EmulatedVehicleHal.cpp b/automotive/vehicle/2.1/default/impl/vhal_v2_1/EmulatedVehicleHal.cpp
deleted file mode 100644
index 46e062b..0000000
--- a/automotive/vehicle/2.1/default/impl/vhal_v2_1/EmulatedVehicleHal.cpp
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "DefaultVehicleHal_v2_1"
-#include <android/log.h>
-
-#include <log/log.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
-#include <algorithm>
-
-#include "EmulatedVehicleHal.h"
-
-#define DEBUG_SOCKET    (33452)
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace vehicle {
-namespace V2_1 {
-
-namespace impl {
-
-static std::unique_ptr<Obd2SensorStore> fillDefaultObd2Frame(
-        size_t numVendorIntegerSensors,
-        size_t numVendorFloatSensors) {
-    std::unique_ptr<Obd2SensorStore> sensorStore(new Obd2SensorStore(
-            numVendorIntegerSensors, numVendorFloatSensors));
-
-    sensorStore->setIntegerSensor(
-        Obd2IntegerSensorIndex::FUEL_SYSTEM_STATUS,
-        V2_0::toInt(FuelSystemStatus::CLOSED_LOOP));
-    sensorStore->setIntegerSensor(
-        Obd2IntegerSensorIndex::MALFUNCTION_INDICATOR_LIGHT_ON, 0);
-    sensorStore->setIntegerSensor(
-        Obd2IntegerSensorIndex::IGNITION_MONITORS_SUPPORTED,
-        V2_0::toInt(IgnitionMonitorKind::SPARK));
-    sensorStore->setIntegerSensor(Obd2IntegerSensorIndex::IGNITION_SPECIFIC_MONITORS,
-        CommonIgnitionMonitors::COMPONENTS_AVAILABLE |
-        CommonIgnitionMonitors::MISFIRE_AVAILABLE |
-        SparkIgnitionMonitors::AC_REFRIGERANT_AVAILABLE |
-        SparkIgnitionMonitors::EVAPORATIVE_SYSTEM_AVAILABLE);
-    sensorStore->setIntegerSensor(
-        Obd2IntegerSensorIndex::INTAKE_AIR_TEMPERATURE, 35);
-    sensorStore->setIntegerSensor(
-        Obd2IntegerSensorIndex::COMMANDED_SECONDARY_AIR_STATUS,
-        V2_0::toInt(SecondaryAirStatus::FROM_OUTSIDE_OR_OFF));
-    sensorStore->setIntegerSensor(
-        Obd2IntegerSensorIndex::NUM_OXYGEN_SENSORS_PRESENT, 1);
-    sensorStore->setIntegerSensor(
-        Obd2IntegerSensorIndex::RUNTIME_SINCE_ENGINE_START, 500);
-    sensorStore->setIntegerSensor(
-        Obd2IntegerSensorIndex::DISTANCE_TRAVELED_WITH_MALFUNCTION_INDICATOR_LIGHT_ON, 0);
-    sensorStore->setIntegerSensor(
-        Obd2IntegerSensorIndex::WARMUPS_SINCE_CODES_CLEARED, 51);
-    sensorStore->setIntegerSensor(
-        Obd2IntegerSensorIndex::DISTANCE_TRAVELED_SINCE_CODES_CLEARED, 365);
-    sensorStore->setIntegerSensor(
-        Obd2IntegerSensorIndex::ABSOLUTE_BAROMETRIC_PRESSURE, 30);
-    sensorStore->setIntegerSensor(
-        Obd2IntegerSensorIndex::CONTROL_MODULE_VOLTAGE, 12);
-    sensorStore->setIntegerSensor(
-        Obd2IntegerSensorIndex::AMBIENT_AIR_TEMPERATURE, 18);
-    sensorStore->setIntegerSensor(
-        Obd2IntegerSensorIndex::MAX_FUEL_AIR_EQUIVALENCE_RATIO, 1);
-    sensorStore->setIntegerSensor(
-        Obd2IntegerSensorIndex::FUEL_TYPE, V2_0::toInt(FuelType::GASOLINE));
-    sensorStore->setFloatSensor(
-        Obd2FloatSensorIndex::CALCULATED_ENGINE_LOAD, 0.153);
-    sensorStore->setFloatSensor(
-        Obd2FloatSensorIndex::SHORT_TERM_FUEL_TRIM_BANK1, -0.16);
-    sensorStore->setFloatSensor(
-        Obd2FloatSensorIndex::LONG_TERM_FUEL_TRIM_BANK1, -0.16);
-    sensorStore->setFloatSensor(
-        Obd2FloatSensorIndex::SHORT_TERM_FUEL_TRIM_BANK2, -0.16);
-    sensorStore->setFloatSensor(
-        Obd2FloatSensorIndex::LONG_TERM_FUEL_TRIM_BANK2, -0.16);
-    sensorStore->setFloatSensor(
-        Obd2FloatSensorIndex::INTAKE_MANIFOLD_ABSOLUTE_PRESSURE, 7.5);
-    sensorStore->setFloatSensor(
-        Obd2FloatSensorIndex::ENGINE_RPM, 1250.);
-    sensorStore->setFloatSensor(
-        Obd2FloatSensorIndex::VEHICLE_SPEED, 40.);
-    sensorStore->setFloatSensor(
-        Obd2FloatSensorIndex::TIMING_ADVANCE, 2.5);
-    sensorStore->setFloatSensor(
-        Obd2FloatSensorIndex::THROTTLE_POSITION, 19.75);
-    sensorStore->setFloatSensor(
-        Obd2FloatSensorIndex::OXYGEN_SENSOR1_VOLTAGE, 0.265);
-    sensorStore->setFloatSensor(
-        Obd2FloatSensorIndex::FUEL_TANK_LEVEL_INPUT, 0.824);
-    sensorStore->setFloatSensor(
-        Obd2FloatSensorIndex::EVAPORATION_SYSTEM_VAPOR_PRESSURE, -0.373);
-    sensorStore->setFloatSensor(
-        Obd2FloatSensorIndex::CATALYST_TEMPERATURE_BANK1_SENSOR1, 190.);
-    sensorStore->setFloatSensor(
-        Obd2FloatSensorIndex::RELATIVE_THROTTLE_POSITION, 3.);
-    sensorStore->setFloatSensor(
-        Obd2FloatSensorIndex::ABSOLUTE_THROTTLE_POSITION_B, 0.306);
-    sensorStore->setFloatSensor(
-        Obd2FloatSensorIndex::ACCELERATOR_PEDAL_POSITION_D, 0.188);
-    sensorStore->setFloatSensor(
-        Obd2FloatSensorIndex::ACCELERATOR_PEDAL_POSITION_E, 0.094);
-    sensorStore->setFloatSensor(
-        Obd2FloatSensorIndex::COMMANDED_THROTTLE_ACTUATOR, 0.024);
-
-    return sensorStore;
-}
-
-void EmulatedVehicleHal::initObd2LiveFrame(const V2_0::VehiclePropConfig& propConfig) {
-    auto liveObd2Frame = createVehiclePropValue(V2_0::VehiclePropertyType::COMPLEX, 0);
-    auto sensorStore = fillDefaultObd2Frame(static_cast<size_t>(propConfig.configArray[0]),
-                                            static_cast<size_t>(propConfig.configArray[1]));
-    sensorStore->fillPropValue("", liveObd2Frame.get());
-    liveObd2Frame->prop = OBD2_LIVE_FRAME;
-
-    mPropStore->writeValue(*liveObd2Frame);
-}
-
-void EmulatedVehicleHal::initObd2FreezeFrame(const V2_0::VehiclePropConfig& propConfig) {
-    auto sensorStore = fillDefaultObd2Frame(static_cast<size_t>(propConfig.configArray[0]),
-                                            static_cast<size_t>(propConfig.configArray[1]));
-
-    static std::vector<std::string> sampleDtcs = { "P0070", "P0102" "P0123" };
-    for (auto&& dtc : sampleDtcs) {
-        auto freezeFrame = createVehiclePropValue(V2_0::VehiclePropertyType::COMPLEX, 0);
-        sensorStore->fillPropValue(dtc, freezeFrame.get());
-        freezeFrame->prop = OBD2_FREEZE_FRAME;
-
-        mPropStore->writeValue(*freezeFrame);
-    }
-}
-
-V2_0::StatusCode EmulatedVehicleHal::fillObd2FreezeFrame(
-        const V2_0::VehiclePropValue& requestedPropValue,
-        V2_0::VehiclePropValue* outValue) {
-    if (requestedPropValue.value.int64Values.size() != 1) {
-        ALOGE("asked for OBD2_FREEZE_FRAME without valid timestamp");
-        return V2_0::StatusCode::INVALID_ARG;
-    }
-    auto timestamp = requestedPropValue.value.int64Values[0];
-    auto freezeFrame = mPropStore->readValueOrNull(OBD2_FREEZE_FRAME, 0, timestamp);
-    if(freezeFrame == nullptr) {
-        ALOGE("asked for OBD2_FREEZE_FRAME at invalid timestamp");
-        return V2_0::StatusCode::INVALID_ARG;
-    }
-    outValue->prop = OBD2_FREEZE_FRAME;
-    outValue->value.int32Values = freezeFrame->value.int32Values;
-    outValue->value.floatValues = freezeFrame->value.floatValues;
-    outValue->value.bytes = freezeFrame->value.bytes;
-    outValue->value.stringValue = freezeFrame->value.stringValue;
-    outValue->timestamp = freezeFrame->timestamp;
-    return V2_0::StatusCode::OK;
-}
-
-V2_0::StatusCode EmulatedVehicleHal::clearObd2FreezeFrames(const V2_0::VehiclePropValue& propValue) {
-    if (propValue.value.int64Values.size() == 0) {
-        mPropStore->removeValuesForProperty(OBD2_FREEZE_FRAME);
-        return V2_0::StatusCode::OK;
-    } else {
-        for(int64_t timestamp: propValue.value.int64Values) {
-            auto freezeFrame = mPropStore->readValueOrNull(OBD2_FREEZE_FRAME, 0, timestamp);
-            if(freezeFrame == nullptr) {
-                ALOGE("asked for OBD2_FREEZE_FRAME at invalid timestamp");
-                return V2_0::StatusCode::INVALID_ARG;
-            }
-            mPropStore->removeValue(*freezeFrame);
-        }
-    }
-    return V2_0::StatusCode::OK;
-}
-
-V2_0::StatusCode EmulatedVehicleHal::fillObd2DtcInfo(V2_0::VehiclePropValue* outValue) {
-    std::vector<int64_t> timestamps;
-    for(const auto& freezeFrame: mPropStore->readValuesForProperty(OBD2_FREEZE_FRAME)) {
-        timestamps.push_back(freezeFrame.timestamp);
-    }
-    outValue->value.int64Values = timestamps;
-    return V2_0::StatusCode::OK;
-}
-
-void EmulatedVehicleHal::onCreate() {
-    V2_0::impl::EmulatedVehicleHal::onCreate();
-
-    initObd2LiveFrame(*mPropStore->getConfigOrDie(OBD2_LIVE_FRAME));
-    initObd2FreezeFrame(*mPropStore->getConfigOrDie(OBD2_FREEZE_FRAME));
-}
-
-void EmulatedVehicleHal::initStaticConfig() {
-    for (auto&& cfg = std::begin(kVehicleProperties); cfg != std::end(kVehicleProperties); ++cfg) {
-        V2_0::VehiclePropertyStore::TokenFunction tokenFunction = nullptr;
-
-        switch (cfg->prop) {
-            case OBD2_FREEZE_FRAME: {
-                tokenFunction = [] (const V2_0::VehiclePropValue& propValue) {
-                    return propValue.timestamp;
-                };
-                break;
-            }
-            default:
-                break;
-        }
-
-        mPropStore->registerProperty(*cfg, tokenFunction);
-    }
-}
-
-EmulatedVehicleHal::VehiclePropValuePtr EmulatedVehicleHal::get(
-        const V2_0::VehiclePropValue& requestedPropValue,
-        V2_0::StatusCode* outStatus) {
-
-    auto propId = requestedPropValue.prop;
-    VehiclePropValuePtr v = nullptr;
-    auto& pool = *getValuePool();
-
-    switch (propId) {
-    case OBD2_FREEZE_FRAME:
-        v = pool.obtainComplex();
-        *outStatus = fillObd2FreezeFrame(requestedPropValue, v.get());
-        return v;
-    case OBD2_FREEZE_FRAME_INFO:
-        v = pool.obtainComplex();
-        *outStatus = fillObd2DtcInfo(v.get());
-        return v;
-    default:
-        return V2_0::impl::EmulatedVehicleHal::get(requestedPropValue, outStatus);
-    }
-}
-
-V2_0::StatusCode EmulatedVehicleHal::set(const V2_0::VehiclePropValue& propValue) {
-    auto propId = propValue.prop;
-    switch (propId) {
-    case OBD2_FREEZE_FRAME_CLEAR:
-        return clearObd2FreezeFrames(propValue);
-    case VEHICLE_MAP_SERVICE:
-        // Placeholder for future implementation of VMS property in the default hal. For now, just
-        // returns OK; otherwise, hal clients crash with property not supported.
-        return V2_0::StatusCode::OK;
-    default:
-        return V2_0::impl::EmulatedVehicleHal::set(propValue);
-    }
-}
-
-}  // impl
-
-}  // namespace V2_1
-}  // namespace vehicle
-}  // namespace automotive
-}  // namespace hardware
-}  // namespace android
diff --git a/automotive/vehicle/2.1/default/impl/vhal_v2_1/EmulatedVehicleHal.h b/automotive/vehicle/2.1/default/impl/vhal_v2_1/EmulatedVehicleHal.h
deleted file mode 100644
index 7cc3b79..0000000
--- a/automotive/vehicle/2.1/default/impl/vhal_v2_1/EmulatedVehicleHal.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef android_hardware_automotive_vehicle_V2_1_impl_EmulatedVehicleHal_H_
-#define android_hardware_automotive_vehicle_V2_1_impl_EmulatedVehicleHal_H_
-
-#include <memory>
-
-#include <utils/SystemClock.h>
-
-#include <vhal_v2_0/EmulatedVehicleHal.h>
-#include <vhal_v2_0/VehicleHal.h>
-#include <vhal_v2_0/VehiclePropertyStore.h>
-#include <vhal_v2_1/Obd2SensorStore.h>
-
-#include "DefaultConfig.h"
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace vehicle {
-namespace V2_1 {
-
-namespace impl {
-
-using namespace std::placeholders;
-
-class EmulatedVehicleHal : public V2_0::impl::EmulatedVehicleHal {
-public:
-    EmulatedVehicleHal(V2_0::VehiclePropertyStore* propStore)
-        : V2_0::impl::EmulatedVehicleHal(propStore), mPropStore(propStore) {
-        initStaticConfig();
-    }
-
-    VehiclePropValuePtr get(const V2_0::VehiclePropValue& requestedPropValue,
-                            V2_0::StatusCode* outStatus) override;
-
-    V2_0::StatusCode set(const V2_0::VehiclePropValue& propValue) override;
-
-    void onCreate() override;
-
-private:
-    void initStaticConfig();
-    void initObd2LiveFrame(const V2_0::VehiclePropConfig& propConfig);
-    void initObd2FreezeFrame(const V2_0::VehiclePropConfig& propConfig);
-    V2_0::StatusCode fillObd2FreezeFrame(const V2_0::VehiclePropValue& requestedPropValue,
-                                        V2_0::VehiclePropValue* outValue);
-    V2_0::StatusCode fillObd2DtcInfo(V2_0::VehiclePropValue *outValue);
-    V2_0::StatusCode clearObd2FreezeFrames(const V2_0::VehiclePropValue& propValue);
-
-private:
-    V2_0::VehiclePropertyStore* mPropStore;
-};
-
-}  // impl
-
-}  // namespace V2_1
-}  // namespace vehicle
-}  // namespace automotive
-}  // namespace hardware
-}  // namespace android
-
-
-#endif  // android_hardware_automotive_vehicle_V2_0_impl_EmulatedVehicleHal_H_
diff --git a/automotive/vehicle/2.1/default/service.cpp b/automotive/vehicle/2.1/default/service.cpp
deleted file mode 100644
index bae64fd..0000000
--- a/automotive/vehicle/2.1/default/service.cpp
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "automotive.vehicle@2.1-service"
-#include <android/log.h>
-#include <hidl/HidlTransportSupport.h>
-
-#include <iostream>
-
-#include <android/hardware/automotive/vehicle/2.1/IVehicle.h>
-
-#include <vhal_v2_0/VehicleHalManager.h>
-#include <vhal_v2_0/VehiclePropertyStore.h>
-#include <vhal_v2_0/EmulatedVehicleHal.h>
-
-#include <vhal_v2_1/EmulatedVehicleHal.h>
-
-using namespace android;
-using namespace android::hardware;
-
-namespace V2_1 = ::android::hardware::automotive::vehicle::V2_1;
-namespace V2_0 = ::android::hardware::automotive::vehicle::V2_0;
-
-using StatusCode = V2_0::StatusCode;
-using VehiclePropValue = V2_0::VehiclePropValue;
-
-/* Just wrapper that passes all calls to the provided V2_0::IVehicle object */
-struct Vehicle_V2_1 : public V2_1::IVehicle {
-
-    Vehicle_V2_1(V2_0::IVehicle* vehicle20) : mVehicle20(vehicle20) {}
-
-    // Methods derived from IVehicle
-    Return<void> getAllPropConfigs(getAllPropConfigs_cb _hidl_cb)  override {
-        return mVehicle20->getAllPropConfigs(_hidl_cb);
-    }
-
-    Return<void> getPropConfigs(const hidl_vec<int32_t>& properties,
-                                getPropConfigs_cb _hidl_cb)  override {
-        return mVehicle20->getPropConfigs(properties, _hidl_cb);
-    }
-
-    Return<void> get(const V2_0::VehiclePropValue& requestedPropValue,
-                     get_cb _hidl_cb)  override {
-        return mVehicle20->get(requestedPropValue, _hidl_cb);
-    }
-
-    Return<StatusCode> set(const VehiclePropValue& value) override {
-        return mVehicle20->set(value);
-    }
-
-    Return<StatusCode> subscribe(const sp<V2_0::IVehicleCallback>& callback,
-                                 const hidl_vec<V2_0::SubscribeOptions>&
-                                 options)  override {
-        return mVehicle20->subscribe(callback, options);
-    }
-
-    Return<StatusCode> unsubscribe(const sp<V2_0::IVehicleCallback>& callback,
-                                   int32_t propId)  override {
-        return mVehicle20->unsubscribe(callback, propId);
-    }
-
-    Return<void> debugDump(debugDump_cb _hidl_cb = nullptr) override {
-        return mVehicle20->debugDump(_hidl_cb);
-    }
-
-private:
-    V2_0::IVehicle* mVehicle20;
-};
-
-int main(int /* argc */, char* /* argv */ []) {
-    auto store = std::make_unique<V2_0::VehiclePropertyStore>();
-    auto hal = std::make_unique<V2_1::impl::EmulatedVehicleHal>(store.get());
-    auto emulator = std::make_unique<V2_0::impl::VehicleEmulator>(hal.get());
-    auto vehicleManager = std::make_unique<V2_0::VehicleHalManager>(hal.get());
-
-    Vehicle_V2_1 vehicle21(vehicleManager.get());
-
-    configureRpcThreadpool(1, true /* callerWillJoin */);
-
-    ALOGI("Registering as service...");
-    status_t status = vehicle21.registerAsService();
-
-    if (status != OK) {
-        ALOGE("Unable to register vehicle service (%d).", status);
-        return 1;
-    }
-
-    ALOGI("Ready");
-    joinRpcThreadpool();
-    return 1;
-}
diff --git a/automotive/vehicle/2.1/default/tests/Obd2SensorStore_test.cpp b/automotive/vehicle/2.1/default/tests/Obd2SensorStore_test.cpp
deleted file mode 100644
index a01c0f4..0000000
--- a/automotive/vehicle/2.1/default/tests/Obd2SensorStore_test.cpp
+++ /dev/null
@@ -1,285 +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.
- */
-
- #include <gtest/gtest.h>
-
-#include "vhal_v2_0/Obd2SensorStore.h"
-#include "vhal_v2_0/VehicleUtils.h"
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace vehicle {
-namespace V2_0 {
-
-namespace {
-
-static constexpr size_t getNumVendorIntegerSensors() {
-    return 5;
-}
-static constexpr size_t getNumVendorFloatSensors() {
-    return 3;
-}
-
-// this struct holds information necessary for a test to be able to validate
-// that the sensor bitmask contains the right data:
-//   - the index of the byte at which the bit for a given sensor lives
-//   - the expected value of that byte given that a certain sensor is present
-class BitmaskIndexingInfo {
-public:
-    size_t mByteIndex;
-    uint8_t mExpectedByteValue;
-
-    // Returns the information required to validate the bitmask for an
-    // integer-valued sensor.
-    static BitmaskIndexingInfo getForIntegerSensor(size_t index) {
-        const size_t indexInBitstream = index;
-        return getForBitstreamIndex(indexInBitstream);
-    }
-
-    // Returns the information required to validate the bitmask for a
-    // float-valued sensor.
-    static BitmaskIndexingInfo getForFloatSensor(size_t index) {
-        const size_t indexInBitstream = toInt(Obd2IntegerSensorIndex::LAST_SYSTEM_INDEX) +
-                                        1 + getNumVendorIntegerSensors() + index;
-        return getForBitstreamIndex(indexInBitstream);
-    }
-
-private:
-    static BitmaskIndexingInfo getForBitstreamIndex(size_t indexInBitstream) {
-        BitmaskIndexingInfo indexingInfo;
-        indexingInfo.mByteIndex = indexInBitstream / 8;
-        indexingInfo.mExpectedByteValue = 1 << (indexInBitstream % 8);
-        return indexingInfo;
-    }
-};
-
-static Obd2SensorStore getSensorStore() {
-    return Obd2SensorStore(getNumVendorIntegerSensors(),
-                           getNumVendorFloatSensors());
-}
-
-// Test that one can set and retrieve a value for the first integer sensor.
-TEST(Obd2SensorStoreTest, setFirstIntegerSensor) {
-    Obd2SensorStore sensorStore(getSensorStore());
-    sensorStore.setIntegerSensor(
-        Obd2IntegerSensorIndex::FUEL_SYSTEM_STATUS,
-        toInt(FuelSystemStatus::CLOSED_LOOP));
-    const auto& integerSensors(sensorStore.getIntegerSensors());
-    const auto& sensorBitmask(sensorStore.getSensorsBitmask());
-    ASSERT_EQ(
-        toInt(FuelSystemStatus::CLOSED_LOOP),
-        integerSensors[toInt(Obd2IntegerSensorIndex::FUEL_SYSTEM_STATUS)]);
-    const BitmaskIndexingInfo indexingInfo(BitmaskIndexingInfo::getForIntegerSensor(
-        toInt(Obd2IntegerSensorIndex::FUEL_SYSTEM_STATUS)));
-    ASSERT_EQ(
-        indexingInfo.mExpectedByteValue,
-        sensorBitmask[indexingInfo.mByteIndex]);
-}
-
-// Test that one can set and retrieve a value for the first float sensor.
-TEST(Obd2SensorStoreTest, setFirstFloatSensor) {
-    Obd2SensorStore sensorStore(getSensorStore());
-    sensorStore.setFloatSensor(
-        Obd2FloatSensorIndex::CALCULATED_ENGINE_LOAD,
-        1.25f);
-    const auto& floatSensors(sensorStore.getFloatSensors());
-    const auto& sensorBitmask(sensorStore.getSensorsBitmask());
-    ASSERT_EQ(
-        1.25f,
-        floatSensors[toInt(Obd2FloatSensorIndex::CALCULATED_ENGINE_LOAD)]);
-    const BitmaskIndexingInfo indexingInfo(BitmaskIndexingInfo::getForFloatSensor(
-        toInt(Obd2FloatSensorIndex::CALCULATED_ENGINE_LOAD)));
-    ASSERT_EQ(
-        indexingInfo.mExpectedByteValue,
-        sensorBitmask[indexingInfo.mByteIndex]);
-}
-
-// Test that one can set and retrieve a value for an integer sensor.
-TEST(Obd2SensorStoreTest, setAnyIntegerSensor) {
-    Obd2SensorStore sensorStore(getSensorStore());
-    sensorStore.setIntegerSensor(
-        Obd2IntegerSensorIndex::ABSOLUTE_BAROMETRIC_PRESSURE,
-        4000);
-    const auto& integerSensors(sensorStore.getIntegerSensors());
-    const auto& sensorBitmask(sensorStore.getSensorsBitmask());
-    ASSERT_EQ(4000,
-        integerSensors[toInt(Obd2IntegerSensorIndex::ABSOLUTE_BAROMETRIC_PRESSURE)]);
-    const BitmaskIndexingInfo indexingInfo(BitmaskIndexingInfo::getForIntegerSensor(
-        toInt(Obd2IntegerSensorIndex::ABSOLUTE_BAROMETRIC_PRESSURE)));
-    ASSERT_EQ(
-        indexingInfo.mExpectedByteValue,
-        sensorBitmask[indexingInfo.mByteIndex]);
-}
-
-// Test that one can set and retrieve a value for a float sensor.
-TEST(Obd2SensorStoreTest, setAnyFloatSensor) {
-    Obd2SensorStore sensorStore(getSensorStore());
-    sensorStore.setFloatSensor(
-        Obd2FloatSensorIndex::OXYGEN_SENSOR3_VOLTAGE,
-        2.5f);
-    const auto& floatSensors(sensorStore.getFloatSensors());
-    const auto& sensorBitmask(sensorStore.getSensorsBitmask());
-    ASSERT_EQ(2.5f,
-        floatSensors[toInt(Obd2FloatSensorIndex::OXYGEN_SENSOR3_VOLTAGE)]);
-    const BitmaskIndexingInfo indexingInfo(BitmaskIndexingInfo::getForFloatSensor(
-        toInt(Obd2FloatSensorIndex::OXYGEN_SENSOR3_VOLTAGE)));
-    ASSERT_EQ(
-        indexingInfo.mExpectedByteValue,
-        sensorBitmask[indexingInfo.mByteIndex]);
-}
-
-// Test that one can set and retrieve a value for the last system integer sensor.
-TEST(Obd2SensorStoreTest, setLastSystemIntegerSensor) {
-    Obd2SensorStore sensorStore(getSensorStore());
-    sensorStore.setIntegerSensor(
-        Obd2IntegerSensorIndex::LAST_SYSTEM_INDEX,
-        30);
-    const auto& integerSensors(sensorStore.getIntegerSensors());
-    const auto& sensorBitmask(sensorStore.getSensorsBitmask());
-    ASSERT_EQ(30,
-        integerSensors[toInt(Obd2IntegerSensorIndex::LAST_SYSTEM_INDEX)]);
-    const BitmaskIndexingInfo indexingInfo(BitmaskIndexingInfo::getForIntegerSensor(
-        toInt(Obd2IntegerSensorIndex::LAST_SYSTEM_INDEX)));
-    ASSERT_EQ(
-        indexingInfo.mExpectedByteValue,
-        sensorBitmask[indexingInfo.mByteIndex]);
-}
-
-// Test that one can set and retrieve a value for the last system float sensor.
-TEST(Obd2SensorStoreTest, setLastSystemFloatSensor) {
-    Obd2SensorStore sensorStore(getSensorStore());
-    sensorStore.setFloatSensor(
-        Obd2FloatSensorIndex::LAST_SYSTEM_INDEX,
-        2.5f);
-    const auto& floatSensors(sensorStore.getFloatSensors());
-    const auto& sensorBitmask(sensorStore.getSensorsBitmask());
-    ASSERT_EQ(2.5f,
-        floatSensors[toInt(Obd2FloatSensorIndex::LAST_SYSTEM_INDEX)]);
-    const BitmaskIndexingInfo indexingInfo(BitmaskIndexingInfo::getForFloatSensor(
-        toInt(Obd2FloatSensorIndex::LAST_SYSTEM_INDEX)));
-    ASSERT_EQ(
-        indexingInfo.mExpectedByteValue,
-        sensorBitmask[indexingInfo.mByteIndex]);
-}
-
-// Test that one can set and retrieve a value for two integer sensors at once.
-TEST(Obd2SensorStoreTest, setTwoIntegerSensors) {
-    Obd2SensorStore sensorStore(getSensorStore());
-    sensorStore.setIntegerSensor(
-        Obd2IntegerSensorIndex::CONTROL_MODULE_VOLTAGE,
-        6);
-    sensorStore.setIntegerSensor(
-        Obd2IntegerSensorIndex::TIME_SINCE_TROUBLE_CODES_CLEARED,
-        1245);
-    const auto& integerSensors(sensorStore.getIntegerSensors());
-    const auto& sensorBitmask(sensorStore.getSensorsBitmask());
-    ASSERT_EQ(6,
-        integerSensors[toInt(Obd2IntegerSensorIndex::CONTROL_MODULE_VOLTAGE)]);
-    ASSERT_EQ(1245,
-        integerSensors[toInt(Obd2IntegerSensorIndex::TIME_SINCE_TROUBLE_CODES_CLEARED)]);
-    const BitmaskIndexingInfo voltageIndexingInfo(BitmaskIndexingInfo::getForIntegerSensor(
-        toInt(Obd2IntegerSensorIndex::CONTROL_MODULE_VOLTAGE)));
-    const BitmaskIndexingInfo timeIndexingInfo(BitmaskIndexingInfo::getForIntegerSensor(
-        toInt(Obd2IntegerSensorIndex::TIME_SINCE_TROUBLE_CODES_CLEARED)));
-    if (voltageIndexingInfo.mByteIndex == timeIndexingInfo.mByteIndex) {
-        ASSERT_EQ(
-            voltageIndexingInfo.mExpectedByteValue |
-            timeIndexingInfo.mExpectedByteValue,
-            sensorBitmask[timeIndexingInfo.mByteIndex]);
-    }
-    else {
-        ASSERT_EQ(
-            timeIndexingInfo.mExpectedByteValue,
-            sensorBitmask[timeIndexingInfo.mByteIndex]);
-        ASSERT_EQ(
-            voltageIndexingInfo.mExpectedByteValue,
-            sensorBitmask[voltageIndexingInfo.mByteIndex]);
-    }
-}
-
-// Test that one can set and retrieve a value for two float sensors at once.
-TEST(Obd2SensorStoreTest, setTwoFloatSensors) {
-    Obd2SensorStore sensorStore(getSensorStore());
-    sensorStore.setFloatSensor(
-        Obd2FloatSensorIndex::VEHICLE_SPEED,
-        1.25f);
-    sensorStore.setFloatSensor(
-        Obd2FloatSensorIndex::MAF_AIR_FLOW_RATE,
-        2.5f);
-    const auto& floatSensors(sensorStore.getFloatSensors());
-    const auto& sensorBitmask(sensorStore.getSensorsBitmask());
-    ASSERT_EQ(1.25f,
-        floatSensors[toInt(Obd2FloatSensorIndex::VEHICLE_SPEED)]);
-    ASSERT_EQ(2.5f,
-        floatSensors[toInt(Obd2FloatSensorIndex::MAF_AIR_FLOW_RATE)]);
-    const BitmaskIndexingInfo speedIndexingInfo(BitmaskIndexingInfo::getForFloatSensor(
-        toInt(Obd2FloatSensorIndex::VEHICLE_SPEED)));
-    const BitmaskIndexingInfo airflowIndexingInfo(BitmaskIndexingInfo::getForFloatSensor(
-        toInt(Obd2FloatSensorIndex::MAF_AIR_FLOW_RATE)));
-    if (speedIndexingInfo.mByteIndex == airflowIndexingInfo.mByteIndex) {
-        ASSERT_EQ(
-            speedIndexingInfo.mExpectedByteValue |
-            airflowIndexingInfo.mExpectedByteValue,
-            sensorBitmask[airflowIndexingInfo.mByteIndex]);
-    }
-    else {
-        ASSERT_EQ(
-            speedIndexingInfo.mExpectedByteValue,
-            sensorBitmask[speedIndexingInfo.mByteIndex]);
-        ASSERT_EQ(
-            airflowIndexingInfo.mExpectedByteValue,
-            sensorBitmask[airflowIndexingInfo.mByteIndex]);
-    }
-}
-
-// Test that one can set and retrieve a value for a vendor integer sensor.
-TEST(Obd2SensorStoreTest, setVendorIntegerSensor) {
-    const size_t sensorIndex = toInt(Obd2IntegerSensorIndex::LAST_SYSTEM_INDEX) + 2;
-    Obd2SensorStore sensorStore(getSensorStore());
-    sensorStore.setIntegerSensor(sensorIndex, 22);
-    const auto& integerSensors(sensorStore.getIntegerSensors());
-    const auto& sensorBitmask(sensorStore.getSensorsBitmask());
-    ASSERT_EQ(22, integerSensors[sensorIndex]);
-    const BitmaskIndexingInfo indexingInfo(BitmaskIndexingInfo::getForIntegerSensor(
-        sensorIndex));
-    ASSERT_EQ(
-        indexingInfo.mExpectedByteValue,
-        sensorBitmask[indexingInfo.mByteIndex]);
-}
-
-// Test that one can set and retrieve a value for a vendor float sensor.
-TEST(Obd2SensorStoreTest, setVendorFloatSensor) {
-    const size_t sensorIndex = toInt(Obd2FloatSensorIndex::LAST_SYSTEM_INDEX) + 2;
-    Obd2SensorStore sensorStore(getSensorStore());
-    sensorStore.setFloatSensor(sensorIndex, 1.25f);
-    const auto& floatSensors(sensorStore.getFloatSensors());
-    const auto& sensorBitmask(sensorStore.getSensorsBitmask());
-    ASSERT_EQ(1.25f, floatSensors[sensorIndex]);
-    const BitmaskIndexingInfo indexingInfo(BitmaskIndexingInfo::getForFloatSensor(
-        sensorIndex));
-    ASSERT_EQ(
-        indexingInfo.mExpectedByteValue,
-        sensorBitmask[indexingInfo.mByteIndex]);
-}
-
-}  // namespace anonymous
-
-}  // namespace V2_0
-}  // namespace vehicle
-}  // namespace automotive
-}  // namespace hardware
-}  // namespace android
diff --git a/automotive/vehicle/2.1/types.hal b/automotive/vehicle/2.1/types.hal
deleted file mode 100644
index 7be611c..0000000
--- a/automotive/vehicle/2.1/types.hal
+++ /dev/null
@@ -1,653 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.1 (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.1
- *
- * 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.automotive.vehicle@2.1;
-
-import android.hardware.automotive.vehicle@2.0;
-
-/**
- * Extension of VehicleProperty enum declared in Vehicle HAL 2.0
- */
-enum VehicleProperty: @2.0::VehicleProperty {
-    /**
-     * Reports wheel rotational distance in meters since last wheel tick
-     * event
-     *
-     * The value is a vector each element represents distance for individual
-     * wheel in the following order: left front, right front, left rear,
-     * right rear. VehiclePropValue.timestamp must be correctly filled in.
-     *
-     * Vendors must specify wheels that support this sensor in
-     * VehiclePropConfig.configFlags. The format of this field is a bitset of
-     * values from Wheel enum.
-     *
-     * @change_mode VehiclePropertyChangeMode:ON_CHANGE |VehiclePropertyChangeMode:CONTINUOUS
-     * @access VehiclePropertyAccess:READ
-     * @unit VehicleUnit:METER
-     */
-    WHEEL_TICK = (
-      0x0306
-      | VehiclePropertyGroup:SYSTEM
-      | VehiclePropertyType:FLOAT_VEC
-      | VehicleArea:GLOBAL),
-
-    /**
-     * OBD2 Live Sensor Data
-     *
-     * This property uses COMPLEX data to send a snapshot of the current (live)
-     * values of the OBD2 sensors provided by the vehicle.
-     *
-     * VehiclePropConfig
-     *   configArray[0] : number of vendor-specific integer-valued sensors
-     *                    that can be returned in a frame.
-     *   configArray[1] : number of vendor-specific float-valued sensors
-     *                    that can be returned in a frame.
-     *
-     * The values are to be interpreted as follows:
-     * the indices defined in Obd2IntegerSensorIndex are to be used to
-     * read from int32Values;
-     * the indices defined in Obd2FloatSensorIndex are to be used to
-     * read from floatValues.
-     * the elements of bytes are to be interpreted as a bitmask, such that
-     * the bits 0 thru the integer value of
-     * Obd2IntegerSensorIndex.LAST_SYSTEM_INDEX + the value of configArray[0]
-     * are 1 if the corresponding index is a valid sensor index whose value can
-     * be read in the returned int32Values vector, 0 otherwise.
-     * the bits Obd2IntegerSensorIndex.LAST_SYSTEM_INDEX+1 thru
-     * Obd2FloatingSensorIndex.LAST_SYSTEM_INDEX + the value of configArray[1]
-     * are 1 if the corresponding index is a valid sensor index whose value
-     * can be read in the returned floatValues vector, 0 otherwise.
-     *
-     * For example, int32Values[0] corresponds to FUEL_SYSTEM_STATUS, and
-     * floatValues[0] corresponds to CALCULATED_ENGINE_LOAD, but that mapping
-     * is only valid if the corresponding bits in the bytes vector are set to 1.
-     *
-     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
-     * @access VehiclePropertyAccess:READ
-     */
-    OBD2_LIVE_FRAME = (
-      0x0D00
-      | VehiclePropertyGroup:SYSTEM
-      | VehiclePropertyType:COMPLEX
-      | VehicleArea:GLOBAL),
-
-    /**
-     * OBD2 Freeze Frame Sensor Data
-     *
-     * This property uses COMPLEX data to send a snapshot of the values of the
-     * OBD2 sensors provided by the vehicle at the time that a diagnostic
-     * troubleshooting code (DTC) was recorded by the vehicle.
-     *
-     * VehiclePropConfig
-     *   configArray[0] : number of vendor-specific integer-valued sensors
-     *                    that can be returned in a frame.
-     *   configArray[1] : number of vendor-specific float-valued sensors
-     *                    that can be returned in a frame.
-     *
-     * A get of this property must take the following form:
-     *   int64Values[0]: timestamp of the freeze frame to retrieve.
-     *                   Valid timestamps are given by OBD2_DTC_INFO.
-     *
-     * The values are to be interpreted as follows:
-     * the indices defined in Obd2IntegerSensorIndex are to be used to
-     * read from int32Values;
-     * the indices defined in Obd2FloatSensorIndex are to be used to
-     * read from floatValues;
-     * the elements of bytes are to be interpreted as a bitmask, such that
-     * the bits 0 thru the integer value of
-     * Obd2IntegerSensorIndex.LAST_SYSTEM_INDEX + the value of configArray[0]
-     * are 1 if the corresponding index is a valid sensor index whose value can
-     * be read in the returned int32Values vector, 0 otherwise.
-     * the bits Obd2IntegerSensorIndex.LAST_SYSTEM_INDEX+1 thru
-     * Obd2FloatingSensorIndex.LAST_SYSTEM_INDEX + the value of configArray[1]
-     * are 1 if the corresponding index is a valid sensor index whose value
-     * can be read in the returned floatValues vector, 0 otherwise.
-     * stringValue is the DTC that caused this freeze frame to be recorded.
-     *
-     * For example, int32Values[0] corresponds to FUEL_SYSTEM_STATUS, and
-     * floatValues[0] corresponds to CALCULATED_ENGINE_LOAD, but that mapping
-     * is only valid if the corresponding bits in the bytes vector are set to 1,
-     * and a possible valid stringValue is "P0176" to indicate a malfunction
-     * of the fuel composition sensor circuit.
-     *
-     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
-     * @access VehiclePropertyAccess:READ
-     */
-    OBD2_FREEZE_FRAME = (
-      0x0D01
-      | VehiclePropertyGroup:SYSTEM
-      | VehiclePropertyType:COMPLEX
-      | VehicleArea:GLOBAL),
-
-    /**
-     * OBD2 Freeze Frame Information
-     *
-     * This property describes the current freeze frames stored in vehicle
-     * memory and available for retrieval via OBD2_FREEZE_FRAME.
-     *
-     * The values are to be interpreted as follows:
-     * each element of int64Values is the timestamp at which a a fault code
-     * has been detected and the corresponding freeze frame stored, and each
-     * such element can be used as the key to OBD2_FREEZE_FRAME to retrieve
-     * the corresponding freeze frame.
-     *
-     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
-     * @access VehiclePropertyAccess:READ
-     */
-    OBD2_FREEZE_FRAME_INFO = (
-      0x0D02
-      | VehiclePropertyGroup:SYSTEM
-      | VehiclePropertyType:COMPLEX
-      | VehicleArea:GLOBAL),
-
-    /**
-     * OBD2 Freeze Frame Clear
-     *
-     * This property allows deletion of any of the freeze frames stored in
-     * vehicle memory, as described by OBD2_DTC_INFO.
-     *
-     * A set of this property is to be interpreted as follows:
-     * if int64Values contains no elements, then all DTCs stored will be cleared;
-     * if int64Values contains one or more elements, then DTCs at the timestamps
-     * stored in int64Values will be cleared, and the others not cleared, except
-     * the memory will be compacted so that all remaining DTCs are stored
-     * contiguously.
-     *
-     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
-     * @access VehiclePropertyAccess:WRITE
-     */
-    OBD2_FREEZE_FRAME_CLEAR = (
-      0x0D03
-      | VehiclePropertyGroup:SYSTEM
-      | VehiclePropertyType:COMPLEX
-      | VehicleArea:GLOBAL),
-
-    /**
-     * Vehicle Maps Service (VMS) message
-     *
-     * This property uses COMPLEX data to communicate vms messages.
-     *
-     * Its contents are to be interpreted as follows:
-     * the indices defined in VmsMessageIntegerValuesIndex are to be used to
-     * read from int32Values;
-     * bytes is a serialized VMS message as defined in the vms protocol
-     * which is opaque to the framework;
-     *
-     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
-     * @access VehiclePropertyAccess:READ_WRITE
-     */
-    VEHICLE_MAP_SERVICE = (
-        0x0C00
-        | VehiclePropertyGroup:SYSTEM
-        | VehiclePropertyType:COMPLEX
-        | VehicleArea:GLOBAL),
-};
-
-/** The status of a fuel system as described by the OBD2 specification. */
-enum FuelSystemStatus : int32_t {
-  OPEN_INSUFFICIENT_ENGINE_TEMPERATURE = 1,
-
-  CLOSED_LOOP = 2,
-
-  OPEN_ENGINE_LOAD_OR_DECELERATION = 4,
-
-  OPEN_SYSTEM_FAILURE = 8,
-
-  CLOSED_LOOP_BUT_FEEDBACK_FAULT = 16,
-};
-
-/** Defines which ignition monitors are available to be read. */
-enum IgnitionMonitorKind : int32_t {
-  SPARK = 0,
-
-  COMPRESSION = 1,
-};
-
-/** These ignition monitors are common to both SPARK and COMPRESSION. */
-enum CommonIgnitionMonitors : int32_t {
-  COMPONENTS_AVAILABLE = 0x1 << 0,
-  COMPONENTS_INCOMPLETE = 0x1 << 1,
-
-  FUEL_SYSTEM_AVAILABLE = 0x1 << 2,
-  FUEL_SYSTEM_INCOMPLETE = 0x1 << 3,
-
-  MISFIRE_AVAILABLE = 0x1 << 4,
-  MISFIRE_INCOMPLETE = 0x1 << 5,
-};
-
-/** Ignition monitors available for SPARK vehicles. */
-enum SparkIgnitionMonitors : CommonIgnitionMonitors {
-  EGR_AVAILABLE = 0x1 << 6,
-  EGR_INCOMPLETE = 0x1 << 7,
-
-  OXYGEN_SENSOR_HEATER_AVAILABLE = 0x1 << 8,
-  OXYGEN_SENSOR_HEATER_INCOMPLETE = 0x1 << 9,
-
-  OXYGEN_SENSOR_AVAILABLE = 0x1 << 10,
-  OXYGEN_SENSOR_INCOMPLETE = 0x1 << 11,
-
-  AC_REFRIGERANT_AVAILABLE = 0x1 << 12,
-  AC_REFRIGERANT_INCOMPLETE = 0x1 << 13,
-
-  SECONDARY_AIR_SYSTEM_AVAILABLE = 0x1 << 14,
-  SECONDARY_AIR_SYSTEM_INCOMPLETE = 0x1 << 15,
-
-  EVAPORATIVE_SYSTEM_AVAILABLE = 0x1 << 16,
-  EVAPORATIVE_SYSTEM_INCOMPLETE = 0x1 << 17,
-
-  HEATED_CATALYST_AVAILABLE = 0x1 << 18,
-  HEATED_CATALYST_INCOMPLETE = 0x1 << 19,
-
-  CATALYST_AVAILABLE = 0x1 << 20,
-  CATALYST_INCOMPLETE = 0x1 << 21,
-};
-
-/** Ignition monitors only available for COMPRESSION vehicles. */
-enum CompressionIgnitionMonitors : CommonIgnitionMonitors {
-  EGR_OR_VVT_AVAILABLE = 0x1 << 6,
-  EGR_OR_VVT_INCOMPLETE = 0x1 << 7,
-
-  PM_FILTER_AVAILABLE = 0x1 << 8,
-  PM_FILTER_INCOMPLETE = 0x1 << 9,
-
-  EXHAUST_GAS_SENSOR_AVAILABLE = 0x1 << 10,
-  EXHAUST_GAS_SENSOR_INCOMPLETE = 0x1 << 11,
-
-  BOOST_PRESSURE_AVAILABLE = 0x1 << 12,
-  BOOST_PRESSURE_INCOMPLETE = 0x1 << 13,
-
-  NOx_SCR__AVAILABLE = 0x1 << 14,
-  NOx_SCR_INCOMPLETE = 0x1 << 15,
-
-  NMHC_CATALYST_AVAILABLE = 0x1 << 16,
-  NMHC_CATALYST_INCOMPLETE = 0x1 << 17,
-};
-
-enum SecondaryAirStatus : int32_t {
-  UPSTREAM = 1,
-
-  DOWNSTREAM_OF_CATALYCIC_CONVERTER = 2,
-
-  FROM_OUTSIDE_OR_OFF = 4,
-
-  PUMP_ON_FOR_DIAGNOSTICS = 8,
-};
-
-enum FuelType : int32_t {
-  NOT_AVAILABLE = 0,
-
-  GASOLINE = 1,
-
-  METHANOL = 2,
-
-  ETHANOL = 3,
-
-  DIESEL = 4,
-
-  LPG = 5,
-
-  CNG = 6,
-
-  PROPANE = 7,
-
-  ELECTRIC = 8,
-
-  BIFUEL_RUNNING_GASOLINE = 9,
-
-  BIFUEL_RUNNING_METHANOL = 10,
-
-  BIFUEL_RUNNING_ETHANOL = 11,
-
-  BIFUEL_RUNNING_LPG = 12,
-
-  BIFUEL_RUNNING_CNG = 13,
-
-  BIFUEL_RUNNING_PROPANE = 14,
-
-  BIFUEL_RUNNING_ELECTRIC = 15,
-
-  BIFUEL_RUNNING_ELECTRIC_AND_COMBUSTION = 16,
-
-  HYBRID_GASOLINE = 17,
-
-  HYBRID_ETHANOL = 18,
-
-  HYBRID_DIESEL = 19,
-
-  HYBRID_ELECTRIC = 20,
-
-  HYBRID_RUNNING_ELECTRIC_AND_COMBUSTION = 21,
-
-  HYBRID_REGENERATIVE = 22,
-
-  BIFUEL_RUNNING_DIESEL = 23,
-};
-
-/**
- * This enum provides the canonical mapping for sensor properties that have an integer value.
- * The ordering of the values is taken from the OBD2 specification.
- * Some of the properties are represented as an integer mapping to another enum. In those cases
- * expect a comment by the property definition describing the enum to look at for the mapping.
- * Any value greater than the last reserved index is available to vendors to map their extensions.
- */
-enum Obd2IntegerSensorIndex : int32_t {
-  /** refer to FuelSystemStatus for a description of this value. */
-  FUEL_SYSTEM_STATUS = 0,
-
-  MALFUNCTION_INDICATOR_LIGHT_ON = 1,
-
-  /** refer to IgnitionMonitorKind for a description of this value. */
-  IGNITION_MONITORS_SUPPORTED = 2,
-
-  /**
-   * The value of this sensor is a bitmask that specifies whether ignition-specific
-   * tests are available and whether they are complete. The semantics of the individual
-   * bits in this value are given by, respectively, SparkIgnitionMonitors and
-   * CompressionIgnitionMonitors depending on the value of IGNITION_MONITORS_SUPPORTED.
-   */
-  IGNITION_SPECIFIC_MONITORS = 3,
-
-  INTAKE_AIR_TEMPERATURE = 4,
-
-  /** refer to SecondaryAirStatus for a description of this value. */
-  COMMANDED_SECONDARY_AIR_STATUS = 5,
-
-  NUM_OXYGEN_SENSORS_PRESENT = 6,
-
-  RUNTIME_SINCE_ENGINE_START = 7,
-
-  DISTANCE_TRAVELED_WITH_MALFUNCTION_INDICATOR_LIGHT_ON = 8,
-
-  WARMUPS_SINCE_CODES_CLEARED = 9,
-
-  DISTANCE_TRAVELED_SINCE_CODES_CLEARED = 10,
-
-  ABSOLUTE_BAROMETRIC_PRESSURE = 11,
-
-  CONTROL_MODULE_VOLTAGE = 12,
-
-  AMBIENT_AIR_TEMPERATURE = 13,
-
-  TIME_WITH_MALFUNCTION_LIGHT_ON = 14,
-
-  TIME_SINCE_TROUBLE_CODES_CLEARED = 15,
-
-  MAX_FUEL_AIR_EQUIVALENCE_RATIO = 16,
-
-  MAX_OXYGEN_SENSOR_VOLTAGE = 17,
-
-  MAX_OXYGEN_SENSOR_CURRENT = 18,
-
-  MAX_INTAKE_MANIFOLD_ABSOLUTE_PRESSURE = 19,
-
-  MAX_AIR_FLOW_RATE_FROM_MASS_AIR_FLOW_SENSOR = 20,
-
-  /** refer to FuelType for a description of this value. */
-  FUEL_TYPE = 21,
-
-  FUEL_RAIL_ABSOLUTE_PRESSURE = 22,
-
-  ENGINE_OIL_TEMPERATURE = 23,
-
-  DRIVER_DEMAND_PERCENT_TORQUE = 24,
-
-  ENGINE_ACTUAL_PERCENT_TORQUE = 25,
-
-  ENGINE_REFERENCE_PERCENT_TORQUE = 26,
-
-  ENGINE_PERCENT_TORQUE_DATA_IDLE = 27,
-
-  ENGINE_PERCENT_TORQUE_DATA_POINT1 = 28,
-
-  ENGINE_PERCENT_TORQUE_DATA_POINT2 = 29,
-
-  ENGINE_PERCENT_TORQUE_DATA_POINT3 = 30,
-
-  ENGINE_PERCENT_TORQUE_DATA_POINT4 = 31,
-
-  LAST_SYSTEM_INDEX = ENGINE_PERCENT_TORQUE_DATA_POINT4,
-};
-
-/**
- * This enum provides the canonical mapping for sensor properties that have a floating-point value.
- * The ordering of the values is taken from the OBD2 specification.
- * Any value greater than the last reserved index is available to vendors to map their extensions.
- */
-enum Obd2FloatSensorIndex : int32_t {
-  CALCULATED_ENGINE_LOAD = 0,
-
-  ENGINE_COOLANT_TEMPERATURE = 1,
-
-  SHORT_TERM_FUEL_TRIM_BANK1 = 2,
-
-  LONG_TERM_FUEL_TRIM_BANK1 = 3,
-
-  SHORT_TERM_FUEL_TRIM_BANK2 = 4,
-
-  LONG_TERM_FUEL_TRIM_BANK2 = 5,
-
-  FUEL_PRESSURE = 6,
-
-  INTAKE_MANIFOLD_ABSOLUTE_PRESSURE = 7,
-
-  ENGINE_RPM = 8,
-
-  VEHICLE_SPEED = 9,
-
-  TIMING_ADVANCE = 10,
-
-  MAF_AIR_FLOW_RATE = 11,
-
-  THROTTLE_POSITION = 12,
-
-  OXYGEN_SENSOR1_VOLTAGE = 13,
-
-  OXYGEN_SENSOR1_SHORT_TERM_FUEL_TRIM = 14,
-
-  OXYGEN_SENSOR1_FUEL_AIR_EQUIVALENCE_RATIO = 15,
-
-  OXYGEN_SENSOR2_VOLTAGE = 16,
-
-  OXYGEN_SENSOR2_SHORT_TERM_FUEL_TRIM = 17,
-
-  OXYGEN_SENSOR2_FUEL_AIR_EQUIVALENCE_RATIO = 18,
-
-  OXYGEN_SENSOR3_VOLTAGE = 19,
-
-  OXYGEN_SENSOR3_SHORT_TERM_FUEL_TRIM = 20,
-
-  OXYGEN_SENSOR3_FUEL_AIR_EQUIVALENCE_RATIO = 21,
-
-  OXYGEN_SENSOR4_VOLTAGE = 22,
-
-  OXYGEN_SENSOR4_SHORT_TERM_FUEL_TRIM = 23,
-
-  OXYGEN_SENSOR4_FUEL_AIR_EQUIVALENCE_RATIO = 24,
-
-  OXYGEN_SENSOR5_VOLTAGE = 25,
-
-  OXYGEN_SENSOR5_SHORT_TERM_FUEL_TRIM = 26,
-
-  OXYGEN_SENSOR5_FUEL_AIR_EQUIVALENCE_RATIO = 27,
-
-  OXYGEN_SENSOR6_VOLTAGE = 28,
-
-  OXYGEN_SENSOR6_SHORT_TERM_FUEL_TRIM = 29,
-
-  OXYGEN_SENSOR6_FUEL_AIR_EQUIVALENCE_RATIO = 30,
-
-  OXYGEN_SENSOR7_VOLTAGE = 31,
-
-  OXYGEN_SENSOR7_SHORT_TERM_FUEL_TRIM = 32,
-
-  OXYGEN_SENSOR7_FUEL_AIR_EQUIVALENCE_RATIO = 33,
-
-  OXYGEN_SENSOR8_VOLTAGE = 34,
-
-  OXYGEN_SENSOR8_SHORT_TERM_FUEL_TRIM = 35,
-
-  OXYGEN_SENSOR8_FUEL_AIR_EQUIVALENCE_RATIO = 36,
-
-  FUEL_RAIL_PRESSURE = 37,
-
-  FUEL_RAIL_GAUGE_PRESSURE = 38,
-
-  COMMANDED_EXHAUST_GAS_RECIRCULATION = 39,
-
-  EXHAUST_GAS_RECIRCULATION_ERROR = 40,
-
-  COMMANDED_EVAPORATIVE_PURGE = 41,
-
-  FUEL_TANK_LEVEL_INPUT = 42,
-
-  EVAPORATION_SYSTEM_VAPOR_PRESSURE = 43,
-
-  CATALYST_TEMPERATURE_BANK1_SENSOR1 = 44,
-
-  CATALYST_TEMPERATURE_BANK2_SENSOR1 = 45,
-
-  CATALYST_TEMPERATURE_BANK1_SENSOR2 = 46,
-
-  CATALYST_TEMPERATURE_BANK2_SENSOR2 = 47,
-
-  ABSOLUTE_LOAD_VALUE = 48,
-
-  FUEL_AIR_COMMANDED_EQUIVALENCE_RATIO = 49,
-
-  RELATIVE_THROTTLE_POSITION = 50,
-
-  ABSOLUTE_THROTTLE_POSITION_B = 51,
-
-  ABSOLUTE_THROTTLE_POSITION_C = 52,
-
-  ACCELERATOR_PEDAL_POSITION_D = 53,
-
-  ACCELERATOR_PEDAL_POSITION_E = 54,
-
-  ACCELERATOR_PEDAL_POSITION_F = 55,
-
-  COMMANDED_THROTTLE_ACTUATOR = 56,
-
-  ETHANOL_FUEL_PERCENTAGE = 57,
-
-  ABSOLUTE_EVAPORATION_SYSTEM_VAPOR_PRESSURE = 58,
-
-  SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK1 = 59,
-
-  SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK2 = 60,
-
-  SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK3 = 61,
-
-  SHORT_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK4 = 62,
-
-  LONG_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK1 = 63,
-
-  LONG_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK2 = 64,
-
-  LONG_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK3 = 65,
-
-  LONG_TERM_SECONDARY_OXYGEN_SENSOR_TRIM_BANK4 = 66,
-
-  RELATIVE_ACCELERATOR_PEDAL_POSITION = 67,
-
-  HYBRID_BATTERY_PACK_REMAINING_LIFE = 68,
-
-  FUEL_INJECTION_TIMING = 69,
-
-  ENGINE_FUEL_RATE = 70,
-
-  LAST_SYSTEM_INDEX = ENGINE_FUEL_RATE,
-};
-
-/**
- * This enum lists the types of supported VMS messages.
- */
-enum VmsMessageType : int32_t {
-  /** A client subscribes to a layer. */
-  SUBSCRIBE = 1,
-
-  /** A client unsubscribes from a layer. */
-  UNSUBSCRIBE = 2,
-
-  /** A client publishes a data packet. */
-  DATA = 3,
-
-  /* A client declaring layers offering. */
-  OFFERING = 4,
-
-  /* Requesting the list of available layers. */
-  AVAILABILITY_REQUEST = 5,
-
-  /* Returning the list of available layers. */
-  AVAILABILITY_RESPONSE = 6,
-
-  /** Requesting layers that have subscribers. */
-  SUBSCRIPTION_REQUEST = 7,
-
-  /** Returning layers that have subscribers. */
-  SUBSCRIPTION_RESPONSE = 8,
-};
-
-/**
- * This enum provides the canonical mapping for VMS properties that have an
- * integer value.
- */
-enum VmsBaseMessageIntegerValuesIndex : int32_t {
-  /* The message type as enumerated by VmsMessageType enum. */
-  VMS_MESSAGE_TYPE = 0,
-};
-
-/*
- * This enum provides the canonical mapping for VMS SUBMIT, UNSUBMIT and DATA
- * messages integer value properties.
- */
-enum VmsSimpleMessageIntegerValuesIndex : VmsBaseMessageIntegerValuesIndex {
-  /* The layer ID as defined in the vms protocol. */
-  VMS_LAYER_ID = 1,
-
-  /* The version of the VMS layer. */
-  VMS_LAYER_VERSION = 2,
-};
-
-/*
- * This enum provides the canonical mapping for VMS offering messages integer
- * value properties
- */
-enum VmsOfferingMessageIntegerValuesIndex : VmsBaseMessageIntegerValuesIndex {
-  /* The number of VMS layer dependencies. */
-  VMS_NUMBER_OF_LAYERS_DEPENDENCIES = 1,
-
-  /* The first index that contain dependencies */
-  FIRST_DEPENDENCIES_INDEX = 2,
-};
-
-/**
- * A VMS subscription request only contains its message type. The format of a VMS subscription
- * response is described below.
- */
-enum VmsSubscriptionResponseFormat : VmsBaseMessageIntegerValuesIndex {
-  /**
-    * Recipients should ignore any packet with a sequence number that is less than the highest
-    * sequence number they have seen thus far.
-    */
-  SEQUENCE_NUMBER = 1,
-
-  /** The number of VMS layers. Each layer has two integers: type and version. */
-  NUMBER_OF_LAYERS = 2,
-
-  /** The first index that contains a layer. */
-  FIRST_LAYER = 3,
-};
diff --git a/biometrics/fingerprint/2.1/Android.bp b/biometrics/fingerprint/2.1/Android.bp
index c16fd78..3898da5 100644
--- a/biometrics/fingerprint/2.1/Android.bp
+++ b/biometrics/fingerprint/2.1/Android.bp
@@ -46,13 +46,16 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.biometrics.fingerprint@2.1",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.biometrics.fingerprint@2.1_genc++"],
     generated_headers: ["android.hardware.biometrics.fingerprint@2.1_genc++_headers"],
     export_generated_headers: ["android.hardware.biometrics.fingerprint@2.1_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/biometrics/fingerprint/2.1/default/BiometricsFingerprint.cpp b/biometrics/fingerprint/2.1/default/BiometricsFingerprint.cpp
index c6774ca..f687959 100644
--- a/biometrics/fingerprint/2.1/default/BiometricsFingerprint.cpp
+++ b/biometrics/fingerprint/2.1/default/BiometricsFingerprint.cpp
@@ -145,6 +145,7 @@
 
 Return<uint64_t> BiometricsFingerprint::setNotify(
         const sp<IBiometricsFingerprintClientCallback>& clientCallback) {
+    std::lock_guard<std::mutex> lock(mClientCallbackMutex);
     mClientCallback = clientCallback;
     // This is here because HAL 2.1 doesn't have a way to propagate a
     // unique token for its driver. Subsequent versions should send a unique
@@ -259,6 +260,7 @@
 void BiometricsFingerprint::notify(const fingerprint_msg_t *msg) {
     BiometricsFingerprint* thisPtr = static_cast<BiometricsFingerprint*>(
             BiometricsFingerprint::getInstance());
+    std::lock_guard<std::mutex> lock(thisPtr->mClientCallbackMutex);
     if (thisPtr == nullptr || thisPtr->mClientCallback == nullptr) {
         ALOGE("Receiving callbacks before the client callback is registered.");
         return;
diff --git a/biometrics/fingerprint/2.1/default/BiometricsFingerprint.h b/biometrics/fingerprint/2.1/default/BiometricsFingerprint.h
index 5923c84..6d64e3d 100644
--- a/biometrics/fingerprint/2.1/default/BiometricsFingerprint.h
+++ b/biometrics/fingerprint/2.1/default/BiometricsFingerprint.h
@@ -69,6 +69,7 @@
     static FingerprintAcquiredInfo VendorAcquiredFilter(int32_t error, int32_t* vendorCode);
     static BiometricsFingerprint* sInstance;
 
+    std::mutex mClientCallbackMutex;
     sp<IBiometricsFingerprintClientCallback> mClientCallback;
     fingerprint_device_t *mDevice;
 };
diff --git a/biometrics/fingerprint/2.1/vts/functional/Android.bp b/biometrics/fingerprint/2.1/vts/functional/Android.bp
index 27b7157..bee3657 100644
--- a/biometrics/fingerprint/2.1/vts/functional/Android.bp
+++ b/biometrics/fingerprint/2.1/vts/functional/Android.bp
@@ -16,21 +16,8 @@
 
 cc_test {
     name: "VtsHalBiometricsFingerprintV2_1TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalBiometricsFingerprintV2_1TargetTest.cpp"],
-    shared_libs: [
-        "libbase",
-        "libhidltransport",
-        "libhardware",
-        "libhidlbase",
-        "liblog",
-        "libutils",
-        "android.hardware.biometrics.fingerprint@2.1",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ]
+    static_libs: ["android.hardware.biometrics.fingerprint@2.1"],
 }
 
diff --git a/bluetooth/1.0/Android.bp b/bluetooth/1.0/Android.bp
index 48159b3..c883c59 100644
--- a/bluetooth/1.0/Android.bp
+++ b/bluetooth/1.0/Android.bp
@@ -46,13 +46,16 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.bluetooth@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.bluetooth@1.0_genc++"],
     generated_headers: ["android.hardware.bluetooth@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.bluetooth@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/bluetooth/1.0/default/async_fd_watcher.cc b/bluetooth/1.0/default/async_fd_watcher.cc
index bc0bc92..78676b2 100644
--- a/bluetooth/1.0/default/async_fd_watcher.cc
+++ b/bluetooth/1.0/default/async_fd_watcher.cc
@@ -24,7 +24,7 @@
 #include <map>
 #include <mutex>
 #include <thread>
-#include <utils/Log.h>
+#include <log/log.h>
 #include <vector>
 #include "fcntl.h"
 #include "sys/select.h"
diff --git a/bluetooth/1.0/default/bluetooth_address.cc b/bluetooth/1.0/default/bluetooth_address.cc
index 65dc6a6..fd53e78 100644
--- a/bluetooth/1.0/default/bluetooth_address.cc
+++ b/bluetooth/1.0/default/bluetooth_address.cc
@@ -19,6 +19,7 @@
 #include <cutils/properties.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <unistd.h>
 #include <utils/Log.h>
 
 namespace android {
diff --git a/bluetooth/1.0/default/bluetooth_hci.h b/bluetooth/1.0/default/bluetooth_hci.h
index 6912405..e2797b1 100644
--- a/bluetooth/1.0/default/bluetooth_hci.h
+++ b/bluetooth/1.0/default/bluetooth_hci.h
@@ -21,6 +21,8 @@
 
 #include <hidl/MQDescriptor.h>
 
+#include <functional>
+
 namespace android {
 namespace hardware {
 namespace bluetooth {
diff --git a/bluetooth/1.0/default/h4_protocol.cc b/bluetooth/1.0/default/h4_protocol.cc
index 2008b00..163cc33 100644
--- a/bluetooth/1.0/default/h4_protocol.cc
+++ b/bluetooth/1.0/default/h4_protocol.cc
@@ -22,6 +22,7 @@
 #include <fcntl.h>
 #include <log/log.h>
 #include <sys/uio.h>
+#include <unistd.h>
 
 namespace android {
 namespace hardware {
@@ -81,6 +82,12 @@
       }
     }
     hci_packet_type_ = static_cast<HciPacketType>(buffer[0]);
+    if (hci_packet_type_ != HCI_PACKET_TYPE_ACL_DATA &&
+        hci_packet_type_ != HCI_PACKET_TYPE_SCO_DATA &&
+        hci_packet_type_ != HCI_PACKET_TYPE_EVENT) {
+      LOG_ALWAYS_FATAL("%s: Unimplemented packet type %d", __func__,
+                       static_cast<int>(hci_packet_type_));
+    }
   } else {
     hci_packetizer_.OnDataReady(fd, hci_packet_type_);
   }
diff --git a/bluetooth/1.0/default/hci_packetizer.cc b/bluetooth/1.0/default/hci_packetizer.cc
index 2da1254..fde08ac 100644
--- a/bluetooth/1.0/default/hci_packetizer.cc
+++ b/bluetooth/1.0/default/hci_packetizer.cc
@@ -21,6 +21,7 @@
 #include <dlfcn.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <unistd.h>
 #include <utils/Log.h>
 
 namespace {
diff --git a/bluetooth/1.0/default/hci_protocol.cc b/bluetooth/1.0/default/hci_protocol.cc
index a208da1..bf94dfe 100644
--- a/bluetooth/1.0/default/hci_protocol.cc
+++ b/bluetooth/1.0/default/hci_protocol.cc
@@ -18,7 +18,9 @@
 
 #define LOG_TAG "android.hardware.bluetooth-hci-hci_protocol"
 #include <assert.h>
+#include <errno.h>
 #include <fcntl.h>
+#include <unistd.h>
 #include <log/log.h>
 
 namespace android {
diff --git a/bluetooth/1.0/default/vendor_interface.cc b/bluetooth/1.0/default/vendor_interface.cc
index 15b6c74..6ce2f11 100644
--- a/bluetooth/1.0/default/vendor_interface.cc
+++ b/bluetooth/1.0/default/vendor_interface.cc
@@ -162,8 +162,10 @@
     InitializeCompleteCallback initialize_complete_cb,
     PacketReadCallback event_cb, PacketReadCallback acl_cb,
     PacketReadCallback sco_cb) {
-  LOG_ALWAYS_FATAL_IF(g_vendor_interface, "%s: No previous Shutdown()?",
-                      __func__);
+  if (g_vendor_interface) {
+    ALOGE("%s: No previous Shutdown()?", __func__);
+    return false;
+  }
   g_vendor_interface = new VendorInterface();
   return g_vendor_interface->Open(initialize_complete_cb, event_cb, acl_cb,
                                   sco_cb);
diff --git a/bluetooth/1.0/vts/functional/Android.bp b/bluetooth/1.0/vts/functional/Android.bp
index d2e6553..2e60588 100644
--- a/bluetooth/1.0/vts/functional/Android.bp
+++ b/bluetooth/1.0/vts/functional/Android.bp
@@ -16,21 +16,10 @@
 
 cc_test {
     name: "VtsHalBluetoothV1_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalBluetoothV1_0TargetTest.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libnativehelper",
-        "libutils",
+    static_libs: [
         "android.hardware.bluetooth@1.0",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
+        "libbluetooth-types",
     ],
 }
diff --git a/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.cpp b/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.cpp
index fb53366..6c9aa18 100644
--- a/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.cpp
+++ b/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.cpp
@@ -464,8 +464,9 @@
 
 // Return the number of completed packets reported by the controller.
 int BluetoothHidlTest::wait_for_completed_packets_event(uint16_t handle) {
-    EXPECT_TRUE(bluetooth_cb->WaitForCallback(kCallbackNameHciEventReceived)
-                    .no_timeout);
+    if (!bluetooth_cb->WaitForCallback(kCallbackNameHciEventReceived).no_timeout) {
+        ALOGW("%s: WaitForCallback timed out.", __func__);
+    }
     int packets_processed = 0;
     while (event_queue.size() > 0) {
         hidl_vec<uint8_t> event = event_queue.front();
@@ -604,20 +605,24 @@
 
   // This should work, but breaks on some current platforms.  Figure out how to
   // grandfather older devices but test new ones.
-  int sco_packets_sent = 0;
   if (0 && sco_connection_handles.size() > 0) {
     sendAndCheckSCO(1, max_sco_data_packet_length, sco_connection_handles[0]);
-    sco_packets_sent = 1;
-    EXPECT_EQ(sco_packets_sent,
-              wait_for_completed_packets_event(sco_connection_handles[0]));
+    int sco_packets_sent = 1;
+    int completed_packets = wait_for_completed_packets_event(sco_connection_handles[0]);
+    if (sco_packets_sent != completed_packets) {
+        ALOGW("%s: packets_sent (%d) != completed_packets (%d)", __func__, sco_packets_sent,
+              completed_packets);
+    }
   }
 
-  int acl_packets_sent = 0;
   if (acl_connection_handles.size() > 0) {
     sendAndCheckACL(1, max_acl_data_packet_length, acl_connection_handles[0]);
-    acl_packets_sent = 1;
-    EXPECT_EQ(acl_packets_sent,
-              wait_for_completed_packets_event(acl_connection_handles[0]));
+    int acl_packets_sent = 1;
+    int completed_packets = wait_for_completed_packets_event(acl_connection_handles[0]);
+    if (acl_packets_sent != completed_packets) {
+        ALOGW("%s: packets_sent (%d) != completed_packets (%d)", __func__, acl_packets_sent,
+              completed_packets);
+    }
   }
 }
 
@@ -633,22 +638,26 @@
 
   // This should work, but breaks on some current platforms.  Figure out how to
   // grandfather older devices but test new ones.
-  int sco_packets_sent = 0;
   if (0 && sco_connection_handles.size() > 0) {
     sendAndCheckSCO(NUM_SCO_PACKETS_BANDWIDTH, max_sco_data_packet_length,
                     sco_connection_handles[0]);
-    sco_packets_sent = NUM_SCO_PACKETS_BANDWIDTH;
-    EXPECT_EQ(sco_packets_sent,
-              wait_for_completed_packets_event(sco_connection_handles[0]));
+    int sco_packets_sent = NUM_SCO_PACKETS_BANDWIDTH;
+    int completed_packets = wait_for_completed_packets_event(sco_connection_handles[0]);
+    if (sco_packets_sent != completed_packets) {
+        ALOGW("%s: packets_sent (%d) != completed_packets (%d)", __func__, sco_packets_sent,
+              completed_packets);
+    }
   }
 
-  int acl_packets_sent = 0;
   if (acl_connection_handles.size() > 0) {
     sendAndCheckACL(NUM_ACL_PACKETS_BANDWIDTH, max_acl_data_packet_length,
                     acl_connection_handles[0]);
-    acl_packets_sent = NUM_ACL_PACKETS_BANDWIDTH;
-    EXPECT_EQ(acl_packets_sent,
-              wait_for_completed_packets_event(acl_connection_handles[0]));
+    int acl_packets_sent = NUM_ACL_PACKETS_BANDWIDTH;
+    int completed_packets = wait_for_completed_packets_event(acl_connection_handles[0]);
+    if (acl_packets_sent != completed_packets) {
+        ALOGW("%s: packets_sent (%d) != completed_packets (%d)", __func__, acl_packets_sent,
+              completed_packets);
+    }
   }
 }
 
diff --git a/boot/1.0/Android.bp b/boot/1.0/Android.bp
index de42647..4e4efa3 100644
--- a/boot/1.0/Android.bp
+++ b/boot/1.0/Android.bp
@@ -39,13 +39,16 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.boot@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.boot@1.0_genc++"],
     generated_headers: ["android.hardware.boot@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.boot@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/boot/1.0/vts/functional/Android.bp b/boot/1.0/vts/functional/Android.bp
index 5b14f54..2ef89f3 100644
--- a/boot/1.0/vts/functional/Android.bp
+++ b/boot/1.0/vts/functional/Android.bp
@@ -16,20 +16,7 @@
 
 cc_test {
     name: "VtsHalBootV1_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalBootV1_0TargetTest.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libnativehelper",
-        "libutils",
-        "android.hardware.boot@1.0",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ]
+    static_libs: ["android.hardware.boot@1.0"],
 }
diff --git a/broadcastradio/1.0/Android.bp b/broadcastradio/1.0/Android.bp
index f0c4b22..5b8e239 100644
--- a/broadcastradio/1.0/Android.bp
+++ b/broadcastradio/1.0/Android.bp
@@ -60,13 +60,16 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.broadcastradio@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.broadcastradio@1.0_genc++"],
     generated_headers: ["android.hardware.broadcastradio@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.broadcastradio@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/broadcastradio/1.0/default/OWNERS b/broadcastradio/1.0/default/OWNERS
new file mode 100644
index 0000000..b159083
--- /dev/null
+++ b/broadcastradio/1.0/default/OWNERS
@@ -0,0 +1,4 @@
+elaurent@google.com
+krocard@google.com
+mnaganov@google.com
+twasilczyk@google.com
diff --git a/broadcastradio/1.0/types.hal b/broadcastradio/1.0/types.hal
index 045231d..8c3ec11 100644
--- a/broadcastradio/1.0/types.hal
+++ b/broadcastradio/1.0/types.hal
@@ -146,8 +146,11 @@
     /** String */
     TEXT       = 1,
     /**
-     * Raw binary data (icon or art)
-       This data must be transparent to the android framework */
+     * Raw binary data (icon or art).
+     *
+     * The data should be a valid PNG, JPEG, GIF or BMP file.
+     * Invalid format must be handled gracefully as if the field was missing.
+     */
     RAW        = 2,
     /** clock data, see MetaDataClock */
     CLOCK      = 3,
@@ -155,7 +158,7 @@
 
 enum MetadataKey : int32_t {
     INVALID      = -1,
-    /** RDS PI                 - string  */
+    /** RDS PI                 - int32_t  */
     RDS_PI       = 0,
     /** RDS PS                 - string */
     RDS_PS       = 1,
@@ -173,9 +176,9 @@
     ALBUM        = 7,
     /** Musical genre          - string  */
     GENRE        = 8,
-    /** Station icon           - raw  */
+    /** Station icon           - raw (int32_t for HAL 1.1) */
     ICON         = 9,
-    /** Album art              - raw  */
+    /** Album art              - raw (int32_t for HAL 1.1) */
     ART          = 10,
     /** Clock                  - MetaDataClock */
     CLOCK        = 11,
@@ -208,10 +211,24 @@
 struct ProgramInfo {
     uint32_t     channel;   /** current channel. (e.g kHz for band type AM_FM) */
     uint32_t     subChannel; /** current sub channel. (FM_HD) */
-    bool         tuned;     /** tuned to a program or not */
+
+    /**
+     * Tuned to a program (not a noise). It's the same condition that would
+     * stop scan operation.
+     */
+    bool         tuned;
+
     bool         stereo;    /** program is stereo or not */
     bool         digital;   /** digital program or not (e.g HD Radio program) */
-    uint32_t     signalStrength; /** signal strength from 0 to 100 */
-    vec<MetaData> metadata; /** non empty if meta data are present (e.g PTY, song title ...) */
+
+    /**
+     * Signal quality measured in 0% to 100% range.
+     *
+     * Despite the name, this is not a signal strength.
+     * The purpose of this field is primarily informative.
+     */
+    uint32_t signalStrength;
+
+    vec<MetaData> metadata; /** Metadata: PTY, song title etc. */
 };
 
diff --git a/broadcastradio/1.0/vts/functional/Android.bp b/broadcastradio/1.0/vts/functional/Android.bp
index cf52f49..f31a2dc 100644
--- a/broadcastradio/1.0/vts/functional/Android.bp
+++ b/broadcastradio/1.0/vts/functional/Android.bp
@@ -16,21 +16,7 @@
 
 cc_test {
     name: "VtsHalBroadcastradioV1_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalBroadcastradioV1_0TargetTest.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libnativehelper",
-        "libutils",
-        "android.hardware.broadcastradio@1.0",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ],
+    static_libs: ["android.hardware.broadcastradio@1.0"],
 }
diff --git a/broadcastradio/1.1/Android.bp b/broadcastradio/1.1/Android.bp
index 3b50416..12e23d6 100644
--- a/broadcastradio/1.1/Android.bp
+++ b/broadcastradio/1.1/Android.bp
@@ -60,13 +60,16 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.broadcastradio@1.1",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.broadcastradio@1.1_genc++"],
     generated_headers: ["android.hardware.broadcastradio@1.1_genc++_headers"],
     export_generated_headers: ["android.hardware.broadcastradio@1.1_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/broadcastradio/1.1/IBroadcastRadio.hal b/broadcastradio/1.1/IBroadcastRadio.hal
index dd37d49..dadba2a 100644
--- a/broadcastradio/1.1/IBroadcastRadio.hal
+++ b/broadcastradio/1.1/IBroadcastRadio.hal
@@ -27,4 +27,38 @@
      */
     getProperties_1_1() generates (Properties properties);
 
+    /**
+     * Fetch image from radio module.
+     *
+     * This call is meant to make V1_0::MetaData lightweight - instead of
+     * passing an image data blob in the MetadataType.RAW field, the HAL
+     * implementation only passes the identifier, so the client may cache images
+     * or even not fetch them.
+     *
+     * The identifier may be any arbitrary number - sequential, sha256 prefix,
+     * or any other unique value selected by the vendor.
+     *
+     * The data should be a valid PNG, JPEG, GIF or BMP file.
+     * Image data with an invalid format must be handled gracefully in the same
+     * way as a missing image.
+     *
+     * The image identifier may become invalid after some time from passing it
+     * with metadata struct (due to resource cleanup at the HAL implementation).
+     * However, it must remain valid for a currently tuned program at least
+     * until currentProgramInfoChanged or programListChanged is called and
+     * metadata changes for the current program.
+     *
+     * There is still a race condition possible (if the HAL deletes the old
+     * image immediately after notifying about the new one) between
+     * currentProgramInfoChanged callback propagating through the framework and
+     * the HAL implementation removing previous image. In such case, client
+     * application may expect the new currentProgramInfoChanged callback with
+     * updated image identifier.
+     *
+     * @param id Identifier of an image;
+     *           value of 0 is reserved and should be treated as invalid image.
+     * @return image A binary blob with image data
+     *               or a zero-length vector if identifier doesn't exist.
+     */
+    getImage(int32_t id) generates (vec<uint8_t> image);
 };
diff --git a/broadcastradio/1.1/IBroadcastRadioFactory.hal b/broadcastradio/1.1/IBroadcastRadioFactory.hal
index fce1cc0..edf78ff 100644
--- a/broadcastradio/1.1/IBroadcastRadioFactory.hal
+++ b/broadcastradio/1.1/IBroadcastRadioFactory.hal
@@ -19,8 +19,10 @@
 import @1.0::IBroadcastRadioFactory;
 
 /**
- * To use 1.1 features you must cast specific interfaces after being returned from 1.0 HAL,
- * for example V1_1::ITuner::castFrom() after retrieving it from IBroadcastRadio::openTuner().
+ * To use 1.1 features you must cast specific interfaces returned from the
+ * 1.0 HAL. For example V1_0::IBroadcastRadio::openTuner() returns V1_0::ITuner,
+ * which can be cast with V1_1::ITuner::castFrom() call.
+ *
  * The 1.1 server must always return the 1.1 version of specific interface.
  */
 interface IBroadcastRadioFactory extends @1.0::IBroadcastRadioFactory {
diff --git a/broadcastradio/1.1/ITuner.hal b/broadcastradio/1.1/ITuner.hal
index 7511629..b20c5f4 100644
--- a/broadcastradio/1.1/ITuner.hal
+++ b/broadcastradio/1.1/ITuner.hal
@@ -21,6 +21,45 @@
 interface ITuner extends @1.0::ITuner {
 
     /**
+     * Tune to a specified program.
+     *
+     * For AM/FM, it must be called when a valid configuration has been applied.
+     * Automatically cancels pending scan, step or tune.
+     *
+     * If method returns OK, ITunerCallback.tuneComplete_1_1() MUST be called:
+     * - once successfully tuned;
+     * - after a time out;
+     * - after a full band scan, if no station found.
+     *
+     * The tuned field of ProgramInfo should indicate if tuned to a valid
+     * station or not.
+     *
+     * @param program Program to tune to.
+     * @return result OK if successfully started tunning.
+     *                INVALID_ARGUMENTS if invalid arguments are passed.
+     *                NOT_INITIALIZED if another error occurs.
+     */
+    tuneByProgramSelector(ProgramSelector program) generates (Result result);
+
+    /**
+     * Cancels announcement.
+     *
+     * If it was traffic announcement, trafficAnnouncement(false) callback
+     * should be called (just like it was ended in a normal way). Similarly for
+     * emergency announcement. If there was no announcement, then no action
+     * should be taken.
+     *
+     * There is a race condition between calling cancelAnnouncement and the
+     * actual announcement being finished, so trafficAnnouncement /
+     * emergencyAnnouncement callback should be tracked with proper locking.
+     *
+     * @return result OK if successfully cancelled announcement or there was
+     *                no announcement.
+     *                NOT_INITIALIZED if another error occurs.
+     */
+    cancelAnnouncement() generates (Result result);
+
+    /**
      * Retrieve current station information.
      * @return result OK if scan successfully started
      *                NOT_INITIALIZED if another error occurs
@@ -45,6 +84,13 @@
      * subsequent calls to startBackgroundScan, issuing a single
      * backgroundScanComplete callback.
      *
+     * If a device supports continuous background scanning, it may succeed
+     * (return OK and call backgroundScanComplete) without any additional
+     * operation performed.
+     *
+     * Foreground scanning may be implemented in the front end app with
+     * @1.0::ITuner scan operation.
+     *
      * @return result OK if the scan was properly scheduled (this does not mean
      *                it successfully finished).
      *                UNAVAILABLE if the background scan is unavailable,
@@ -60,10 +106,8 @@
      * This call does not trigger actual scan, but operates on the list cached
      * internally at the driver level.
      *
-     * @param filter vendor-specific filter for the stations to be retrieved.
-     *               An empty string MUST result in full list.
-     *               Client application MUST verify vendor/product name
-     *               before setting this parameter to anything else.
+     * @param vendorFilter vendor-specific filter for the stations to be retrieved.
+     *               An empty vector MUST result in full list for a given tuner.
      * @return result OK if the list was successfully retrieved.
      *                INVALID_ARGUMENTS if invalid arguments are passed
      *                NOT_READY if the scan is in progress.
@@ -72,23 +116,10 @@
      *                NOT_INITIALIZED if any other error occurs.
      * @return programList List of stations available for user.
      */
-    getProgramList(string filter)
+    getProgramList(vec<VendorKeyValue> vendorFilter)
         generates (ProgramListResult result, vec<ProgramInfo> programList);
 
     /**
-     * Checks, if the analog playback is forced, see setAnalogForced.
-     *
-     * The isForced value is only valid if result was OK.
-     *
-     * @return result OK if the call succeeded and isForced is valid.
-     *                INVALID_STATE if the switch is not supported at current
-     *                configuration.
-     *                NOT_INITIALIZED if any other error occurs.
-     * @return isForced true if analog is forced, false otherwise.
-     */
-    isAnalogForced() generates (Result result, bool isForced);
-
-    /**
      * Forces the analog playback for the supporting radio technology.
      *
      * User may disable digital playback for FM HD Radio or hybrid FM/DAB with
@@ -104,4 +135,17 @@
      *                NOT_INITIALIZED if any other error occurs.
      */
     setAnalogForced(bool isForced) generates (Result result);
+
+    /**
+     * Checks, if the analog playback is forced, see setAnalogForced.
+     *
+     * The isForced value is only valid if result was OK.
+     *
+     * @return result OK if the call succeeded and isForced is valid.
+     *                INVALID_STATE if the switch is not supported at current
+     *                configuration.
+     *                NOT_INITIALIZED if any other error occurs.
+     * @return isForced true if analog is forced, false otherwise.
+     */
+    isAnalogForced() generates (Result result, bool isForced);
 };
diff --git a/broadcastradio/1.1/ITunerCallback.hal b/broadcastradio/1.1/ITunerCallback.hal
index 158e217..8bf5b7f 100644
--- a/broadcastradio/1.1/ITunerCallback.hal
+++ b/broadcastradio/1.1/ITunerCallback.hal
@@ -28,16 +28,19 @@
     /**
      * Method called by the HAL when a tuning operation completes
      * following a step(), scan() or tune() command.
+     *
+     * This callback supersedes V1_0::tuneComplete.
+     * The 1.0 callback must not be called when HAL implementation detects
+     * 1.1 client (by casting V1_0::ITunerCallback to V1_1::ITunerCallback).
+     *
+     * In case of success, currentProgramInfoChanged must be called too.
+     * It means the success case may (or may not) be handled by the client in
+     * currentProgramInfoChanged, instead of here.
+     *
      * @param result OK if tune succeeded or TIMEOUT in case of time out.
-     * @param info A ProgramInfo structure describing the tuned station.
+     * @param selector A ProgramSelector structure describing the tuned station.
      */
-    oneway tuneComplete_1_1(Result result, ProgramInfo info);
-
-    /**
-     * Method called by the HAL when a frequency switch occurs.
-     * @param info A ProgramInfo structure describing the new tuned station.
-     */
-    oneway afSwitch_1_1(ProgramInfo info);
+    oneway tuneComplete_1_1(Result result, ProgramSelector selector);
 
     /**
      * Called by the HAL when background scan feature becomes available or not.
@@ -63,10 +66,31 @@
      * call it immediately, ie. it may wait for a short time to accumulate
      * multiple list change notifications into a single event.
      *
+     * This callback is only for notifying about insertions and deletions,
+     * not about metadata changes.
+     *
      * It may be triggered either by an explicitly issued background scan,
      * or a scan issued by the device internally.
      *
      * Client may retrieve the actual list with ITuner::getProgramList.
      */
     oneway programListChanged();
+
+    /**
+     * Method called by the HAL when current program information (including
+     * metadata) is updated.
+     *
+     * Client may retrieve the actual program info with
+     * ITuner::getProgramInformation_1_1.
+     *
+     * This may be called together with tuneComplete_1_1 or afSwitch_1_1.
+     *
+     * This callback supersedes V1_0::newMetadata and V1_0::afSwitch;
+     * partly V1_0::tuneComplete.
+     * 1.0 callbacks must not be called when HAL implementation detects
+     * 1.1 client (by casting V1_0::ITunerCallback to V1_1::ITunerCallback).
+     *
+     * @param info current program information
+     */
+    oneway currentProgramInfoChanged(ProgramInfo info);
 };
diff --git a/broadcastradio/1.1/WARNING b/broadcastradio/1.1/WARNING
deleted file mode 100644
index e867cfa..0000000
--- a/broadcastradio/1.1/WARNING
+++ /dev/null
@@ -1 +0,0 @@
-This is experimental interface, do not use it yet.
diff --git a/broadcastradio/1.1/default/Android.bp b/broadcastradio/1.1/default/Android.bp
index 759eb09..6d26b11 100644
--- a/broadcastradio/1.1/default/Android.bp
+++ b/broadcastradio/1.1/default/Android.bp
@@ -14,8 +14,9 @@
 // limitations under the License.
 //
 
-cc_library_shared {
-    name: "android.hardware.broadcastradio@1.1-impl",
+cc_binary {
+    name: "android.hardware.broadcastradio@1.1-service",
+    init_rc: ["android.hardware.broadcastradio@1.1-service.rc"],
     vendor: true,
     relative_install_path: "hw",
     cflags: [
@@ -27,16 +28,20 @@
         "BroadcastRadio.cpp",
         "BroadcastRadioFactory.cpp",
         "Tuner.cpp",
-        "Utils.cpp",
+        "VirtualProgram.cpp",
+        "VirtualRadio.cpp",
+        "service.cpp"
+    ],
+    static_libs: [
+        "android.hardware.broadcastradio@1.1-utils-lib",
     ],
     shared_libs: [
-        "libhidlbase",
-        "libhidltransport",
-        "libutils",
-        "liblog",
-        "libhardware",
         "android.hardware.broadcastradio@1.0",
         "android.hardware.broadcastradio@1.1",
-        "libradio_metadata",
+        "libbase",
+        "libhidlbase",
+        "libhidltransport",
+        "liblog",
+        "libutils",
     ],
 }
diff --git a/broadcastradio/1.1/default/BroadcastRadio.cpp b/broadcastradio/1.1/default/BroadcastRadio.cpp
index 68c9b93..1bcfd82 100644
--- a/broadcastradio/1.1/default/BroadcastRadio.cpp
+++ b/broadcastradio/1.1/default/BroadcastRadio.cpp
@@ -13,14 +13,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#define LOG_TAG "BroadcastRadio"
-//#define LOG_NDEBUG 0
+#define LOG_TAG "BroadcastRadioDefault.module"
+#define LOG_NDEBUG 0
+
+#include "BroadcastRadio.h"
 
 #include <log/log.h>
 
-#include "BroadcastRadio.h"
-#include "Tuner.h"
-#include "Utils.h"
+#include "resources.h"
 
 namespace android {
 namespace hardware {
@@ -28,117 +28,163 @@
 namespace V1_1 {
 namespace implementation {
 
-using ::android::sp;
+using V1_0::Band;
+using V1_0::BandConfig;
+using V1_0::Class;
+using V1_0::Deemphasis;
+using V1_0::Rds;
+
+using std::lock_guard;
+using std::map;
+using std::mutex;
+using std::vector;
+
+// clang-format off
+static const map<Class, ModuleConfig> gModuleConfigs{
+    {Class::AM_FM, ModuleConfig({
+        "Digital radio mock",
+        {  // amFmBands
+            AmFmBandConfig({
+                Band::AM,
+                153,         // lowerLimit
+                26100,       // upperLimit
+                {5, 9, 10},  // spacings
+            }),
+            AmFmBandConfig({
+                Band::FM,
+                65800,           // lowerLimit
+                108000,          // upperLimit
+                {10, 100, 200},  // spacings
+            }),
+            AmFmBandConfig({
+                Band::AM_HD,
+                153,         // lowerLimit
+                26100,       // upperLimit
+                {5, 9, 10},  // spacings
+            }),
+            AmFmBandConfig({
+                Band::FM_HD,
+                87700,   // lowerLimit
+                107900,  // upperLimit
+                {200},   // spacings
+            }),
+        },
+    })},
+
+    {Class::SAT, ModuleConfig({
+        "Satellite radio mock",
+        {},  // amFmBands
+    })},
+};
+// clang-format on
 
 BroadcastRadio::BroadcastRadio(Class classId)
-        : mStatus(Result::NOT_INITIALIZED), mClassId(classId), mHwDevice(NULL)
-{
+    : mClassId(classId), mConfig(gModuleConfigs.at(classId)) {}
+
+bool BroadcastRadio::isSupported(Class classId) {
+    return gModuleConfigs.find(classId) != gModuleConfigs.end();
 }
 
-BroadcastRadio::~BroadcastRadio()
-{
-    if (mHwDevice != NULL) {
-        radio_hw_device_close(mHwDevice);
-    }
+Return<void> BroadcastRadio::getProperties(getProperties_cb _hidl_cb) {
+    ALOGV("%s", __func__);
+    return getProperties_1_1(
+        [&](const Properties& properties) { _hidl_cb(Result::OK, properties.base); });
 }
 
-void BroadcastRadio::onFirstRef()
-{
-    const hw_module_t *mod;
-    int rc;
-    ALOGI("%s mClassId %d", __FUNCTION__, mClassId);
+Return<void> BroadcastRadio::getProperties_1_1(getProperties_1_1_cb _hidl_cb) {
+    ALOGV("%s", __func__);
+    Properties prop11 = {};
+    auto& prop10 = prop11.base;
 
-    mHwDevice = NULL;
-    const char *classString = Utils::getClassString(mClassId);
-    if (classString == NULL) {
-        ALOGE("invalid class ID %d", mClassId);
-        mStatus = Result::INVALID_ARGUMENTS;
-        return;
+    prop10.classId = mClassId;
+    prop10.implementor = "Google";
+    prop10.product = mConfig.productName;
+    prop10.numTuners = 1;
+    prop10.numAudioSources = 1;
+    prop10.supportsCapture = false;
+    prop11.supportsBackgroundScanning = false;
+    prop11.supportedProgramTypes = hidl_vec<uint32_t>({
+        static_cast<uint32_t>(ProgramType::AM), static_cast<uint32_t>(ProgramType::FM),
+        static_cast<uint32_t>(ProgramType::AM_HD), static_cast<uint32_t>(ProgramType::FM_HD),
+    });
+    prop11.supportedIdentifierTypes = hidl_vec<uint32_t>({
+        static_cast<uint32_t>(IdentifierType::AMFM_FREQUENCY),
+        static_cast<uint32_t>(IdentifierType::RDS_PI),
+        static_cast<uint32_t>(IdentifierType::HD_STATION_ID_EXT),
+        static_cast<uint32_t>(IdentifierType::HD_SUBCHANNEL),
+    });
+    prop11.vendorInfo = hidl_vec<VendorKeyValue>({
+        {"com.google.dummy", "dummy"},
+    });
+
+    prop10.bands.resize(mConfig.amFmBands.size());
+    for (size_t i = 0; i < mConfig.amFmBands.size(); i++) {
+        auto& src = mConfig.amFmBands[i];
+        auto& dst = prop10.bands[i];
+
+        dst.type = src.type;
+        dst.antennaConnected = true;
+        dst.lowerLimit = src.lowerLimit;
+        dst.upperLimit = src.upperLimit;
+        dst.spacings = src.spacings;
+
+        if (utils::isAm(src.type)) {
+            dst.ext.am.stereo = true;
+        } else if (utils::isFm(src.type)) {
+            dst.ext.fm.deemphasis = static_cast<Deemphasis>(Deemphasis::D50 | Deemphasis::D75);
+            dst.ext.fm.stereo = true;
+            dst.ext.fm.rds = static_cast<Rds>(Rds::WORLD | Rds::US);
+            dst.ext.fm.ta = true;
+            dst.ext.fm.af = true;
+            dst.ext.fm.ea = true;
+        }
     }
 
-    ALOGI("%s RADIO_HARDWARE_MODULE_ID %s %s",
-            __FUNCTION__, RADIO_HARDWARE_MODULE_ID, classString);
-
-    rc = hw_get_module_by_class(RADIO_HARDWARE_MODULE_ID, classString, &mod);
-    if (rc != 0) {
-        ALOGE("couldn't load radio module %s.%s (%s)",
-                RADIO_HARDWARE_MODULE_ID, classString, strerror(-rc));
-        return;
-    }
-    rc = radio_hw_device_open(mod, &mHwDevice);
-    if (rc != 0) {
-        ALOGE("couldn't open radio hw device in %s.%s (%s)",
-                RADIO_HARDWARE_MODULE_ID, "primary", strerror(-rc));
-        mHwDevice = NULL;
-        return;
-    }
-    if (mHwDevice->common.version != RADIO_DEVICE_API_VERSION_CURRENT) {
-        ALOGE("wrong radio hw device version %04x", mHwDevice->common.version);
-        radio_hw_device_close(mHwDevice);
-        mHwDevice = NULL;
-    } else {
-        mStatus = Result::OK;
-    }
-}
-
-int BroadcastRadio::closeHalTuner(const struct radio_tuner *halTuner)
-{
-    ALOGV("%s", __FUNCTION__);
-    if (mHwDevice == NULL) {
-        return -ENODEV;
-    }
-    if (halTuner == 0) {
-        return -EINVAL;
-    }
-    return mHwDevice->close_tuner(mHwDevice, halTuner);
-}
-
-
-// Methods from ::android::hardware::broadcastradio::V1_1::IBroadcastRadio follow.
-Return<void> BroadcastRadio::getProperties(getProperties_cb _hidl_cb)
-{
-    int rc;
-    radio_hal_properties_t halProperties;
-    Properties properties;
-
-    if (mHwDevice == NULL) {
-        rc = -ENODEV;
-        goto exit;
-    }
-    rc = mHwDevice->get_properties(mHwDevice, &halProperties);
-    if (rc == 0) {
-        Utils::convertPropertiesFromHal(&properties, &halProperties);
-    }
-
-exit:
-    _hidl_cb(Utils::convertHalResult(rc), properties);
+    _hidl_cb(prop11);
     return Void();
 }
 
-Return<void> BroadcastRadio::getProperties_1_1(getProperties_1_1_cb _hidl_cb __unused)
-{
-    return Status::fromExceptionCode(Status::EX_UNSUPPORTED_OPERATION);
-}
+Return<void> BroadcastRadio::openTuner(const BandConfig& config, bool audio __unused,
+                                       const sp<V1_0::ITunerCallback>& callback,
+                                       openTuner_cb _hidl_cb) {
+    ALOGV("%s(%s)", __func__, toString(config.type).c_str());
+    lock_guard<mutex> lk(mMut);
 
-Return<void> BroadcastRadio::openTuner(const BandConfig& config, bool audio,
-    const sp<V1_0::ITunerCallback>& callback, openTuner_cb _hidl_cb)
-{
-    sp<Tuner> tunerImpl = new Tuner(callback, this);
-
-    radio_hal_band_config_t halConfig;
-    const struct radio_tuner *halTuner;
-    Utils::convertBandConfigToHal(&halConfig, &config);
-    int rc = mHwDevice->open_tuner(mHwDevice, &halConfig, audio, Tuner::callback,
-            tunerImpl.get(), &halTuner);
-    if (rc == 0) {
-        tunerImpl->setHalTuner(halTuner);
+    auto oldTuner = mTuner.promote();
+    if (oldTuner != nullptr) {
+        ALOGI("Force-closing previously opened tuner");
+        oldTuner->forceClose();
+        mTuner = nullptr;
     }
 
-    _hidl_cb(Utils::convertHalResult(rc), tunerImpl);
+    sp<Tuner> newTuner = new Tuner(mClassId, callback);
+    mTuner = newTuner;
+    if (mClassId == Class::AM_FM) {
+        auto ret = newTuner->setConfiguration(config);
+        if (ret != Result::OK) {
+            _hidl_cb(Result::INVALID_ARGUMENTS, {});
+            return Void();
+        }
+    }
+
+    _hidl_cb(Result::OK, newTuner);
     return Void();
 }
 
-} // namespace implementation
+Return<void> BroadcastRadio::getImage(int32_t id, getImage_cb _hidl_cb) {
+    ALOGV("%s(%x)", __func__, id);
+
+    if (id == resources::demoPngId) {
+        _hidl_cb(std::vector<uint8_t>(resources::demoPng, std::end(resources::demoPng)));
+        return {};
+    }
+
+    ALOGI("Image %x doesn't exists", id);
+    _hidl_cb({});
+    return Void();
+}
+
+}  // namespace implementation
 }  // namespace V1_1
 }  // namespace broadcastradio
 }  // namespace hardware
diff --git a/broadcastradio/1.1/default/BroadcastRadio.h b/broadcastradio/1.1/default/BroadcastRadio.h
index 7de31a0..a96a2ab 100644
--- a/broadcastradio/1.1/default/BroadcastRadio.h
+++ b/broadcastradio/1.1/default/BroadcastRadio.h
@@ -16,9 +16,10 @@
 #ifndef ANDROID_HARDWARE_BROADCASTRADIO_V1_1_BROADCASTRADIO_H
 #define ANDROID_HARDWARE_BROADCASTRADIO_V1_1_BROADCASTRADIO_H
 
+#include "Tuner.h"
+
 #include <android/hardware/broadcastradio/1.1/IBroadcastRadio.h>
 #include <android/hardware/broadcastradio/1.1/types.h>
-#include <hardware/radio.h>
 
 namespace android {
 namespace hardware {
@@ -26,42 +27,49 @@
 namespace V1_1 {
 namespace implementation {
 
-using V1_0::Class;
-using V1_0::BandConfig;
-using V1_0::Properties;
+struct AmFmBandConfig {
+    V1_0::Band type;
+    uint32_t lowerLimit;  // kHz
+    uint32_t upperLimit;  // kHz
+    std::vector<uint32_t> spacings;  // kHz
+};
+
+struct ModuleConfig {
+    std::string productName;
+    std::vector<AmFmBandConfig> amFmBands;
+};
 
 struct BroadcastRadio : public V1_1::IBroadcastRadio {
+    /**
+     * Constructs new broadcast radio module.
+     *
+     * Before calling a constructor with a given classId, it must be checked with isSupported
+     * method first. Otherwise it results in undefined behaviour.
+     *
+     * @param classId type of a radio.
+     */
+    BroadcastRadio(V1_0::Class classId);
 
-    BroadcastRadio(Class classId);
+    /**
+     * Checks, if a given radio type is supported.
+     *
+     * @param classId type of a radio.
+     */
+    static bool isSupported(V1_0::Class classId);
 
-    // Methods from ::android::hardware::broadcastradio::V1_1::IBroadcastRadio follow.
+    // V1_1::IBroadcastRadio methods
     Return<void> getProperties(getProperties_cb _hidl_cb) override;
     Return<void> getProperties_1_1(getProperties_1_1_cb _hidl_cb) override;
-    Return<void> openTuner(const BandConfig& config, bool audio,
-            const sp<V1_0::ITunerCallback>& callback, openTuner_cb _hidl_cb) override;
+    Return<void> openTuner(const V1_0::BandConfig& config, bool audio,
+                           const sp<V1_0::ITunerCallback>& callback,
+                           openTuner_cb _hidl_cb) override;
+    Return<void> getImage(int32_t id, getImage_cb _hidl_cb);
 
-    // RefBase
-    virtual void onFirstRef() override;
-
-    Result initCheck() { return mStatus; }
-    int closeHalTuner(const struct radio_tuner *halTuner);
-
-private:
-    virtual ~BroadcastRadio();
-
-    static const char * sClassModuleNames[];
-
-    Result convertHalResult(int rc);
-    void convertBandConfigFromHal(BandConfig *config,
-            const radio_hal_band_config_t *halConfig);
-    void convertPropertiesFromHal(Properties *properties,
-            const radio_hal_properties_t *halProperties);
-    void convertBandConfigToHal(radio_hal_band_config_t *halConfig,
-            const BandConfig *config);
-
-    Result mStatus;
-    Class mClassId;
-    struct radio_hw_device *mHwDevice;
+   private:
+    std::mutex mMut;
+    V1_0::Class mClassId;
+    ModuleConfig mConfig;
+    wp<Tuner> mTuner;
 };
 
 }  // namespace implementation
diff --git a/broadcastradio/1.1/default/BroadcastRadioFactory.cpp b/broadcastradio/1.1/default/BroadcastRadioFactory.cpp
index c8b6c39..f57bc79 100644
--- a/broadcastradio/1.1/default/BroadcastRadioFactory.cpp
+++ b/broadcastradio/1.1/default/BroadcastRadioFactory.cpp
@@ -13,29 +13,51 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#define LOG_TAG "BroadcastRadioDefault.factory"
+#define LOG_NDEBUG 0
+
 #include "BroadcastRadioFactory.h"
+
 #include "BroadcastRadio.h"
 
+#include <log/log.h>
+
 namespace android {
 namespace hardware {
 namespace broadcastradio {
 namespace V1_1 {
 namespace implementation {
 
-// Methods from ::android::hardware::broadcastradio::V1_0::IBroadcastRadioFactory follow.
-Return<void> BroadcastRadioFactory::connectModule(Class classId, connectModule_cb _hidl_cb)  {
-    sp<BroadcastRadio> impl = new BroadcastRadio(classId);
-    Result retval = Result::NOT_INITIALIZED;
-    if (impl != 0) {
-        retval = impl->initCheck();
-    }
-    _hidl_cb(retval, impl);
-    return Void();
+using V1_0::Class;
+
+using std::vector;
+
+static const vector<Class> gAllClasses = {
+    Class::AM_FM, Class::SAT, Class::DT,
+};
+
+IBroadcastRadioFactory* HIDL_FETCH_IBroadcastRadioFactory(const char* name __unused) {
+    return new BroadcastRadioFactory();
 }
 
+BroadcastRadioFactory::BroadcastRadioFactory() {
+    for (auto&& classId : gAllClasses) {
+        if (!BroadcastRadio::isSupported(classId)) continue;
+        mRadioModules[classId] = new BroadcastRadio(classId);
+    }
+}
 
-IBroadcastRadioFactory* HIDL_FETCH_IBroadcastRadioFactory(const char* /* name */) {
-    return new BroadcastRadioFactory();
+Return<void> BroadcastRadioFactory::connectModule(Class classId, connectModule_cb _hidl_cb) {
+    ALOGV("%s(%s)", __func__, toString(classId).c_str());
+
+    auto moduleIt = mRadioModules.find(classId);
+    if (moduleIt == mRadioModules.end()) {
+        _hidl_cb(Result::INVALID_ARGUMENTS, nullptr);
+    } else {
+        _hidl_cb(Result::OK, moduleIt->second);
+    }
+
+    return Void();
 }
 
 }  // namespace implementation
diff --git a/broadcastradio/1.1/default/BroadcastRadioFactory.h b/broadcastradio/1.1/default/BroadcastRadioFactory.h
index 8eb8514..8b67ac3 100644
--- a/broadcastradio/1.1/default/BroadcastRadioFactory.h
+++ b/broadcastradio/1.1/default/BroadcastRadioFactory.h
@@ -16,6 +16,7 @@
 #ifndef ANDROID_HARDWARE_BROADCASTRADIO_V1_1_BROADCASTRADIOFACTORY_H
 #define ANDROID_HARDWARE_BROADCASTRADIO_V1_1_BROADCASTRADIOFACTORY_H
 
+#include <android/hardware/broadcastradio/1.1/IBroadcastRadio.h>
 #include <android/hardware/broadcastradio/1.1/IBroadcastRadioFactory.h>
 #include <android/hardware/broadcastradio/1.1/types.h>
 
@@ -25,14 +26,17 @@
 namespace V1_1 {
 namespace implementation {
 
-using V1_0::Class;
+extern "C" IBroadcastRadioFactory* HIDL_FETCH_IBroadcastRadioFactory(const char* name);
 
 struct BroadcastRadioFactory : public IBroadcastRadioFactory {
-    // Methods from ::android::hardware::broadcastradio::V1_0::IBroadcastRadioFactory follow.
-    Return<void> connectModule(Class classId, connectModule_cb _hidl_cb) override;
-};
+    BroadcastRadioFactory();
 
-extern "C" IBroadcastRadioFactory* HIDL_FETCH_IBroadcastRadioFactory(const char* name);
+    // V1_0::IBroadcastRadioFactory methods
+    Return<void> connectModule(V1_0::Class classId, connectModule_cb _hidl_cb) override;
+
+   private:
+    std::map<V1_0::Class, sp<IBroadcastRadio>> mRadioModules;
+};
 
 }  // namespace implementation
 }  // namespace V1_1
diff --git a/broadcastradio/1.1/default/OWNERS b/broadcastradio/1.1/default/OWNERS
new file mode 100644
index 0000000..0c27b71
--- /dev/null
+++ b/broadcastradio/1.1/default/OWNERS
@@ -0,0 +1,4 @@
+# Automotive team
+egranata@google.com
+keunyoung@google.com
+twasilczyk@google.com
diff --git a/broadcastradio/1.1/default/Tuner.cpp b/broadcastradio/1.1/default/Tuner.cpp
index ae5848c..9a34cb1 100644
--- a/broadcastradio/1.1/default/Tuner.cpp
+++ b/broadcastradio/1.1/default/Tuner.cpp
@@ -14,15 +14,14 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "Tuner"
-//#define LOG_NDEBUG 0
-
-#include <log/log.h>
+#define LOG_TAG "BroadcastRadioDefault.tuner"
+#define LOG_NDEBUG 0
 
 #include "BroadcastRadio.h"
 #include "Tuner.h"
-#include "Utils.h"
-#include <system/RadioMetadataWrapper.h>
+
+#include <broadcastradio-utils/Utils.h>
+#include <log/log.h>
 
 namespace android {
 namespace hardware {
@@ -30,199 +29,351 @@
 namespace V1_1 {
 namespace implementation {
 
-void Tuner::onCallback(radio_hal_event_t *halEvent)
-{
-    BandConfig config;
-    ProgramInfo info;
-    hidl_vec<MetaData> metadata;
+using namespace std::chrono_literals;
 
-    if (mCallback != 0) {
-        switch(halEvent->type) {
-        case RADIO_EVENT_CONFIG:
-            Utils::convertBandConfigFromHal(&config, &halEvent->config);
-            mCallback->configChange(Utils::convertHalResult(halEvent->status), config);
-            break;
-        case RADIO_EVENT_ANTENNA:
-            mCallback->antennaStateChange(halEvent->on);
-            break;
-        case RADIO_EVENT_TUNED:
-            Utils::convertProgramInfoFromHal(&info, &halEvent->info);
-            if (mCallback1_1 != nullptr) {
-                mCallback1_1->tuneComplete_1_1(Utils::convertHalResult(halEvent->status), info);
+using V1_0::Band;
+using V1_0::BandConfig;
+using V1_0::Class;
+using V1_0::Direction;
+using utils::HalRevision;
+
+using std::chrono::milliseconds;
+using std::lock_guard;
+using std::move;
+using std::mutex;
+using std::sort;
+using std::vector;
+
+const struct {
+    milliseconds config = 50ms;
+    milliseconds scan = 200ms;
+    milliseconds step = 100ms;
+    milliseconds tune = 150ms;
+} gDefaultDelay;
+
+Tuner::Tuner(V1_0::Class classId, const sp<V1_0::ITunerCallback>& callback)
+    : mClassId(classId),
+      mCallback(callback),
+      mCallback1_1(ITunerCallback::castFrom(callback).withDefault(nullptr)),
+      mVirtualRadio(getRadio(classId)),
+      mIsAnalogForced(false) {}
+
+void Tuner::forceClose() {
+    lock_guard<mutex> lk(mMut);
+    mIsClosed = true;
+    mThread.cancelAll();
+}
+
+Return<Result> Tuner::setConfiguration(const BandConfig& config) {
+    ALOGV("%s", __func__);
+    lock_guard<mutex> lk(mMut);
+    if (mIsClosed) return Result::NOT_INITIALIZED;
+    if (mClassId != Class::AM_FM) {
+        ALOGE("Can't set AM/FM configuration on SAT/DT radio tuner");
+        return Result::INVALID_STATE;
+    }
+
+    if (config.lowerLimit >= config.upperLimit) return Result::INVALID_ARGUMENTS;
+
+    auto task = [this, config]() {
+        ALOGI("Setting AM/FM config");
+        lock_guard<mutex> lk(mMut);
+
+        mAmfmConfig = move(config);
+        mAmfmConfig.antennaConnected = true;
+        mCurrentProgram = utils::make_selector(mAmfmConfig.type, mAmfmConfig.lowerLimit);
+
+        if (utils::isFm(mAmfmConfig.type)) {
+            mVirtualRadio = std::ref(getFmRadio());
+        } else {
+            mVirtualRadio = std::ref(getAmRadio());
+        }
+
+        mIsAmfmConfigSet = true;
+        mCallback->configChange(Result::OK, mAmfmConfig);
+    };
+    mThread.schedule(task, gDefaultDelay.config);
+
+    return Result::OK;
+}
+
+Return<void> Tuner::getConfiguration(getConfiguration_cb _hidl_cb) {
+    ALOGV("%s", __func__);
+    lock_guard<mutex> lk(mMut);
+
+    if (!mIsClosed && mIsAmfmConfigSet) {
+        _hidl_cb(Result::OK, mAmfmConfig);
+    } else {
+        _hidl_cb(Result::NOT_INITIALIZED, {});
+    }
+    return {};
+}
+
+// makes ProgramInfo that points to no program
+static ProgramInfo makeDummyProgramInfo(const ProgramSelector& selector) {
+    ProgramInfo info11 = {};
+    auto& info10 = info11.base;
+
+    utils::getLegacyChannel(selector, &info10.channel, &info10.subChannel);
+    info11.selector = selector;
+    info11.flags |= ProgramInfoFlags::MUTED;
+
+    return info11;
+}
+
+HalRevision Tuner::getHalRev() const {
+    if (mCallback1_1 != nullptr) {
+        return HalRevision::V1_1;
+    } else {
+        return HalRevision::V1_0;
+    }
+}
+
+void Tuner::tuneInternalLocked(const ProgramSelector& sel) {
+    VirtualProgram virtualProgram;
+    if (mVirtualRadio.get().getProgram(sel, virtualProgram)) {
+        mCurrentProgram = virtualProgram.selector;
+        mCurrentProgramInfo = virtualProgram.getProgramInfo(getHalRev());
+    } else {
+        mCurrentProgram = sel;
+        mCurrentProgramInfo = makeDummyProgramInfo(sel);
+    }
+    mIsTuneCompleted = true;
+
+    if (mCallback1_1 == nullptr) {
+        mCallback->tuneComplete(Result::OK, mCurrentProgramInfo.base);
+    } else {
+        mCallback1_1->tuneComplete_1_1(Result::OK, mCurrentProgramInfo.selector);
+        mCallback1_1->currentProgramInfoChanged(mCurrentProgramInfo);
+    }
+}
+
+Return<Result> Tuner::scan(Direction direction, bool skipSubChannel __unused) {
+    ALOGV("%s", __func__);
+    lock_guard<mutex> lk(mMut);
+    if (mIsClosed) return Result::NOT_INITIALIZED;
+
+    auto list = mVirtualRadio.get().getProgramList();
+
+    if (list.empty()) {
+        mIsTuneCompleted = false;
+        auto task = [this, direction]() {
+            ALOGI("Performing failed scan %s", toString(direction).c_str());
+
+            if (mCallback1_1 == nullptr) {
+                mCallback->tuneComplete(Result::TIMEOUT, {});
+            } else {
+                mCallback1_1->tuneComplete_1_1(Result::TIMEOUT, {});
             }
-            mCallback->tuneComplete(Utils::convertHalResult(halEvent->status), info.base);
-            break;
-        case RADIO_EVENT_METADATA: {
-            uint32_t channel;
-            uint32_t sub_channel;
-            if (radio_metadata_get_channel(halEvent->metadata, &channel, &sub_channel) == 0) {
-                Utils::convertMetaDataFromHal(metadata, halEvent->metadata);
-                mCallback->newMetadata(channel, sub_channel, metadata);
-            }
-            } break;
-        case RADIO_EVENT_TA:
-            mCallback->trafficAnnouncement(halEvent->on);
-            break;
-        case RADIO_EVENT_AF_SWITCH:
-            Utils::convertProgramInfoFromHal(&info, &halEvent->info);
-            if (mCallback1_1 != nullptr) {
-                mCallback1_1->afSwitch_1_1(info);
-            }
-            mCallback->afSwitch(info.base);
-            break;
-        case RADIO_EVENT_EA:
-            mCallback->emergencyAnnouncement(halEvent->on);
-            break;
-        case RADIO_EVENT_HW_FAILURE:
-        default:
-            mCallback->hardwareFailure();
-            break;
+        };
+        mThread.schedule(task, gDefaultDelay.scan);
+
+        return Result::OK;
+    }
+
+    // Not optimal (O(sort) instead of O(n)), but not a big deal here;
+    // also, it's likely that list is already sorted (so O(n) anyway).
+    sort(list.begin(), list.end());
+    auto current = mCurrentProgram;
+    auto found = lower_bound(list.begin(), list.end(), VirtualProgram({current}));
+    if (direction == Direction::UP) {
+        if (found < list.end() - 1) {
+            if (utils::tunesTo(current, found->selector)) found++;
+        } else {
+            found = list.begin();
+        }
+    } else {
+        if (found > list.begin() && found != list.end()) {
+            found--;
+        } else {
+            found = list.end() - 1;
         }
     }
+    auto tuneTo = found->selector;
+
+    mIsTuneCompleted = false;
+    auto task = [this, tuneTo, direction]() {
+        ALOGI("Performing scan %s", toString(direction).c_str());
+
+        lock_guard<mutex> lk(mMut);
+        tuneInternalLocked(tuneTo);
+    };
+    mThread.schedule(task, gDefaultDelay.scan);
+
+    return Result::OK;
 }
 
-//static
-void Tuner::callback(radio_hal_event_t *halEvent, void *cookie)
-{
-    wp<Tuner> weak(reinterpret_cast<Tuner*>(cookie));
-    sp<Tuner> tuner = weak.promote();
-    if (tuner == 0) return;
-    tuner->onCallback(halEvent);
-}
+Return<Result> Tuner::step(Direction direction, bool skipSubChannel) {
+    ALOGV("%s", __func__);
+    lock_guard<mutex> lk(mMut);
+    if (mIsClosed) return Result::NOT_INITIALIZED;
 
-Tuner::Tuner(const sp<V1_0::ITunerCallback>& callback, const wp<BroadcastRadio>& parentDevice)
-        : mHalTuner(NULL), mCallback(callback), mCallback1_1(ITunerCallback::castFrom(callback)),
-        mParentDevice(parentDevice)
-{
-    ALOGV("%s", __FUNCTION__);
-}
+    ALOGW_IF(!skipSubChannel, "can't step to next frequency without ignoring subChannel");
 
-
-Tuner::~Tuner()
-{
-    ALOGV("%s", __FUNCTION__);
-    const sp<BroadcastRadio> parentDevice = mParentDevice.promote();
-    if (parentDevice != 0) {
-        parentDevice->closeHalTuner(mHalTuner);
-    }
-}
-
-// Methods from ::android::hardware::broadcastradio::V1_1::ITuner follow.
-Return<Result> Tuner::setConfiguration(const BandConfig& config)  {
-    ALOGV("%s", __FUNCTION__);
-    if (mHalTuner == NULL) {
-        return Utils::convertHalResult(-ENODEV);
-    }
-    radio_hal_band_config_t halConfig;
-    Utils::convertBandConfigToHal(&halConfig, &config);
-    int rc = mHalTuner->set_configuration(mHalTuner, &halConfig);
-    return Utils::convertHalResult(rc);
-}
-
-Return<void> Tuner::getConfiguration(getConfiguration_cb _hidl_cb)  {
-    int rc;
-    radio_hal_band_config_t halConfig;
-    BandConfig config;
-
-    ALOGV("%s", __FUNCTION__);
-    if (mHalTuner == NULL) {
-        rc = -ENODEV;
-        goto exit;
-    }
-    rc = mHalTuner->get_configuration(mHalTuner, &halConfig);
-    if (rc == 0) {
-        Utils::convertBandConfigFromHal(&config, &halConfig);
+    if (!utils::isAmFm(utils::getType(mCurrentProgram))) {
+        ALOGE("Can't step in anything else than AM/FM");
+        return Result::NOT_INITIALIZED;
     }
 
-exit:
-    _hidl_cb(Utils::convertHalResult(rc), config);
-    return Void();
-}
-
-Return<Result> Tuner::scan(Direction direction, bool skipSubChannel)  {
-    if (mHalTuner == NULL) {
-        return Utils::convertHalResult(-ENODEV);
+    if (!mIsAmfmConfigSet) {
+        ALOGW("AM/FM config not set");
+        return Result::INVALID_STATE;
     }
-    int rc = mHalTuner->scan(mHalTuner, static_cast<radio_direction_t>(direction), skipSubChannel);
-    return Utils::convertHalResult(rc);
+    mIsTuneCompleted = false;
+
+    auto task = [this, direction]() {
+        ALOGI("Performing step %s", toString(direction).c_str());
+
+        lock_guard<mutex> lk(mMut);
+
+        auto current = utils::getId(mCurrentProgram, IdentifierType::AMFM_FREQUENCY, 0);
+
+        if (direction == Direction::UP) {
+            current += mAmfmConfig.spacings[0];
+        } else {
+            current -= mAmfmConfig.spacings[0];
+        }
+
+        if (current > mAmfmConfig.upperLimit) current = mAmfmConfig.lowerLimit;
+        if (current < mAmfmConfig.lowerLimit) current = mAmfmConfig.upperLimit;
+
+        tuneInternalLocked(utils::make_selector(mAmfmConfig.type, current));
+    };
+    mThread.schedule(task, gDefaultDelay.step);
+
+    return Result::OK;
 }
 
-Return<Result> Tuner::step(Direction direction, bool skipSubChannel)  {
-    if (mHalTuner == NULL) {
-        return Utils::convertHalResult(-ENODEV);
+Return<Result> Tuner::tune(uint32_t channel, uint32_t subChannel) {
+    ALOGV("%s(%d, %d)", __func__, channel, subChannel);
+    Band band;
+    {
+        lock_guard<mutex> lk(mMut);
+        band = mAmfmConfig.type;
     }
-    int rc = mHalTuner->step(mHalTuner, static_cast<radio_direction_t>(direction), skipSubChannel);
-    return Utils::convertHalResult(rc);
+    return tuneByProgramSelector(utils::make_selector(band, channel, subChannel));
 }
 
-Return<Result> Tuner::tune(uint32_t channel, uint32_t subChannel)  {
-    if (mHalTuner == NULL) {
-        return Utils::convertHalResult(-ENODEV);
+Return<Result> Tuner::tuneByProgramSelector(const ProgramSelector& sel) {
+    ALOGV("%s(%s)", __func__, toString(sel).c_str());
+    lock_guard<mutex> lk(mMut);
+    if (mIsClosed) return Result::NOT_INITIALIZED;
+
+    // checking if ProgramSelector is valid
+    auto programType = utils::getType(sel);
+    if (utils::isAmFm(programType)) {
+        if (!mIsAmfmConfigSet) {
+            ALOGW("AM/FM config not set");
+            return Result::INVALID_STATE;
+        }
+
+        auto freq = utils::getId(sel, IdentifierType::AMFM_FREQUENCY);
+        if (freq < mAmfmConfig.lowerLimit || freq > mAmfmConfig.upperLimit) {
+            return Result::INVALID_ARGUMENTS;
+        }
+    } else if (programType == ProgramType::DAB) {
+        if (!utils::hasId(sel, IdentifierType::DAB_SIDECC)) return Result::INVALID_ARGUMENTS;
+    } else if (programType == ProgramType::DRMO) {
+        if (!utils::hasId(sel, IdentifierType::DRMO_SERVICE_ID)) return Result::INVALID_ARGUMENTS;
+    } else if (programType == ProgramType::SXM) {
+        if (!utils::hasId(sel, IdentifierType::SXM_SERVICE_ID)) return Result::INVALID_ARGUMENTS;
+    } else {
+        return Result::INVALID_ARGUMENTS;
     }
-    int rc = mHalTuner->tune(mHalTuner, channel, subChannel);
-    return Utils::convertHalResult(rc);
+
+    mIsTuneCompleted = false;
+    auto task = [this, sel]() {
+        lock_guard<mutex> lk(mMut);
+        tuneInternalLocked(sel);
+    };
+    mThread.schedule(task, gDefaultDelay.tune);
+
+    return Result::OK;
 }
 
-Return<Result> Tuner::cancel()  {
-    if (mHalTuner == NULL) {
-        return Utils::convertHalResult(-ENODEV);
-    }
-    int rc = mHalTuner->cancel(mHalTuner);
-    return Utils::convertHalResult(rc);
+Return<Result> Tuner::cancel() {
+    ALOGV("%s", __func__);
+    lock_guard<mutex> lk(mMut);
+    if (mIsClosed) return Result::NOT_INITIALIZED;
+
+    mThread.cancelAll();
+    return Result::OK;
 }
 
-Return<void> Tuner::getProgramInformation(getProgramInformation_cb _hidl_cb)  {
-    ALOGV("%s", __FUNCTION__);
+Return<Result> Tuner::cancelAnnouncement() {
+    ALOGV("%s", __func__);
+    lock_guard<mutex> lk(mMut);
+    if (mIsClosed) return Result::NOT_INITIALIZED;
+
+    return Result::OK;
+}
+
+Return<void> Tuner::getProgramInformation(getProgramInformation_cb _hidl_cb) {
+    ALOGV("%s", __func__);
     return getProgramInformation_1_1([&](Result result, const ProgramInfo& info) {
         _hidl_cb(result, info.base);
     });
 }
 
-Return<void> Tuner::getProgramInformation_1_1(getProgramInformation_1_1_cb _hidl_cb)  {
-    int rc;
-    radio_program_info_t halInfo;
-    RadioMetadataWrapper metadataWrapper(&halInfo.metadata);
-    ProgramInfo info;
+Return<void> Tuner::getProgramInformation_1_1(getProgramInformation_1_1_cb _hidl_cb) {
+    ALOGV("%s", __func__);
+    lock_guard<mutex> lk(mMut);
 
-    ALOGV("%s", __FUNCTION__);
-    if (mHalTuner == NULL) {
-        rc = -ENODEV;
-        goto exit;
+    if (mIsClosed) {
+        _hidl_cb(Result::NOT_INITIALIZED, {});
+    } else if (mIsTuneCompleted) {
+        _hidl_cb(Result::OK, mCurrentProgramInfo);
+    } else {
+        _hidl_cb(Result::NOT_INITIALIZED, makeDummyProgramInfo(mCurrentProgram));
     }
-
-    rc = mHalTuner->get_program_information(mHalTuner, &halInfo);
-    if (rc == 0) {
-        Utils::convertProgramInfoFromHal(&info, &halInfo);
-    }
-
-exit:
-    _hidl_cb(Utils::convertHalResult(rc), info);
-    return Void();
+    return {};
 }
 
 Return<ProgramListResult> Tuner::startBackgroundScan() {
+    ALOGV("%s", __func__);
+    lock_guard<mutex> lk(mMut);
+    if (mIsClosed) return ProgramListResult::NOT_INITIALIZED;
+
     return ProgramListResult::UNAVAILABLE;
 }
 
-Return<void> Tuner::getProgramList(const hidl_string& filter __unused, getProgramList_cb _hidl_cb) {
-    hidl_vec<ProgramInfo> pList;
-    // TODO(b/34054813): do the actual implementation.
-    _hidl_cb(ProgramListResult::NOT_STARTED, pList);
-    return Void();
+Return<void> Tuner::getProgramList(const hidl_vec<VendorKeyValue>& vendorFilter,
+                                   getProgramList_cb _hidl_cb) {
+    ALOGV("%s(%s)", __func__, toString(vendorFilter).substr(0, 100).c_str());
+    lock_guard<mutex> lk(mMut);
+    if (mIsClosed) {
+        _hidl_cb(ProgramListResult::NOT_INITIALIZED, {});
+        return {};
+    }
+
+    auto list = mVirtualRadio.get().getProgramList();
+    ALOGD("returning a list of %zu programs", list.size());
+    _hidl_cb(ProgramListResult::OK, getProgramInfoVector(list, getHalRev()));
+    return {};
+}
+
+Return<Result> Tuner::setAnalogForced(bool isForced) {
+    ALOGV("%s", __func__);
+    lock_guard<mutex> lk(mMut);
+    if (mIsClosed) return Result::NOT_INITIALIZED;
+
+    mIsAnalogForced = isForced;
+    return Result::OK;
 }
 
 Return<void> Tuner::isAnalogForced(isAnalogForced_cb _hidl_cb) {
-    // TODO(b/34348946): do the actual implementation.
-    _hidl_cb(Result::INVALID_STATE, false);
-    return Void();
+    ALOGV("%s", __func__);
+    lock_guard<mutex> lk(mMut);
+
+    if (mIsClosed) {
+        _hidl_cb(Result::NOT_INITIALIZED, false);
+    } else {
+        _hidl_cb(Result::OK, mIsAnalogForced);
+    }
+    return {};
 }
 
-Return<Result> Tuner::setAnalogForced(bool isForced __unused) {
-    // TODO(b/34348946): do the actual implementation.
-    return Result::INVALID_STATE;
-}
-
-} // namespace implementation
+}  // namespace implementation
 }  // namespace V1_1
 }  // namespace broadcastradio
 }  // namespace hardware
diff --git a/broadcastradio/1.1/default/Tuner.h b/broadcastradio/1.1/default/Tuner.h
index 57eafd3..07d3189 100644
--- a/broadcastradio/1.1/default/Tuner.h
+++ b/broadcastradio/1.1/default/Tuner.h
@@ -16,8 +16,11 @@
 #ifndef ANDROID_HARDWARE_BROADCASTRADIO_V1_1_TUNER_H
 #define ANDROID_HARDWARE_BROADCASTRADIO_V1_1_TUNER_H
 
+#include "VirtualRadio.h"
+
 #include <android/hardware/broadcastradio/1.1/ITuner.h>
 #include <android/hardware/broadcastradio/1.1/ITunerCallback.h>
+#include <broadcastradio-utils/WorkerThread.h>
 
 namespace android {
 namespace hardware {
@@ -25,43 +28,48 @@
 namespace V1_1 {
 namespace implementation {
 
-using V1_0::Direction;
-
-struct BroadcastRadio;
-
 struct Tuner : public ITuner {
+    Tuner(V1_0::Class classId, const sp<V1_0::ITunerCallback>& callback);
 
-    Tuner(const sp<V1_0::ITunerCallback>& callback, const wp<BroadcastRadio>& mParentDevice);
+    void forceClose();
 
-    // Methods from ::android::hardware::broadcastradio::V1_1::ITuner follow.
-    Return<Result> setConfiguration(const BandConfig& config) override;
-    Return<void> getConfiguration(getConfiguration_cb _hidl_cb) override;
-    Return<Result> scan(Direction direction, bool skipSubChannel) override;
-    Return<Result> step(Direction direction, bool skipSubChannel) override;
-    Return<Result> tune(uint32_t channel, uint32_t subChannel) override;
-    Return<Result> cancel() override;
-    Return<void> getProgramInformation(getProgramInformation_cb _hidl_cb) override;
-    Return<void> getProgramInformation_1_1(getProgramInformation_1_1_cb _hidl_cb) override;
-    Return<ProgramListResult> startBackgroundScan() override;
-    Return<void> getProgramList(const hidl_string& filter, getProgramList_cb _hidl_cb) override;
-    Return<void> isAnalogForced(isAnalogForced_cb _hidl_cb) override;
-    Return<Result> setAnalogForced(bool isForced) override;
+    // V1_1::ITuner methods
+    virtual Return<Result> setConfiguration(const V1_0::BandConfig& config) override;
+    virtual Return<void> getConfiguration(getConfiguration_cb _hidl_cb) override;
+    virtual Return<Result> scan(V1_0::Direction direction, bool skipSubChannel) override;
+    virtual Return<Result> step(V1_0::Direction direction, bool skipSubChannel) override;
+    virtual Return<Result> tune(uint32_t channel, uint32_t subChannel) override;
+    virtual Return<Result> tuneByProgramSelector(const ProgramSelector& program) override;
+    virtual Return<Result> cancel() override;
+    virtual Return<Result> cancelAnnouncement() override;
+    virtual Return<void> getProgramInformation(getProgramInformation_cb _hidl_cb) override;
+    virtual Return<void> getProgramInformation_1_1(getProgramInformation_1_1_cb _hidl_cb) override;
+    virtual Return<ProgramListResult> startBackgroundScan() override;
+    virtual Return<void> getProgramList(const hidl_vec<VendorKeyValue>& filter,
+                                        getProgramList_cb _hidl_cb) override;
+    virtual Return<Result> setAnalogForced(bool isForced) override;
+    virtual Return<void> isAnalogForced(isAnalogForced_cb _hidl_cb) override;
 
-    static void callback(radio_hal_event_t *halEvent, void *cookie);
-    void onCallback(radio_hal_event_t *halEvent);
+   private:
+    std::mutex mMut;
+    WorkerThread mThread;
+    bool mIsClosed = false;
 
-    void setHalTuner(const struct radio_tuner *halTuner) { mHalTuner = halTuner; }
-    const struct radio_tuner *getHalTuner() { return mHalTuner; }
-
-private:
-    ~Tuner();
-
-    const struct radio_tuner *mHalTuner;
+    V1_0::Class mClassId;
     const sp<V1_0::ITunerCallback> mCallback;
     const sp<V1_1::ITunerCallback> mCallback1_1;
-    const wp<BroadcastRadio> mParentDevice;
-};
 
+    std::reference_wrapper<VirtualRadio> mVirtualRadio;
+    bool mIsAmfmConfigSet = false;
+    V1_0::BandConfig mAmfmConfig;
+    bool mIsTuneCompleted = false;
+    ProgramSelector mCurrentProgram = {};
+    ProgramInfo mCurrentProgramInfo = {};
+    std::atomic<bool> mIsAnalogForced;
+
+    utils::HalRevision getHalRev() const;
+    void tuneInternalLocked(const ProgramSelector& sel);
+};
 
 }  // namespace implementation
 }  // namespace V1_1
diff --git a/broadcastradio/1.1/default/Utils.cpp b/broadcastradio/1.1/default/Utils.cpp
deleted file mode 100644
index e21344e..0000000
--- a/broadcastradio/1.1/default/Utils.cpp
+++ /dev/null
@@ -1,299 +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.
- */
-#define LOG_TAG "BroadcastRadioHalUtils"
-//#define LOG_NDEBUG 0
-
-#include <log/log.h>
-#include <system/radio_metadata.h>
-
-#include "Utils.h"
-
-namespace android {
-namespace hardware {
-namespace broadcastradio {
-namespace V1_1 {
-namespace implementation {
-
-using V1_0::Band;
-using V1_0::Deemphasis;
-using V1_0::Direction;
-using V1_0::MetadataKey;
-using V1_0::MetadataType;
-using V1_0::Rds;
-
-const char *Utils::sClassModuleNames[] = {
-    RADIO_HARDWARE_MODULE_ID_FM, /* corresponds to RADIO_CLASS_AM_FM */
-    RADIO_HARDWARE_MODULE_ID_SAT,  /* corresponds to RADIO_CLASS_SAT */
-    RADIO_HARDWARE_MODULE_ID_DT,   /* corresponds to RADIO_CLASS_DT */
-};
-
-// make sure HIDL enum values are aligned with legacy values
-static_assert(RADIO_CLASS_AM_FM == static_cast<int>(Class::AM_FM),
-        "AM/FM class mismatch with legacy");
-static_assert(RADIO_CLASS_SAT == static_cast<int>(Class::SAT),
-        "SAT class mismatch with legacy");
-static_assert(RADIO_CLASS_DT == static_cast<int>(Class::DT),
-        "DT class mismatch with legacy");
-
-static_assert(RADIO_BAND_AM == static_cast<int>(Band::AM),
-        "AM band mismatch with legacy");
-static_assert(RADIO_BAND_FM == static_cast<int>(Band::FM),
-        "FM band mismatch with legacy");
-static_assert(RADIO_BAND_AM_HD == static_cast<int>(Band::AM_HD),
-        "AM HD band mismatch with legacy");
-static_assert(RADIO_BAND_FM_HD == static_cast<int>(Band::FM_HD),
-        "FM HD band mismatch with legacy");
-
-static_assert(RADIO_RDS_NONE == static_cast<int>(Rds::NONE),
-        "RDS NONE mismatch with legacy");
-static_assert(RADIO_RDS_WORLD == static_cast<int>(Rds::WORLD),
-        "RDS WORLD mismatch with legacy");
-static_assert(RADIO_RDS_US == static_cast<int>(Rds::US),
-        "RDS US mismatch with legacy");
-
-static_assert(RADIO_DEEMPHASIS_50 == static_cast<int>(Deemphasis::D50),
-        "De-emphasis 50 mismatch with legacy");
-static_assert(RADIO_DEEMPHASIS_75 == static_cast<int>(Deemphasis::D75),
-        "De-emphasis 75 mismatch with legacy");
-
-static_assert(RADIO_DIRECTION_UP == static_cast<int>(Direction::UP),
-        "Direction Up mismatch with legacy");
-static_assert(RADIO_DIRECTION_DOWN == static_cast<int>(Direction::DOWN),
-        "Direction Up mismatch with legacy");
-
-static_assert(RADIO_METADATA_TYPE_INVALID == static_cast<int>(MetadataType::INVALID),
-        "Metadata type INVALID mismatch with legacy");
-static_assert(RADIO_METADATA_TYPE_INT == static_cast<int>(MetadataType::INT),
-        "Metadata type INT mismatch with legacy");
-static_assert(RADIO_METADATA_TYPE_TEXT == static_cast<int>(MetadataType::TEXT),
-        "Metadata type TEXT mismatch with legacy");
-static_assert(RADIO_METADATA_TYPE_RAW == static_cast<int>(MetadataType::RAW),
-        "Metadata type RAW mismatch with legacy");
-static_assert(RADIO_METADATA_TYPE_CLOCK == static_cast<int>(MetadataType::CLOCK),
-        "Metadata type CLOCK mismatch with legacy");
-
-static_assert(RADIO_METADATA_KEY_INVALID == static_cast<int>(MetadataKey::INVALID),
-        "Metadata key INVALID mismatch with legacy");
-static_assert(RADIO_METADATA_KEY_RDS_PI == static_cast<int>(MetadataKey::RDS_PI),
-        "Metadata key RDS_PI mismatch with legacy");
-static_assert(RADIO_METADATA_KEY_RDS_PS == static_cast<int>(MetadataKey::RDS_PS),
-        "Metadata key RDS_PS mismatch with legacy");
-static_assert(RADIO_METADATA_KEY_RDS_PTY == static_cast<int>(MetadataKey::RDS_PTY),
-        "Metadata key RDS_PTY mismatch with legacy");
-static_assert(RADIO_METADATA_KEY_RBDS_PTY == static_cast<int>(MetadataKey::RBDS_PTY),
-        "Metadata key RBDS_PTY mismatch with legacy");
-static_assert(RADIO_METADATA_KEY_RDS_RT == static_cast<int>(MetadataKey::RDS_RT),
-        "Metadata key RDS_RT mismatch with legacy");
-static_assert(RADIO_METADATA_KEY_TITLE == static_cast<int>(MetadataKey::TITLE),
-        "Metadata key TITLE mismatch with legacy");
-static_assert(RADIO_METADATA_KEY_ARTIST == static_cast<int>(MetadataKey::ARTIST),
-        "Metadata key ARTIST mismatch with legacy");
-static_assert(RADIO_METADATA_KEY_ALBUM == static_cast<int>(MetadataKey::ALBUM),
-        "Metadata key ALBUM mismatch with legacy");
-static_assert(RADIO_METADATA_KEY_GENRE == static_cast<int>(MetadataKey::GENRE),
-        "Metadata key GENRE mismatch with legacy");
-static_assert(RADIO_METADATA_KEY_ICON == static_cast<int>(MetadataKey::ICON),
-        "Metadata key ICON mismatch with legacy");
-static_assert(RADIO_METADATA_KEY_ART == static_cast<int>(MetadataKey::ART),
-        "Metadata key ART mismatch with legacy");
-static_assert(RADIO_METADATA_KEY_CLOCK == static_cast<int>(MetadataKey::CLOCK),
-        "Metadata key CLOCK mismatch with legacy");
-
-
-//static
-const char * Utils::getClassString(Class ClassId)
-{
-    int id = static_cast<int>(ClassId);
-
-    if ((id < 0) ||
-            (id >= NELEM(sClassModuleNames))) {
-        ALOGE("invalid class ID %d", id);
-        return NULL;
-    }
-    return sClassModuleNames[id];
-}
-
-//static
-Result Utils::convertHalResult(int rc)
-{
-    switch (rc) {
-        case 0:
-            return Result::OK;
-        case -EINVAL:
-            return Result::INVALID_ARGUMENTS;
-        case -ENOSYS:
-            return Result::INVALID_STATE;
-        case -ETIMEDOUT:
-            return Result::TIMEOUT;
-        case -ENODEV:
-        default:
-            return Result::NOT_INITIALIZED;
-    }
-}
-
-//static
-void Utils::convertBandConfigFromHal(
-        BandConfig *config,
-        const radio_hal_band_config_t *halConfig)
-{
-
-    config->type = static_cast<Band>(halConfig->type);
-    config->antennaConnected = halConfig->antenna_connected;
-    config->lowerLimit = halConfig->lower_limit;
-    config->upperLimit = halConfig->upper_limit;
-    config->spacings.setToExternal(const_cast<unsigned int *>(&halConfig->spacings[0]),
-            halConfig->num_spacings * sizeof(uint32_t));
-    // FIXME: transfer buffer ownership. should have a method for that in hidl_vec
-    config->spacings.resize(halConfig->num_spacings);
-
-    if (config->type == Band::FM) {
-        config->ext.fm.deemphasis = static_cast<Deemphasis>(halConfig->fm.deemphasis);
-        config->ext.fm.stereo = halConfig->fm.stereo;
-        config->ext.fm.rds = static_cast<Rds>(halConfig->fm.rds);
-        config->ext.fm.ta = halConfig->fm.ta;
-        config->ext.fm.af = halConfig->fm.af;
-        config->ext.fm.ea = halConfig->fm.ea;
-    } else {
-        config->ext.am.stereo = halConfig->am.stereo;
-    }
-}
-
-//static
-void Utils::convertPropertiesFromHal(Properties *properties,
-        const radio_hal_properties_t *halProperties)
-{
-    properties->classId = static_cast<Class>(halProperties->class_id);
-    properties->implementor.setToExternal(halProperties->implementor, strlen(halProperties->implementor));
-    properties->product.setToExternal(halProperties->product, strlen(halProperties->product));
-    properties->version.setToExternal(halProperties->version, strlen(halProperties->version));
-    properties->serial.setToExternal(halProperties->serial, strlen(halProperties->serial));
-    properties->numTuners = halProperties->num_tuners;
-    properties->numAudioSources = halProperties->num_audio_sources;
-    properties->supportsCapture = halProperties->supports_capture;
-
-    BandConfig *bands =
-            new BandConfig[halProperties->num_bands];
-    for (size_t i = 0; i < halProperties->num_bands; i++) {
-        convertBandConfigFromHal(&bands[i], &halProperties->bands[i]);
-    }
-    properties->bands.setToExternal(bands, halProperties->num_bands);
-    // FIXME: transfer buffer ownership. should have a method for that in hidl_vec
-    properties->bands.resize(halProperties->num_bands);
-    delete[] bands;
-}
-
-//static
-void Utils::convertBandConfigToHal(radio_hal_band_config_t *halConfig, const BandConfig *config)
-{
-    halConfig->type = static_cast<radio_band_t>(config->type);
-    halConfig->antenna_connected = config->antennaConnected;
-    halConfig->lower_limit = config->lowerLimit;
-    halConfig->upper_limit = config->upperLimit;
-    halConfig->num_spacings = config->spacings.size();
-    if (halConfig->num_spacings > RADIO_NUM_SPACINGS_MAX) {
-        halConfig->num_spacings = RADIO_NUM_SPACINGS_MAX;
-    }
-    memcpy(halConfig->spacings, config->spacings.data(),
-           sizeof(uint32_t) * halConfig->num_spacings);
-
-    if (config->type == Band::FM) {
-        halConfig->fm.deemphasis = static_cast<radio_deemphasis_t>(config->ext.fm.deemphasis);
-        halConfig->fm.stereo = config->ext.fm.stereo;
-        halConfig->fm.rds = static_cast<radio_rds_t>(config->ext.fm.rds);
-        halConfig->fm.ta = config->ext.fm.ta;
-        halConfig->fm.af = config->ext.fm.af;
-        halConfig->fm.ea = config->ext.fm.ea;
-    } else {
-        halConfig->am.stereo = config->ext.am.stereo;
-    }
-}
-
-
-//static
-void Utils::convertProgramInfoFromHal(ProgramInfo *info, radio_program_info_t *halInfo)
-{
-    auto &info_1_1 = *info;
-    auto &info_1_0 = info->base;
-
-    info_1_0.channel = halInfo->channel;
-    info_1_0.subChannel = halInfo->sub_channel;
-    info_1_0.tuned = halInfo->tuned;
-    info_1_0.stereo = halInfo->stereo;
-    info_1_0.digital = halInfo->digital;
-    info_1_0.signalStrength = halInfo->signal_strength;
-    convertMetaDataFromHal(info_1_0.metadata, halInfo->metadata);
-    // TODO(b/34348946): add support for HAL 1.1 fields
-    info_1_1.flags = 0;
-}
-
-//static
-int Utils::convertMetaDataFromHal(hidl_vec<MetaData>& metadata, radio_metadata_t *halMetadata)
-{
-    if (halMetadata == NULL) {
-        ALOGE("Invalid argument: halMetadata is NULL");
-        return 0;
-    }
-
-    int count = radio_metadata_get_count(halMetadata);
-    if (count <= 0) {
-        return count;
-    }
-    MetaData *newMetadata = new MetaData[count];
-    int outCount = 0;
-    for (int i = 0; i < count; i++) {
-        radio_metadata_key_t key;
-        radio_metadata_type_t type;
-        void *value;
-        size_t size;
-        if (radio_metadata_get_at_index(halMetadata, i , &key, &type, &value, &size) != 0 ||
-                size == 0) {
-            continue;
-        }
-        switch (type) {
-            case RADIO_METADATA_TYPE_INT: {
-                newMetadata[outCount].intValue = *(static_cast<int32_t *>(value));
-            } break;
-            case RADIO_METADATA_TYPE_TEXT: {
-                newMetadata[outCount].stringValue = static_cast<char *>(value);
-            } break;
-            case RADIO_METADATA_TYPE_RAW: {
-                newMetadata[outCount].rawValue.setToExternal(static_cast<uint8_t *>(value), size);
-                // FIXME: transfer buffer ownership. should have a method for that in hidl_vec
-                newMetadata[outCount].rawValue.resize(size);
-            } break;
-            case RADIO_METADATA_TYPE_CLOCK: {
-                radio_metadata_clock_t *clock = static_cast<radio_metadata_clock_t *>(value);
-                newMetadata[outCount].clockValue.utcSecondsSinceEpoch =
-                        clock->utc_seconds_since_epoch;
-                newMetadata[outCount].clockValue.timezoneOffsetInMinutes =
-                        clock->timezone_offset_in_minutes;
-            } break;
-        }
-        newMetadata[outCount].type = static_cast<MetadataType>(type);
-        newMetadata[outCount].key = static_cast<MetadataKey>(key);
-        outCount++;
-    }
-    metadata.setToExternal(newMetadata, outCount);
-    // FIXME: transfer buffer ownership. should have a method for that in hidl_vec
-    metadata.resize(outCount);
-    return outCount;
-}
-
-}  // namespace implementation
-}  // namespace V1_1
-}  // namespace broadcastradio
-}  // namespace hardware
-}  // namespace android
diff --git a/broadcastradio/1.1/default/Utils.h b/broadcastradio/1.1/default/Utils.h
deleted file mode 100644
index 22902ba..0000000
--- a/broadcastradio/1.1/default/Utils.h
+++ /dev/null
@@ -1,58 +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.
- */
-#ifndef ANDROID_HARDWARE_BROADCASTRADIO_V1_1_UTILS_H
-#define ANDROID_HARDWARE_BROADCASTRADIO_V1_1_UTILS_H
-
-#include <android/hardware/broadcastradio/1.1/types.h>
-#include <hardware/radio.h>
-
-namespace android {
-namespace hardware {
-namespace broadcastradio {
-namespace V1_1 {
-namespace implementation {
-
-using V1_0::Class;
-using V1_0::BandConfig;
-using V1_0::MetaData;
-using V1_0::Properties;
-
-class Utils {
-public:
-    static const char * getClassString(Class ClassId);
-    static Result convertHalResult(int rc);
-    static void convertBandConfigFromHal(BandConfig *config,
-            const radio_hal_band_config_t *halConfig);
-    static void convertPropertiesFromHal(Properties *properties,
-            const radio_hal_properties_t *halProperties);
-    static void convertBandConfigToHal(radio_hal_band_config_t *halConfig,
-            const BandConfig *config);
-    static void convertProgramInfoFromHal(ProgramInfo *info,
-                                          radio_program_info_t *halInfo);
-    static int convertMetaDataFromHal(hidl_vec<MetaData>& metadata,
-                                       radio_metadata_t *halMetadata);
-private:
-    static const char * sClassModuleNames[];
-
-};
-
-}  // namespace implementation
-}  // namespace V1_1
-}  // namespace broadcastradio
-}  // namespace hardware
-}  // namespace android
-
-#endif  // ANDROID_HARDWARE_BROADCASTRADIO_V1_1_UTILS_H
diff --git a/broadcastradio/1.1/default/VirtualProgram.cpp b/broadcastradio/1.1/default/VirtualProgram.cpp
new file mode 100644
index 0000000..7977391
--- /dev/null
+++ b/broadcastradio/1.1/default/VirtualProgram.cpp
@@ -0,0 +1,106 @@
+/*
+ * 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.
+ */
+#include "VirtualProgram.h"
+
+#include <broadcastradio-utils/Utils.h>
+
+#include "resources.h"
+
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace V1_1 {
+namespace implementation {
+
+using std::vector;
+
+using V1_0::MetaData;
+using V1_0::MetadataKey;
+using V1_0::MetadataType;
+using utils::HalRevision;
+
+static MetaData createDemoBitmap(MetadataKey key, HalRevision halRev) {
+    MetaData bmp = {MetadataType::INT, key, resources::demoPngId, {}, {}, {}};
+    if (halRev < HalRevision::V1_1) {
+        bmp.type = MetadataType::RAW;
+        bmp.intValue = 0;
+        bmp.rawValue = hidl_vec<uint8_t>(resources::demoPng, std::end(resources::demoPng));
+    }
+    return bmp;
+}
+
+ProgramInfo VirtualProgram::getProgramInfo(HalRevision halRev) const {
+    ProgramInfo info11 = {};
+    auto& info10 = info11.base;
+
+    utils::getLegacyChannel(selector, &info10.channel, &info10.subChannel);
+    info11.selector = selector;
+    info10.tuned = true;
+    info10.stereo = true;
+    info10.digital = utils::isDigital(selector);
+    info10.signalStrength = info10.digital ? 100 : 80;
+
+    info10.metadata = hidl_vec<MetaData>({
+        {MetadataType::TEXT, MetadataKey::RDS_PS, {}, {}, programName, {}},
+        {MetadataType::TEXT, MetadataKey::TITLE, {}, {}, songTitle, {}},
+        {MetadataType::TEXT, MetadataKey::ARTIST, {}, {}, songArtist, {}},
+        createDemoBitmap(MetadataKey::ICON, halRev),
+        createDemoBitmap(MetadataKey::ART, halRev),
+    });
+
+    info11.vendorInfo = hidl_vec<VendorKeyValue>({
+        {"com.google.dummy", "dummy"},
+        {"com.google.dummy.VirtualProgram", std::to_string(reinterpret_cast<uintptr_t>(this))},
+    });
+
+    return info11;
+}
+
+// Defining order on virtual programs, how they appear on band.
+// It's mostly for default implementation purposes, may not be complete or correct.
+bool operator<(const VirtualProgram& lhs, const VirtualProgram& rhs) {
+    auto& l = lhs.selector;
+    auto& r = rhs.selector;
+
+    // Two programs with the same primaryId is considered the same.
+    if (l.programType != r.programType) return l.programType < r.programType;
+    if (l.primaryId.type != r.primaryId.type) return l.primaryId.type < r.primaryId.type;
+    if (l.primaryId.value != r.primaryId.value) return l.primaryId.value < r.primaryId.value;
+
+    // A little exception for HD Radio subchannel - we check secondary ID too.
+    if (utils::hasId(l, IdentifierType::HD_SUBCHANNEL) &&
+        utils::hasId(r, IdentifierType::HD_SUBCHANNEL)) {
+        return utils::getId(l, IdentifierType::HD_SUBCHANNEL) <
+               utils::getId(r, IdentifierType::HD_SUBCHANNEL);
+    }
+
+    return false;
+}
+
+vector<ProgramInfo> getProgramInfoVector(const vector<VirtualProgram>& vec, HalRevision halRev) {
+    vector<ProgramInfo> out;
+    out.reserve(vec.size());
+    for (auto&& program : vec) {
+        out.push_back(program.getProgramInfo(halRev));
+    }
+    return out;
+}
+
+}  // namespace implementation
+}  // namespace V1_1
+}  // namespace broadcastradio
+}  // namespace hardware
+}  // namespace android
diff --git a/broadcastradio/1.1/default/VirtualProgram.h b/broadcastradio/1.1/default/VirtualProgram.h
new file mode 100644
index 0000000..a14830d
--- /dev/null
+++ b/broadcastradio/1.1/default/VirtualProgram.h
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+#ifndef ANDROID_HARDWARE_BROADCASTRADIO_V1_1_VIRTUALPROGRAM_H
+#define ANDROID_HARDWARE_BROADCASTRADIO_V1_1_VIRTUALPROGRAM_H
+
+#include <android/hardware/broadcastradio/1.1/types.h>
+#include <broadcastradio-utils/Utils.h>
+
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace V1_1 {
+namespace implementation {
+
+/**
+ * A radio program mock.
+ *
+ * This represents broadcast waves flying over the air,
+ * not an entry for a captured station in the radio tuner memory.
+ */
+struct VirtualProgram {
+    ProgramSelector selector;
+
+    std::string programName = "";
+    std::string songArtist = "";
+    std::string songTitle = "";
+
+    ProgramInfo getProgramInfo(utils::HalRevision halRev) const;
+
+    friend bool operator<(const VirtualProgram& lhs, const VirtualProgram& rhs);
+};
+
+std::vector<ProgramInfo> getProgramInfoVector(const std::vector<VirtualProgram>& vec,
+                                              utils::HalRevision halRev);
+
+}  // namespace implementation
+}  // namespace V1_1
+}  // namespace broadcastradio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_BROADCASTRADIO_V1_1_VIRTUALPROGRAM_H
diff --git a/broadcastradio/1.1/default/VirtualRadio.cpp b/broadcastradio/1.1/default/VirtualRadio.cpp
new file mode 100644
index 0000000..36d47a9
--- /dev/null
+++ b/broadcastradio/1.1/default/VirtualRadio.cpp
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define LOG_TAG "BroadcastRadioDefault.VirtualRadio"
+//#define LOG_NDEBUG 0
+
+#include "VirtualRadio.h"
+
+#include <broadcastradio-utils/Utils.h>
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace V1_1 {
+namespace implementation {
+
+using V1_0::Band;
+using V1_0::Class;
+
+using std::lock_guard;
+using std::move;
+using std::mutex;
+using std::vector;
+
+using utils::make_selector;
+
+static const vector<VirtualProgram> gInitialFmPrograms{
+    {make_selector(Band::FM, 94900), "Wild 94.9", "Drake ft. Rihanna", "Too Good"},
+    {make_selector(Band::FM, 96500), "KOIT", "Celine Dion", "All By Myself"},
+    {make_selector(Band::FM, 97300), "Alice@97.3", "Drops of Jupiter", "Train"},
+    {make_selector(Band::FM, 99700), "99.7 Now!", "The Chainsmokers", "Closer"},
+    {make_selector(Band::FM, 101300), "101-3 KISS-FM", "Justin Timberlake", "Rock Your Body"},
+    {make_selector(Band::FM, 103700), "iHeart80s @ 103.7", "Michael Jackson", "Billie Jean"},
+    {make_selector(Band::FM, 106100), "106 KMEL", "Drake", "Marvins Room"},
+};
+
+static VirtualRadio gEmptyRadio({});
+static VirtualRadio gFmRadio(gInitialFmPrograms);
+
+VirtualRadio::VirtualRadio(const vector<VirtualProgram> initialList) : mPrograms(initialList) {}
+
+vector<VirtualProgram> VirtualRadio::getProgramList() {
+    lock_guard<mutex> lk(mMut);
+    return mPrograms;
+}
+
+bool VirtualRadio::getProgram(const ProgramSelector& selector, VirtualProgram& programOut) {
+    lock_guard<mutex> lk(mMut);
+    for (auto&& program : mPrograms) {
+        if (utils::tunesTo(selector, program.selector)) {
+            programOut = program;
+            return true;
+        }
+    }
+    return false;
+}
+
+VirtualRadio& getRadio(V1_0::Class classId) {
+    switch (classId) {
+        case Class::AM_FM:
+            return getFmRadio();
+        case Class::SAT:
+            return getSatRadio();
+        case Class::DT:
+            return getDigitalRadio();
+        default:
+            ALOGE("Invalid class ID");
+            return gEmptyRadio;
+    }
+}
+
+VirtualRadio& getAmRadio() {
+    return gEmptyRadio;
+}
+
+VirtualRadio& getFmRadio() {
+    return gFmRadio;
+}
+
+VirtualRadio& getSatRadio() {
+    return gEmptyRadio;
+}
+
+VirtualRadio& getDigitalRadio() {
+    return gEmptyRadio;
+}
+
+}  // namespace implementation
+}  // namespace V1_1
+}  // namespace broadcastradio
+}  // namespace hardware
+}  // namespace android
diff --git a/broadcastradio/1.1/default/VirtualRadio.h b/broadcastradio/1.1/default/VirtualRadio.h
new file mode 100644
index 0000000..3c7ae5c
--- /dev/null
+++ b/broadcastradio/1.1/default/VirtualRadio.h
@@ -0,0 +1,80 @@
+/*
+ * 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.
+ */
+#ifndef ANDROID_HARDWARE_BROADCASTRADIO_V1_1_VIRTUALRADIO_H
+#define ANDROID_HARDWARE_BROADCASTRADIO_V1_1_VIRTUALRADIO_H
+
+#include "VirtualProgram.h"
+
+#include <mutex>
+#include <vector>
+
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace V1_1 {
+namespace implementation {
+
+/**
+ * A radio frequency space mock.
+ *
+ * This represents all broadcast waves in the air for a given radio technology,
+ * not a captured station list in the radio tuner memory.
+ *
+ * It's meant to abstract out radio content from default tuner implementation.
+ */
+class VirtualRadio {
+   public:
+    VirtualRadio(const std::vector<VirtualProgram> initialList);
+
+    std::vector<VirtualProgram> getProgramList();
+    bool getProgram(const ProgramSelector& selector, VirtualProgram& program);
+
+   private:
+    std::mutex mMut;
+    std::vector<VirtualProgram> mPrograms;
+};
+
+/**
+ * Get virtual radio space for a given radio class.
+ *
+ * As a space, each virtual radio always exists. For example, DAB frequencies
+ * exists in US, but contains no programs.
+ *
+ * The lifetime of the virtual radio space is virtually infinite, but for the
+ * needs of default implementation, it's bound with the lifetime of default
+ * implementation process.
+ *
+ * Internally, it's a static object, so trying to access the reference during
+ * default implementation library unloading may result in segmentation fault.
+ * It's unlikely for testing purposes.
+ *
+ * @param classId A class of radio technology.
+ * @return A reference to virtual radio space for a given technology.
+ */
+VirtualRadio& getRadio(V1_0::Class classId);
+
+VirtualRadio& getAmRadio();
+VirtualRadio& getFmRadio();
+VirtualRadio& getSatRadio();
+VirtualRadio& getDigitalRadio();
+
+}  // namespace implementation
+}  // namespace V1_1
+}  // namespace broadcastradio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_BROADCASTRADIO_V1_1_VIRTUALRADIO_H
diff --git a/broadcastradio/1.1/default/android.hardware.broadcastradio@1.1-service.rc b/broadcastradio/1.1/default/android.hardware.broadcastradio@1.1-service.rc
new file mode 100644
index 0000000..7c57135
--- /dev/null
+++ b/broadcastradio/1.1/default/android.hardware.broadcastradio@1.1-service.rc
@@ -0,0 +1,4 @@
+service broadcastradio-hal /vendor/bin/hw/android.hardware.broadcastradio@1.1-service
+    class hal
+    user audioserver
+    group audio
diff --git a/broadcastradio/1.1/default/resources.h b/broadcastradio/1.1/default/resources.h
new file mode 100644
index 0000000..b7e709f
--- /dev/null
+++ b/broadcastradio/1.1/default/resources.h
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+#ifndef ANDROID_HARDWARE_BROADCASTRADIO_V1_1_RESOURCES_H
+#define ANDROID_HARDWARE_BROADCASTRADIO_V1_1_RESOURCES_H
+
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace V1_1 {
+namespace implementation {
+namespace resources {
+
+constexpr int32_t demoPngId = 123456;
+constexpr uint8_t demoPng[] = {
+    0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44,
+    0x52, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x08, 0x02, 0x00, 0x00, 0x00, 0x25,
+    0x0b, 0xe6, 0x89, 0x00, 0x00, 0x00, 0x5d, 0x49, 0x44, 0x41, 0x54, 0x68, 0xde, 0xed, 0xd9,
+    0xc1, 0x09, 0x00, 0x30, 0x08, 0x04, 0xc1, 0x33, 0xfd, 0xf7, 0x6c, 0x6a, 0xc8, 0x23, 0x04,
+    0xc9, 0x6c, 0x01, 0xc2, 0x20, 0xbe, 0x4c, 0x86, 0x57, 0x49, 0xba, 0xfb, 0xd6, 0xf4, 0xba,
+    0x3e, 0x7f, 0x4d, 0xdf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x8f, 0x00, 0xbd, 0xce, 0x7f,
+    0xc0, 0x11, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0xb8, 0x0d, 0x32, 0xd4, 0x0c, 0x77, 0xbd,
+    0xfb, 0xc1, 0xce, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82};
+
+}  // namespace resources
+}  // namespace implementation
+}  // namespace V1_1
+}  // namespace broadcastradio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_BROADCASTRADIO_V1_1_RESOURCES_H
diff --git a/broadcastradio/1.1/default/service.cpp b/broadcastradio/1.1/default/service.cpp
new file mode 100644
index 0000000..f8af0b7
--- /dev/null
+++ b/broadcastradio/1.1/default/service.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define LOG_TAG "BroadcastRadioDefault.service"
+
+#include <android-base/logging.h>
+#include <hidl/HidlTransportSupport.h>
+
+#include "BroadcastRadioFactory.h"
+
+using android::hardware::configureRpcThreadpool;
+using android::hardware::joinRpcThreadpool;
+using android::hardware::broadcastradio::V1_1::implementation::BroadcastRadioFactory;
+
+int main(int /* argc */, char** /* argv */) {
+    configureRpcThreadpool(4, true);
+
+    BroadcastRadioFactory broadcastRadioFactory;
+    auto status = broadcastRadioFactory.registerAsService();
+    CHECK_EQ(status, android::OK) << "Failed to register Broadcast Radio HAL implementation";
+
+    joinRpcThreadpool();
+    return 1;  // joinRpcThreadpool shouldn't exit
+}
diff --git a/broadcastradio/1.1/tests/Android.bp b/broadcastradio/1.1/tests/Android.bp
new file mode 100644
index 0000000..fa1fd94
--- /dev/null
+++ b/broadcastradio/1.1/tests/Android.bp
@@ -0,0 +1,29 @@
+//
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_test {
+    name: "android.hardware.broadcastradio@1.1-utils-tests",
+    vendor: true,
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+    ],
+    srcs: [
+        "WorkerThread_test.cpp",
+    ],
+    static_libs: ["android.hardware.broadcastradio@1.1-utils-lib"],
+}
diff --git a/broadcastradio/1.1/tests/OWNERS b/broadcastradio/1.1/tests/OWNERS
new file mode 100644
index 0000000..aa5ce82
--- /dev/null
+++ b/broadcastradio/1.1/tests/OWNERS
@@ -0,0 +1,8 @@
+# Automotive team
+egranata@google.com
+keunyoung@google.com
+twasilczyk@google.com
+
+# VTS team
+ryanjcampbell@google.com
+yim@google.com
diff --git a/broadcastradio/1.1/tests/WorkerThread_test.cpp b/broadcastradio/1.1/tests/WorkerThread_test.cpp
new file mode 100644
index 0000000..ed36de3
--- /dev/null
+++ b/broadcastradio/1.1/tests/WorkerThread_test.cpp
@@ -0,0 +1,138 @@
+/*
+ * 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.
+ */
+
+#include <broadcastradio-utils/WorkerThread.h>
+#include <gtest/gtest.h>
+
+namespace {
+
+using namespace std::chrono_literals;
+
+using android::WorkerThread;
+
+using std::atomic;
+using std::chrono::time_point;
+using std::chrono::steady_clock;
+using std::is_sorted;
+using std::lock_guard;
+using std::mutex;
+using std::this_thread::sleep_for;
+using std::vector;
+
+#define ASSERT_EQ_WITH_TOLERANCE(val1, val2, tolerance) \
+    ASSERT_LE((val1) - (tolerance), (val2));            \
+    ASSERT_GE((val1) + (tolerance), (val2));
+
+TEST(WorkerThreadTest, oneTask) {
+    atomic<bool> executed(false);
+    atomic<time_point<steady_clock>> stop;
+    WorkerThread thread;
+
+    auto start = steady_clock::now();
+    thread.schedule(
+        [&]() {
+            stop = steady_clock::now();
+            executed = true;
+        },
+        100ms);
+
+    sleep_for(150ms);
+
+    ASSERT_TRUE(executed);
+    auto delta = stop.load() - start;
+    ASSERT_EQ_WITH_TOLERANCE(delta, 100ms, 50ms);
+}
+
+TEST(WorkerThreadTest, cancelSecond) {
+    atomic<bool> executed1(false);
+    atomic<bool> executed2(false);
+    WorkerThread thread;
+
+    thread.schedule([&]() { executed2 = true; }, 100ms);
+    thread.schedule([&]() { executed1 = true; }, 25ms);
+
+    sleep_for(50ms);
+    thread.cancelAll();
+    sleep_for(100ms);
+
+    ASSERT_TRUE(executed1);
+    ASSERT_FALSE(executed2);
+}
+
+TEST(WorkerThreadTest, executeInOrder) {
+    mutex mut;
+    vector<int> order;
+    WorkerThread thread;
+
+    thread.schedule(
+        [&]() {
+            lock_guard<mutex> lk(mut);
+            order.push_back(0);
+        },
+        50ms);
+
+    thread.schedule(
+        [&]() {
+            lock_guard<mutex> lk(mut);
+            order.push_back(4);
+        },
+        400ms);
+
+    thread.schedule(
+        [&]() {
+            lock_guard<mutex> lk(mut);
+            order.push_back(1);
+        },
+        100ms);
+
+    thread.schedule(
+        [&]() {
+            lock_guard<mutex> lk(mut);
+            order.push_back(3);
+        },
+        300ms);
+
+    thread.schedule(
+        [&]() {
+            lock_guard<mutex> lk(mut);
+            order.push_back(2);
+        },
+        200ms);
+
+    sleep_for(500ms);
+
+    ASSERT_EQ(5u, order.size());
+    ASSERT_TRUE(is_sorted(order.begin(), order.end()));
+}
+
+TEST(WorkerThreadTest, dontExecuteAfterDestruction) {
+    atomic<bool> executed1(false);
+    atomic<bool> executed2(false);
+    {
+        WorkerThread thread;
+
+        thread.schedule([&]() { executed2 = true; }, 100ms);
+        thread.schedule([&]() { executed1 = true; }, 25ms);
+
+        sleep_for(50ms);
+    }
+    sleep_for(100ms);
+
+    ASSERT_TRUE(executed1);
+    ASSERT_FALSE(executed2);
+}
+
+}  // anonymous namespace
diff --git a/broadcastradio/1.1/types.hal b/broadcastradio/1.1/types.hal
index 5577ea0..8b8fc6f 100644
--- a/broadcastradio/1.1/types.hal
+++ b/broadcastradio/1.1/types.hal
@@ -43,6 +43,35 @@
      * increasing volume too much.
      */
     MUTED = 1 << 1,
+
+    /**
+     * Station broadcasts traffic information regularly,
+     * but not necessarily right now.
+     */
+    TRAFFIC_PROGRAM = 1 << 2,
+
+    /**
+     * Station is broadcasting traffic information at the very moment.
+     */
+    TRAFFIC_ANNOUNCEMENT = 1 << 3,
+};
+
+/**
+ * A key-value pair for vendor-specific information to be passed as-is through
+ * Android framework to the front-end application.
+ */
+struct VendorKeyValue {
+    /**
+     * Key must be prefixed with unique vendor Java-style namespace,
+     * eg. 'com.somecompany.parameter1'.
+     */
+    string key;
+
+    /**
+     * Value must be passed through the framework without any changes.
+     * Format of this string can vary across vendors.
+     */
+    string value;
 };
 
 struct Properties {
@@ -55,16 +84,204 @@
     bool supportsBackgroundScanning;
 
     /**
-     * Opaque vendor-specific string, to be passed to front-end without changes.
-     * Format of this string can vary across vendors.
+     * A list of supported ProgramType values.
      *
-     * It may be used for extra features, that's not supported by a platform,
-     * for example: "preset-slots=6;ultra-hd-capable=false".
+     * If a program type is supported by radio module, it means it can tune
+     * to ProgramSelector of a given type.
      *
-     * Front-end application MUST verify vendor/product name from the
-     * @1.0::Properties struct before doing any interpretation of this value.
+     * Support for VENDOR program type does not guarantee compatibility, as
+     * other module properties (implementor, product, version) must be checked.
      */
-    string vendorExension;
+    vec<uint32_t> supportedProgramTypes;
+
+    /**
+     * A list of supported IdentifierType values.
+     *
+     * If an identifier is supported by radio module, it means it can use it for
+     * tuning to ProgramSelector with either primary or secondary Identifier of
+     * a given type.
+     *
+     * Support for VENDOR identifier type does not guarantee compatibility, as
+     * other module properties (implementor, product, version) must be checked.
+     */
+    vec<uint32_t> supportedIdentifierTypes;
+
+    /**
+     * Vendor-specific information.
+     *
+     * It may be used for extra features, not supported by the platform,
+     * for example: com.me.preset-slots=6; com.me.ultra-hd-capable=false.
+     */
+    vec<VendorKeyValue> vendorInfo;
+};
+
+/**
+ * Type of modulation.
+ *
+ * Used as a value for DRMO_MODULATION IdentifierType.
+ */
+enum Modulation : uint32_t {
+    AM = 1,
+    FM,
+};
+
+/**
+ * Type of a radio technology.
+ *
+ * VENDOR program types must be opaque to the framework.
+ *
+ * There are multiple VENDOR program types just to make vendor implementation
+ * easier with multiple properitary radio technologies. They are treated the
+ * same by the framework.
+ *
+ * All other values are reserved for future use.
+ * Values not matching any enumerated constant must be ignored.
+ */
+enum ProgramType : uint32_t {
+    AM = 1,  // analogue AM radio (with or without RDS)
+    FM,      // analogue FM radio (with or without RDS)
+    AM_HD,   // AM HD Radio
+    FM_HD,   // FM HD Radio
+    DAB,     // Digital audio broadcasting
+    DRMO,    // Digital Radio Mondiale
+    SXM,     // SiriusXM Satellite Radio
+
+    // Vendor-specific, not synced across devices.
+    VENDOR_START = 1000,
+    VENDOR_END = 1999,
+};
+
+/**
+ * Type of program identifier component.
+ *
+ * It MUST match the radio technology for primary ID but does not have to match
+ * it for secondary IDs. For example, a satellite program may set AM/FM fallback
+ * frequency, if a station broadcasts both via satellite and AM/FM.
+ *
+ * VENDOR identifier types must be opaque to the framework.
+ *
+ * The value format for each (but VENDOR_PRIMARY) identifier is strictly defined
+ * to maintain interoperability between devices made by different vendors.
+ *
+ * All other values are reserved for future use.
+ * Values not matching any enumerated constant must be ignored.
+ */
+enum IdentifierType : uint32_t {
+    AMFM_FREQUENCY = 1,  // kHz
+    RDS_PI,              // 16bit
+
+    /**
+     * 64bit compound primary identifier for HD Radio.
+     *
+     * Consists of (from the LSB):
+     * - 32bit: Station ID number;
+     * - 4bit: HD_SUBCHANNEL;
+     * - 18bit: AMFM_FREQUENCY.
+     * The remaining bits should be set to zeros when writing on the chip side
+     * and ignored when read.
+     */
+    HD_STATION_ID_EXT,
+
+    /**
+     * HD Radio subchannel - a value of range 0-7.
+     *
+     * The subchannel index is 0-based (where 0 is MPS and 1..7 are SPS),
+     * as opposed to HD Radio standard (where it's 1-based).
+     */
+    HD_SUBCHANNEL,
+
+    /**
+     * 24bit compound primary identifier for DAB.
+     *
+     * Consists of (from the LSB):
+     * - 16bit: SId;
+     * - 8bit: ECC code.
+     * The remaining bits should be set to zeros when writing on the chip side
+     * and ignored when read.
+     */
+    DAB_SIDECC,
+
+    DAB_ENSEMBLE,     // 16bit
+    DAB_SCID,         // 12bit
+    DAB_FREQUENCY,    // kHz
+    DRMO_SERVICE_ID,  // 24bit
+    DRMO_FREQUENCY,   // kHz
+    DRMO_MODULATION,  // Modulation enum
+    SXM_SERVICE_ID,   // 32bit
+    SXM_CHANNEL,      // 0-999 range
+
+    /**
+     * Primary identifier for vendor-specific radio technology.
+     * The value format is determined by a vendor.
+     *
+     * It must not be used in any other programType than corresponding VENDOR
+     * type between VENDOR_START and VENDOR_END (eg. identifier type 1015 must
+     * not be used in any program type other than 1015).
+     */
+    VENDOR_PRIMARY_START = ProgramType:VENDOR_START,
+    VENDOR_PRIMARY_END = ProgramType:VENDOR_END,
+};
+
+/**
+ * A single program identifier component, eg. frequency or channel ID.
+ *
+ * The uint32_t type field maps to IdentifierType enum. It's not straight,
+ * because the enum may be extended in future versions of the HAL. Values out of
+ * the enum range must not be used when writing and ignored when reading.
+ *
+ * The uint64_t value field holds the value in format described in comments for
+ * IdentifierType enum.
+ */
+struct ProgramIdentifier {
+    uint32_t type;  // IdentifierType
+    uint64_t value;
+};
+
+/**
+ * A set of identifiers necessary to tune to a given station.
+ *
+ * This can hold various identifiers, like
+ * - AM/FM frequency
+ * - HD Radio subchannel
+ * - DAB channel info
+ *
+ * The uint32_t programType field maps to ProgramType enum. It's not straight,
+ * because the enum may be extended in future versions of the HAL. Values out of
+ * the enum range must not be used when writing and ignored when reading.
+ *
+ * The primary ID uniquely identifies a station and can be used for equality
+ * check. The secondary IDs are supplementary and can speed up tuning process,
+ * but the primary ID is sufficient (ie. after a full band scan).
+ *
+ * Two selectors with different secondary IDs, but the same primary ID are
+ * considered equal. In particular, secondary IDs vector may get updated for
+ * an entry on the program list (ie. when a better frequency for a given
+ * station is found).
+ *
+ * The primaryId of a given programType MUST be of a specific type:
+ * - AM, FM: RDS_PI if the station broadcasts RDS, AMFM_FREQUENCY otherwise;
+ * - AM_HD, FM_HD: HD_STATION_ID_EXT;
+ * - DAB: DAB_SIDECC;
+ * - DRMO: DRMO_SERVICE_ID;
+ * - SXM: SXM_SERVICE_ID;
+ * - VENDOR: VENDOR_PRIMARY.
+ */
+struct ProgramSelector {
+    uint32_t programType;  // ProgramType
+    ProgramIdentifier primaryId;  // uniquely identifies a station
+    vec<ProgramIdentifier> secondaryIds;
+
+    /**
+     * Opaque vendor-specific identifiers, to be passed to front-end
+     * without changes.
+     *
+     * The order is meaningful, ie. the first element may be defined as
+     * frequency, second as the subchannel etc.
+     *
+     * The vector is not serialized (either locally or to the cloud),
+     * unless it's a VENDOR program type.
+     */
+    vec<uint64_t> vendorIds;
 };
 
 /**
@@ -73,17 +290,16 @@
  */
 struct ProgramInfo {
     @1.0::ProgramInfo base;
+
+    ProgramSelector selector;
+
     bitfield<ProgramInfoFlags> flags;
 
     /**
-     * Opaque vendor-specific string, to be passed to front-end without changes.
-     * Format of this string can vary across vendors.
+     * Vendor-specific information.
      *
-     * It may be used for extra features, that's not supported by a platform,
-     * for example: "paid-service=true;bitrate=320kbps".
-     *
-     * Front-end application MUST verify vendor/product name from the
-     * @1.0::Properties struct before doing any interpretation of this value.
+     * It may be used for extra features, not supported by the platform,
+     * for example: paid-service=true; bitrate=320kbps.
      */
-    string vendorExension;
+    vec<VendorKeyValue> vendorInfo;
 };
diff --git a/broadcastradio/1.1/utils/Android.bp b/broadcastradio/1.1/utils/Android.bp
new file mode 100644
index 0000000..e80d133
--- /dev/null
+++ b/broadcastradio/1.1/utils/Android.bp
@@ -0,0 +1,34 @@
+//
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_library_static {
+    name: "android.hardware.broadcastradio@1.1-utils-lib",
+    vendor_available: true,
+    relative_install_path: "hw",
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+    ],
+    srcs: [
+        "Utils.cpp",
+        "WorkerThread.cpp",
+    ],
+    export_include_dirs: ["include"],
+    shared_libs: [
+        "android.hardware.broadcastradio@1.1",
+    ],
+}
diff --git a/broadcastradio/1.1/utils/OWNERS b/broadcastradio/1.1/utils/OWNERS
new file mode 100644
index 0000000..0c27b71
--- /dev/null
+++ b/broadcastradio/1.1/utils/OWNERS
@@ -0,0 +1,4 @@
+# Automotive team
+egranata@google.com
+keunyoung@google.com
+twasilczyk@google.com
diff --git a/broadcastradio/1.1/utils/Utils.cpp b/broadcastradio/1.1/utils/Utils.cpp
new file mode 100644
index 0000000..4dd6b13
--- /dev/null
+++ b/broadcastradio/1.1/utils/Utils.cpp
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#define LOG_TAG "BroadcastRadioDefault.utils"
+//#define LOG_NDEBUG 0
+
+#include <broadcastradio-utils/Utils.h>
+
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace V1_1 {
+namespace utils {
+
+using V1_0::Band;
+
+static bool isCompatibleProgramType(const uint32_t ia, const uint32_t ib) {
+    auto a = static_cast<ProgramType>(ia);
+    auto b = static_cast<ProgramType>(ib);
+
+    if (a == b) return true;
+    if (a == ProgramType::AM && b == ProgramType::AM_HD) return true;
+    if (a == ProgramType::AM_HD && b == ProgramType::AM) return true;
+    if (a == ProgramType::FM && b == ProgramType::FM_HD) return true;
+    if (a == ProgramType::FM_HD && b == ProgramType::FM) return true;
+    return false;
+}
+
+static bool bothHaveId(const ProgramSelector& a, const ProgramSelector& b,
+                       const IdentifierType type) {
+    return hasId(a, type) && hasId(b, type);
+}
+
+static bool anyHaveId(const ProgramSelector& a, const ProgramSelector& b,
+                      const IdentifierType type) {
+    return hasId(a, type) || hasId(b, type);
+}
+
+static bool haveEqualIds(const ProgramSelector& a, const ProgramSelector& b,
+                         const IdentifierType type) {
+    if (!bothHaveId(a, b, type)) return false;
+    /* We should check all Ids of a given type (ie. other AF),
+     * but it doesn't matter for default implementation.
+     */
+    auto aId = getId(a, type);
+    auto bId = getId(b, type);
+    return aId == bId;
+}
+
+bool tunesTo(const ProgramSelector& a, const ProgramSelector& b) {
+    if (!isCompatibleProgramType(a.programType, b.programType)) return false;
+
+    auto type = getType(a);
+
+    switch (type) {
+        case ProgramType::AM:
+        case ProgramType::AM_HD:
+        case ProgramType::FM:
+        case ProgramType::FM_HD:
+            if (haveEqualIds(a, b, IdentifierType::HD_STATION_ID_EXT)) return true;
+
+            // if HD Radio subchannel is specified, it must match
+            if (anyHaveId(a, b, IdentifierType::HD_SUBCHANNEL)) {
+                // missing subchannel (analog) is an equivalent of first subchannel (MPS)
+                auto aCh = getId(a, IdentifierType::HD_SUBCHANNEL, 0);
+                auto bCh = getId(b, IdentifierType::HD_SUBCHANNEL, 0);
+                if (aCh != bCh) return false;
+            }
+
+            if (haveEqualIds(a, b, IdentifierType::RDS_PI)) return true;
+
+            return haveEqualIds(a, b, IdentifierType::AMFM_FREQUENCY);
+        case ProgramType::DAB:
+            return haveEqualIds(a, b, IdentifierType::DAB_SIDECC);
+        case ProgramType::DRMO:
+            return haveEqualIds(a, b, IdentifierType::DRMO_SERVICE_ID);
+        case ProgramType::SXM:
+            if (anyHaveId(a, b, IdentifierType::SXM_SERVICE_ID)) {
+                return haveEqualIds(a, b, IdentifierType::SXM_SERVICE_ID);
+            }
+            return haveEqualIds(a, b, IdentifierType::SXM_CHANNEL);
+        default:  // includes all vendor types
+            ALOGW("Unsupported program type: %s", toString(type).c_str());
+            return false;
+    }
+}
+
+ProgramType getType(const ProgramSelector& sel) {
+    return static_cast<ProgramType>(sel.programType);
+}
+
+bool isAmFm(const ProgramType type) {
+    switch (type) {
+        case ProgramType::AM:
+        case ProgramType::FM:
+        case ProgramType::AM_HD:
+        case ProgramType::FM_HD:
+            return true;
+        default:
+            return false;
+    }
+}
+
+bool isAm(const Band band) {
+    return band == Band::AM || band == Band::AM_HD;
+}
+
+bool isFm(const Band band) {
+    return band == Band::FM || band == Band::FM_HD;
+}
+
+bool hasId(const ProgramSelector& sel, const IdentifierType type) {
+    auto itype = static_cast<uint32_t>(type);
+    if (sel.primaryId.type == itype) return true;
+    // not optimal, but we don't care in default impl
+    for (auto&& id : sel.secondaryIds) {
+        if (id.type == itype) return true;
+    }
+    return false;
+}
+
+uint64_t getId(const ProgramSelector& sel, const IdentifierType type) {
+    auto itype = static_cast<uint32_t>(type);
+    if (sel.primaryId.type == itype) return sel.primaryId.value;
+    // not optimal, but we don't care in default impl
+    for (auto&& id : sel.secondaryIds) {
+        if (id.type == itype) return id.value;
+    }
+    ALOGW("Identifier %s not found", toString(type).c_str());
+    return 0;
+}
+
+uint64_t getId(const ProgramSelector& sel, const IdentifierType type, uint64_t defval) {
+    if (!hasId(sel, type)) return defval;
+    return getId(sel, type);
+}
+
+ProgramSelector make_selector(Band band, uint32_t channel, uint32_t subChannel) {
+    ProgramSelector sel = {};
+
+    ALOGW_IF((subChannel > 0) && (band == Band::AM || band == Band::FM),
+             "got subChannel for non-HD AM/FM");
+
+    // we can't use ProgramType::AM_HD or FM_HD, because we don't know HD station ID
+    ProgramType type;
+    if (isAm(band)) {
+        type = ProgramType::AM;
+    } else if (isFm(band)) {
+        type = ProgramType::FM;
+    } else {
+        LOG_ALWAYS_FATAL("Unsupported band: %s", toString(band).c_str());
+    }
+
+    sel.programType = static_cast<uint32_t>(type);
+    sel.primaryId.type = static_cast<uint32_t>(IdentifierType::AMFM_FREQUENCY);
+    sel.primaryId.value = channel;
+    if (subChannel > 0) {
+        /* stating sub channel for AM/FM channel does not give any guarantees,
+         * but we can't do much more without HD station ID
+         *
+         * The legacy APIs had 1-based subChannels, while ProgramSelector is 0-based.
+         */
+        sel.secondaryIds = hidl_vec<ProgramIdentifier>{
+            {static_cast<uint32_t>(IdentifierType::HD_SUBCHANNEL), subChannel - 1},
+        };
+    }
+
+    return sel;
+}
+
+bool getLegacyChannel(const ProgramSelector& sel, uint32_t* channelOut, uint32_t* subChannelOut) {
+    if (channelOut) *channelOut = 0;
+    if (subChannelOut) *subChannelOut = 0;
+    if (isAmFm(getType(sel))) {
+        if (channelOut) *channelOut = getId(sel, IdentifierType::AMFM_FREQUENCY);
+        if (subChannelOut && hasId(sel, IdentifierType::HD_SUBCHANNEL)) {
+            // The legacy APIs had 1-based subChannels, while ProgramSelector is 0-based.
+            *subChannelOut = getId(sel, IdentifierType::HD_SUBCHANNEL) + 1;
+        }
+        return true;
+    }
+    return false;
+}
+
+bool isDigital(const ProgramSelector& sel) {
+    switch (getType(sel)) {
+        case ProgramType::AM:
+        case ProgramType::FM:
+            return false;
+        default:
+            // VENDOR might not be digital, but it doesn't matter for default impl.
+            return true;
+    }
+}
+
+}  // namespace utils
+}  // namespace V1_1
+
+namespace V1_0 {
+
+bool operator==(const BandConfig& l, const BandConfig& r) {
+    if (l.type != r.type) return false;
+    if (l.antennaConnected != r.antennaConnected) return false;
+    if (l.lowerLimit != r.lowerLimit) return false;
+    if (l.upperLimit != r.upperLimit) return false;
+    if (l.spacings != r.spacings) return false;
+    if (V1_1::utils::isAm(l.type)) {
+        return l.ext.am == r.ext.am;
+    } else if (V1_1::utils::isFm(l.type)) {
+        return l.ext.fm == r.ext.fm;
+    } else {
+        ALOGW("Unsupported band config type: %s", toString(l.type).c_str());
+        return false;
+    }
+}
+
+}  // namespace V1_0
+}  // namespace broadcastradio
+}  // namespace hardware
+}  // namespace android
diff --git a/broadcastradio/1.1/utils/WorkerThread.cpp b/broadcastradio/1.1/utils/WorkerThread.cpp
new file mode 100644
index 0000000..bfcbb39
--- /dev/null
+++ b/broadcastradio/1.1/utils/WorkerThread.cpp
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "WorkerThread"
+//#define LOG_NDEBUG 0
+
+#include <broadcastradio-utils/WorkerThread.h>
+
+#include <log/log.h>
+
+namespace android {
+
+using std::chrono::milliseconds;
+using std::chrono::steady_clock;
+using std::function;
+using std::lock_guard;
+using std::mutex;
+using std::priority_queue;
+using std::this_thread::sleep_for;
+using std::unique_lock;
+
+bool operator<(const WorkerThread::Task& lhs, const WorkerThread::Task& rhs) {
+    return lhs.when > rhs.when;
+}
+
+WorkerThread::WorkerThread() : mIsTerminating(false), mThread(&WorkerThread::threadLoop, this) {}
+
+WorkerThread::~WorkerThread() {
+    ALOGV("%s", __func__);
+    {
+        lock_guard<mutex> lk(mMut);
+        mIsTerminating = true;
+        mCond.notify_one();
+    }
+    mThread.join();
+}
+
+void WorkerThread::schedule(function<void()> task, milliseconds delay) {
+    ALOGV("%s", __func__);
+
+    auto when = steady_clock::now() + delay;
+
+    lock_guard<mutex> lk(mMut);
+    mTasks.push(Task({when, task}));
+    mCond.notify_one();
+}
+
+void WorkerThread::cancelAll() {
+    ALOGV("%s", __func__);
+
+    lock_guard<mutex> lk(mMut);
+    priority_queue<Task>().swap(mTasks);  // empty queue
+}
+
+void WorkerThread::threadLoop() {
+    ALOGV("%s", __func__);
+    while (!mIsTerminating) {
+        unique_lock<mutex> lk(mMut);
+        if (mTasks.empty()) {
+            mCond.wait(lk);
+            continue;
+        }
+
+        auto task = mTasks.top();
+        if (task.when > steady_clock::now()) {
+            mCond.wait_until(lk, task.when);
+            continue;
+        }
+
+        mTasks.pop();
+        lk.unlock();  // what() might need to schedule another task
+        task.what();
+    }
+}
+
+}  // namespace android
diff --git a/broadcastradio/1.1/utils/include/broadcastradio-utils/Utils.h b/broadcastradio/1.1/utils/include/broadcastradio-utils/Utils.h
new file mode 100644
index 0000000..24c60ee
--- /dev/null
+++ b/broadcastradio/1.1/utils/include/broadcastradio-utils/Utils.h
@@ -0,0 +1,89 @@
+/*
+ * 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.
+ */
+#ifndef ANDROID_HARDWARE_BROADCASTRADIO_V1_1_UTILS_H
+#define ANDROID_HARDWARE_BROADCASTRADIO_V1_1_UTILS_H
+
+#include <android/hardware/broadcastradio/1.1/types.h>
+#include <chrono>
+#include <queue>
+#include <thread>
+
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace V1_1 {
+namespace utils {
+
+// TODO(b/64115813): move it out from frameworks/base/services/core/jni/BroadcastRadio/types.h
+enum class HalRevision : uint32_t {
+    V1_0 = 1,
+    V1_1,
+};
+
+/**
+ * Checks, if {@code pointer} tunes to {@channel}.
+ *
+ * For example, having a channel {AMFM_FREQUENCY = 103.3}:
+ * - selector {AMFM_FREQUENCY = 103.3, HD_SUBCHANNEL = 0} can tune to this channel;
+ * - selector {AMFM_FREQUENCY = 103.3, HD_SUBCHANNEL = 1} can't.
+ *
+ * @param pointer selector we're trying to match against channel.
+ * @param channel existing channel.
+ */
+bool tunesTo(const ProgramSelector& pointer, const ProgramSelector& channel);
+
+ProgramType getType(const ProgramSelector& sel);
+bool isAmFm(const ProgramType type);
+
+bool isAm(const V1_0::Band band);
+bool isFm(const V1_0::Band band);
+
+bool hasId(const ProgramSelector& sel, const IdentifierType type);
+
+/**
+ * Returns ID (either primary or secondary) for a given program selector.
+ *
+ * If the selector does not contain given type, returns 0 and emits a warning.
+ */
+uint64_t getId(const ProgramSelector& sel, const IdentifierType type);
+
+/**
+ * Returns ID (either primary or secondary) for a given program selector.
+ *
+ * If the selector does not contain given type, returns default value.
+ */
+uint64_t getId(const ProgramSelector& sel, const IdentifierType type, uint64_t defval);
+
+ProgramSelector make_selector(V1_0::Band band, uint32_t channel, uint32_t subChannel = 0);
+
+bool getLegacyChannel(const ProgramSelector& sel, uint32_t* channelOut, uint32_t* subChannelOut);
+
+bool isDigital(const ProgramSelector& sel);
+
+}  // namespace utils
+}  // namespace V1_1
+
+namespace V1_0 {
+
+bool operator==(const BandConfig& l, const BandConfig& r);
+
+}  // namespace V1_0
+
+}  // namespace broadcastradio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_BROADCASTRADIO_V1_1_UTILS_H
diff --git a/broadcastradio/1.1/utils/include/broadcastradio-utils/WorkerThread.h b/broadcastradio/1.1/utils/include/broadcastradio-utils/WorkerThread.h
new file mode 100644
index 0000000..635876f
--- /dev/null
+++ b/broadcastradio/1.1/utils/include/broadcastradio-utils/WorkerThread.h
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+#ifndef ANDROID_HARDWARE_BROADCASTRADIO_V1_1_WORKERTHREAD_H
+#define ANDROID_HARDWARE_BROADCASTRADIO_V1_1_WORKERTHREAD_H
+
+#include <chrono>
+#include <queue>
+#include <thread>
+
+namespace android {
+
+class WorkerThread {
+   public:
+    WorkerThread();
+    virtual ~WorkerThread();
+
+    void schedule(std::function<void()> task, std::chrono::milliseconds delay);
+    void cancelAll();
+
+   private:
+    struct Task {
+        std::chrono::time_point<std::chrono::steady_clock> when;
+        std::function<void()> what;
+    };
+    friend bool operator<(const Task& lhs, const Task& rhs);
+
+    std::atomic<bool> mIsTerminating;
+    std::mutex mMut;
+    std::condition_variable mCond;
+    std::thread mThread;
+    std::priority_queue<Task> mTasks;
+
+    void threadLoop();
+};
+
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_BROADCASTRADIO_V1_1_WORKERTHREAD_H
diff --git a/broadcastradio/1.1/vts/OWNERS b/broadcastradio/1.1/vts/OWNERS
new file mode 100644
index 0000000..aa5ce82
--- /dev/null
+++ b/broadcastradio/1.1/vts/OWNERS
@@ -0,0 +1,8 @@
+# Automotive team
+egranata@google.com
+keunyoung@google.com
+twasilczyk@google.com
+
+# VTS team
+ryanjcampbell@google.com
+yim@google.com
diff --git a/broadcastradio/1.1/vts/functional/Android.bp b/broadcastradio/1.1/vts/functional/Android.bp
index a4c0849..4b93cbc 100644
--- a/broadcastradio/1.1/vts/functional/Android.bp
+++ b/broadcastradio/1.1/vts/functional/Android.bp
@@ -16,22 +16,13 @@
 
 cc_test {
     name: "VtsHalBroadcastradioV1_1TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalBroadcastradioV1_1TargetTest.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libnativehelper",
-        "libutils",
+    static_libs: [
         "android.hardware.broadcastradio@1.0",
         "android.hardware.broadcastradio@1.1",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
+        "android.hardware.broadcastradio@1.1-utils-lib",
+        "android.hardware.broadcastradio@1.1-vts-utils-lib",
+        "libgmock",
     ],
 }
diff --git a/broadcastradio/1.1/vts/functional/VtsHalBroadcastradioV1_1TargetTest.cpp b/broadcastradio/1.1/vts/functional/VtsHalBroadcastradioV1_1TargetTest.cpp
index aa5ab54..a46378e 100644
--- a/broadcastradio/1.1/vts/functional/VtsHalBroadcastradioV1_1TargetTest.cpp
+++ b/broadcastradio/1.1/vts/functional/VtsHalBroadcastradioV1_1TargetTest.cpp
@@ -14,463 +14,527 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "BroadcastRadioHidlHalTest"
-#include <VtsHalHidlTargetTestBase.h>
-#include <android-base/logging.h>
-#include <cutils/native_handle.h>
-#include <cutils/properties.h>
-#include <hidl/HidlTransportSupport.h>
-#include <utils/threads.h>
+#define LOG_TAG "broadcastradio.vts"
 
+#include <VtsHalHidlTargetTestBase.h>
+#include <android/hardware/broadcastradio/1.1/IBroadcastRadio.h>
 #include <android/hardware/broadcastradio/1.1/IBroadcastRadioFactory.h>
-#include <android/hardware/broadcastradio/1.0/IBroadcastRadio.h>
 #include <android/hardware/broadcastradio/1.1/ITuner.h>
 #include <android/hardware/broadcastradio/1.1/ITunerCallback.h>
 #include <android/hardware/broadcastradio/1.1/types.h>
+#include <android-base/logging.h>
+#include <broadcastradio-utils/Utils.h>
+#include <broadcastradio-vts-utils/call-barrier.h>
+#include <broadcastradio-vts-utils/mock-timeout.h>
+#include <cutils/native_handle.h>
+#include <cutils/properties.h>
+#include <gmock/gmock.h>
+#include <hidl/HidlTransportSupport.h>
+#include <utils/threads.h>
 
+#include <chrono>
 
-namespace V1_0 = ::android::hardware::broadcastradio::V1_0;
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace V1_1 {
+namespace vts {
 
-using ::android::sp;
-using ::android::Mutex;
-using ::android::Condition;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-using ::android::hardware::broadcastradio::V1_0::BandConfig;
-using ::android::hardware::broadcastradio::V1_0::Class;
-using ::android::hardware::broadcastradio::V1_0::Direction;
-using ::android::hardware::broadcastradio::V1_0::IBroadcastRadio;
-using ::android::hardware::broadcastradio::V1_0::MetaData;
-using ::android::hardware::broadcastradio::V1_0::Properties;
-using ::android::hardware::broadcastradio::V1_1::IBroadcastRadioFactory;
-using ::android::hardware::broadcastradio::V1_1::ITuner;
-using ::android::hardware::broadcastradio::V1_1::ITunerCallback;
-using ::android::hardware::broadcastradio::V1_1::ProgramInfo;
-using ::android::hardware::broadcastradio::V1_1::Result;
-using ::android::hardware::broadcastradio::V1_1::ProgramListResult;
+using namespace std::chrono_literals;
 
+using testing::_;
+using testing::AnyNumber;
+using testing::ByMove;
+using testing::DoAll;
+using testing::Invoke;
+using testing::SaveArg;
 
-// The main test class for Broadcast Radio HIDL HAL.
+using broadcastradio::vts::CallBarrier;
+using V1_0::BandConfig;
+using V1_0::Class;
+using V1_0::MetaData;
+using V1_0::MetadataKey;
+using V1_0::MetadataType;
 
-class BroadcastRadioHidlTest : public ::testing::VtsHalHidlTargetTestBase {
- protected:
-    virtual void SetUp() override {
-        auto factory = ::testing::VtsHalHidlTargetTestBase::getService<IBroadcastRadioFactory>();
-        if (factory != 0) {
-            factory->connectModule(Class::AM_FM,
-                             [&](Result retval, const ::android::sp<IBroadcastRadio>& result) {
-                if (retval == Result::OK) {
-                  mRadio = IBroadcastRadio::castFrom(result);
-                }
-            });
-        }
-        mTunerCallback = new MyCallback(this);
-        ASSERT_NE(nullptr, mRadio.get());
-        ASSERT_NE(nullptr, mTunerCallback.get());
-    }
+using std::chrono::steady_clock;
+using std::this_thread::sleep_for;
 
-    virtual void TearDown() override {
-        mTuner.clear();
-        mRadio.clear();
-    }
+static constexpr auto kConfigTimeout = 10s;
+static constexpr auto kConnectModuleTimeout = 1s;
+static constexpr auto kTuneTimeout = 30s;
+static constexpr auto kEventPropagationTimeout = 1s;
+static constexpr auto kFullScanTimeout = 1min;
 
-    class MyCallback : public ITunerCallback {
-     public:
+static constexpr ProgramType kStandardProgramTypes[] = {
+    ProgramType::AM,  ProgramType::FM,   ProgramType::AM_HD, ProgramType::FM_HD,
+    ProgramType::DAB, ProgramType::DRMO, ProgramType::SXM};
 
-        // ITunerCallback methods (see doc in ITunerCallback.hal)
-        virtual Return<void> hardwareFailure() {
-            ALOGI("%s", __FUNCTION__);
-            mParentTest->onHwFailureCallback();
-            return Void();
-        }
-
-        virtual Return<void> configChange(Result result, const BandConfig& config __unused) {
-            ALOGI("%s result %d", __FUNCTION__, result);
-            mParentTest->onResultCallback(result);
-            return Void();
-        }
-
-        virtual Return<void> tuneComplete(Result result __unused, const V1_0::ProgramInfo& info __unused) {
-            return Void();
-        }
-
-        virtual Return<void> tuneComplete_1_1(Result result, const ProgramInfo& info __unused) {
-            ALOGI("%s result %d", __FUNCTION__, result);
-            mParentTest->onResultCallback(result);
-            return Void();
-        }
-
-        virtual Return<void> afSwitch(const V1_0::ProgramInfo& info __unused) {
-            return Void();
-        }
-
-        virtual Return<void> afSwitch_1_1(const ProgramInfo& info __unused) {
-            return Void();
-        }
-
-        virtual Return<void> antennaStateChange(bool connected) {
-            ALOGI("%s connected %d", __FUNCTION__, connected);
-            return Void();
-        }
-
-        virtual Return<void> trafficAnnouncement(bool active) {
-            ALOGI("%s active %d", __FUNCTION__, active);
-            return Void();
-        }
-
-        virtual Return<void> emergencyAnnouncement(bool active) {
-            ALOGI("%s active %d", __FUNCTION__, active);
-            return Void();
-        }
-
-        virtual Return<void> newMetadata(uint32_t channel __unused, uint32_t subChannel __unused,
-                           const ::android::hardware::hidl_vec<MetaData>& metadata __unused) {
-            ALOGI("%s", __FUNCTION__);
-            return Void();
-        }
-
-        virtual Return<void> backgroundScanAvailable(bool isAvailable __unused) {
-            return Void();
-        }
-
-        virtual Return<void> backgroundScanComplete(ProgramListResult result __unused) {
-            return Void();
-        }
-
-        virtual Return<void> programListChanged() {
-            return Void();
-        }
-
-                MyCallback(BroadcastRadioHidlTest *parentTest) : mParentTest(parentTest) {}
-
-     private:
-        // BroadcastRadioHidlTest instance to which callbacks will be notified.
-        BroadcastRadioHidlTest *mParentTest;
-    };
-
-
-    /**
-     * Method called by MyCallback when a callback with no status or boolean value is received
-     */
-    void onCallback() {
-        Mutex::Autolock _l(mLock);
-        onCallback_l();
-    }
-
-    /**
-     * Method called by MyCallback when hardwareFailure() callback is received
-     */
-    void onHwFailureCallback() {
-        Mutex::Autolock _l(mLock);
-        mHwFailure = true;
-        onCallback_l();
-    }
-
-    /**
-     * Method called by MyCallback when a callback with status is received
-     */
-    void onResultCallback(Result result) {
-        Mutex::Autolock _l(mLock);
-        mResultCallbackData = result;
-        onCallback_l();
-    }
-
-    /**
-     * Method called by MyCallback when a boolean indication is received
-     */
-    void onBoolCallback(bool result) {
-        Mutex::Autolock _l(mLock);
-        mBoolCallbackData = result;
-        onCallback_l();
-    }
-
-
-        BroadcastRadioHidlTest() :
-            mCallbackCalled(false), mBoolCallbackData(false),
-            mResultCallbackData(Result::OK), mHwFailure(false) {}
-
-    void onCallback_l() {
-        if (!mCallbackCalled) {
-            mCallbackCalled = true;
-            mCallbackCond.broadcast();
-        }
-    }
-
-
-    bool waitForCallback(nsecs_t reltime = 0) {
-        Mutex::Autolock _l(mLock);
-        nsecs_t endTime = systemTime() + reltime;
-        while (!mCallbackCalled) {
-            if (reltime == 0) {
-                mCallbackCond.wait(mLock);
-            } else {
-                nsecs_t now = systemTime();
-                if (now > endTime) {
-                    return false;
-                }
-                mCallbackCond.waitRelative(mLock, endTime - now);
-            }
-        }
-        return true;
-    }
-
-    bool getProperties();
-    bool openTuner();
-    bool checkAntenna();
-
-    static const nsecs_t kConfigCallbacktimeoutNs = seconds_to_nanoseconds(10);
-    static const nsecs_t kTuneCallbacktimeoutNs = seconds_to_nanoseconds(30);
-
-    sp<IBroadcastRadio> mRadio;
-    Properties mHalProperties;
-    sp<ITuner> mTuner;
-    sp<MyCallback> mTunerCallback;
-    Mutex mLock;
-    Condition mCallbackCond;
-    bool mCallbackCalled;
-    bool mBoolCallbackData;
-    Result mResultCallbackData;
-    bool mHwFailure;
-};
-
-// A class for test environment setup (kept since this file is a template).
-class BroadcastRadioHidlEnvironment : public ::testing::Environment {
- public:
-    virtual void SetUp() {}
-    virtual void TearDown() {}
-};
-
-bool BroadcastRadioHidlTest::getProperties()
-{
-    if (mHalProperties.bands.size() == 0) {
-        Result halResult = Result::NOT_INITIALIZED;
-        Return<void> hidlReturn =
-                mRadio->getProperties([&](Result result, const Properties& properties) {
-                        halResult = result;
-                        if (result == Result::OK) {
-                            mHalProperties = properties;
-                        }
-                    });
-
-        EXPECT_TRUE(hidlReturn.isOk());
-        EXPECT_EQ(Result::OK, halResult);
-        EXPECT_EQ(Class::AM_FM, mHalProperties.classId);
-        EXPECT_GT(mHalProperties.numTuners, 0u);
-        EXPECT_GT(mHalProperties.bands.size(), 0u);
-    }
-    return mHalProperties.bands.size() > 0;
+static void printSkipped(std::string msg) {
+    std::cout << "[  SKIPPED ] " << msg << std::endl;
 }
 
-bool BroadcastRadioHidlTest::openTuner()
-{
-    if (!getProperties()) {
-        return false;
+struct TunerCallbackMock : public ITunerCallback {
+    TunerCallbackMock() { EXPECT_CALL(*this, hardwareFailure()).Times(0); }
+
+    MOCK_METHOD0(hardwareFailure, Return<void>());
+    MOCK_TIMEOUT_METHOD2(configChange, Return<void>(Result, const BandConfig&));
+    MOCK_METHOD2(tuneComplete, Return<void>(Result, const V1_0::ProgramInfo&));
+    MOCK_TIMEOUT_METHOD2(tuneComplete_1_1, Return<void>(Result, const ProgramSelector&));
+    MOCK_METHOD1(afSwitch, Return<void>(const V1_0::ProgramInfo&));
+    MOCK_METHOD1(antennaStateChange, Return<void>(bool connected));
+    MOCK_METHOD1(trafficAnnouncement, Return<void>(bool active));
+    MOCK_METHOD1(emergencyAnnouncement, Return<void>(bool active));
+    MOCK_METHOD3(newMetadata, Return<void>(uint32_t ch, uint32_t subCh, const hidl_vec<MetaData>&));
+    MOCK_METHOD1(backgroundScanAvailable, Return<void>(bool));
+    MOCK_TIMEOUT_METHOD1(backgroundScanComplete, Return<void>(ProgramListResult));
+    MOCK_METHOD0(programListChanged, Return<void>());
+    MOCK_TIMEOUT_METHOD1(currentProgramInfoChanged, Return<void>(const ProgramInfo&));
+};
+
+class BroadcastRadioHalTest : public ::testing::VtsHalHidlTargetTestBase,
+                              public ::testing::WithParamInterface<Class> {
+   protected:
+    virtual void SetUp() override;
+    virtual void TearDown() override;
+
+    bool openTuner();
+    bool nextBand();
+    bool getProgramList(std::function<void(const hidl_vec<ProgramInfo>& list)> cb);
+
+    Class radioClass;
+    bool skipped = false;
+
+    sp<IBroadcastRadio> mRadioModule;
+    sp<ITuner> mTuner;
+    sp<TunerCallbackMock> mCallback = new TunerCallbackMock();
+
+   private:
+    const BandConfig& getBand(unsigned idx);
+
+    unsigned currentBandIndex = 0;
+    hidl_vec<BandConfig> mBands;
+};
+
+/**
+ * Clears strong pointer and waits until the object gets destroyed.
+ *
+ * @param ptr The pointer to get cleared.
+ * @param timeout Time to wait for other references.
+ */
+template <typename T>
+static void clearAndWait(sp<T>& ptr, std::chrono::milliseconds timeout) {
+    wp<T> wptr = ptr;
+    ptr.clear();
+    auto limit = steady_clock::now() + timeout;
+    while (wptr.promote() != nullptr) {
+        constexpr auto step = 10ms;
+        if (steady_clock::now() + step > limit) {
+            FAIL() << "Pointer was not released within timeout";
+            break;
+        }
+        sleep_for(step);
     }
-    if (mTuner.get() == nullptr) {
+}
+
+void BroadcastRadioHalTest::SetUp() {
+    radioClass = GetParam();
+
+    // lookup HIDL service
+    auto factory = getService<IBroadcastRadioFactory>();
+    ASSERT_NE(nullptr, factory.get());
+
+    // connect radio module
+    Result connectResult;
+    CallBarrier onConnect;
+    factory->connectModule(radioClass, [&](Result ret, const sp<V1_0::IBroadcastRadio>& radio) {
+        connectResult = ret;
+        if (ret == Result::OK) mRadioModule = IBroadcastRadio::castFrom(radio);
+        onConnect.call();
+    });
+    ASSERT_TRUE(onConnect.waitForCall(kConnectModuleTimeout));
+
+    if (connectResult == Result::INVALID_ARGUMENTS) {
+        printSkipped("This device class is not supported.");
+        skipped = true;
+        return;
+    }
+    ASSERT_EQ(connectResult, Result::OK);
+    ASSERT_NE(nullptr, mRadioModule.get());
+
+    // get module properties
+    Properties prop11;
+    auto& prop10 = prop11.base;
+    auto propResult =
+        mRadioModule->getProperties_1_1([&](const Properties& properties) { prop11 = properties; });
+
+    ASSERT_TRUE(propResult.isOk());
+    EXPECT_EQ(radioClass, prop10.classId);
+    EXPECT_GT(prop10.numTuners, 0u);
+    EXPECT_GT(prop11.supportedProgramTypes.size(), 0u);
+    EXPECT_GT(prop11.supportedIdentifierTypes.size(), 0u);
+    if (radioClass == Class::AM_FM) {
+        EXPECT_GT(prop10.bands.size(), 0u);
+    }
+    mBands = prop10.bands;
+}
+
+void BroadcastRadioHalTest::TearDown() {
+    mTuner.clear();
+    mRadioModule.clear();
+    clearAndWait(mCallback, 1s);
+}
+
+bool BroadcastRadioHalTest::openTuner() {
+    EXPECT_EQ(nullptr, mTuner.get());
+
+    if (radioClass == Class::AM_FM) {
+        EXPECT_TIMEOUT_CALL(*mCallback, configChange, Result::OK, _);
+    }
+
+    Result halResult = Result::NOT_INITIALIZED;
+    auto openCb = [&](Result result, const sp<V1_0::ITuner>& tuner) {
+        halResult = result;
+        if (result != Result::OK) return;
+        mTuner = ITuner::castFrom(tuner);
+    };
+    currentBandIndex = 0;
+    auto hidlResult = mRadioModule->openTuner(getBand(0), true, mCallback, openCb);
+
+    EXPECT_TRUE(hidlResult.isOk());
+    EXPECT_EQ(Result::OK, halResult);
+    EXPECT_NE(nullptr, mTuner.get());
+    if (radioClass == Class::AM_FM && mTuner != nullptr) {
+        EXPECT_TIMEOUT_CALL_WAIT(*mCallback, configChange, kConfigTimeout);
+
+        BandConfig halConfig;
         Result halResult = Result::NOT_INITIALIZED;
-        auto hidlReturn = mRadio->openTuner(mHalProperties.bands[0], true, mTunerCallback,
-                [&](Result result, const sp<V1_0::ITuner>& tuner) {
-                    halResult = result;
-                    if (result == Result::OK) {
-                        mTuner = ITuner::castFrom(tuner);
-                    }
-                });
-        EXPECT_TRUE(hidlReturn.isOk());
+        mTuner->getConfiguration([&](Result result, const BandConfig& config) {
+            halResult = result;
+            halConfig = config;
+        });
         EXPECT_EQ(Result::OK, halResult);
-        EXPECT_TRUE(waitForCallback(kConfigCallbacktimeoutNs));
+        EXPECT_TRUE(halConfig.antennaConnected);
     }
+
     EXPECT_NE(nullptr, mTuner.get());
     return nullptr != mTuner.get();
 }
 
-bool BroadcastRadioHidlTest::checkAntenna()
-{
-    BandConfig halConfig;
-    Result halResult = Result::NOT_INITIALIZED;
-    Return<void> hidlReturn =
-            mTuner->getConfiguration([&](Result result, const BandConfig& config) {
-                halResult = result;
-                if (result == Result::OK) {
-                    halConfig = config;
-                }
-            });
+const BandConfig& BroadcastRadioHalTest::getBand(unsigned idx) {
+    static const BandConfig dummyBandConfig = {};
 
-    return ((halResult == Result::OK) && (halConfig.antennaConnected == true));
-}
-
-
-/**
- * Test IBroadcastRadio::getProperties() method
- *
- * Verifies that:
- *  - the HAL implements the method
- *  - the method returns 0 (no error)
- *  - the implementation class is AM_FM
- *  - the implementation supports at least one tuner
- *  - the implementation supports at one band
- */
-TEST_F(BroadcastRadioHidlTest, GetProperties) {
-    EXPECT_TRUE(getProperties());
-}
-
-/**
- * Test IBroadcastRadio::openTuner() method
- *
- * Verifies that:
- *  - the HAL implements the method
- *  - the method returns 0 (no error) and a valid ITuner interface
- */
-TEST_F(BroadcastRadioHidlTest, OpenTuner) {
-    EXPECT_TRUE(openTuner());
-}
-
-/**
- * Test ITuner::setConfiguration() and getConfiguration methods
- *
- * Verifies that:
- *  - the HAL implements both methods
- *  - the methods return 0 (no error)
- *  - the configuration callback is received within kConfigCallbacktimeoutNs ns
- *  - the configuration read back from HAl has the same class Id
- */
-TEST_F(BroadcastRadioHidlTest, SetAndGetConfiguration) {
-    ASSERT_TRUE(openTuner());
-    // test setConfiguration
-    mCallbackCalled = false;
-    Return<Result> hidlResult = mTuner->setConfiguration(mHalProperties.bands[0]);
-    EXPECT_TRUE(hidlResult.isOk());
-    EXPECT_EQ(Result::OK, hidlResult);
-    EXPECT_TRUE(waitForCallback(kConfigCallbacktimeoutNs));
-    EXPECT_EQ(Result::OK, mResultCallbackData);
-
-    // test getConfiguration
-    BandConfig halConfig;
-    Result halResult;
-    Return<void> hidlReturn =
-            mTuner->getConfiguration([&](Result result, const BandConfig& config) {
-                halResult = result;
-                if (result == Result::OK) {
-                    halConfig = config;
-                }
-            });
-    EXPECT_TRUE(hidlReturn.isOk());
-    EXPECT_EQ(Result::OK, halResult);
-    EXPECT_EQ(mHalProperties.bands[0].type, halConfig.type);
-}
-
-/**
- * Test ITuner::scan
- *
- * Verifies that:
- *  - the HAL implements the method
- *  - the method returns 0 (no error)
- *  - the tuned callback is received within kTuneCallbacktimeoutNs ns
- */
-TEST_F(BroadcastRadioHidlTest, Scan) {
-    ASSERT_TRUE(openTuner());
-    ASSERT_TRUE(checkAntenna());
-    // test scan UP
-    mCallbackCalled = false;
-    Return<Result> hidlResult = mTuner->scan(Direction::UP, true);
-    EXPECT_TRUE(hidlResult.isOk());
-    EXPECT_EQ(Result::OK, hidlResult);
-    EXPECT_TRUE(waitForCallback(kTuneCallbacktimeoutNs));
-
-    // test scan DOWN
-    mCallbackCalled = false;
-    hidlResult = mTuner->scan(Direction::DOWN, true);
-    EXPECT_TRUE(hidlResult.isOk());
-    EXPECT_EQ(Result::OK, hidlResult);
-    EXPECT_TRUE(waitForCallback(kTuneCallbacktimeoutNs));
-}
-
-/**
- * Test ITuner::step
- *
- * Verifies that:
- *  - the HAL implements the method
- *  - the method returns 0 (no error)
- *  - the tuned callback is received within kTuneCallbacktimeoutNs ns
- */
-TEST_F(BroadcastRadioHidlTest, Step) {
-    ASSERT_TRUE(openTuner());
-    ASSERT_TRUE(checkAntenna());
-    // test step UP
-    mCallbackCalled = false;
-    Return<Result> hidlResult = mTuner->step(Direction::UP, true);
-    EXPECT_TRUE(hidlResult.isOk());
-    EXPECT_EQ(Result::OK, hidlResult);
-    EXPECT_TRUE(waitForCallback(kTuneCallbacktimeoutNs));
-
-    // test step DOWN
-    mCallbackCalled = false;
-    hidlResult = mTuner->step(Direction::DOWN, true);
-    EXPECT_TRUE(hidlResult.isOk());
-    EXPECT_EQ(Result::OK, hidlResult);
-    EXPECT_TRUE(waitForCallback(kTuneCallbacktimeoutNs));
-}
-
-/**
- * Test ITuner::tune,  getProgramInformation and cancel methods
- *
- * Verifies that:
- *  - the HAL implements the methods
- *  - the methods return 0 (no error)
- *  - the tuned callback is received within kTuneCallbacktimeoutNs ns after tune()
- */
-TEST_F(BroadcastRadioHidlTest, TuneAndGetProgramInformationAndCancel) {
-    ASSERT_TRUE(openTuner());
-    ASSERT_TRUE(checkAntenna());
-
-    // test tune
-    ASSERT_GT(mHalProperties.bands[0].spacings.size(), 0u);
-    ASSERT_GT(mHalProperties.bands[0].upperLimit, mHalProperties.bands[0].lowerLimit);
-
-    // test scan UP
-    uint32_t lowerLimit = mHalProperties.bands[0].lowerLimit;
-    uint32_t upperLimit = mHalProperties.bands[0].upperLimit;
-    uint32_t spacing = mHalProperties.bands[0].spacings[0];
-
-    uint32_t channel =
-            lowerLimit + (((upperLimit - lowerLimit) / 2 + spacing - 1) / spacing) * spacing;
-    mCallbackCalled = false;
-    mResultCallbackData = Result::NOT_INITIALIZED;
-    Return<Result> hidlResult = mTuner->tune(channel, 0);
-    EXPECT_TRUE(hidlResult.isOk());
-    EXPECT_EQ(Result::OK, hidlResult);
-    EXPECT_TRUE(waitForCallback(kTuneCallbacktimeoutNs));
-
-    // test getProgramInformation
-    ProgramInfo halInfo;
-    Result halResult = Result::NOT_INITIALIZED;
-    Return<void> hidlReturn = mTuner->getProgramInformation_1_1(
-        [&](Result result, const ProgramInfo& info) {
-            halResult = result;
-            if (result == Result::OK) {
-                halInfo = info;
-            }
-        });
-    EXPECT_TRUE(hidlReturn.isOk());
-    EXPECT_EQ(Result::OK, halResult);
-    auto &halInfo_1_1 = halInfo.base;
-    if (mResultCallbackData == Result::OK) {
-        EXPECT_TRUE(halInfo_1_1.tuned);
-        EXPECT_LE(halInfo_1_1.channel, upperLimit);
-        EXPECT_GE(halInfo_1_1.channel, lowerLimit);
-    } else {
-        EXPECT_EQ(false, halInfo_1_1.tuned);
+    if (radioClass != Class::AM_FM) {
+        ALOGD("Not AM/FM radio, returning dummy band config");
+        return dummyBandConfig;
     }
 
-    // test cancel
-    mTuner->tune(lowerLimit, 0);
-    hidlResult = mTuner->cancel();
+    EXPECT_GT(mBands.size(), idx);
+    if (mBands.size() <= idx) {
+        ALOGD("Band index out of bound, returning dummy band config");
+        return dummyBandConfig;
+    }
+
+    auto& band = mBands[idx];
+    ALOGD("Returning %s band", toString(band.type).c_str());
+    return band;
+}
+
+bool BroadcastRadioHalTest::nextBand() {
+    if (currentBandIndex + 1 >= mBands.size()) return false;
+    currentBandIndex++;
+
+    BandConfig bandCb;
+    EXPECT_TIMEOUT_CALL(*mCallback, configChange, Result::OK, _)
+        .WillOnce(DoAll(SaveArg<1>(&bandCb), testing::Return(ByMove(Void()))));
+    auto hidlResult = mTuner->setConfiguration(getBand(currentBandIndex));
+    EXPECT_EQ(Result::OK, hidlResult);
+    EXPECT_TIMEOUT_CALL_WAIT(*mCallback, configChange, kConfigTimeout);
+    EXPECT_EQ(getBand(currentBandIndex), bandCb);
+
+    return true;
+}
+
+bool BroadcastRadioHalTest::getProgramList(
+    std::function<void(const hidl_vec<ProgramInfo>& list)> cb) {
+    ProgramListResult getListResult = ProgramListResult::NOT_INITIALIZED;
+    bool isListEmpty = true;
+    auto getListCb = [&](ProgramListResult result, const hidl_vec<ProgramInfo>& list) {
+        ALOGD("getListCb(%s, ProgramInfo[%zu])", toString(result).c_str(), list.size());
+        getListResult = result;
+        if (result != ProgramListResult::OK) return;
+        isListEmpty = (list.size() == 0);
+        if (!isListEmpty) cb(list);
+    };
+
+    // first try...
+    EXPECT_TIMEOUT_CALL(*mCallback, backgroundScanComplete, ProgramListResult::OK)
+        .Times(AnyNumber());
+    auto hidlResult = mTuner->getProgramList({}, getListCb);
     EXPECT_TRUE(hidlResult.isOk());
+    if (!hidlResult.isOk()) return false;
+
+    if (getListResult == ProgramListResult::NOT_STARTED) {
+        auto result = mTuner->startBackgroundScan();
+        EXPECT_EQ(ProgramListResult::OK, result);
+        getListResult = ProgramListResult::NOT_READY;  // continue as in NOT_READY case
+    }
+    if (getListResult == ProgramListResult::NOT_READY) {
+        EXPECT_TIMEOUT_CALL_WAIT(*mCallback, backgroundScanComplete, kFullScanTimeout);
+
+        // second (last) try...
+        hidlResult = mTuner->getProgramList({}, getListCb);
+        EXPECT_TRUE(hidlResult.isOk());
+        if (!hidlResult.isOk()) return false;
+        EXPECT_EQ(ProgramListResult::OK, getListResult);
+    }
+
+    return !isListEmpty;
+}
+
+/**
+ * Test IBroadcastRadio::openTuner() method called twice.
+ *
+ * Verifies that:
+ *  - the openTuner method succeeds when called for the second time without
+ *    deleting previous ITuner instance.
+ *
+ * This is a more strict requirement than in 1.0, where a second openTuner
+ * might fail.
+ */
+TEST_P(BroadcastRadioHalTest, OpenTunerTwice) {
+    if (skipped) return;
+
+    ASSERT_TRUE(openTuner());
+
+    auto secondTuner = mTuner;
+    mTuner.clear();
+
+    ASSERT_TRUE(openTuner());
+}
+
+/**
+ * Test tuning to program list entry.
+ *
+ * Verifies that:
+ *  - getProgramList either succeeds or returns NOT_STARTED/NOT_READY status;
+ *  - if the program list is NOT_STARTED, startBackgroundScan makes it completed
+ *    within a full scan timeout and the next getProgramList call succeeds;
+ *  - if the program list is not empty, tuneByProgramSelector call succeeds;
+ *  - getProgramInformation_1_1 returns the same selector as returned in tuneComplete_1_1 call.
+ */
+TEST_P(BroadcastRadioHalTest, TuneFromProgramList) {
+    if (skipped) return;
+    ASSERT_TRUE(openTuner());
+
+    ProgramInfo firstProgram;
+    bool foundAny = false;
+    do {
+        auto getCb = [&](const hidl_vec<ProgramInfo>& list) {
+            // don't copy the whole list out, it might be heavy
+            firstProgram = list[0];
+        };
+        if (getProgramList(getCb)) foundAny = true;
+    } while (nextBand());
+    if (HasFailure()) return;
+    if (!foundAny) {
+        printSkipped("Program list is empty.");
+        return;
+    }
+
+    ProgramInfo infoCb;
+    ProgramSelector selCb;
+    EXPECT_CALL(*mCallback, tuneComplete(_, _)).Times(0);
+    EXPECT_TIMEOUT_CALL(*mCallback, tuneComplete_1_1, Result::OK, _)
+        .WillOnce(DoAll(SaveArg<1>(&selCb), testing::Return(ByMove(Void()))));
+    EXPECT_TIMEOUT_CALL(*mCallback, currentProgramInfoChanged, _)
+        .WillOnce(DoAll(SaveArg<0>(&infoCb), testing::Return(ByMove(Void()))));
+    auto tuneResult = mTuner->tuneByProgramSelector(firstProgram.selector);
+    ASSERT_EQ(Result::OK, tuneResult);
+    EXPECT_TIMEOUT_CALL_WAIT(*mCallback, tuneComplete_1_1, kTuneTimeout);
+    EXPECT_TIMEOUT_CALL_WAIT(*mCallback, currentProgramInfoChanged, kEventPropagationTimeout);
+    EXPECT_EQ(firstProgram.selector.primaryId, selCb.primaryId);
+    EXPECT_EQ(infoCb.selector, selCb);
+
+    bool called = false;
+    auto getResult = mTuner->getProgramInformation_1_1([&](Result result, ProgramInfo info) {
+        called = true;
+        EXPECT_EQ(Result::OK, result);
+        EXPECT_EQ(selCb, info.selector);
+    });
+    ASSERT_TRUE(getResult.isOk());
+    ASSERT_TRUE(called);
+}
+
+/**
+ * Test that primary vendor identifier isn't used for standard program types.
+ *
+ * Verifies that:
+ *  - tuneByProgramSelector fails when VENDORn_PRIMARY is set as a primary
+ *    identifier for program types other than VENDORn.
+ */
+TEST_P(BroadcastRadioHalTest, TuneFailsForPrimaryVendor) {
+    if (skipped) return;
+    ASSERT_TRUE(openTuner());
+
+    for (auto ptype : kStandardProgramTypes) {
+        ALOGD("Checking %s...", toString(ptype).c_str());
+        ProgramSelector sel = {};
+        sel.programType = static_cast<uint32_t>(ptype);
+        sel.primaryId.type = static_cast<uint32_t>(IdentifierType::VENDOR_PRIMARY_START);
+
+        auto tuneResult = mTuner->tuneByProgramSelector(sel);
+        ASSERT_NE(Result::OK, tuneResult);
+    }
+}
+
+/**
+ * Test that tune with unknown program type fails.
+ *
+ * Verifies that:
+ *  - tuneByProgramSelector fails with INVALID_ARGUMENT when unknown program type is passed.
+ */
+TEST_P(BroadcastRadioHalTest, TuneFailsForUnknownProgram) {
+    if (skipped) return;
+    ASSERT_TRUE(openTuner());
+
+    // Program type is 1-based, so 0 will be always invalid.
+    ProgramSelector sel = {};
+    auto tuneResult = mTuner->tuneByProgramSelector(sel);
+    ASSERT_EQ(Result::INVALID_ARGUMENTS, tuneResult);
+}
+
+/**
+ * Test cancelling announcement.
+ *
+ * Verifies that:
+ *  - cancelAnnouncement succeeds either when there is an announcement or there is none.
+ */
+TEST_P(BroadcastRadioHalTest, CancelAnnouncement) {
+    if (skipped) return;
+    ASSERT_TRUE(openTuner());
+
+    auto hidlResult = mTuner->cancelAnnouncement();
     EXPECT_EQ(Result::OK, hidlResult);
 }
 
+/**
+ * Test getImage call with invalid image ID.
+ *
+ * Verifies that:
+ * - getImage call handles argument 0 gracefully.
+ */
+TEST_P(BroadcastRadioHalTest, GetNoImage) {
+    if (skipped) return;
+
+    size_t len = 0;
+    auto hidlResult =
+        mRadioModule->getImage(0, [&](hidl_vec<uint8_t> rawImage) { len = rawImage.size(); });
+
+    ASSERT_TRUE(hidlResult.isOk());
+    ASSERT_EQ(0u, len);
+}
+
+/**
+ * Test proper image format in metadata.
+ *
+ * Verifies that:
+ * - all images in metadata are provided out-of-band (by id, not as a binary blob);
+ * - images are available for getImage call.
+ */
+TEST_P(BroadcastRadioHalTest, OobImagesOnly) {
+    if (skipped) return;
+    ASSERT_TRUE(openTuner());
+
+    std::vector<int> imageIds;
+
+    do {
+        auto getCb = [&](const hidl_vec<ProgramInfo>& list) {
+            for (auto&& program : list) {
+                for (auto&& entry : program.base.metadata) {
+                    EXPECT_NE(MetadataType::RAW, entry.type);
+                    if (entry.key != MetadataKey::ICON && entry.key != MetadataKey::ART) continue;
+                    EXPECT_NE(0, entry.intValue);
+                    EXPECT_EQ(0u, entry.rawValue.size());
+                    if (entry.intValue != 0) imageIds.push_back(entry.intValue);
+                }
+            }
+        };
+        getProgramList(getCb);
+    } while (nextBand());
+
+    if (imageIds.size() == 0) {
+        printSkipped("No images found");
+        return;
+    }
+
+    for (auto id : imageIds) {
+        ALOGD("Checking image %d", id);
+
+        size_t len = 0;
+        auto hidlResult =
+            mRadioModule->getImage(id, [&](hidl_vec<uint8_t> rawImage) { len = rawImage.size(); });
+
+        ASSERT_TRUE(hidlResult.isOk());
+        ASSERT_GT(len, 0u);
+    }
+}
+
+/**
+ * Test AnalogForced switch.
+ *
+ * Verifies that:
+ * - setAnalogForced results either with INVALID_STATE, or isAnalogForced replying the same.
+ */
+TEST_P(BroadcastRadioHalTest, AnalogForcedSwitch) {
+    if (skipped) return;
+    ASSERT_TRUE(openTuner());
+
+    bool forced;
+    Result halIsResult;
+    auto isCb = [&](Result result, bool isForced) {
+        halIsResult = result;
+        forced = isForced;
+    };
+
+    // set analog mode
+    auto setResult = mTuner->setAnalogForced(true);
+    ASSERT_TRUE(setResult.isOk());
+    if (Result::INVALID_STATE == setResult) {
+        // if setter fails, getter should fail too - it means the switch is not supported at all
+        auto isResult = mTuner->isAnalogForced(isCb);
+        ASSERT_TRUE(isResult.isOk());
+        EXPECT_EQ(Result::INVALID_STATE, halIsResult);
+        return;
+    }
+    ASSERT_EQ(Result::OK, setResult);
+
+    // check, if it's analog
+    auto isResult = mTuner->isAnalogForced(isCb);
+    ASSERT_TRUE(isResult.isOk());
+    EXPECT_EQ(Result::OK, halIsResult);
+    ASSERT_TRUE(forced);
+
+    // set digital mode
+    setResult = mTuner->setAnalogForced(false);
+    ASSERT_EQ(Result::OK, setResult);
+
+    // check, if it's digital
+    isResult = mTuner->isAnalogForced(isCb);
+    ASSERT_TRUE(isResult.isOk());
+    EXPECT_EQ(Result::OK, halIsResult);
+    ASSERT_FALSE(forced);
+}
+
+INSTANTIATE_TEST_CASE_P(BroadcastRadioHalTestCases, BroadcastRadioHalTest,
+                        ::testing::Values(Class::AM_FM, Class::SAT, Class::DT));
+
+}  // namespace vts
+}  // namespace V1_1
+}  // namespace broadcastradio
+}  // namespace hardware
+}  // namespace android
 
 int main(int argc, char** argv) {
-  ::testing::AddGlobalTestEnvironment(new BroadcastRadioHidlEnvironment);
   ::testing::InitGoogleTest(&argc, argv);
   int status = RUN_ALL_TESTS();
   ALOGI("Test result = %d", status);
diff --git a/broadcastradio/1.1/vts/utils/Android.bp b/broadcastradio/1.1/vts/utils/Android.bp
new file mode 100644
index 0000000..0c7e2a4
--- /dev/null
+++ b/broadcastradio/1.1/vts/utils/Android.bp
@@ -0,0 +1,28 @@
+//
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_library_static {
+    name: "android.hardware.broadcastradio@1.1-vts-utils-lib",
+    srcs: [
+        "call-barrier.cpp",
+    ],
+    export_include_dirs: ["include"],
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+    ],
+}
diff --git a/broadcastradio/1.1/vts/utils/call-barrier.cpp b/broadcastradio/1.1/vts/utils/call-barrier.cpp
new file mode 100644
index 0000000..d8c4716
--- /dev/null
+++ b/broadcastradio/1.1/vts/utils/call-barrier.cpp
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+#include <broadcastradio-vts-utils/call-barrier.h>
+
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace vts {
+
+using std::lock_guard;
+using std::mutex;
+using std::unique_lock;
+
+void CallBarrier::call() {
+    lock_guard<mutex> lk(mMut);
+    mWasCalled = true;
+    mCond.notify_all();
+}
+
+bool CallBarrier::waitForCall(std::chrono::milliseconds timeout) {
+    unique_lock<mutex> lk(mMut);
+
+    if (mWasCalled) return true;
+
+    auto status = mCond.wait_for(lk, timeout);
+    return status == std::cv_status::no_timeout;
+}
+
+}  // namespace vts
+}  // namespace broadcastradio
+}  // namespace hardware
+}  // namespace android
diff --git a/broadcastradio/1.1/vts/utils/include/broadcastradio-vts-utils/call-barrier.h b/broadcastradio/1.1/vts/utils/include/broadcastradio-vts-utils/call-barrier.h
new file mode 100644
index 0000000..462396a
--- /dev/null
+++ b/broadcastradio/1.1/vts/utils/include/broadcastradio-vts-utils/call-barrier.h
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+#ifndef ANDROID_HARDWARE_BROADCASTRADIO_V1_1_CALL_BARRIER
+#define ANDROID_HARDWARE_BROADCASTRADIO_V1_1_CALL_BARRIER
+
+#include <chrono>
+#include <thread>
+
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace vts {
+
+/**
+ * A barrier for thread synchronization, where one should wait for another to
+ * reach a specific point in execution.
+ */
+class CallBarrier {
+   public:
+    /**
+     * Notify the other thread it may continue execution.
+     *
+     * This may be called before the other thread starts waiting on the barrier.
+     */
+    void call();
+
+    /**
+     * Wait for the other thread to reach call() execution point.
+     *
+     * @param timeout a maximum time to wait.
+     * @returns {@code false} if timed out, {@code true} otherwise.
+     */
+    bool waitForCall(std::chrono::milliseconds timeout);
+
+   private:
+    bool mWasCalled = false;
+    std::mutex mMut;
+    std::condition_variable mCond;
+};
+
+}  // namespace vts
+}  // namespace broadcastradio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_BROADCASTRADIO_V1_1_CALL_BARRIER
diff --git a/broadcastradio/1.1/vts/utils/include/broadcastradio-vts-utils/mock-timeout.h b/broadcastradio/1.1/vts/utils/include/broadcastradio-vts-utils/mock-timeout.h
new file mode 100644
index 0000000..b0ce088
--- /dev/null
+++ b/broadcastradio/1.1/vts/utils/include/broadcastradio-vts-utils/mock-timeout.h
@@ -0,0 +1,111 @@
+/*
+ * 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.
+ */
+#ifndef ANDROID_HARDWARE_BROADCASTRADIO_V1_1_MOCK_TIMEOUT
+#define ANDROID_HARDWARE_BROADCASTRADIO_V1_1_MOCK_TIMEOUT
+
+#include <gmock/gmock.h>
+#include <thread>
+
+/**
+ * Common helper objects for gmock timeout extension.
+ *
+ * INTERNAL IMPLEMENTATION - don't use in user code.
+ */
+#define EGMOCK_TIMEOUT_METHOD_DEF_(Method, ...) \
+    std::atomic<bool> egmock_called_##Method;   \
+    std::mutex egmock_mut_##Method;             \
+    std::condition_variable egmock_cond_##Method;
+
+/**
+ * Common method body for gmock timeout extension.
+ *
+ * INTERNAL IMPLEMENTATION - don't use in user code.
+ */
+#define EGMOCK_TIMEOUT_METHOD_BODY_(Method, ...)             \
+    auto ret = egmock_##Method(__VA_ARGS__);                 \
+    {                                                        \
+        std::lock_guard<std::mutex> lk(egmock_mut_##Method); \
+        egmock_called_##Method = true;                       \
+        egmock_cond_##Method.notify_all();                   \
+    }                                                        \
+    return ret;
+
+/**
+ * Gmock MOCK_METHOD0 timeout-capable extension.
+ */
+#define MOCK_TIMEOUT_METHOD0(Method, ...)       \
+    MOCK_METHOD0(egmock_##Method, __VA_ARGS__); \
+    EGMOCK_TIMEOUT_METHOD_DEF_(Method);         \
+    virtual GMOCK_RESULT_(, __VA_ARGS__) Method() { EGMOCK_TIMEOUT_METHOD_BODY_(Method); }
+
+/**
+ * Gmock MOCK_METHOD1 timeout-capable extension.
+ */
+#define MOCK_TIMEOUT_METHOD1(Method, ...)                                                 \
+    MOCK_METHOD1(egmock_##Method, __VA_ARGS__);                                           \
+    EGMOCK_TIMEOUT_METHOD_DEF_(Method);                                                   \
+    virtual GMOCK_RESULT_(, __VA_ARGS__) Method(GMOCK_ARG_(, 1, __VA_ARGS__) egmock_a1) { \
+        EGMOCK_TIMEOUT_METHOD_BODY_(Method, egmock_a1);                                   \
+    }
+
+/**
+ * Gmock MOCK_METHOD2 timeout-capable extension.
+ */
+#define MOCK_TIMEOUT_METHOD2(Method, ...)                                                        \
+    MOCK_METHOD2(egmock_##Method, __VA_ARGS__);                                                  \
+    EGMOCK_TIMEOUT_METHOD_DEF_(Method);                                                          \
+    virtual GMOCK_RESULT_(, __VA_ARGS__)                                                         \
+        Method(GMOCK_ARG_(, 1, __VA_ARGS__) egmock_a1, GMOCK_ARG_(, 2, __VA_ARGS__) egmock_a2) { \
+        EGMOCK_TIMEOUT_METHOD_BODY_(Method, egmock_a1, egmock_a2);                               \
+    }
+
+/**
+ * Gmock EXPECT_CALL timeout-capable extension.
+ *
+ * It has slightly different syntax from the original macro, to make method name accessible.
+ * So, instead of typing
+ *     EXPECT_CALL(account, charge(100, Currency::USD));
+ * you need to inline arguments
+ *     EXPECT_TIMEOUT_CALL(account, charge, 100, Currency::USD);
+ */
+#define EXPECT_TIMEOUT_CALL(obj, Method, ...) \
+    (obj).egmock_called_##Method = false;     \
+    EXPECT_CALL(obj, egmock_##Method(__VA_ARGS__))
+
+/**
+ * Waits for an earlier EXPECT_TIMEOUT_CALL to execute.
+ *
+ * It does not fully support special constraints of the EXPECT_CALL clause, just proceeds when the
+ * first call to a given method comes. For example, in the following code:
+ *     EXPECT_TIMEOUT_CALL(account, charge, 100, _);
+ *     account.charge(50, Currency::USD);
+ *     EXPECT_TIMEOUT_CALL_WAIT(account, charge, 500ms);
+ * the wait clause will just continue, as the charge method was called.
+ *
+ * @param obj object for a call
+ * @param Method the method to wait for
+ * @param timeout the maximum time for waiting
+ */
+#define EXPECT_TIMEOUT_CALL_WAIT(obj, Method, timeout)                      \
+    {                                                                       \
+        std::unique_lock<std::mutex> lk((obj).egmock_mut_##Method);         \
+        if (!(obj).egmock_called_##Method) {                                \
+            auto status = (obj).egmock_cond_##Method.wait_for(lk, timeout); \
+            EXPECT_EQ(std::cv_status::no_timeout, status);                  \
+        }                                                                   \
+    }
+
+#endif  // ANDROID_HARDWARE_BROADCASTRADIO_V1_1_MOCK_TIMEOUT
diff --git a/broadcastradio/Android.bp b/broadcastradio/Android.bp
index 7a315fa..8c65bf6 100644
--- a/broadcastradio/Android.bp
+++ b/broadcastradio/Android.bp
@@ -5,5 +5,8 @@
     "1.0/vts/functional",
     "1.1",
     "1.1/default",
+    "1.1/tests",
+    "1.1/utils",
     "1.1/vts/functional",
+    "1.1/vts/utils",
 ]
diff --git a/camera/Android.bp b/camera/Android.bp
index 3869766..83a2803 100644
--- a/camera/Android.bp
+++ b/camera/Android.bp
@@ -6,6 +6,7 @@
     "device/1.0/default",
     "device/3.2",
     "device/3.2/default",
+    "device/3.3",
     "metadata/3.2",
     "provider/2.4",
     "provider/2.4/default",
diff --git a/camera/common/1.0/Android.bp b/camera/common/1.0/Android.bp
index 252d490..ade7260 100644
--- a/camera/common/1.0/Android.bp
+++ b/camera/common/1.0/Android.bp
@@ -32,13 +32,16 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.camera.common@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.camera.common@1.0_genc++"],
     generated_headers: ["android.hardware.camera.common@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.camera.common@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/camera/common/1.0/default/CameraParameters.cpp b/camera/common/1.0/default/CameraParameters.cpp
index d224483..e707b08 100644
--- a/camera/common/1.0/default/CameraParameters.cpp
+++ b/camera/common/1.0/default/CameraParameters.cpp
@@ -20,6 +20,7 @@
 
 #include <string.h>
 #include <stdlib.h>
+#include <unistd.h>
 #include "CameraParameters.h"
 #include <system/graphics.h>
 
diff --git a/camera/device/1.0/Android.bp b/camera/device/1.0/Android.bp
index 3ef40c8..b8335f9 100644
--- a/camera/device/1.0/Android.bp
+++ b/camera/device/1.0/Android.bp
@@ -53,13 +53,16 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.camera.device@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.camera.device@1.0_genc++"],
     generated_headers: ["android.hardware.camera.device@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.camera.device@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/camera/device/1.0/default/Android.bp b/camera/device/1.0/default/Android.bp
index 1a349d6..e0b31f0 100644
--- a/camera/device/1.0/default/Android.bp
+++ b/camera/device/1.0/default/Android.bp
@@ -26,6 +26,9 @@
     static_libs: [
         "android.hardware.camera.common@1.0-helper"
     ],
+    header_libs: [
+        "media_plugin_headers",
+    ],
     include_dirs: [
         "frameworks/native/include/media/openmax"
     ],
diff --git a/camera/device/1.0/default/OWNERS b/camera/device/1.0/default/OWNERS
new file mode 100644
index 0000000..18acfee
--- /dev/null
+++ b/camera/device/1.0/default/OWNERS
@@ -0,0 +1,6 @@
+cychen@google.com
+epeev@google.com
+etalvala@google.com
+shuzhenwang@google.com
+yinchiayeh@google.com
+zhijunhe@google.com
diff --git a/camera/device/3.2/Android.bp b/camera/device/3.2/Android.bp
index dbc80ab..24c2151 100644
--- a/camera/device/3.2/Android.bp
+++ b/camera/device/3.2/Android.bp
@@ -53,13 +53,16 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.camera.device@3.2",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.camera.device@3.2_genc++"],
     generated_headers: ["android.hardware.camera.device@3.2_genc++_headers"],
     export_generated_headers: ["android.hardware.camera.device@3.2_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/camera/device/3.2/default/OWNERS b/camera/device/3.2/default/OWNERS
new file mode 100644
index 0000000..18acfee
--- /dev/null
+++ b/camera/device/3.2/default/OWNERS
@@ -0,0 +1,6 @@
+cychen@google.com
+epeev@google.com
+etalvala@google.com
+shuzhenwang@google.com
+yinchiayeh@google.com
+zhijunhe@google.com
diff --git a/camera/device/3.3/Android.bp b/camera/device/3.3/Android.bp
new file mode 100644
index 0000000..2a19991
--- /dev/null
+++ b/camera/device/3.3/Android.bp
@@ -0,0 +1,72 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+filegroup {
+    name: "android.hardware.camera.device@3.3_hal",
+    srcs: [
+        "types.hal",
+        "ICameraDeviceSession.hal",
+    ],
+}
+
+genrule {
+    name: "android.hardware.camera.device@3.3_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++-sources -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.camera.device@3.3",
+    srcs: [
+        ":android.hardware.camera.device@3.3_hal",
+    ],
+    out: [
+        "android/hardware/camera/device/3.3/types.cpp",
+        "android/hardware/camera/device/3.3/CameraDeviceSessionAll.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.camera.device@3.3_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++-headers -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.camera.device@3.3",
+    srcs: [
+        ":android.hardware.camera.device@3.3_hal",
+    ],
+    out: [
+        "android/hardware/camera/device/3.3/types.h",
+        "android/hardware/camera/device/3.3/hwtypes.h",
+        "android/hardware/camera/device/3.3/ICameraDeviceSession.h",
+        "android/hardware/camera/device/3.3/IHwCameraDeviceSession.h",
+        "android/hardware/camera/device/3.3/BnHwCameraDeviceSession.h",
+        "android/hardware/camera/device/3.3/BpHwCameraDeviceSession.h",
+        "android/hardware/camera/device/3.3/BsCameraDeviceSession.h",
+    ],
+}
+
+cc_library {
+    name: "android.hardware.camera.device@3.3",
+    defaults: ["hidl-module-defaults"],
+    generated_sources: ["android.hardware.camera.device@3.3_genc++"],
+    generated_headers: ["android.hardware.camera.device@3.3_genc++_headers"],
+    export_generated_headers: ["android.hardware.camera.device@3.3_genc++_headers"],
+    vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "android.hardware.camera.common@1.0",
+        "android.hardware.camera.device@3.2",
+        "android.hardware.graphics.common@1.0",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hardware.camera.common@1.0",
+        "android.hardware.camera.device@3.2",
+        "android.hardware.graphics.common@1.0",
+    ],
+}
diff --git a/camera/device/3.3/ICameraDeviceSession.hal b/camera/device/3.3/ICameraDeviceSession.hal
new file mode 100644
index 0000000..764392f
--- /dev/null
+++ b/camera/device/3.3/ICameraDeviceSession.hal
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+package android.hardware.camera.device@3.3;
+
+import android.hardware.camera.common@1.0::Status;
+import android.hardware.camera.device@3.2::ICameraDeviceSession;
+import android.hardware.camera.device@3.2::StreamConfiguration;
+
+/**
+ * Camera device active session interface.
+ *
+ * Obtained via ICameraDevice::open(), this interface contains the methods to
+ * configure and request captures from an active camera device.
+ *
+ */
+interface ICameraDeviceSession extends @3.2::ICameraDeviceSession {
+
+    /**
+     * configureStreams_3_3:
+     *
+     * Identical to @3.2::ICameraDeviceSession.configureStreams, except that:
+     *
+     * - The output HalStreamConfiguration now contains an overrideDataspace
+     *   field, to be used by the HAL to select a different dataspace for some
+     *   use cases when dealing with the IMPLEMENTATION_DEFINED pixel format.
+     *
+     * Clients may invoke either this method or
+     * @3.2::ICameraDeviceSession.configureStreams() for stream configuration.
+     * This method is recommended for clients to use since it provides more
+     * flexibility.
+     */
+    configureStreams_3_3(StreamConfiguration requestedConfiguration)
+            generates (Status status,
+                    @3.3::HalStreamConfiguration halConfiguration);
+
+};
diff --git a/camera/device/3.3/types.hal b/camera/device/3.3/types.hal
new file mode 100644
index 0000000..b4ad702
--- /dev/null
+++ b/camera/device/3.3/types.hal
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+
+package android.hardware.camera.device@3.3;
+
+import android.hardware.camera.device@3.2::DataspaceFlags;
+import android.hardware.camera.device@3.2::HalStream;
+
+/**
+ * HalStream:
+ *
+ * The camera HAL's response to each requested stream configuration.
+ *
+ * This version extends the @3.2 HalStream with the overrideDataspace
+ * field
+ */
+struct HalStream {
+    /**
+     * The definition of HalStream from the prior version.
+     */
+    @3.2::HalStream v3_2;
+
+    /**
+     * An override dataSpace for the buffers in this stream.
+     *
+     * The HAL must respect the requested dataSpace in Stream unless it is
+     * IMPLEMENTATION_DEFINED, in which case the override dataSpace here must be
+     * used by the client instead, for this stream. This allows cross-platform
+     * HALs to use a specific dataSpace since IMPLEMENTATION_DEFINED formats often
+     * require device-specific information for correct selection. In all other cases, the
+     * overrideFormat must match the requested format.
+     */
+    DataspaceFlags overrideDataSpace;
+};
+
+/**
+ * HalStreamConfiguration:
+ *
+ * Identical to @3.2::HalStreamConfiguration, except that it contains @3.3::HalStream entries.
+ *
+ */
+struct HalStreamConfiguration {
+    vec<HalStream> streams;
+};
diff --git a/camera/device/README.md b/camera/device/README.md
index 6e5703a..9f60781 100644
--- a/camera/device/README.md
+++ b/camera/device/README.md
@@ -33,6 +33,8 @@
 This HAL interface version only allows support at the LEGACY level for the
 android.hardware.camera2 API.
 
+Added in Android 8.0.
+
 Subsidiary HALs:
 
 #### ICameraDevice1PreviewCallback.hal@1.0:
@@ -62,6 +64,8 @@
 interface for operating the active camera. It takes a Callback interface as an
 argument.
 
+Added in Android 8.0.
+
 Subsidiary HALs:
 
 #### ICameraDevice3Session.hal@3.2:
@@ -74,3 +78,12 @@
 
 Callback interface for sending completed captures and other asynchronous events
 from tehe HAL to the client.
+
+### ICameraDevice.hal@3.3:
+
+A minor revision to the ICameraDevice.hal@3.2.
+
+  - Adds support for overriding the output dataspace of a stream, which was
+    supported in the legacy camera HAL.
+
+Added in Android 8.1.
diff --git a/camera/metadata/3.2/Android.bp b/camera/metadata/3.2/Android.bp
index 707b521..3c4b5e9 100644
--- a/camera/metadata/3.2/Android.bp
+++ b/camera/metadata/3.2/Android.bp
@@ -32,13 +32,16 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.camera.metadata@3.2",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.camera.metadata@3.2_genc++"],
     generated_headers: ["android.hardware.camera.metadata@3.2_genc++_headers"],
     export_generated_headers: ["android.hardware.camera.metadata@3.2_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/camera/provider/2.4/Android.bp b/camera/provider/2.4/Android.bp
index 36a726a..82a3a78 100644
--- a/camera/provider/2.4/Android.bp
+++ b/camera/provider/2.4/Android.bp
@@ -42,13 +42,16 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.camera.provider@2.4",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.camera.provider@2.4_genc++"],
     generated_headers: ["android.hardware.camera.provider@2.4_genc++_headers"],
     export_generated_headers: ["android.hardware.camera.provider@2.4_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/camera/provider/2.4/default/OWNERS b/camera/provider/2.4/default/OWNERS
new file mode 100644
index 0000000..18acfee
--- /dev/null
+++ b/camera/provider/2.4/default/OWNERS
@@ -0,0 +1,6 @@
+cychen@google.com
+epeev@google.com
+etalvala@google.com
+shuzhenwang@google.com
+yinchiayeh@google.com
+zhijunhe@google.com
diff --git a/camera/provider/2.4/vts/OWNERS b/camera/provider/2.4/vts/OWNERS
new file mode 100644
index 0000000..003fe71
--- /dev/null
+++ b/camera/provider/2.4/vts/OWNERS
@@ -0,0 +1,11 @@
+# Camera team
+cychen@google.com
+epeev@google.com
+etalvala@google.com
+shuzhenwang@google.com
+yinchiayeh@google.com
+zhijunhe@google.com
+
+# VTS team
+yim@google.com
+zhuoyao@google.com
diff --git a/camera/provider/2.4/vts/functional/Android.bp b/camera/provider/2.4/vts/functional/Android.bp
index 439fe3d..84d76f1 100644
--- a/camera/provider/2.4/vts/functional/Android.bp
+++ b/camera/provider/2.4/vts/functional/Android.bp
@@ -16,30 +16,27 @@
 
 cc_test {
     name: "VtsHalCameraProviderV2_4TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalCameraProviderV2_4TargetTest.cpp"],
+
+    // TODO(b/64437680): Assume these are always available on the device.
     shared_libs: [
-        "liblog",
-        "libhidlbase",
-        "libhidltransport",
-        "libcutils",
-        "libutils",
-        "android.hardware.camera.provider@2.4",
-        "android.hardware.camera.device@3.2",
-        "android.hardware.camera.device@1.0",
-        "libcamera_metadata",
         "libbinder",
+        "libcamera_metadata",
+        "libfmq",
         "libgui",
         "libui",
-        "libfmq",
     ],
+
+    // Statically link to libs not guaranteed to be present on the device.
     static_libs: [
-        "VtsHalHidlTargetTestBase",
-        "libgrallocusage",
+        "android.hardware.camera.common@1.0",
         "android.hardware.camera.common@1.0-helper",
-    ],
-    cflags: [
-        "-O0",
-        "-g",
+        "android.hardware.camera.device@1.0",
+        "android.hardware.camera.device@3.2",
+        "android.hardware.camera.provider@2.4",
+        "android.hardware.graphics.common@1.0",
+        "android.hardware.graphics.mapper@2.0",
+        "libgrallocusage",
     ],
 }
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index 6f04efc..1392896 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -43,6 +43,7 @@
 #include <ui/GraphicBuffer.h>
 
 #include <VtsHalHidlTargetTestBase.h>
+#include <VtsHalHidlTargetTestEnvBase.h>
 
 using ::android::hardware::Return;
 using ::android::hardware::Void;
@@ -100,8 +101,6 @@
 using ResultMetadataQueue = MessageQueue<uint8_t, kSynchronizedReadWrite>;
 using ::android::hidl::manager::V1_0::IServiceManager;
 
-const char kCameraPassthroughServiceName[] = "legacy/0";
-const char *kProviderFQName = "android.hardware.camera.provider@2.4::ICameraProvider";
 const uint32_t kMaxPreviewWidth = 1920;
 const uint32_t kMaxPreviewHeight = 1080;
 const uint32_t kMaxVideoWidth = 4096;
@@ -231,66 +230,26 @@
 }
 
 // Test environment for camera
-class CameraHidlEnvironment : public ::testing::Environment {
-public:
+class CameraHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
+   public:
     // get the test environment singleton
     static CameraHidlEnvironment* Instance() {
         static CameraHidlEnvironment* instance = new CameraHidlEnvironment;
         return instance;
     }
 
-    virtual void SetUp() override;
-    virtual void TearDown() override;
+    virtual void HidlSetUp() override { ALOGI("SetUp CameraHidlEnvironment"); }
 
-    std::unordered_map<std::string, sp<ICameraProvider> > mProviders;
+    virtual void HidlTearDown() override { ALOGI("TearDown CameraHidlEnvironment"); }
 
-private:
+    virtual void registerTestServices() override { registerTestService<ICameraProvider>(); }
+
+   private:
     CameraHidlEnvironment() {}
 
     GTEST_DISALLOW_COPY_AND_ASSIGN_(CameraHidlEnvironment);
 };
 
-void CameraHidlEnvironment::SetUp() {
-    sp<IServiceManager> manager = IServiceManager::getService();
-    ASSERT_NE(manager, nullptr);
-
-    manager->listByInterface(kProviderFQName,
-                             [this](const hidl_vec<hidl_string> &registered) {
-        std::string name;
-        uint32_t id;
-        sp<ICameraProvider> provider = nullptr;
-        for (size_t i = 0; i < registered.size(); i++) {
-            ASSERT_TRUE(parseProviderName(registered[i],
-                    &name /*out*/, &id /*out*/));
-            provider = ICameraProvider::tryGetService(registered[i]);
-            ALOGI_IF(provider, "provider is not nullptr, %p", provider.get());
-            if (nullptr != provider.get()) {
-                mProviders.emplace(name, provider);
-            }
-        }
-    });
-
-    std::string legacyName;
-    uint32_t legacyId;
-    ASSERT_TRUE(parseProviderName(kCameraPassthroughServiceName,
-            &legacyName /*out*/, &legacyId /*out*/));
-    auto legacyIt = mProviders.find(legacyName);
-    //Add any legacy passthrough implementations
-    if (legacyIt == mProviders.end()) {
-        sp<ICameraProvider> provider = ICameraProvider::tryGetService(
-                kCameraPassthroughServiceName);
-        if (nullptr != provider.get()) {
-            mProviders.emplace(legacyName, provider);
-        }
-    }
-
-    ASSERT_FALSE(mProviders.empty());
-}
-
-void CameraHidlEnvironment::TearDown() {
-    ALOGI("TearDown CameraHidlEnvironment");
-}
-
 struct BufferItemHander: public BufferItemConsumer::FrameAvailableListener {
     BufferItemHander(wp<BufferItemConsumer> consumer) : mConsumer(consumer) {}
 
@@ -533,23 +492,32 @@
 // The main test class for camera HIDL HAL.
 class CameraHidlTest : public ::testing::VtsHalHidlTargetTestBase {
 public:
-    virtual void SetUp() override {}
-    virtual void TearDown() override {}
+ virtual void SetUp() override {
+     string service_name = CameraHidlEnvironment::Instance()->getServiceName<ICameraProvider>();
+     ALOGI("get service with name: %s", service_name.c_str());
+     mProvider = ::testing::VtsHalHidlTargetTestBase::getService<ICameraProvider>(service_name);
+     ASSERT_NE(mProvider, nullptr);
 
-    hidl_vec<hidl_string> getCameraDeviceNames(sp<ICameraProvider> provider);
+     uint32_t id;
+     ASSERT_TRUE(parseProviderName(service_name, &mProviderType, &id));
+ }
+ virtual void TearDown() override {}
 
-    struct EmptyDeviceCb : public ICameraDeviceCallback {
-        virtual Return<void> processCaptureResult(const hidl_vec<CaptureResult>& /*results*/) override {
-            ALOGI("processCaptureResult callback");
-            ADD_FAILURE(); // Empty callback should not reach here
-            return Void();
-        }
+ hidl_vec<hidl_string> getCameraDeviceNames(sp<ICameraProvider> provider);
 
-        virtual Return<void> notify(const hidl_vec<NotifyMsg>& /*msgs*/) override {
-            ALOGI("notify callback");
-            ADD_FAILURE(); // Empty callback should not reach here
-            return Void();
-        }
+ struct EmptyDeviceCb : public ICameraDeviceCallback {
+     virtual Return<void> processCaptureResult(
+         const hidl_vec<CaptureResult>& /*results*/) override {
+         ALOGI("processCaptureResult callback");
+         ADD_FAILURE();  // Empty callback should not reach here
+         return Void();
+     }
+
+     virtual Return<void> notify(const hidl_vec<NotifyMsg>& /*msgs*/) override {
+         ALOGI("notify callback");
+         ADD_FAILURE();  // Empty callback should not reach here
+         return Void();
+     }
     };
 
     struct DeviceCb : public ICameraDeviceCallback {
@@ -743,6 +711,11 @@
 
     // Holds camera registered buffers
     std::unordered_map<uint32_t, sp<::android::MemoryHeapBase> > mMemoryPool;
+
+    // Camera provider service
+    sp<ICameraProvider> mProvider;
+    // Camera provider type.
+    std::string mProviderType;
 };
 
 Return<void> CameraHidlTest::Camera1DeviceCb::notifyCallback(
@@ -1044,59 +1017,45 @@
 // Test if ICameraProvider::isTorchModeSupported returns Status::OK
 TEST_F(CameraHidlTest, isTorchModeSupported) {
     Return<void> ret;
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        ret = provider.second->isSetTorchModeSupported(
-            [&](auto status, bool support) {
-                ALOGI("isSetTorchModeSupported returns status:%d supported:%d",
-                        (int)status, support);
-                ASSERT_EQ(Status::OK, status);
-            });
-        ASSERT_TRUE(ret.isOk());
-    }
+    ret = mProvider->isSetTorchModeSupported([&](auto status, bool support) {
+        ALOGI("isSetTorchModeSupported returns status:%d supported:%d", (int)status, support);
+        ASSERT_EQ(Status::OK, status);
+    });
+    ASSERT_TRUE(ret.isOk());
 }
 
 // TODO: consider removing this test if getCameraDeviceNames() has the same coverage
 TEST_F(CameraHidlTest, getCameraIdList) {
     Return<void> ret;
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        ret = provider.second->getCameraIdList(
-            [&](auto status, const auto& idList) {
-                ALOGI("getCameraIdList returns status:%d", (int)status);
-                for (size_t i = 0; i < idList.size(); i++) {
-                    ALOGI("Camera Id[%zu] is %s", i, idList[i].c_str());
-                }
-                ASSERT_EQ(Status::OK, status);
-                // This is true for internal camera provider.
-                // Not necessary hold for external cameras providers
-                ASSERT_GT(idList.size(), 0u);
-            });
-        ASSERT_TRUE(ret.isOk());
-    }
+    ret = mProvider->getCameraIdList([&](auto status, const auto& idList) {
+        ALOGI("getCameraIdList returns status:%d", (int)status);
+        for (size_t i = 0; i < idList.size(); i++) {
+            ALOGI("Camera Id[%zu] is %s", i, idList[i].c_str());
+        }
+        ASSERT_EQ(Status::OK, status);
+        // This is true for internal camera provider.
+        // Not necessary hold for external cameras providers
+        ASSERT_GT(idList.size(), 0u);
+    });
+    ASSERT_TRUE(ret.isOk());
 }
 
 // Test if ICameraProvider::getVendorTags returns Status::OK
 TEST_F(CameraHidlTest, getVendorTags) {
     Return<void> ret;
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        ret = provider.second->getVendorTags(
-            [&](auto status, const auto& vendorTagSecs) {
-                ALOGI("getVendorTags returns status:%d numSections %zu",
-                        (int)status, vendorTagSecs.size());
-                for (size_t i = 0; i < vendorTagSecs.size(); i++) {
-                    ALOGI("Vendor tag section %zu name %s",
-                            i, vendorTagSecs[i].sectionName.c_str());
-                    for (size_t j = 0; j < vendorTagSecs[i].tags.size(); j++) {
-                        const auto& tag = vendorTagSecs[i].tags[j];
-                        ALOGI("Vendor tag id %u name %s type %d",
-                                tag.tagId,
-                                tag.tagName.c_str(),
-                                (int) tag.tagType);
-                    }
-                }
-                ASSERT_EQ(Status::OK, status);
-            });
-        ASSERT_TRUE(ret.isOk());
-    }
+    ret = mProvider->getVendorTags([&](auto status, const auto& vendorTagSecs) {
+        ALOGI("getVendorTags returns status:%d numSections %zu", (int)status, vendorTagSecs.size());
+        for (size_t i = 0; i < vendorTagSecs.size(); i++) {
+            ALOGI("Vendor tag section %zu name %s", i, vendorTagSecs[i].sectionName.c_str());
+            for (size_t j = 0; j < vendorTagSecs[i].tags.size(); j++) {
+                const auto& tag = vendorTagSecs[i].tags[j];
+                ALOGI("Vendor tag id %u name %s type %d", tag.tagId, tag.tagName.c_str(),
+                      (int)tag.tagType);
+            }
+        }
+        ASSERT_EQ(Status::OK, status);
+    });
+    ASSERT_TRUE(ret.isOk());
 }
 
 // Test if ICameraProvider::setCallback returns Status::OK
@@ -1119,49 +1078,37 @@
         }
     };
     sp<ProviderCb> cb = new ProviderCb;
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        auto status = provider.second->setCallback(cb);
-        ASSERT_TRUE(status.isOk());
-        ASSERT_EQ(Status::OK, status);
-        // Reset callback since cb will go out of scope
-        status = provider.second->setCallback(nullptr);
-        ASSERT_TRUE(status.isOk());
-        ASSERT_EQ(Status::OK, status);
-    }
+    auto status = mProvider->setCallback(cb);
+    ASSERT_TRUE(status.isOk());
+    ASSERT_EQ(Status::OK, status);
+    status = mProvider->setCallback(nullptr);
+    ASSERT_TRUE(status.isOk());
+    ASSERT_EQ(Status::OK, status);
 }
 
 // Test if ICameraProvider::getCameraDeviceInterface returns Status::OK and non-null device
 TEST_F(CameraHidlTest, getCameraDeviceInterface) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
 
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_3_2) {
-                Return<void> ret;
-                ret = provider.second->getCameraDeviceInterface_V3_x(
-                    name,
-                    [&](auto status, const auto& device3_2) {
-                        ALOGI("getCameraDeviceInterface_V3_x returns status:%d",
-                              (int)status);
-                        ASSERT_EQ(Status::OK, status);
-                        ASSERT_NE(device3_2, nullptr);
-                    });
-                ASSERT_TRUE(ret.isOk());
-            } else if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_1_0) {
-                Return<void> ret;
-                ret = provider.second->getCameraDeviceInterface_V1_x(
-                    name,
-                    [&](auto status, const auto& device1) {
-                        ALOGI("getCameraDeviceInterface_V1_x returns status:%d",
-                              (int)status);
-                        ASSERT_EQ(Status::OK, status);
-                        ASSERT_NE(device1, nullptr);
-                    });
-                ASSERT_TRUE(ret.isOk());
-            }
+    for (const auto& name : cameraDeviceNames) {
+        if (getCameraDeviceVersion(name, mProviderType) == CAMERA_DEVICE_API_VERSION_3_2) {
+            Return<void> ret;
+            ret = mProvider->getCameraDeviceInterface_V3_x(
+                name, [&](auto status, const auto& device3_2) {
+                    ALOGI("getCameraDeviceInterface_V3_x returns status:%d", (int)status);
+                    ASSERT_EQ(Status::OK, status);
+                    ASSERT_NE(device3_2, nullptr);
+                });
+            ASSERT_TRUE(ret.isOk());
+        } else if (getCameraDeviceVersion(name, mProviderType) == CAMERA_DEVICE_API_VERSION_1_0) {
+            Return<void> ret;
+            ret = mProvider->getCameraDeviceInterface_V1_x(
+                name, [&](auto status, const auto& device1) {
+                    ALOGI("getCameraDeviceInterface_V1_x returns status:%d", (int)status);
+                    ASSERT_EQ(Status::OK, status);
+                    ASSERT_NE(device1, nullptr);
+                });
+            ASSERT_TRUE(ret.isOk());
         }
     }
 }
@@ -1169,66 +1116,55 @@
 // Verify that the device resource cost can be retrieved and the values are
 // sane.
 TEST_F(CameraHidlTest, getResourceCost) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
 
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_3_2) {
-                ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice> device3_2;
-                ALOGI("getResourceCost: Testing camera device %s", name.c_str());
-                Return<void> ret;
-                ret = provider.second->getCameraDeviceInterface_V3_x(
-                    name,
-                    [&](auto status, const auto& device) {
-                        ALOGI("getCameraDeviceInterface_V3_x returns status:%d",
-                              (int)status);
-                        ASSERT_EQ(Status::OK, status);
-                        ASSERT_NE(device, nullptr);
-                        device3_2 = device;
-                    });
-                ASSERT_TRUE(ret.isOk());
+    for (const auto& name : cameraDeviceNames) {
+        if (getCameraDeviceVersion(name, mProviderType) == CAMERA_DEVICE_API_VERSION_3_2) {
+            ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice> device3_2;
+            ALOGI("getResourceCost: Testing camera device %s", name.c_str());
+            Return<void> ret;
+            ret = mProvider->getCameraDeviceInterface_V3_x(
+                name, [&](auto status, const auto& device) {
+                    ALOGI("getCameraDeviceInterface_V3_x returns status:%d", (int)status);
+                    ASSERT_EQ(Status::OK, status);
+                    ASSERT_NE(device, nullptr);
+                    device3_2 = device;
+                });
+            ASSERT_TRUE(ret.isOk());
 
-                ret = device3_2->getResourceCost(
-                    [&](auto status, const auto& resourceCost) {
-                        ALOGI("getResourceCost returns status:%d", (int)status);
-                        ASSERT_EQ(Status::OK, status);
-                        ALOGI("    Resource cost is %d", resourceCost.resourceCost);
-                        ASSERT_LE(resourceCost.resourceCost, 100u);
-                        for (const auto& name : resourceCost.conflictingDevices) {
-                            ALOGI("    Conflicting device: %s", name.c_str());
-                        }
-                    });
-                ASSERT_TRUE(ret.isOk());
-            } else {
-                ::android::sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
-                ALOGI("getResourceCost: Testing camera device %s", name.c_str());
-                Return<void> ret;
-                ret = provider.second->getCameraDeviceInterface_V1_x(
-                    name,
-                    [&](auto status, const auto& device) {
-                        ALOGI("getCameraDeviceInterface_V1_x returns status:%d",
-                              (int)status);
-                        ASSERT_EQ(Status::OK, status);
-                        ASSERT_NE(device, nullptr);
-                        device1 = device;
-                    });
-                ASSERT_TRUE(ret.isOk());
+            ret = device3_2->getResourceCost([&](auto status, const auto& resourceCost) {
+                ALOGI("getResourceCost returns status:%d", (int)status);
+                ASSERT_EQ(Status::OK, status);
+                ALOGI("    Resource cost is %d", resourceCost.resourceCost);
+                ASSERT_LE(resourceCost.resourceCost, 100u);
+                for (const auto& name : resourceCost.conflictingDevices) {
+                    ALOGI("    Conflicting device: %s", name.c_str());
+                }
+            });
+            ASSERT_TRUE(ret.isOk());
+        } else {
+            ::android::sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
+            ALOGI("getResourceCost: Testing camera device %s", name.c_str());
+            Return<void> ret;
+            ret = mProvider->getCameraDeviceInterface_V1_x(
+                name, [&](auto status, const auto& device) {
+                    ALOGI("getCameraDeviceInterface_V1_x returns status:%d", (int)status);
+                    ASSERT_EQ(Status::OK, status);
+                    ASSERT_NE(device, nullptr);
+                    device1 = device;
+                });
+            ASSERT_TRUE(ret.isOk());
 
-                ret = device1->getResourceCost(
-                    [&](auto status, const auto& resourceCost) {
-                        ALOGI("getResourceCost returns status:%d", (int)status);
-                        ASSERT_EQ(Status::OK, status);
-                        ALOGI("    Resource cost is %d",
-                              resourceCost.resourceCost);
-                        ASSERT_LE(resourceCost.resourceCost, 100u);
-                        for (const auto& name : resourceCost.conflictingDevices) {
-                            ALOGI("    Conflicting device: %s", name.c_str());
-                        }
-                    });
-                ASSERT_TRUE(ret.isOk());
-            }
+            ret = device1->getResourceCost([&](auto status, const auto& resourceCost) {
+                ALOGI("getResourceCost returns status:%d", (int)status);
+                ASSERT_EQ(Status::OK, status);
+                ALOGI("    Resource cost is %d", resourceCost.resourceCost);
+                ASSERT_LE(resourceCost.resourceCost, 100u);
+                for (const auto& name : resourceCost.conflictingDevices) {
+                    ALOGI("    Conflicting device: %s", name.c_str());
+                }
+            });
+            ASSERT_TRUE(ret.isOk());
         }
     }
 }
@@ -1236,143 +1172,117 @@
 // Verify that the static camera info can be retrieved
 // successfully.
 TEST_F(CameraHidlTest, getCameraInfo) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
 
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_1_0) {
-                ::android::sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
-                ALOGI("getCameraCharacteristics: Testing camera device %s",
-                      name.c_str());
-                Return<void> ret;
-                ret = provider.second->getCameraDeviceInterface_V1_x(
-                    name,
-                    [&](auto status, const auto& device) {
-                        ALOGI("getCameraDeviceInterface_V1_x returns status:%d",
-                              (int)status);
-                        ASSERT_EQ(Status::OK, status);
-                        ASSERT_NE(device, nullptr);
-                        device1 = device;
-                    });
-                ASSERT_TRUE(ret.isOk());
+    for (const auto& name : cameraDeviceNames) {
+        if (getCameraDeviceVersion(name, mProviderType) == CAMERA_DEVICE_API_VERSION_1_0) {
+            ::android::sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
+            ALOGI("getCameraCharacteristics: Testing camera device %s", name.c_str());
+            Return<void> ret;
+            ret = mProvider->getCameraDeviceInterface_V1_x(
+                name, [&](auto status, const auto& device) {
+                    ALOGI("getCameraDeviceInterface_V1_x returns status:%d", (int)status);
+                    ASSERT_EQ(Status::OK, status);
+                    ASSERT_NE(device, nullptr);
+                    device1 = device;
+                });
+            ASSERT_TRUE(ret.isOk());
 
-                ret = device1->getCameraInfo(
-                    [&](auto status, const auto& info) {
-                        ALOGI("getCameraInfo returns status:%d", (int)status);
-                        ASSERT_EQ(Status::OK, status);
-                        switch(info.orientation) {
-                            case 0:
-                            case 90:
-                            case 180:
-                            case 270:
-                                //Expected cases
-                                ALOGI("camera orientation: %d", info.orientation);
-                                break;
-                            default:
-                                FAIL() << "Unexpected camera orientation:" << info.orientation;
-                        }
-                        switch(info.facing) {
-                            case CameraFacing::BACK:
-                            case CameraFacing::FRONT:
-                            case CameraFacing::EXTERNAL:
-                                //Expected cases
-                                ALOGI("camera facing: %d", info.facing);
-                                break;
-                            default:
-                                FAIL() << "Unexpected camera facing:" << static_cast<uint32_t> (
-                                        info.facing);
-                        }
-                    });
-                ASSERT_TRUE(ret.isOk());
-            }
+            ret = device1->getCameraInfo([&](auto status, const auto& info) {
+                ALOGI("getCameraInfo returns status:%d", (int)status);
+                ASSERT_EQ(Status::OK, status);
+                switch (info.orientation) {
+                    case 0:
+                    case 90:
+                    case 180:
+                    case 270:
+                        // Expected cases
+                        ALOGI("camera orientation: %d", info.orientation);
+                        break;
+                    default:
+                        FAIL() << "Unexpected camera orientation:" << info.orientation;
+                }
+                switch (info.facing) {
+                    case CameraFacing::BACK:
+                    case CameraFacing::FRONT:
+                    case CameraFacing::EXTERNAL:
+                        // Expected cases
+                        ALOGI("camera facing: %d", info.facing);
+                        break;
+                    default:
+                        FAIL() << "Unexpected camera facing:" << static_cast<uint32_t>(info.facing);
+                }
+            });
+            ASSERT_TRUE(ret.isOk());
         }
     }
 }
 
 // Check whether preview window can be configured
 TEST_F(CameraHidlTest, setPreviewWindow) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
 
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_1_0) {
-                sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
-                openCameraDevice(name, provider.second, &device1 /*out*/);
-                ASSERT_NE(nullptr, device1.get());
-                sp<BufferItemConsumer> bufferItemConsumer;
-                sp<BufferItemHander> bufferHandler;
-                setupPreviewWindow(device1,
-                        &bufferItemConsumer /*out*/, &bufferHandler /*out*/);
+    for (const auto& name : cameraDeviceNames) {
+        if (getCameraDeviceVersion(name, mProviderType) == CAMERA_DEVICE_API_VERSION_1_0) {
+            sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
+            openCameraDevice(name, mProvider, &device1 /*out*/);
+            ASSERT_NE(nullptr, device1.get());
+            sp<BufferItemConsumer> bufferItemConsumer;
+            sp<BufferItemHander> bufferHandler;
+            setupPreviewWindow(device1, &bufferItemConsumer /*out*/, &bufferHandler /*out*/);
 
-                Return<void> ret;
-                ret = device1->close();
-                ASSERT_TRUE(ret.isOk());
-            }
+            Return<void> ret;
+            ret = device1->close();
+            ASSERT_TRUE(ret.isOk());
         }
     }
 }
 
 // Verify that setting preview window fails in case device is not open
 TEST_F(CameraHidlTest, setPreviewWindowInvalid) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
 
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_1_0) {
-                ::android::sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
-                ALOGI("getCameraCharacteristics: Testing camera device %s",
-                      name.c_str());
-                Return<void> ret;
-                ret = provider.second->getCameraDeviceInterface_V1_x(
-                    name,
-                    [&](auto status, const auto& device) {
-                        ALOGI("getCameraDeviceInterface_V1_x returns status:%d",
-                              (int)status);
-                        ASSERT_EQ(Status::OK, status);
-                        ASSERT_NE(device, nullptr);
-                        device1 = device;
-                    });
-                ASSERT_TRUE(ret.isOk());
+    for (const auto& name : cameraDeviceNames) {
+        if (getCameraDeviceVersion(name, mProviderType) == CAMERA_DEVICE_API_VERSION_1_0) {
+            ::android::sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
+            ALOGI("getCameraCharacteristics: Testing camera device %s", name.c_str());
+            Return<void> ret;
+            ret = mProvider->getCameraDeviceInterface_V1_x(
+                name, [&](auto status, const auto& device) {
+                    ALOGI("getCameraDeviceInterface_V1_x returns status:%d", (int)status);
+                    ASSERT_EQ(Status::OK, status);
+                    ASSERT_NE(device, nullptr);
+                    device1 = device;
+                });
+            ASSERT_TRUE(ret.isOk());
 
-                Return<Status> returnStatus = device1->setPreviewWindow(nullptr);
-                ASSERT_TRUE(returnStatus.isOk());
-                ASSERT_EQ(Status::OPERATION_NOT_SUPPORTED, returnStatus);
-            }
+            Return<Status> returnStatus = device1->setPreviewWindow(nullptr);
+            ASSERT_TRUE(returnStatus.isOk());
+            ASSERT_EQ(Status::OPERATION_NOT_SUPPORTED, returnStatus);
         }
     }
 }
 
 // Start and stop preview checking whether it gets enabled in between.
 TEST_F(CameraHidlTest, startStopPreview) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
 
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_1_0) {
-                sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
-                openCameraDevice(name, provider.second, &device1 /*out*/);
-                ASSERT_NE(nullptr, device1.get());
-                sp<BufferItemConsumer> bufferItemConsumer;
-                sp<BufferItemHander> bufferHandler;
-                setupPreviewWindow(device1,
-                        &bufferItemConsumer /*out*/, &bufferHandler /*out*/);
+    for (const auto& name : cameraDeviceNames) {
+        if (getCameraDeviceVersion(name, mProviderType) == CAMERA_DEVICE_API_VERSION_1_0) {
+            sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
+            openCameraDevice(name, mProvider, &device1 /*out*/);
+            ASSERT_NE(nullptr, device1.get());
+            sp<BufferItemConsumer> bufferItemConsumer;
+            sp<BufferItemHander> bufferHandler;
+            setupPreviewWindow(device1, &bufferItemConsumer /*out*/, &bufferHandler /*out*/);
 
-                startPreview(device1);
+            startPreview(device1);
 
-                Return<bool> returnBoolStatus = device1->previewEnabled();
-                ASSERT_TRUE(returnBoolStatus.isOk());
-                ASSERT_TRUE(returnBoolStatus);
+            Return<bool> returnBoolStatus = device1->previewEnabled();
+            ASSERT_TRUE(returnBoolStatus.isOk());
+            ASSERT_TRUE(returnBoolStatus);
 
-                stopPreviewAndClose(device1);
-            }
+            stopPreviewAndClose(device1);
         }
     }
 }
@@ -1380,646 +1290,552 @@
 // Start preview without active preview window. Preview should start as soon
 // as a valid active window gets configured.
 TEST_F(CameraHidlTest, startStopPreviewDelayed) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
 
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_1_0) {
-                sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
-                openCameraDevice(name, provider.second, &device1 /*out*/);
-                ASSERT_NE(nullptr, device1.get());
+    for (const auto& name : cameraDeviceNames) {
+        if (getCameraDeviceVersion(name, mProviderType) == CAMERA_DEVICE_API_VERSION_1_0) {
+            sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
+            openCameraDevice(name, mProvider, &device1 /*out*/);
+            ASSERT_NE(nullptr, device1.get());
 
-                Return<Status> returnStatus = device1->setPreviewWindow(nullptr);
-                ASSERT_TRUE(returnStatus.isOk());
-                ASSERT_EQ(Status::OK, returnStatus);
+            Return<Status> returnStatus = device1->setPreviewWindow(nullptr);
+            ASSERT_TRUE(returnStatus.isOk());
+            ASSERT_EQ(Status::OK, returnStatus);
 
-                startPreview(device1);
+            startPreview(device1);
 
-                sp<BufferItemConsumer> bufferItemConsumer;
-                sp<BufferItemHander> bufferHandler;
-                setupPreviewWindow(device1, &bufferItemConsumer /*out*/,
-                        &bufferHandler /*out*/);
+            sp<BufferItemConsumer> bufferItemConsumer;
+            sp<BufferItemHander> bufferHandler;
+            setupPreviewWindow(device1, &bufferItemConsumer /*out*/, &bufferHandler /*out*/);
 
-                //Preview should get enabled now
-                Return<bool> returnBoolStatus = device1->previewEnabled();
-                ASSERT_TRUE(returnBoolStatus.isOk());
-                ASSERT_TRUE(returnBoolStatus);
+            // Preview should get enabled now
+            Return<bool> returnBoolStatus = device1->previewEnabled();
+            ASSERT_TRUE(returnBoolStatus.isOk());
+            ASSERT_TRUE(returnBoolStatus);
 
-                stopPreviewAndClose(device1);
-            }
+            stopPreviewAndClose(device1);
         }
     }
 }
 
 // Verify that image capture behaves as expected along with preview callbacks.
 TEST_F(CameraHidlTest, takePicture) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
 
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_1_0) {
-                sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
-                openCameraDevice(name, provider.second, &device1 /*out*/);
-                ASSERT_NE(nullptr, device1.get());
-                sp<BufferItemConsumer> bufferItemConsumer;
-                sp<BufferItemHander> bufferHandler;
-                setupPreviewWindow(device1, &bufferItemConsumer /*out*/,
-                        &bufferHandler /*out*/);
+    for (const auto& name : cameraDeviceNames) {
+        if (getCameraDeviceVersion(name, mProviderType) == CAMERA_DEVICE_API_VERSION_1_0) {
+            sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
+            openCameraDevice(name, mProvider, &device1 /*out*/);
+            ASSERT_NE(nullptr, device1.get());
+            sp<BufferItemConsumer> bufferItemConsumer;
+            sp<BufferItemHander> bufferHandler;
+            setupPreviewWindow(device1, &bufferItemConsumer /*out*/, &bufferHandler /*out*/);
 
-                {
-                    std::unique_lock<std::mutex> l(mLock);
-                    mDataMessageTypeReceived = DataCallbackMsg::RAW_IMAGE_NOTIFY;
-                }
-
-                enableMsgType((unsigned int)DataCallbackMsg::PREVIEW_FRAME,
-                              device1);
-                startPreview(device1);
-
-                {
-                    std::unique_lock<std::mutex> l(mLock);
-                    waitForFrameLocked(DataCallbackMsg::PREVIEW_FRAME, l);
-                }
-
-                disableMsgType((unsigned int)DataCallbackMsg::PREVIEW_FRAME,
-                                device1);
-                enableMsgType((unsigned int)DataCallbackMsg::COMPRESSED_IMAGE,
-                        device1);
-
-                {
-                    std::unique_lock<std::mutex> l(mLock);
-                    mDataMessageTypeReceived = DataCallbackMsg::RAW_IMAGE_NOTIFY;
-                }
-
-                Return<Status> returnStatus = device1->takePicture();
-                ASSERT_TRUE(returnStatus.isOk());
-                ASSERT_EQ(Status::OK, returnStatus);
-
-                {
-                    std::unique_lock<std::mutex> l(mLock);
-                    waitForFrameLocked(DataCallbackMsg::COMPRESSED_IMAGE, l);
-                }
-
-                disableMsgType((unsigned int)DataCallbackMsg::COMPRESSED_IMAGE,
-                        device1);
-                stopPreviewAndClose(device1);
+            {
+                std::unique_lock<std::mutex> l(mLock);
+                mDataMessageTypeReceived = DataCallbackMsg::RAW_IMAGE_NOTIFY;
             }
+
+            enableMsgType((unsigned int)DataCallbackMsg::PREVIEW_FRAME, device1);
+            startPreview(device1);
+
+            {
+                std::unique_lock<std::mutex> l(mLock);
+                waitForFrameLocked(DataCallbackMsg::PREVIEW_FRAME, l);
+            }
+
+            disableMsgType((unsigned int)DataCallbackMsg::PREVIEW_FRAME, device1);
+            enableMsgType((unsigned int)DataCallbackMsg::COMPRESSED_IMAGE, device1);
+
+            {
+                std::unique_lock<std::mutex> l(mLock);
+                mDataMessageTypeReceived = DataCallbackMsg::RAW_IMAGE_NOTIFY;
+            }
+
+            Return<Status> returnStatus = device1->takePicture();
+            ASSERT_TRUE(returnStatus.isOk());
+            ASSERT_EQ(Status::OK, returnStatus);
+
+            {
+                std::unique_lock<std::mutex> l(mLock);
+                waitForFrameLocked(DataCallbackMsg::COMPRESSED_IMAGE, l);
+            }
+
+            disableMsgType((unsigned int)DataCallbackMsg::COMPRESSED_IMAGE, device1);
+            stopPreviewAndClose(device1);
         }
     }
 }
 
 // Image capture should fail in case preview didn't get enabled first.
 TEST_F(CameraHidlTest, takePictureFail) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
 
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_1_0) {
-                sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
-                openCameraDevice(name, provider.second, &device1 /*out*/);
-                ASSERT_NE(nullptr, device1.get());
+    for (const auto& name : cameraDeviceNames) {
+        if (getCameraDeviceVersion(name, mProviderType) == CAMERA_DEVICE_API_VERSION_1_0) {
+            sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
+            openCameraDevice(name, mProvider, &device1 /*out*/);
+            ASSERT_NE(nullptr, device1.get());
 
-                Return<Status> returnStatus = device1->takePicture();
-                ASSERT_TRUE(returnStatus.isOk());
-                ASSERT_NE(Status::OK, returnStatus);
+            Return<Status> returnStatus = device1->takePicture();
+            ASSERT_TRUE(returnStatus.isOk());
+            ASSERT_NE(Status::OK, returnStatus);
 
-                Return<void> ret = device1->close();
-                ASSERT_TRUE(ret.isOk());
-            }
+            Return<void> ret = device1->close();
+            ASSERT_TRUE(ret.isOk());
         }
     }
 }
 
 // Verify that image capture can be cancelled.
 TEST_F(CameraHidlTest, cancelPicture) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
 
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_1_0) {
-                sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
-                openCameraDevice(name, provider.second, &device1 /*out*/);
-                ASSERT_NE(nullptr, device1.get());
-                sp<BufferItemConsumer> bufferItemConsumer;
-                sp<BufferItemHander> bufferHandler;
-                setupPreviewWindow(device1, &bufferItemConsumer /*out*/,
-                        &bufferHandler /*out*/);
-                startPreview(device1);
+    for (const auto& name : cameraDeviceNames) {
+        if (getCameraDeviceVersion(name, mProviderType) == CAMERA_DEVICE_API_VERSION_1_0) {
+            sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
+            openCameraDevice(name, mProvider, &device1 /*out*/);
+            ASSERT_NE(nullptr, device1.get());
+            sp<BufferItemConsumer> bufferItemConsumer;
+            sp<BufferItemHander> bufferHandler;
+            setupPreviewWindow(device1, &bufferItemConsumer /*out*/, &bufferHandler /*out*/);
+            startPreview(device1);
 
-                Return<Status> returnStatus = device1->takePicture();
-                ASSERT_TRUE(returnStatus.isOk());
-                ASSERT_EQ(Status::OK, returnStatus);
+            Return<Status> returnStatus = device1->takePicture();
+            ASSERT_TRUE(returnStatus.isOk());
+            ASSERT_EQ(Status::OK, returnStatus);
 
-                returnStatus = device1->cancelPicture();
-                ASSERT_TRUE(returnStatus.isOk());
-                ASSERT_EQ(Status::OK, returnStatus);
+            returnStatus = device1->cancelPicture();
+            ASSERT_TRUE(returnStatus.isOk());
+            ASSERT_EQ(Status::OK, returnStatus);
 
-                stopPreviewAndClose(device1);
-            }
+            stopPreviewAndClose(device1);
         }
     }
 }
 
 // Image capture cancel is a no-op when image capture is not running.
 TEST_F(CameraHidlTest, cancelPictureNOP) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
 
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_1_0) {
-                sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
-                openCameraDevice(name, provider.second, &device1 /*out*/);
-                ASSERT_NE(nullptr, device1.get());
-                sp<BufferItemConsumer> bufferItemConsumer;
-                sp<BufferItemHander> bufferHandler;
-                setupPreviewWindow(device1, &bufferItemConsumer /*out*/,
-                        &bufferHandler /*out*/);
-                startPreview(device1);
+    for (const auto& name : cameraDeviceNames) {
+        if (getCameraDeviceVersion(name, mProviderType) == CAMERA_DEVICE_API_VERSION_1_0) {
+            sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
+            openCameraDevice(name, mProvider, &device1 /*out*/);
+            ASSERT_NE(nullptr, device1.get());
+            sp<BufferItemConsumer> bufferItemConsumer;
+            sp<BufferItemHander> bufferHandler;
+            setupPreviewWindow(device1, &bufferItemConsumer /*out*/, &bufferHandler /*out*/);
+            startPreview(device1);
 
-                Return<Status> returnStatus = device1->cancelPicture();
-                ASSERT_TRUE(returnStatus.isOk());
-                ASSERT_EQ(Status::OK, returnStatus);
+            Return<Status> returnStatus = device1->cancelPicture();
+            ASSERT_TRUE(returnStatus.isOk());
+            ASSERT_EQ(Status::OK, returnStatus);
 
-                stopPreviewAndClose(device1);
-            }
+            stopPreviewAndClose(device1);
         }
     }
 }
 
 // Test basic video recording.
 TEST_F(CameraHidlTest, startStopRecording) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
 
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_1_0) {
-                sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
-                openCameraDevice(name, provider.second, &device1 /*out*/);
-                ASSERT_NE(nullptr, device1.get());
-                sp<BufferItemConsumer> bufferItemConsumer;
-                sp<BufferItemHander> bufferHandler;
-                setupPreviewWindow(device1, &bufferItemConsumer /*out*/,
-                        &bufferHandler /*out*/);
+    for (const auto& name : cameraDeviceNames) {
+        if (getCameraDeviceVersion(name, mProviderType) == CAMERA_DEVICE_API_VERSION_1_0) {
+            sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
+            openCameraDevice(name, mProvider, &device1 /*out*/);
+            ASSERT_NE(nullptr, device1.get());
+            sp<BufferItemConsumer> bufferItemConsumer;
+            sp<BufferItemHander> bufferHandler;
+            setupPreviewWindow(device1, &bufferItemConsumer /*out*/, &bufferHandler /*out*/);
 
-                {
-                    std::unique_lock<std::mutex> l(mLock);
-                    mDataMessageTypeReceived = DataCallbackMsg::RAW_IMAGE_NOTIFY;
-                }
-
-                enableMsgType((unsigned int)DataCallbackMsg::PREVIEW_FRAME,
-                        device1);
-                startPreview(device1);
-
-                {
-                    std::unique_lock<std::mutex> l(mLock);
-                    waitForFrameLocked(DataCallbackMsg::PREVIEW_FRAME, l);
-                    mDataMessageTypeReceived = DataCallbackMsg::RAW_IMAGE_NOTIFY;
-                    mVideoBufferIndex = UINT32_MAX;
-                }
-
-                disableMsgType((unsigned int)DataCallbackMsg::PREVIEW_FRAME,
-                        device1);
-
-                bool videoMetaEnabled = false;
-                Return<Status> returnStatus = device1->storeMetaDataInBuffers(
-                        true);
-                ASSERT_TRUE(returnStatus.isOk());
-                // It is allowed for devices to not support this feature
-                ASSERT_TRUE((Status::OK == returnStatus) ||
-                        (Status::OPERATION_NOT_SUPPORTED == returnStatus));
-                if (Status::OK == returnStatus) {
-                    videoMetaEnabled = true;
-                }
-
-                enableMsgType((unsigned int)DataCallbackMsg::VIDEO_FRAME,
-                        device1);
-                Return<bool> returnBoolStatus = device1->recordingEnabled();
-                ASSERT_TRUE(returnBoolStatus.isOk());
-                ASSERT_FALSE(returnBoolStatus);
-
-                returnStatus = device1->startRecording();
-                ASSERT_TRUE(returnStatus.isOk());
-                ASSERT_EQ(Status::OK, returnStatus);
-
-                {
-                    std::unique_lock<std::mutex> l(mLock);
-                    waitForFrameLocked(DataCallbackMsg::VIDEO_FRAME, l);
-                    ASSERT_NE(UINT32_MAX, mVideoBufferIndex);
-                    disableMsgType((unsigned int)DataCallbackMsg::VIDEO_FRAME,
-                            device1);
-                }
-
-                returnBoolStatus = device1->recordingEnabled();
-                ASSERT_TRUE(returnBoolStatus.isOk());
-                ASSERT_TRUE(returnBoolStatus);
-
-                Return<void> ret;
-                if (videoMetaEnabled) {
-                    ret = device1->releaseRecordingFrameHandle(mVideoData,
-                            mVideoBufferIndex, mVideoNativeHandle);
-                    ASSERT_TRUE(ret.isOk());
-                } else {
-                    ret = device1->releaseRecordingFrame(mVideoData,
-                            mVideoBufferIndex);
-                    ASSERT_TRUE(ret.isOk());
-                }
-
-                ret = device1->stopRecording();
-                ASSERT_TRUE(ret.isOk());
-
-                stopPreviewAndClose(device1);
+            {
+                std::unique_lock<std::mutex> l(mLock);
+                mDataMessageTypeReceived = DataCallbackMsg::RAW_IMAGE_NOTIFY;
             }
+
+            enableMsgType((unsigned int)DataCallbackMsg::PREVIEW_FRAME, device1);
+            startPreview(device1);
+
+            {
+                std::unique_lock<std::mutex> l(mLock);
+                waitForFrameLocked(DataCallbackMsg::PREVIEW_FRAME, l);
+                mDataMessageTypeReceived = DataCallbackMsg::RAW_IMAGE_NOTIFY;
+                mVideoBufferIndex = UINT32_MAX;
+            }
+
+            disableMsgType((unsigned int)DataCallbackMsg::PREVIEW_FRAME, device1);
+
+            bool videoMetaEnabled = false;
+            Return<Status> returnStatus = device1->storeMetaDataInBuffers(true);
+            ASSERT_TRUE(returnStatus.isOk());
+            // It is allowed for devices to not support this feature
+            ASSERT_TRUE((Status::OK == returnStatus) ||
+                        (Status::OPERATION_NOT_SUPPORTED == returnStatus));
+            if (Status::OK == returnStatus) {
+                videoMetaEnabled = true;
+            }
+
+            enableMsgType((unsigned int)DataCallbackMsg::VIDEO_FRAME, device1);
+            Return<bool> returnBoolStatus = device1->recordingEnabled();
+            ASSERT_TRUE(returnBoolStatus.isOk());
+            ASSERT_FALSE(returnBoolStatus);
+
+            returnStatus = device1->startRecording();
+            ASSERT_TRUE(returnStatus.isOk());
+            ASSERT_EQ(Status::OK, returnStatus);
+
+            {
+                std::unique_lock<std::mutex> l(mLock);
+                waitForFrameLocked(DataCallbackMsg::VIDEO_FRAME, l);
+                ASSERT_NE(UINT32_MAX, mVideoBufferIndex);
+                disableMsgType((unsigned int)DataCallbackMsg::VIDEO_FRAME, device1);
+            }
+
+            returnBoolStatus = device1->recordingEnabled();
+            ASSERT_TRUE(returnBoolStatus.isOk());
+            ASSERT_TRUE(returnBoolStatus);
+
+            Return<void> ret;
+            if (videoMetaEnabled) {
+                ret = device1->releaseRecordingFrameHandle(mVideoData, mVideoBufferIndex,
+                                                           mVideoNativeHandle);
+                ASSERT_TRUE(ret.isOk());
+            } else {
+                ret = device1->releaseRecordingFrame(mVideoData, mVideoBufferIndex);
+                ASSERT_TRUE(ret.isOk());
+            }
+
+            ret = device1->stopRecording();
+            ASSERT_TRUE(ret.isOk());
+
+            stopPreviewAndClose(device1);
         }
     }
 }
 
 // It shouldn't be possible to start recording without enabling preview first.
 TEST_F(CameraHidlTest, startRecordingFail) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
 
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_1_0) {
-                sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
-                openCameraDevice(name, provider.second, &device1 /*out*/);
-                ASSERT_NE(nullptr, device1.get());
+    for (const auto& name : cameraDeviceNames) {
+        if (getCameraDeviceVersion(name, mProviderType) == CAMERA_DEVICE_API_VERSION_1_0) {
+            sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
+            openCameraDevice(name, mProvider, &device1 /*out*/);
+            ASSERT_NE(nullptr, device1.get());
 
-                Return<bool> returnBoolStatus = device1->recordingEnabled();
-                ASSERT_TRUE(returnBoolStatus.isOk());
-                ASSERT_FALSE(returnBoolStatus);
+            Return<bool> returnBoolStatus = device1->recordingEnabled();
+            ASSERT_TRUE(returnBoolStatus.isOk());
+            ASSERT_FALSE(returnBoolStatus);
 
-                Return<Status> returnStatus = device1->startRecording();
-                ASSERT_TRUE(returnStatus.isOk());
-                ASSERT_NE(Status::OK, returnStatus);
+            Return<Status> returnStatus = device1->startRecording();
+            ASSERT_TRUE(returnStatus.isOk());
+            ASSERT_NE(Status::OK, returnStatus);
 
-                Return<void> ret = device1->close();
-                ASSERT_TRUE(ret.isOk());
-            }
+            Return<void> ret = device1->close();
+            ASSERT_TRUE(ret.isOk());
         }
     }
 }
 
 // Check autofocus support if available.
 TEST_F(CameraHidlTest, autoFocus) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
-        std::vector<const char *> focusModes = {CameraParameters::FOCUS_MODE_AUTO,
-                CameraParameters::FOCUS_MODE_CONTINUOUS_PICTURE,
-                CameraParameters::FOCUS_MODE_CONTINUOUS_VIDEO};
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+    std::vector<const char*> focusModes = {CameraParameters::FOCUS_MODE_AUTO,
+                                           CameraParameters::FOCUS_MODE_CONTINUOUS_PICTURE,
+                                           CameraParameters::FOCUS_MODE_CONTINUOUS_VIDEO};
 
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_1_0) {
-                sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
-                openCameraDevice(name, provider.second, &device1 /*out*/);
-                ASSERT_NE(nullptr, device1.get());
+    for (const auto& name : cameraDeviceNames) {
+        if (getCameraDeviceVersion(name, mProviderType) == CAMERA_DEVICE_API_VERSION_1_0) {
+            sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
+            openCameraDevice(name, mProvider, &device1 /*out*/);
+            ASSERT_NE(nullptr, device1.get());
 
-                CameraParameters cameraParams;
-                getParameters(device1, &cameraParams /*out*/);
+            CameraParameters cameraParams;
+            getParameters(device1, &cameraParams /*out*/);
 
-                if (Status::OK != isAutoFocusModeAvailable(cameraParams,
-                        CameraParameters::FOCUS_MODE_AUTO)) {
-                    Return<void> ret = device1->close();
-                    ASSERT_TRUE(ret.isOk());
+            if (Status::OK !=
+                isAutoFocusModeAvailable(cameraParams, CameraParameters::FOCUS_MODE_AUTO)) {
+                Return<void> ret = device1->close();
+                ASSERT_TRUE(ret.isOk());
+                continue;
+            }
+
+            sp<BufferItemConsumer> bufferItemConsumer;
+            sp<BufferItemHander> bufferHandler;
+            setupPreviewWindow(device1, &bufferItemConsumer /*out*/, &bufferHandler /*out*/);
+            startPreview(device1);
+            enableMsgType((unsigned int)NotifyCallbackMsg::FOCUS, device1);
+
+            for (auto& iter : focusModes) {
+                if (Status::OK != isAutoFocusModeAvailable(cameraParams, iter)) {
                     continue;
                 }
 
-                sp<BufferItemConsumer> bufferItemConsumer;
-                sp<BufferItemHander> bufferHandler;
-                setupPreviewWindow(device1, &bufferItemConsumer /*out*/,
-                        &bufferHandler /*out*/);
-                startPreview(device1);
-                enableMsgType((unsigned int)NotifyCallbackMsg::FOCUS, device1);
-
-                for (auto &iter : focusModes) {
-                    if (Status::OK != isAutoFocusModeAvailable(cameraParams,
-                            iter)) {
-                        continue;
-                    }
-
-                    cameraParams.set(CameraParameters::KEY_FOCUS_MODE, iter);
-                    setParameters(device1, cameraParams);
-                    {
-                        std::unique_lock<std::mutex> l(mLock);
-                        mNotifyMessage = NotifyCallbackMsg::ERROR;
-                    }
-
-                    Return<Status> returnStatus = device1->autoFocus();
-                    ASSERT_TRUE(returnStatus.isOk());
-                    ASSERT_EQ(Status::OK, returnStatus);
-
-                    {
-                        std::unique_lock<std::mutex> l(mLock);
-                        while (NotifyCallbackMsg::FOCUS != mNotifyMessage) {
-                            auto timeout = std::chrono::system_clock::now() +
-                                    std::chrono::seconds(kAutoFocusTimeoutSec);
-                            ASSERT_NE(std::cv_status::timeout,
-                                    mResultCondition.wait_until(l, timeout));
-                        }
-                    }
+                cameraParams.set(CameraParameters::KEY_FOCUS_MODE, iter);
+                setParameters(device1, cameraParams);
+                {
+                    std::unique_lock<std::mutex> l(mLock);
+                    mNotifyMessage = NotifyCallbackMsg::ERROR;
                 }
 
-                disableMsgType((unsigned int)NotifyCallbackMsg::FOCUS, device1);
-                stopPreviewAndClose(device1);
+                Return<Status> returnStatus = device1->autoFocus();
+                ASSERT_TRUE(returnStatus.isOk());
+                ASSERT_EQ(Status::OK, returnStatus);
+
+                {
+                    std::unique_lock<std::mutex> l(mLock);
+                    while (NotifyCallbackMsg::FOCUS != mNotifyMessage) {
+                        auto timeout = std::chrono::system_clock::now() +
+                                       std::chrono::seconds(kAutoFocusTimeoutSec);
+                        ASSERT_NE(std::cv_status::timeout, mResultCondition.wait_until(l, timeout));
+                    }
+                }
             }
+
+            disableMsgType((unsigned int)NotifyCallbackMsg::FOCUS, device1);
+            stopPreviewAndClose(device1);
         }
     }
 }
 
 // In case autofocus is supported verify that it can be cancelled.
 TEST_F(CameraHidlTest, cancelAutoFocus) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
 
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_1_0) {
-                sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
-                openCameraDevice(name, provider.second, &device1 /*out*/);
-                ASSERT_NE(nullptr, device1.get());
+    for (const auto& name : cameraDeviceNames) {
+        if (getCameraDeviceVersion(name, mProviderType) == CAMERA_DEVICE_API_VERSION_1_0) {
+            sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
+            openCameraDevice(name, mProvider, &device1 /*out*/);
+            ASSERT_NE(nullptr, device1.get());
 
-                CameraParameters cameraParams;
-                getParameters(device1, &cameraParams /*out*/);
+            CameraParameters cameraParams;
+            getParameters(device1, &cameraParams /*out*/);
 
-                if (Status::OK != isAutoFocusModeAvailable(cameraParams,
-                        CameraParameters::FOCUS_MODE_AUTO)) {
-                    Return<void> ret = device1->close();
-                    ASSERT_TRUE(ret.isOk());
-                    continue;
-                }
-
-                // It should be fine to call before preview starts.
-                ASSERT_EQ(Status::OK, device1->cancelAutoFocus());
-
-                sp<BufferItemConsumer> bufferItemConsumer;
-                sp<BufferItemHander> bufferHandler;
-                setupPreviewWindow(device1, &bufferItemConsumer /*out*/,
-                        &bufferHandler /*out*/);
-                startPreview(device1);
-
-                // It should be fine to call after preview starts too.
-                Return<Status> returnStatus = device1->cancelAutoFocus();
-                ASSERT_TRUE(returnStatus.isOk());
-                ASSERT_EQ(Status::OK, returnStatus);
-
-                returnStatus = device1->autoFocus();
-                ASSERT_TRUE(returnStatus.isOk());
-                ASSERT_EQ(Status::OK, returnStatus);
-
-                returnStatus = device1->cancelAutoFocus();
-                ASSERT_TRUE(returnStatus.isOk());
-                ASSERT_EQ(Status::OK, returnStatus);
-
-                stopPreviewAndClose(device1);
+            if (Status::OK !=
+                isAutoFocusModeAvailable(cameraParams, CameraParameters::FOCUS_MODE_AUTO)) {
+                Return<void> ret = device1->close();
+                ASSERT_TRUE(ret.isOk());
+                continue;
             }
+
+            // It should be fine to call before preview starts.
+            ASSERT_EQ(Status::OK, device1->cancelAutoFocus());
+
+            sp<BufferItemConsumer> bufferItemConsumer;
+            sp<BufferItemHander> bufferHandler;
+            setupPreviewWindow(device1, &bufferItemConsumer /*out*/, &bufferHandler /*out*/);
+            startPreview(device1);
+
+            // It should be fine to call after preview starts too.
+            Return<Status> returnStatus = device1->cancelAutoFocus();
+            ASSERT_TRUE(returnStatus.isOk());
+            ASSERT_EQ(Status::OK, returnStatus);
+
+            returnStatus = device1->autoFocus();
+            ASSERT_TRUE(returnStatus.isOk());
+            ASSERT_EQ(Status::OK, returnStatus);
+
+            returnStatus = device1->cancelAutoFocus();
+            ASSERT_TRUE(returnStatus.isOk());
+            ASSERT_EQ(Status::OK, returnStatus);
+
+            stopPreviewAndClose(device1);
         }
     }
 }
 
 // Check whether face detection is available and try to enable&disable.
 TEST_F(CameraHidlTest, sendCommandFaceDetection) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
 
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_1_0) {
-                sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
-                openCameraDevice(name, provider.second, &device1 /*out*/);
-                ASSERT_NE(nullptr, device1.get());
+    for (const auto& name : cameraDeviceNames) {
+        if (getCameraDeviceVersion(name, mProviderType) == CAMERA_DEVICE_API_VERSION_1_0) {
+            sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
+            openCameraDevice(name, mProvider, &device1 /*out*/);
+            ASSERT_NE(nullptr, device1.get());
 
-                CameraParameters cameraParams;
-                getParameters(device1, &cameraParams /*out*/);
+            CameraParameters cameraParams;
+            getParameters(device1, &cameraParams /*out*/);
 
-                int32_t hwFaces = cameraParams.getInt(
-                        CameraParameters::KEY_MAX_NUM_DETECTED_FACES_HW);
-                int32_t swFaces = cameraParams.getInt(
-                        CameraParameters::KEY_MAX_NUM_DETECTED_FACES_SW);
-                if ((0 >= hwFaces) && (0 >= swFaces)) {
-                    Return<void> ret = device1->close();
-                    ASSERT_TRUE(ret.isOk());
-                    continue;
-                }
-
-                sp<BufferItemConsumer> bufferItemConsumer;
-                sp<BufferItemHander> bufferHandler;
-                setupPreviewWindow(device1, &bufferItemConsumer /*out*/,
-                        &bufferHandler /*out*/);
-                startPreview(device1);
-
-                if (0 < hwFaces) {
-                    Return<Status> returnStatus = device1->sendCommand(
-                            CommandType::START_FACE_DETECTION,
-                            CAMERA_FACE_DETECTION_HW, 0);
-                    ASSERT_TRUE(returnStatus.isOk());
-                    ASSERT_EQ(Status::OK, returnStatus);
-                    // TODO(epeev) : Enable and check for face notifications
-                    returnStatus = device1->sendCommand(
-                            CommandType::STOP_FACE_DETECTION,
-                            CAMERA_FACE_DETECTION_HW, 0);
-                    ASSERT_TRUE(returnStatus.isOk());
-                    ASSERT_EQ(Status::OK, returnStatus);
-                }
-
-                if (0 < swFaces) {
-                    Return<Status> returnStatus = device1->sendCommand(
-                            CommandType::START_FACE_DETECTION,
-                            CAMERA_FACE_DETECTION_SW, 0);
-                    ASSERT_TRUE(returnStatus.isOk());
-                    ASSERT_EQ(Status::OK, returnStatus);
-                    // TODO(epeev) : Enable and check for face notifications
-                    returnStatus = device1->sendCommand(
-                            CommandType::STOP_FACE_DETECTION,
-                            CAMERA_FACE_DETECTION_SW, 0);
-                    ASSERT_TRUE(returnStatus.isOk());
-                    ASSERT_EQ(Status::OK, returnStatus);
-                }
-
-                stopPreviewAndClose(device1);
+            int32_t hwFaces = cameraParams.getInt(CameraParameters::KEY_MAX_NUM_DETECTED_FACES_HW);
+            int32_t swFaces = cameraParams.getInt(CameraParameters::KEY_MAX_NUM_DETECTED_FACES_SW);
+            if ((0 >= hwFaces) && (0 >= swFaces)) {
+                Return<void> ret = device1->close();
+                ASSERT_TRUE(ret.isOk());
+                continue;
             }
+
+            sp<BufferItemConsumer> bufferItemConsumer;
+            sp<BufferItemHander> bufferHandler;
+            setupPreviewWindow(device1, &bufferItemConsumer /*out*/, &bufferHandler /*out*/);
+            startPreview(device1);
+
+            if (0 < hwFaces) {
+                Return<Status> returnStatus = device1->sendCommand(
+                    CommandType::START_FACE_DETECTION, CAMERA_FACE_DETECTION_HW, 0);
+                ASSERT_TRUE(returnStatus.isOk());
+                ASSERT_EQ(Status::OK, returnStatus);
+                // TODO(epeev) : Enable and check for face notifications
+                returnStatus = device1->sendCommand(CommandType::STOP_FACE_DETECTION,
+                                                    CAMERA_FACE_DETECTION_HW, 0);
+                ASSERT_TRUE(returnStatus.isOk());
+                ASSERT_EQ(Status::OK, returnStatus);
+            }
+
+            if (0 < swFaces) {
+                Return<Status> returnStatus = device1->sendCommand(
+                    CommandType::START_FACE_DETECTION, CAMERA_FACE_DETECTION_SW, 0);
+                ASSERT_TRUE(returnStatus.isOk());
+                ASSERT_EQ(Status::OK, returnStatus);
+                // TODO(epeev) : Enable and check for face notifications
+                returnStatus = device1->sendCommand(CommandType::STOP_FACE_DETECTION,
+                                                    CAMERA_FACE_DETECTION_SW, 0);
+                ASSERT_TRUE(returnStatus.isOk());
+                ASSERT_EQ(Status::OK, returnStatus);
+            }
+
+            stopPreviewAndClose(device1);
         }
     }
 }
 
 // Check whether smooth zoom is available and try to enable&disable.
 TEST_F(CameraHidlTest, sendCommandSmoothZoom) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
 
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_1_0) {
-                sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
-                openCameraDevice(name, provider.second, &device1 /*out*/);
-                ASSERT_NE(nullptr, device1.get());
+    for (const auto& name : cameraDeviceNames) {
+        if (getCameraDeviceVersion(name, mProviderType) == CAMERA_DEVICE_API_VERSION_1_0) {
+            sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
+            openCameraDevice(name, mProvider, &device1 /*out*/);
+            ASSERT_NE(nullptr, device1.get());
 
-                CameraParameters cameraParams;
-                getParameters(device1, &cameraParams /*out*/);
+            CameraParameters cameraParams;
+            getParameters(device1, &cameraParams /*out*/);
 
-                const char *smoothZoomStr = cameraParams.get(
-                        CameraParameters::KEY_SMOOTH_ZOOM_SUPPORTED);
-                bool smoothZoomSupported = ((nullptr != smoothZoomStr) &&
-                        (strcmp(smoothZoomStr, CameraParameters::TRUE) == 0)) ?
-                                true : false;
-                if (!smoothZoomSupported) {
-                    Return<void> ret = device1->close();
-                    ASSERT_TRUE(ret.isOk());
-                    continue;
-                }
-
-                int32_t maxZoom = cameraParams.getInt(
-                        CameraParameters::KEY_MAX_ZOOM);
-                ASSERT_TRUE(0 < maxZoom);
-
-                sp<BufferItemConsumer> bufferItemConsumer;
-                sp<BufferItemHander> bufferHandler;
-                setupPreviewWindow(device1, &bufferItemConsumer /*out*/,
-                        &bufferHandler /*out*/);
-                startPreview(device1);
-                setParameters(device1, cameraParams);
-
-                Return<Status> returnStatus = device1->sendCommand(
-                        CommandType::START_SMOOTH_ZOOM, maxZoom, 0);
-                ASSERT_TRUE(returnStatus.isOk());
-                ASSERT_EQ(Status::OK, returnStatus);
-                // TODO(epeev) : Enable and check for face notifications
-                returnStatus = device1->sendCommand(
-                        CommandType::STOP_SMOOTH_ZOOM, 0, 0);
-                ASSERT_TRUE(returnStatus.isOk());
-                ASSERT_EQ(Status::OK, returnStatus);
-
-                stopPreviewAndClose(device1);
+            const char* smoothZoomStr =
+                cameraParams.get(CameraParameters::KEY_SMOOTH_ZOOM_SUPPORTED);
+            bool smoothZoomSupported =
+                ((nullptr != smoothZoomStr) && (strcmp(smoothZoomStr, CameraParameters::TRUE) == 0))
+                    ? true
+                    : false;
+            if (!smoothZoomSupported) {
+                Return<void> ret = device1->close();
+                ASSERT_TRUE(ret.isOk());
+                continue;
             }
+
+            int32_t maxZoom = cameraParams.getInt(CameraParameters::KEY_MAX_ZOOM);
+            ASSERT_TRUE(0 < maxZoom);
+
+            sp<BufferItemConsumer> bufferItemConsumer;
+            sp<BufferItemHander> bufferHandler;
+            setupPreviewWindow(device1, &bufferItemConsumer /*out*/, &bufferHandler /*out*/);
+            startPreview(device1);
+            setParameters(device1, cameraParams);
+
+            Return<Status> returnStatus =
+                device1->sendCommand(CommandType::START_SMOOTH_ZOOM, maxZoom, 0);
+            ASSERT_TRUE(returnStatus.isOk());
+            ASSERT_EQ(Status::OK, returnStatus);
+            // TODO(epeev) : Enable and check for face notifications
+            returnStatus = device1->sendCommand(CommandType::STOP_SMOOTH_ZOOM, 0, 0);
+            ASSERT_TRUE(returnStatus.isOk());
+            ASSERT_EQ(Status::OK, returnStatus);
+
+            stopPreviewAndClose(device1);
         }
     }
 }
 
 // Basic sanity tests related to camera parameters.
 TEST_F(CameraHidlTest, getSetParameters) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
 
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_1_0) {
-                sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
-                openCameraDevice(name, provider.second, &device1 /*out*/);
-                ASSERT_NE(nullptr, device1.get());
+    for (const auto& name : cameraDeviceNames) {
+        if (getCameraDeviceVersion(name, mProviderType) == CAMERA_DEVICE_API_VERSION_1_0) {
+            sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
+            openCameraDevice(name, mProvider, &device1 /*out*/);
+            ASSERT_NE(nullptr, device1.get());
 
-                CameraParameters cameraParams;
-                getParameters(device1, &cameraParams /*out*/);
+            CameraParameters cameraParams;
+            getParameters(device1, &cameraParams /*out*/);
 
-                int32_t width, height;
-                cameraParams.getPictureSize(&width, &height);
-                ASSERT_TRUE((0 < width) && (0 < height));
-                cameraParams.getPreviewSize(&width, &height);
-                ASSERT_TRUE((0 < width) && (0 < height));
-                int32_t minFps, maxFps;
-                cameraParams.getPreviewFpsRange(&minFps, &maxFps);
-                ASSERT_TRUE((0 < minFps) && (0 < maxFps));
-                ASSERT_NE(nullptr, cameraParams.getPreviewFormat());
-                ASSERT_NE(nullptr, cameraParams.getPictureFormat());
-                ASSERT_TRUE(strcmp(CameraParameters::PIXEL_FORMAT_JPEG,
-                        cameraParams.getPictureFormat()) == 0);
+            int32_t width, height;
+            cameraParams.getPictureSize(&width, &height);
+            ASSERT_TRUE((0 < width) && (0 < height));
+            cameraParams.getPreviewSize(&width, &height);
+            ASSERT_TRUE((0 < width) && (0 < height));
+            int32_t minFps, maxFps;
+            cameraParams.getPreviewFpsRange(&minFps, &maxFps);
+            ASSERT_TRUE((0 < minFps) && (0 < maxFps));
+            ASSERT_NE(nullptr, cameraParams.getPreviewFormat());
+            ASSERT_NE(nullptr, cameraParams.getPictureFormat());
+            ASSERT_TRUE(
+                strcmp(CameraParameters::PIXEL_FORMAT_JPEG, cameraParams.getPictureFormat()) == 0);
 
-                const char *flashMode = cameraParams.get(
-                        CameraParameters::KEY_FLASH_MODE);
-                ASSERT_TRUE((nullptr == flashMode) || (strcmp(
-                        CameraParameters::FLASH_MODE_OFF, flashMode) == 0));
+            const char* flashMode = cameraParams.get(CameraParameters::KEY_FLASH_MODE);
+            ASSERT_TRUE((nullptr == flashMode) ||
+                        (strcmp(CameraParameters::FLASH_MODE_OFF, flashMode) == 0));
 
-                const char *wbMode = cameraParams.get(
-                        CameraParameters::KEY_WHITE_BALANCE);
-                ASSERT_TRUE((nullptr == wbMode) || (strcmp(
-                        CameraParameters::WHITE_BALANCE_AUTO, wbMode) == 0));
+            const char* wbMode = cameraParams.get(CameraParameters::KEY_WHITE_BALANCE);
+            ASSERT_TRUE((nullptr == wbMode) ||
+                        (strcmp(CameraParameters::WHITE_BALANCE_AUTO, wbMode) == 0));
 
-                const char *effect = cameraParams.get(
-                        CameraParameters::KEY_EFFECT);
-                ASSERT_TRUE((nullptr == effect) || (strcmp(
-                        CameraParameters::EFFECT_NONE, effect) == 0));
+            const char* effect = cameraParams.get(CameraParameters::KEY_EFFECT);
+            ASSERT_TRUE((nullptr == effect) ||
+                        (strcmp(CameraParameters::EFFECT_NONE, effect) == 0));
 
-                ::android::Vector<Size> previewSizes;
-                cameraParams.getSupportedPreviewSizes(previewSizes);
-                ASSERT_FALSE(previewSizes.empty());
-                ::android::Vector<Size> pictureSizes;
-                cameraParams.getSupportedPictureSizes(pictureSizes);
-                ASSERT_FALSE(pictureSizes.empty());
-                const char *previewFormats = cameraParams.get(
-                        CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS);
-                ASSERT_NE(nullptr, previewFormats);
-                ::android::String8 previewFormatsString(previewFormats);
-                ASSERT_TRUE(previewFormatsString.contains(
-                        CameraParameters::PIXEL_FORMAT_YUV420SP));
-                ASSERT_NE(nullptr, cameraParams.get(
-                        CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS));
-                ASSERT_NE(nullptr, cameraParams.get(
-                        CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES));
-                const char *focusModes = cameraParams.get(
-                        CameraParameters::KEY_SUPPORTED_FOCUS_MODES);
-                ASSERT_NE(nullptr, focusModes);
-                ::android::String8 focusModesString(focusModes);
-                const char *focusMode = cameraParams.get(
-                        CameraParameters::KEY_FOCUS_MODE);
-                ASSERT_NE(nullptr, focusMode);
-                // Auto focus mode should be default
-                if (focusModesString.contains(
-                        CameraParameters::FOCUS_MODE_AUTO)) {
-                    ASSERT_TRUE(strcmp(
-                            CameraParameters::FOCUS_MODE_AUTO, focusMode) == 0);
-                }
-                ASSERT_TRUE(0 < cameraParams.getInt(
-                        CameraParameters::KEY_FOCAL_LENGTH));
-                int32_t horizontalViewAngle = cameraParams.getInt(
-                        CameraParameters::KEY_HORIZONTAL_VIEW_ANGLE);
-                ASSERT_TRUE((0 < horizontalViewAngle) &&
-                            (360 >= horizontalViewAngle));
-                int32_t verticalViewAngle = cameraParams.getInt(
-                        CameraParameters::KEY_VERTICAL_VIEW_ANGLE);
-                ASSERT_TRUE((0 < verticalViewAngle) &&
-                            (360 >= verticalViewAngle));
-                int32_t jpegQuality = cameraParams.getInt(
-                        CameraParameters::KEY_JPEG_QUALITY);
-                ASSERT_TRUE((1 <= jpegQuality) && (100 >= jpegQuality));
-                int32_t jpegThumbQuality = cameraParams.getInt(
-                        CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY);
-                ASSERT_TRUE((1 <= jpegThumbQuality) &&
-                            (100 >= jpegThumbQuality));
-
-                cameraParams.setPictureSize(pictureSizes[0].width,
-                        pictureSizes[0].height);
-                cameraParams.setPreviewSize(previewSizes[0].width,
-                        previewSizes[0].height);
-
-                setParameters(device1, cameraParams);
-                getParameters(device1, &cameraParams /*out*/);
-
-                cameraParams.getPictureSize(&width, &height);
-                ASSERT_TRUE((pictureSizes[0].width == width) &&
-                        (pictureSizes[0].height == height));
-                cameraParams.getPreviewSize(&width, &height);
-                ASSERT_TRUE((previewSizes[0].width == width) &&
-                        (previewSizes[0].height == height));
-
-                Return<void> ret = device1->close();
-                ASSERT_TRUE(ret.isOk());
+            ::android::Vector<Size> previewSizes;
+            cameraParams.getSupportedPreviewSizes(previewSizes);
+            ASSERT_FALSE(previewSizes.empty());
+            ::android::Vector<Size> pictureSizes;
+            cameraParams.getSupportedPictureSizes(pictureSizes);
+            ASSERT_FALSE(pictureSizes.empty());
+            const char* previewFormats =
+                cameraParams.get(CameraParameters::KEY_SUPPORTED_PREVIEW_FORMATS);
+            ASSERT_NE(nullptr, previewFormats);
+            ::android::String8 previewFormatsString(previewFormats);
+            ASSERT_TRUE(previewFormatsString.contains(CameraParameters::PIXEL_FORMAT_YUV420SP));
+            ASSERT_NE(nullptr, cameraParams.get(CameraParameters::KEY_SUPPORTED_PICTURE_FORMATS));
+            ASSERT_NE(nullptr,
+                      cameraParams.get(CameraParameters::KEY_SUPPORTED_PREVIEW_FRAME_RATES));
+            const char* focusModes = cameraParams.get(CameraParameters::KEY_SUPPORTED_FOCUS_MODES);
+            ASSERT_NE(nullptr, focusModes);
+            ::android::String8 focusModesString(focusModes);
+            const char* focusMode = cameraParams.get(CameraParameters::KEY_FOCUS_MODE);
+            ASSERT_NE(nullptr, focusMode);
+            // Auto focus mode should be default
+            if (focusModesString.contains(CameraParameters::FOCUS_MODE_AUTO)) {
+                ASSERT_TRUE(strcmp(CameraParameters::FOCUS_MODE_AUTO, focusMode) == 0);
             }
+            ASSERT_TRUE(0 < cameraParams.getInt(CameraParameters::KEY_FOCAL_LENGTH));
+            int32_t horizontalViewAngle =
+                cameraParams.getInt(CameraParameters::KEY_HORIZONTAL_VIEW_ANGLE);
+            ASSERT_TRUE((0 < horizontalViewAngle) && (360 >= horizontalViewAngle));
+            int32_t verticalViewAngle =
+                cameraParams.getInt(CameraParameters::KEY_VERTICAL_VIEW_ANGLE);
+            ASSERT_TRUE((0 < verticalViewAngle) && (360 >= verticalViewAngle));
+            int32_t jpegQuality = cameraParams.getInt(CameraParameters::KEY_JPEG_QUALITY);
+            ASSERT_TRUE((1 <= jpegQuality) && (100 >= jpegQuality));
+            int32_t jpegThumbQuality =
+                cameraParams.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_QUALITY);
+            ASSERT_TRUE((1 <= jpegThumbQuality) && (100 >= jpegThumbQuality));
+
+            cameraParams.setPictureSize(pictureSizes[0].width, pictureSizes[0].height);
+            cameraParams.setPreviewSize(previewSizes[0].width, previewSizes[0].height);
+
+            setParameters(device1, cameraParams);
+            getParameters(device1, &cameraParams /*out*/);
+
+            cameraParams.getPictureSize(&width, &height);
+            ASSERT_TRUE((pictureSizes[0].width == width) && (pictureSizes[0].height == height));
+            cameraParams.getPreviewSize(&width, &height);
+            ASSERT_TRUE((previewSizes[0].width == width) && (previewSizes[0].height == height));
+
+            Return<void> ret = device1->close();
+            ASSERT_TRUE(ret.isOk());
         }
     }
 }
@@ -2027,50 +1843,36 @@
 // Verify that the static camera characteristics can be retrieved
 // successfully.
 TEST_F(CameraHidlTest, getCameraCharacteristics) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
 
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_3_2) {
-                ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice> device3_2;
-                ALOGI("getCameraCharacteristics: Testing camera device %s",
-                      name.c_str());
-                Return<void> ret;
-                ret = provider.second->getCameraDeviceInterface_V3_x(
-                    name,
-                    [&](auto status, const auto& device) {
-                        ALOGI("getCameraDeviceInterface_V3_x returns status:%d",
-                              (int)status);
-                        ASSERT_EQ(Status::OK, status);
-                        ASSERT_NE(device, nullptr);
-                        device3_2 = device;
-                    });
-                ASSERT_TRUE(ret.isOk());
+    for (const auto& name : cameraDeviceNames) {
+        if (getCameraDeviceVersion(name, mProviderType) == CAMERA_DEVICE_API_VERSION_3_2) {
+            ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice> device3_2;
+            ALOGI("getCameraCharacteristics: Testing camera device %s", name.c_str());
+            Return<void> ret;
+            ret = mProvider->getCameraDeviceInterface_V3_x(
+                name, [&](auto status, const auto& device) {
+                    ALOGI("getCameraDeviceInterface_V3_x returns status:%d", (int)status);
+                    ASSERT_EQ(Status::OK, status);
+                    ASSERT_NE(device, nullptr);
+                    device3_2 = device;
+                });
+            ASSERT_TRUE(ret.isOk());
 
-                ret = device3_2->getCameraCharacteristics(
-                    [&](auto status, const auto& chars) {
-                        ALOGI("getCameraCharacteristics returns status:%d",
-                              (int)status);
-                        ASSERT_EQ(Status::OK, status);
-                        const camera_metadata_t* metadata =
-                                (camera_metadata_t*) chars.data();
-                        size_t expectedSize = chars.size();
-                        int result = validate_camera_metadata_structure(
-                                metadata, &expectedSize);
-                        ASSERT_TRUE((result == 0) ||
-                                (result == CAMERA_METADATA_VALIDATION_SHIFTED));
-                        size_t entryCount = get_camera_metadata_entry_count(
-                                metadata);
-                        // TODO: we can do better than 0 here. Need to check how many required
-                        // characteristics keys we've defined.
-                        ASSERT_GT(entryCount, 0u);
-                        ALOGI("getCameraCharacteristics metadata entry count is %zu",
-                              entryCount);
-                    });
-                ASSERT_TRUE(ret.isOk());
-            }
+            ret = device3_2->getCameraCharacteristics([&](auto status, const auto& chars) {
+                ALOGI("getCameraCharacteristics returns status:%d", (int)status);
+                ASSERT_EQ(Status::OK, status);
+                const camera_metadata_t* metadata = (camera_metadata_t*)chars.data();
+                size_t expectedSize = chars.size();
+                int result = validate_camera_metadata_structure(metadata, &expectedSize);
+                ASSERT_TRUE((result == 0) || (result == CAMERA_METADATA_VALIDATION_SHIFTED));
+                size_t entryCount = get_camera_metadata_entry_count(metadata);
+                // TODO: we can do better than 0 here. Need to check how many required
+                // characteristics keys we've defined.
+                ASSERT_GT(entryCount, 0u);
+                ALOGI("getCameraCharacteristics metadata entry count is %zu", entryCount);
+            });
+            ASSERT_TRUE(ret.isOk());
         }
     }
 }
@@ -2078,273 +1880,235 @@
 //In case it is supported verify that torch can be enabled.
 //Check for corresponding toch callbacks as well.
 TEST_F(CameraHidlTest, setTorchMode) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
-        bool torchControlSupported = false;
-        Return<void> ret;
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+    bool torchControlSupported = false;
+    Return<void> ret;
 
-        ret = provider.second->isSetTorchModeSupported(
-            [&](auto status, bool support) {
-                ALOGI("isSetTorchModeSupported returns status:%d supported:%d",
-                        (int)status, support);
-                ASSERT_EQ(Status::OK, status);
-                torchControlSupported = support;
-            });
+    ret = mProvider->isSetTorchModeSupported([&](auto status, bool support) {
+        ALOGI("isSetTorchModeSupported returns status:%d supported:%d", (int)status, support);
+        ASSERT_EQ(Status::OK, status);
+        torchControlSupported = support;
+    });
 
+    sp<TorchProviderCb> cb = new TorchProviderCb(this);
+    Return<Status> returnStatus = mProvider->setCallback(cb);
+    ASSERT_TRUE(returnStatus.isOk());
+    ASSERT_EQ(Status::OK, returnStatus);
 
-        sp<TorchProviderCb> cb = new TorchProviderCb(this);
-        Return<Status> returnStatus = provider.second->setCallback(cb);
-        ASSERT_TRUE(returnStatus.isOk());
-        ASSERT_EQ(Status::OK, returnStatus);
+    for (const auto& name : cameraDeviceNames) {
+        if (getCameraDeviceVersion(name, mProviderType) == CAMERA_DEVICE_API_VERSION_3_2) {
+            ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice> device3_2;
+            ALOGI("setTorchMode: Testing camera device %s", name.c_str());
+            ret = mProvider->getCameraDeviceInterface_V3_x(
+                name, [&](auto status, const auto& device) {
+                    ALOGI("getCameraDeviceInterface_V3_x returns status:%d", (int)status);
+                    ASSERT_EQ(Status::OK, status);
+                    ASSERT_NE(device, nullptr);
+                    device3_2 = device;
+                });
+            ASSERT_TRUE(ret.isOk());
 
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_3_2) {
-                ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice> device3_2;
-                ALOGI("setTorchMode: Testing camera device %s", name.c_str());
-                ret = provider.second->getCameraDeviceInterface_V3_x(
-                    name,
-                    [&](auto status, const auto& device) {
-                        ALOGI("getCameraDeviceInterface_V3_x returns status:%d",
-                              (int)status);
-                        ASSERT_EQ(Status::OK, status);
-                        ASSERT_NE(device, nullptr);
-                        device3_2 = device;
-                    });
-                ASSERT_TRUE(ret.isOk());
-
-                mTorchStatus = TorchModeStatus::NOT_AVAILABLE;
-                returnStatus = device3_2->setTorchMode(TorchMode::ON);
-                ASSERT_TRUE(returnStatus.isOk());
-                if (!torchControlSupported) {
-                    ASSERT_EQ(Status::METHOD_NOT_SUPPORTED, returnStatus);
-                } else {
-                    ASSERT_TRUE(returnStatus == Status::OK ||
-                                returnStatus == Status::OPERATION_NOT_SUPPORTED);
-                    if (returnStatus == Status::OK) {
-                        {
-                            std::unique_lock<std::mutex> l(mTorchLock);
-                            while (TorchModeStatus::NOT_AVAILABLE == mTorchStatus) {
-                                auto timeout = std::chrono::system_clock::now() +
-                                        std::chrono::seconds(kTorchTimeoutSec);
-                                ASSERT_NE(std::cv_status::timeout,
-                                        mTorchCond.wait_until(l, timeout));
-                            }
-                            ASSERT_EQ(TorchModeStatus::AVAILABLE_ON,
-                                    mTorchStatus);
-                            mTorchStatus = TorchModeStatus::NOT_AVAILABLE;
+            mTorchStatus = TorchModeStatus::NOT_AVAILABLE;
+            returnStatus = device3_2->setTorchMode(TorchMode::ON);
+            ASSERT_TRUE(returnStatus.isOk());
+            if (!torchControlSupported) {
+                ASSERT_EQ(Status::METHOD_NOT_SUPPORTED, returnStatus);
+            } else {
+                ASSERT_TRUE(returnStatus == Status::OK ||
+                            returnStatus == Status::OPERATION_NOT_SUPPORTED);
+                if (returnStatus == Status::OK) {
+                    {
+                        std::unique_lock<std::mutex> l(mTorchLock);
+                        while (TorchModeStatus::NOT_AVAILABLE == mTorchStatus) {
+                            auto timeout = std::chrono::system_clock::now() +
+                                           std::chrono::seconds(kTorchTimeoutSec);
+                            ASSERT_NE(std::cv_status::timeout, mTorchCond.wait_until(l, timeout));
                         }
+                        ASSERT_EQ(TorchModeStatus::AVAILABLE_ON, mTorchStatus);
+                        mTorchStatus = TorchModeStatus::NOT_AVAILABLE;
+                    }
 
-                        returnStatus = device3_2->setTorchMode(TorchMode::OFF);
-                        ASSERT_TRUE(returnStatus.isOk());
-                        ASSERT_EQ(Status::OK, returnStatus);
+                    returnStatus = device3_2->setTorchMode(TorchMode::OFF);
+                    ASSERT_TRUE(returnStatus.isOk());
+                    ASSERT_EQ(Status::OK, returnStatus);
 
-                        {
-                            std::unique_lock<std::mutex> l(mTorchLock);
-                            while (TorchModeStatus::NOT_AVAILABLE == mTorchStatus) {
-                                auto timeout = std::chrono::system_clock::now() +
-                                        std::chrono::seconds(kTorchTimeoutSec);
-                                ASSERT_NE(std::cv_status::timeout,
-                                        mTorchCond.wait_until(l, timeout));
-                            }
-                            ASSERT_EQ(TorchModeStatus::AVAILABLE_OFF,
-                                    mTorchStatus);
+                    {
+                        std::unique_lock<std::mutex> l(mTorchLock);
+                        while (TorchModeStatus::NOT_AVAILABLE == mTorchStatus) {
+                            auto timeout = std::chrono::system_clock::now() +
+                                           std::chrono::seconds(kTorchTimeoutSec);
+                            ASSERT_NE(std::cv_status::timeout, mTorchCond.wait_until(l, timeout));
                         }
+                        ASSERT_EQ(TorchModeStatus::AVAILABLE_OFF, mTorchStatus);
                     }
                 }
-            } else if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_1_0) {
-                ::android::sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
-                ALOGI("dumpState: Testing camera device %s", name.c_str());
-                ret = provider.second->getCameraDeviceInterface_V1_x(
-                    name,
-                    [&](auto status, const auto& device) {
-                        ALOGI("getCameraDeviceInterface_V1_x returns status:%d",
-                              (int)status);
-                        ASSERT_EQ(Status::OK, status);
-                        ASSERT_NE(device, nullptr);
-                        device1 = device;
-                    });
-                ASSERT_TRUE(ret.isOk());
-
-                mTorchStatus = TorchModeStatus::NOT_AVAILABLE;
-                returnStatus = device1->setTorchMode(TorchMode::ON);
-                ASSERT_TRUE(returnStatus.isOk());
-                if (!torchControlSupported) {
-                    ASSERT_EQ(Status::METHOD_NOT_SUPPORTED, returnStatus);
-                } else {
-                    ASSERT_TRUE(returnStatus == Status::OK ||
-                                returnStatus == Status::OPERATION_NOT_SUPPORTED);
-                    if (returnStatus == Status::OK) {
-                        {
-                            std::unique_lock<std::mutex> l(mTorchLock);
-                            while (TorchModeStatus::NOT_AVAILABLE == mTorchStatus) {
-                                auto timeout = std::chrono::system_clock::now() +
-                                        std::chrono::seconds(kTorchTimeoutSec);
-                                ASSERT_NE(std::cv_status::timeout,
-                                        mTorchCond.wait_until(l, timeout));
-                            }
-                            ASSERT_EQ(TorchModeStatus::AVAILABLE_ON,
-                                    mTorchStatus);
-                            mTorchStatus = TorchModeStatus::NOT_AVAILABLE;
-                        }
-
-                        returnStatus = device1->setTorchMode(TorchMode::OFF);
-                        ASSERT_TRUE(returnStatus.isOk());
-                        ASSERT_EQ(Status::OK, returnStatus);
-
-                        {
-                            std::unique_lock<std::mutex> l(mTorchLock);
-                            while (TorchModeStatus::NOT_AVAILABLE == mTorchStatus) {
-                                auto timeout = std::chrono::system_clock::now() +
-                                        std::chrono::seconds(kTorchTimeoutSec);
-                                ASSERT_NE(std::cv_status::timeout,
-                                        mTorchCond.wait_until(l, timeout));
-                            }
-                            ASSERT_EQ(TorchModeStatus::AVAILABLE_OFF,
-                                    mTorchStatus);
-                        }
-                    }
-                }
-                ret = device1->close();
-                ASSERT_TRUE(ret.isOk());
             }
-        }
+        } else if (getCameraDeviceVersion(name, mProviderType) == CAMERA_DEVICE_API_VERSION_1_0) {
+            ::android::sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
+            ALOGI("dumpState: Testing camera device %s", name.c_str());
+            ret = mProvider->getCameraDeviceInterface_V1_x(
+                name, [&](auto status, const auto& device) {
+                    ALOGI("getCameraDeviceInterface_V1_x returns status:%d", (int)status);
+                    ASSERT_EQ(Status::OK, status);
+                    ASSERT_NE(device, nullptr);
+                    device1 = device;
+                });
+            ASSERT_TRUE(ret.isOk());
 
-        returnStatus = provider.second->setCallback(nullptr);
-        ASSERT_TRUE(returnStatus.isOk());
-        ASSERT_EQ(Status::OK, returnStatus);
+            mTorchStatus = TorchModeStatus::NOT_AVAILABLE;
+            returnStatus = device1->setTorchMode(TorchMode::ON);
+            ASSERT_TRUE(returnStatus.isOk());
+            if (!torchControlSupported) {
+                ASSERT_EQ(Status::METHOD_NOT_SUPPORTED, returnStatus);
+            } else {
+                ASSERT_TRUE(returnStatus == Status::OK ||
+                            returnStatus == Status::OPERATION_NOT_SUPPORTED);
+                if (returnStatus == Status::OK) {
+                    {
+                        std::unique_lock<std::mutex> l(mTorchLock);
+                        while (TorchModeStatus::NOT_AVAILABLE == mTorchStatus) {
+                            auto timeout = std::chrono::system_clock::now() +
+                                           std::chrono::seconds(kTorchTimeoutSec);
+                            ASSERT_NE(std::cv_status::timeout, mTorchCond.wait_until(l, timeout));
+                        }
+                        ASSERT_EQ(TorchModeStatus::AVAILABLE_ON, mTorchStatus);
+                        mTorchStatus = TorchModeStatus::NOT_AVAILABLE;
+                    }
+
+                    returnStatus = device1->setTorchMode(TorchMode::OFF);
+                    ASSERT_TRUE(returnStatus.isOk());
+                    ASSERT_EQ(Status::OK, returnStatus);
+
+                    {
+                        std::unique_lock<std::mutex> l(mTorchLock);
+                        while (TorchModeStatus::NOT_AVAILABLE == mTorchStatus) {
+                            auto timeout = std::chrono::system_clock::now() +
+                                           std::chrono::seconds(kTorchTimeoutSec);
+                            ASSERT_NE(std::cv_status::timeout, mTorchCond.wait_until(l, timeout));
+                        }
+                        ASSERT_EQ(TorchModeStatus::AVAILABLE_OFF, mTorchStatus);
+                    }
+                }
+            }
+            ret = device1->close();
+            ASSERT_TRUE(ret.isOk());
+        }
     }
+
+    returnStatus = mProvider->setCallback(nullptr);
+    ASSERT_TRUE(returnStatus.isOk());
+    ASSERT_EQ(Status::OK, returnStatus);
 }
 
 // Check dump functionality.
 TEST_F(CameraHidlTest, dumpState) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
-        Return<void> ret;
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+    Return<void> ret;
 
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_3_2) {
-                ::android::sp<ICameraDevice> device3_2;
-                ALOGI("dumpState: Testing camera device %s", name.c_str());
-                ret = provider.second->getCameraDeviceInterface_V3_x(
-                    name,
-                    [&](auto status, const auto& device) {
-                        ALOGI("getCameraDeviceInterface_V3_x returns status:%d",
-                              (int)status);
-                        ASSERT_EQ(Status::OK, status);
-                        ASSERT_NE(device, nullptr);
-                        device3_2 = device;
-                    });
-                ASSERT_TRUE(ret.isOk());
+    for (const auto& name : cameraDeviceNames) {
+        if (getCameraDeviceVersion(name, mProviderType) == CAMERA_DEVICE_API_VERSION_3_2) {
+            ::android::sp<ICameraDevice> device3_2;
+            ALOGI("dumpState: Testing camera device %s", name.c_str());
+            ret = mProvider->getCameraDeviceInterface_V3_x(
+                name, [&](auto status, const auto& device) {
+                    ALOGI("getCameraDeviceInterface_V3_x returns status:%d", (int)status);
+                    ASSERT_EQ(Status::OK, status);
+                    ASSERT_NE(device, nullptr);
+                    device3_2 = device;
+                });
+            ASSERT_TRUE(ret.isOk());
 
-                native_handle_t* raw_handle = native_handle_create(1, 0);
-                raw_handle->data[0] = open(kDumpOutput, O_RDWR);
-                ASSERT_GE(raw_handle->data[0], 0);
-                hidl_handle handle = raw_handle;
-                ret= device3_2->dumpState(handle);
-                ASSERT_TRUE(ret.isOk());
-                close(raw_handle->data[0]);
-                native_handle_delete(raw_handle);
-            } else if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_1_0) {
-                ::android::sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
-                ALOGI("dumpState: Testing camera device %s", name.c_str());
-                ret = provider.second->getCameraDeviceInterface_V1_x(
-                    name,
-                    [&](auto status, const auto& device) {
-                        ALOGI("getCameraDeviceInterface_V1_x returns status:%d",
-                              (int)status);
-                        ASSERT_EQ(Status::OK, status);
-                        ASSERT_NE(device, nullptr);
-                        device1 = device;
-                    });
-                ASSERT_TRUE(ret.isOk());
+            native_handle_t* raw_handle = native_handle_create(1, 0);
+            raw_handle->data[0] = open(kDumpOutput, O_RDWR);
+            ASSERT_GE(raw_handle->data[0], 0);
+            hidl_handle handle = raw_handle;
+            ret = device3_2->dumpState(handle);
+            ASSERT_TRUE(ret.isOk());
+            close(raw_handle->data[0]);
+            native_handle_delete(raw_handle);
+        } else if (getCameraDeviceVersion(name, mProviderType) == CAMERA_DEVICE_API_VERSION_1_0) {
+            ::android::sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
+            ALOGI("dumpState: Testing camera device %s", name.c_str());
+            ret = mProvider->getCameraDeviceInterface_V1_x(
+                name, [&](auto status, const auto& device) {
+                    ALOGI("getCameraDeviceInterface_V1_x returns status:%d", (int)status);
+                    ASSERT_EQ(Status::OK, status);
+                    ASSERT_NE(device, nullptr);
+                    device1 = device;
+                });
+            ASSERT_TRUE(ret.isOk());
 
-                native_handle_t* raw_handle = native_handle_create(1, 0);
-                raw_handle->data[0] = open(kDumpOutput, O_RDWR);
-                ASSERT_GE(raw_handle->data[0], 0);
-                hidl_handle handle = raw_handle;
-                Return<Status> returnStatus = device1->dumpState(handle);
-                ASSERT_TRUE(returnStatus.isOk());
-                ASSERT_EQ(Status::OK, returnStatus);
-                close(raw_handle->data[0]);
-                native_handle_delete(raw_handle);
-            }
+            native_handle_t* raw_handle = native_handle_create(1, 0);
+            raw_handle->data[0] = open(kDumpOutput, O_RDWR);
+            ASSERT_GE(raw_handle->data[0], 0);
+            hidl_handle handle = raw_handle;
+            Return<Status> returnStatus = device1->dumpState(handle);
+            ASSERT_TRUE(returnStatus.isOk());
+            ASSERT_EQ(Status::OK, returnStatus);
+            close(raw_handle->data[0]);
+            native_handle_delete(raw_handle);
         }
     }
 }
 
 // Open, dumpStates, then close
 TEST_F(CameraHidlTest, openClose) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
-        Return<void> ret;
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+    Return<void> ret;
 
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_3_2) {
-                ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice> device3_2;
-                ALOGI("openClose: Testing camera device %s", name.c_str());
-                ret = provider.second->getCameraDeviceInterface_V3_x(
-                    name,
-                    [&](auto status, const auto& device) {
-                        ALOGI("getCameraDeviceInterface_V3_x returns status:%d",
-                              (int)status);
-                        ASSERT_EQ(Status::OK, status);
-                        ASSERT_NE(device, nullptr);
-                        device3_2 = device;
-                    });
-                ASSERT_TRUE(ret.isOk());
+    for (const auto& name : cameraDeviceNames) {
+        if (getCameraDeviceVersion(name, mProviderType) == CAMERA_DEVICE_API_VERSION_3_2) {
+            ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice> device3_2;
+            ALOGI("openClose: Testing camera device %s", name.c_str());
+            ret = mProvider->getCameraDeviceInterface_V3_x(
+                name, [&](auto status, const auto& device) {
+                    ALOGI("getCameraDeviceInterface_V3_x returns status:%d", (int)status);
+                    ASSERT_EQ(Status::OK, status);
+                    ASSERT_NE(device, nullptr);
+                    device3_2 = device;
+                });
+            ASSERT_TRUE(ret.isOk());
 
-                sp<EmptyDeviceCb> cb = new EmptyDeviceCb;
-                sp<ICameraDeviceSession> session;
-                ret = device3_2->open(
-                    cb,
-                    [&](auto status, const auto& newSession) {
-                        ALOGI("device::open returns status:%d", (int)status);
-                        ASSERT_EQ(Status::OK, status);
-                        ASSERT_NE(newSession, nullptr);
-                        session = newSession;
-                    });
-                ASSERT_TRUE(ret.isOk());
+            sp<EmptyDeviceCb> cb = new EmptyDeviceCb;
+            sp<ICameraDeviceSession> session;
+            ret = device3_2->open(cb, [&](auto status, const auto& newSession) {
+                ALOGI("device::open returns status:%d", (int)status);
+                ASSERT_EQ(Status::OK, status);
+                ASSERT_NE(newSession, nullptr);
+                session = newSession;
+            });
+            ASSERT_TRUE(ret.isOk());
 
-                native_handle_t* raw_handle = native_handle_create(1, 0);
-                raw_handle->data[0] = open(kDumpOutput, O_RDWR);
-                ASSERT_GE(raw_handle->data[0], 0);
-                hidl_handle handle = raw_handle;
-                ret = device3_2->dumpState(handle);
-                ASSERT_TRUE(ret.isOk());
-                close(raw_handle->data[0]);
-                native_handle_delete(raw_handle);
+            native_handle_t* raw_handle = native_handle_create(1, 0);
+            raw_handle->data[0] = open(kDumpOutput, O_RDWR);
+            ASSERT_GE(raw_handle->data[0], 0);
+            hidl_handle handle = raw_handle;
+            ret = device3_2->dumpState(handle);
+            ASSERT_TRUE(ret.isOk());
+            close(raw_handle->data[0]);
+            native_handle_delete(raw_handle);
 
-                ret = session->close();
-                ASSERT_TRUE(ret.isOk());
-                // TODO: test all session API calls return INTERNAL_ERROR after close
-                // TODO: keep a wp copy here and verify session cannot be promoted out of this scope
-            } else if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_1_0) {
-                sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
-                openCameraDevice(name, provider.second, &device1 /*out*/);
-                ASSERT_NE(nullptr, device1.get());
+            ret = session->close();
+            ASSERT_TRUE(ret.isOk());
+            // TODO: test all session API calls return INTERNAL_ERROR after close
+            // TODO: keep a wp copy here and verify session cannot be promoted out of this scope
+        } else if (getCameraDeviceVersion(name, mProviderType) == CAMERA_DEVICE_API_VERSION_1_0) {
+            sp<::android::hardware::camera::device::V1_0::ICameraDevice> device1;
+            openCameraDevice(name, mProvider, &device1 /*out*/);
+            ASSERT_NE(nullptr, device1.get());
 
-                native_handle_t* raw_handle = native_handle_create(1, 0);
-                raw_handle->data[0] = open(kDumpOutput, O_RDWR);
-                ASSERT_GE(raw_handle->data[0], 0);
-                hidl_handle handle = raw_handle;
-                Return<Status> returnStatus = device1->dumpState(handle);
-                ASSERT_TRUE(returnStatus.isOk());
-                ASSERT_EQ(Status::OK, returnStatus);
-                close(raw_handle->data[0]);
-                native_handle_delete(raw_handle);
+            native_handle_t* raw_handle = native_handle_create(1, 0);
+            raw_handle->data[0] = open(kDumpOutput, O_RDWR);
+            ASSERT_GE(raw_handle->data[0], 0);
+            hidl_handle handle = raw_handle;
+            Return<Status> returnStatus = device1->dumpState(handle);
+            ASSERT_TRUE(returnStatus.isOk());
+            ASSERT_EQ(Status::OK, returnStatus);
+            close(raw_handle->data[0]);
+            native_handle_delete(raw_handle);
 
-                ret = device1->close();
-                ASSERT_TRUE(ret.isOk());
-            }
+            ret = device1->close();
+            ASSERT_TRUE(ret.isOk());
         }
     }
 }
@@ -2352,46 +2116,38 @@
 // Check whether all common default request settings can be sucessfully
 // constructed.
 TEST_F(CameraHidlTest, constructDefaultRequestSettings) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
 
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_3_2) {
-                ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice> device3_2;
-                Return<void> ret;
-                ALOGI("constructDefaultRequestSettings: Testing camera device %s",
-                      name.c_str());
-                ret = provider.second->getCameraDeviceInterface_V3_x(
-                    name,
-                    [&](auto status, const auto& device) {
-                        ALOGI("getCameraDeviceInterface_V3_x returns status:%d",
-                              (int)status);
-                        ASSERT_EQ(Status::OK, status);
-                        ASSERT_NE(device, nullptr);
-                        device3_2 = device;
-                    });
-                ASSERT_TRUE(ret.isOk());
+    for (const auto& name : cameraDeviceNames) {
+        if (getCameraDeviceVersion(name, mProviderType) == CAMERA_DEVICE_API_VERSION_3_2) {
+            ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice> device3_2;
+            Return<void> ret;
+            ALOGI("constructDefaultRequestSettings: Testing camera device %s", name.c_str());
+            ret = mProvider->getCameraDeviceInterface_V3_x(
+                name, [&](auto status, const auto& device) {
+                    ALOGI("getCameraDeviceInterface_V3_x returns status:%d", (int)status);
+                    ASSERT_EQ(Status::OK, status);
+                    ASSERT_NE(device, nullptr);
+                    device3_2 = device;
+                });
+            ASSERT_TRUE(ret.isOk());
 
-                sp<EmptyDeviceCb> cb = new EmptyDeviceCb;
-                sp<ICameraDeviceSession> session;
-                ret = device3_2->open(
-                    cb,
-                    [&](auto status, const auto& newSession) {
-                        ALOGI("device::open returns status:%d", (int)status);
-                        ASSERT_EQ(Status::OK, status);
-                        ASSERT_NE(newSession, nullptr);
-                        session = newSession;
-                    });
-                ASSERT_TRUE(ret.isOk());
+            sp<EmptyDeviceCb> cb = new EmptyDeviceCb;
+            sp<ICameraDeviceSession> session;
+            ret = device3_2->open(cb, [&](auto status, const auto& newSession) {
+                ALOGI("device::open returns status:%d", (int)status);
+                ASSERT_EQ(Status::OK, status);
+                ASSERT_NE(newSession, nullptr);
+                session = newSession;
+            });
+            ASSERT_TRUE(ret.isOk());
 
-                for (uint32_t t = (uint32_t) RequestTemplate::PREVIEW;
-                        t <= (uint32_t) RequestTemplate::MANUAL; t++) {
-                    RequestTemplate reqTemplate = (RequestTemplate) t;
-                    ret = session->constructDefaultRequestSettings(
-                        reqTemplate,
-                        [&](auto status, const auto& req) {
+            for (uint32_t t = (uint32_t)RequestTemplate::PREVIEW;
+                 t <= (uint32_t)RequestTemplate::MANUAL; t++) {
+                RequestTemplate reqTemplate = (RequestTemplate)t;
+                ret =
+                    session->constructDefaultRequestSettings(
+                        reqTemplate, [&](auto status, const auto& req) {
                             ALOGI("constructDefaultRequestSettings returns status:%d",
                                   (int)status);
                             if (reqTemplate == RequestTemplate::ZERO_SHUTTER_LAG ||
@@ -2422,11 +2178,10 @@
                                 ASSERT_EQ(0u, req.size());
                             }
                         });
-                    ASSERT_TRUE(ret.isOk());
-                }
-                ret = session->close();
                 ASSERT_TRUE(ret.isOk());
             }
+            ret = session->close();
+            ASSERT_TRUE(ret.isOk());
         }
     }
 }
@@ -2434,143 +2189,131 @@
 // Verify that all supported stream formats and sizes can be configured
 // successfully.
 TEST_F(CameraHidlTest, configureStreamsAvailableOutputs) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
-        std::vector<AvailableStream> outputStreams;
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+    std::vector<AvailableStream> outputStreams;
 
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_3_2) {
-                camera_metadata_t *staticMeta;
-                Return<void> ret;
-                sp<ICameraDeviceSession> session;
-                openEmptyDeviceSession(name, provider.second, &session /*out*/,
-                        &staticMeta /*out*/);
+    for (const auto& name : cameraDeviceNames) {
+        if (getCameraDeviceVersion(name, mProviderType) == CAMERA_DEVICE_API_VERSION_3_2) {
+            camera_metadata_t* staticMeta;
+            Return<void> ret;
+            sp<ICameraDeviceSession> session;
+            openEmptyDeviceSession(name, mProvider, &session /*out*/, &staticMeta /*out*/);
 
-                outputStreams.clear();
-                ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta,
-                        outputStreams));
-                ASSERT_NE(0u, outputStreams.size());
+            outputStreams.clear();
+            ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta, outputStreams));
+            ASSERT_NE(0u, outputStreams.size());
 
-                int32_t streamId = 0;
-                for (auto &it : outputStreams) {
-                    Stream stream = {streamId, StreamType::OUTPUT,
-                            static_cast<uint32_t> (it.width),
-                            static_cast<uint32_t> (it.height),
-                            static_cast<PixelFormat> (it.format),
-                            GRALLOC1_CONSUMER_USAGE_HWCOMPOSER, 0,
-                            StreamRotation::ROTATION_0};
-                    ::android::hardware::hidl_vec<Stream> streams = {stream};
-                    StreamConfiguration config = {streams,
-                            StreamConfigurationMode::NORMAL_MODE};
-                    ret = session->configureStreams(config, [streamId] (Status s,
-                            HalStreamConfiguration halConfig) {
+            int32_t streamId = 0;
+            for (auto& it : outputStreams) {
+                Stream stream = {streamId,
+                                 StreamType::OUTPUT,
+                                 static_cast<uint32_t>(it.width),
+                                 static_cast<uint32_t>(it.height),
+                                 static_cast<PixelFormat>(it.format),
+                                 GRALLOC1_CONSUMER_USAGE_HWCOMPOSER,
+                                 0,
+                                 StreamRotation::ROTATION_0};
+                ::android::hardware::hidl_vec<Stream> streams = {stream};
+                StreamConfiguration config = {streams, StreamConfigurationMode::NORMAL_MODE};
+                ret = session->configureStreams(
+                    config, [streamId](Status s, HalStreamConfiguration halConfig) {
                         ASSERT_EQ(Status::OK, s);
                         ASSERT_EQ(1u, halConfig.streams.size());
                         ASSERT_EQ(halConfig.streams[0].id, streamId);
                     });
-                    ASSERT_TRUE(ret.isOk());
-                    streamId++;
-                }
-
-                free_camera_metadata(staticMeta);
-                ret = session->close();
                 ASSERT_TRUE(ret.isOk());
+                streamId++;
             }
+
+            free_camera_metadata(staticMeta);
+            ret = session->close();
+            ASSERT_TRUE(ret.isOk());
         }
     }
 }
 
 // Check for correct handling of invalid/incorrect configuration parameters.
 TEST_F(CameraHidlTest, configureStreamsInvalidOutputs) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
-        std::vector<AvailableStream> outputStreams;
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+    std::vector<AvailableStream> outputStreams;
 
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_3_2) {
-                camera_metadata_t *staticMeta;
-                Return<void> ret;
-                sp<ICameraDeviceSession> session;
-                openEmptyDeviceSession(name, provider.second, &session /*out*/,
-                        &staticMeta /*out*/);
+    for (const auto& name : cameraDeviceNames) {
+        if (getCameraDeviceVersion(name, mProviderType) == CAMERA_DEVICE_API_VERSION_3_2) {
+            camera_metadata_t* staticMeta;
+            Return<void> ret;
+            sp<ICameraDeviceSession> session;
+            openEmptyDeviceSession(name, mProvider, &session /*out*/, &staticMeta /*out*/);
 
-                outputStreams.clear();
-                ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta,
-                        outputStreams));
-                ASSERT_NE(0u, outputStreams.size());
+            outputStreams.clear();
+            ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta, outputStreams));
+            ASSERT_NE(0u, outputStreams.size());
 
-                int32_t streamId = 0;
-                Stream stream = {streamId++, StreamType::OUTPUT,
-                        static_cast<uint32_t> (0),
-                        static_cast<uint32_t> (0),
-                        static_cast<PixelFormat> (outputStreams[0].format),
-                        GRALLOC1_CONSUMER_USAGE_HWCOMPOSER, 0,
-                        StreamRotation::ROTATION_0};
-                ::android::hardware::hidl_vec<Stream> streams = {stream};
-                StreamConfiguration config = {streams,
-                        StreamConfigurationMode::NORMAL_MODE};
-                ret = session->configureStreams(config, [] (Status s,
-                        HalStreamConfiguration) {
-                    ASSERT_TRUE((Status::ILLEGAL_ARGUMENT == s) ||
-                                (Status::INTERNAL_ERROR == s));
-                });
-                ASSERT_TRUE(ret.isOk());
+            int32_t streamId = 0;
+            Stream stream = {streamId++,
+                             StreamType::OUTPUT,
+                             static_cast<uint32_t>(0),
+                             static_cast<uint32_t>(0),
+                             static_cast<PixelFormat>(outputStreams[0].format),
+                             GRALLOC1_CONSUMER_USAGE_HWCOMPOSER,
+                             0,
+                             StreamRotation::ROTATION_0};
+            ::android::hardware::hidl_vec<Stream> streams = {stream};
+            StreamConfiguration config = {streams, StreamConfigurationMode::NORMAL_MODE};
+            ret = session->configureStreams(config, [](Status s, HalStreamConfiguration) {
+                ASSERT_TRUE((Status::ILLEGAL_ARGUMENT == s) || (Status::INTERNAL_ERROR == s));
+            });
+            ASSERT_TRUE(ret.isOk());
 
-                stream = {streamId++, StreamType::OUTPUT,
-                        static_cast<uint32_t> (UINT32_MAX),
-                        static_cast<uint32_t> (UINT32_MAX),
-                        static_cast<PixelFormat> (outputStreams[0].format),
-                        GRALLOC1_CONSUMER_USAGE_HWCOMPOSER, 0,
-                        StreamRotation::ROTATION_0};
+            stream = {streamId++,
+                      StreamType::OUTPUT,
+                      static_cast<uint32_t>(UINT32_MAX),
+                      static_cast<uint32_t>(UINT32_MAX),
+                      static_cast<PixelFormat>(outputStreams[0].format),
+                      GRALLOC1_CONSUMER_USAGE_HWCOMPOSER,
+                      0,
+                      StreamRotation::ROTATION_0};
+            streams[0] = stream;
+            config = {streams, StreamConfigurationMode::NORMAL_MODE};
+            ret = session->configureStreams(config, [](Status s, HalStreamConfiguration) {
+                ASSERT_EQ(Status::ILLEGAL_ARGUMENT, s);
+            });
+            ASSERT_TRUE(ret.isOk());
+
+            for (auto& it : outputStreams) {
+                stream = {streamId++,
+                          StreamType::OUTPUT,
+                          static_cast<uint32_t>(it.width),
+                          static_cast<uint32_t>(it.height),
+                          static_cast<PixelFormat>(UINT32_MAX),
+                          GRALLOC1_CONSUMER_USAGE_HWCOMPOSER,
+                          0,
+                          StreamRotation::ROTATION_0};
                 streams[0] = stream;
-                config = {streams,
-                        StreamConfigurationMode::NORMAL_MODE};
-                ret = session->configureStreams(config, [] (Status s,
-                        HalStreamConfiguration) {
+                config = {streams, StreamConfigurationMode::NORMAL_MODE};
+                ret = session->configureStreams(config, [](Status s, HalStreamConfiguration) {
                     ASSERT_EQ(Status::ILLEGAL_ARGUMENT, s);
                 });
                 ASSERT_TRUE(ret.isOk());
 
-                for (auto &it : outputStreams) {
-                    stream = {streamId++, StreamType::OUTPUT,
-                            static_cast<uint32_t> (it.width),
-                            static_cast<uint32_t> (it.height),
-                            static_cast<PixelFormat> (UINT32_MAX),
-                            GRALLOC1_CONSUMER_USAGE_HWCOMPOSER, 0,
-                            StreamRotation::ROTATION_0};
-                    streams[0] = stream;
-                    config = {streams,
-                            StreamConfigurationMode::NORMAL_MODE};
-                    ret = session->configureStreams(config, [] (Status s,
-                            HalStreamConfiguration) {
-                        ASSERT_EQ(Status::ILLEGAL_ARGUMENT, s);
-                    });
-                    ASSERT_TRUE(ret.isOk());
-
-                    stream = {streamId++, StreamType::OUTPUT,
-                            static_cast<uint32_t> (it.width),
-                            static_cast<uint32_t> (it.height),
-                            static_cast<PixelFormat> (it.format),
-                            GRALLOC1_CONSUMER_USAGE_HWCOMPOSER, 0,
-                            static_cast<StreamRotation> (UINT32_MAX)};
-                    streams[0] = stream;
-                    config = {streams,
-                            StreamConfigurationMode::NORMAL_MODE};
-                    ret = session->configureStreams(config, [] (Status s,
-                            HalStreamConfiguration) {
-                        ASSERT_EQ(Status::ILLEGAL_ARGUMENT, s);
-                    });
-                    ASSERT_TRUE(ret.isOk());
-                }
-
-                free_camera_metadata(staticMeta);
-                ret = session->close();
+                stream = {streamId++,
+                          StreamType::OUTPUT,
+                          static_cast<uint32_t>(it.width),
+                          static_cast<uint32_t>(it.height),
+                          static_cast<PixelFormat>(it.format),
+                          GRALLOC1_CONSUMER_USAGE_HWCOMPOSER,
+                          0,
+                          static_cast<StreamRotation>(UINT32_MAX)};
+                streams[0] = stream;
+                config = {streams, StreamConfigurationMode::NORMAL_MODE};
+                ret = session->configureStreams(config, [](Status s, HalStreamConfiguration) {
+                    ASSERT_EQ(Status::ILLEGAL_ARGUMENT, s);
+                });
                 ASSERT_TRUE(ret.isOk());
             }
+
+            free_camera_metadata(staticMeta);
+            ret = session->close();
+            ASSERT_TRUE(ret.isOk());
         }
     }
 }
@@ -2578,87 +2321,84 @@
 // Check whether all supported ZSL output stream combinations can be
 // configured successfully.
 TEST_F(CameraHidlTest, configureStreamsZSLInputOutputs) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
-        std::vector<AvailableStream> inputStreams;
-        std::vector<AvailableZSLInputOutput> inputOutputMap;
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+    std::vector<AvailableStream> inputStreams;
+    std::vector<AvailableZSLInputOutput> inputOutputMap;
 
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_3_2) {
-                camera_metadata_t *staticMeta;
-                Return<void> ret;
-                sp<ICameraDeviceSession> session;
-                openEmptyDeviceSession(name, provider.second, &session /*out*/,
-                        &staticMeta /*out*/);
+    for (const auto& name : cameraDeviceNames) {
+        if (getCameraDeviceVersion(name, mProviderType) == CAMERA_DEVICE_API_VERSION_3_2) {
+            camera_metadata_t* staticMeta;
+            Return<void> ret;
+            sp<ICameraDeviceSession> session;
+            openEmptyDeviceSession(name, mProvider, &session /*out*/, &staticMeta /*out*/);
 
-                Status rc = isZSLModeAvailable(staticMeta);
-                if (Status::METHOD_NOT_SUPPORTED == rc) {
-                    ret = session->close();
-                    ASSERT_TRUE(ret.isOk());
-                    continue;
-                }
-                ASSERT_EQ(Status::OK, rc);
+            Status rc = isZSLModeAvailable(staticMeta);
+            if (Status::METHOD_NOT_SUPPORTED == rc) {
+                ret = session->close();
+                ASSERT_TRUE(ret.isOk());
+                continue;
+            }
+            ASSERT_EQ(Status::OK, rc);
 
-                inputStreams.clear();
-                ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta,
-                        inputStreams));
+            inputStreams.clear();
+            ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta, inputStreams));
+            ASSERT_NE(0u, inputStreams.size());
+
+            inputOutputMap.clear();
+            ASSERT_EQ(Status::OK, getZSLInputOutputMap(staticMeta, inputOutputMap));
+            ASSERT_NE(0u, inputOutputMap.size());
+
+            int32_t streamId = 0;
+            for (auto& inputIter : inputOutputMap) {
+                AvailableStream input;
+                ASSERT_EQ(Status::OK, findLargestSize(inputStreams, inputIter.inputFormat, input));
                 ASSERT_NE(0u, inputStreams.size());
 
-                inputOutputMap.clear();
-                ASSERT_EQ(Status::OK, getZSLInputOutputMap(staticMeta,
-                        inputOutputMap));
-                ASSERT_NE(0u, inputOutputMap.size());
+                AvailableStream outputThreshold = {INT32_MAX, INT32_MAX, inputIter.outputFormat};
+                std::vector<AvailableStream> outputStreams;
+                ASSERT_EQ(Status::OK,
+                          getAvailableOutputStreams(staticMeta, outputStreams, &outputThreshold));
+                for (auto& outputIter : outputStreams) {
+                    Stream zslStream = {streamId++,
+                                        StreamType::OUTPUT,
+                                        static_cast<uint32_t>(input.width),
+                                        static_cast<uint32_t>(input.height),
+                                        static_cast<PixelFormat>(input.format),
+                                        GRALLOC_USAGE_HW_CAMERA_ZSL,
+                                        0,
+                                        StreamRotation::ROTATION_0};
+                    Stream inputStream = {streamId++,
+                                          StreamType::INPUT,
+                                          static_cast<uint32_t>(input.width),
+                                          static_cast<uint32_t>(input.height),
+                                          static_cast<PixelFormat>(input.format),
+                                          0,
+                                          0,
+                                          StreamRotation::ROTATION_0};
+                    Stream outputStream = {streamId++,
+                                           StreamType::OUTPUT,
+                                           static_cast<uint32_t>(outputIter.width),
+                                           static_cast<uint32_t>(outputIter.height),
+                                           static_cast<PixelFormat>(outputIter.format),
+                                           GRALLOC1_CONSUMER_USAGE_HWCOMPOSER,
+                                           0,
+                                           StreamRotation::ROTATION_0};
 
-                int32_t streamId = 0;
-                for (auto &inputIter : inputOutputMap) {
-                    AvailableStream input;
-                    ASSERT_EQ(Status::OK,
-                            findLargestSize(inputStreams, inputIter.inputFormat, input));
-                    ASSERT_NE(0u, inputStreams.size());
-
-                    AvailableStream outputThreshold = {INT32_MAX, INT32_MAX,
-                            inputIter.outputFormat};
-                    std::vector<AvailableStream> outputStreams;
-                    ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta,
-                            outputStreams, &outputThreshold));
-                    for (auto &outputIter : outputStreams) {
-                        Stream zslStream = {streamId++, StreamType::OUTPUT,
-                                static_cast<uint32_t> (input.width),
-                                static_cast<uint32_t> (input.height),
-                                static_cast<PixelFormat> (input.format),
-                                GRALLOC_USAGE_HW_CAMERA_ZSL, 0,
-                                StreamRotation::ROTATION_0};
-                        Stream inputStream = {streamId++, StreamType::INPUT,
-                                static_cast<uint32_t> (input.width),
-                                static_cast<uint32_t> (input.height),
-                                static_cast<PixelFormat> (input.format), 0, 0,
-                                StreamRotation::ROTATION_0};
-                        Stream outputStream = {streamId++, StreamType::OUTPUT,
-                                static_cast<uint32_t> (outputIter.width),
-                                static_cast<uint32_t> (outputIter.height),
-                                static_cast<PixelFormat> (outputIter.format),
-                                GRALLOC1_CONSUMER_USAGE_HWCOMPOSER, 0,
-                                StreamRotation::ROTATION_0};
-
-                        ::android::hardware::hidl_vec<Stream> streams = {
-                                inputStream, zslStream, outputStream};
-                        StreamConfiguration config = {streams,
-                                StreamConfigurationMode::NORMAL_MODE};
-                        ret = session->configureStreams(config,
+                    ::android::hardware::hidl_vec<Stream> streams = {inputStream, zslStream,
+                                                                     outputStream};
+                    StreamConfiguration config = {streams, StreamConfigurationMode::NORMAL_MODE};
+                    ret = session->configureStreams(config,
                                                     [](Status s, HalStreamConfiguration halConfig) {
                                                         ASSERT_EQ(Status::OK, s);
                                                         ASSERT_EQ(3u, halConfig.streams.size());
                                                     });
-                        ASSERT_TRUE(ret.isOk());
-                    }
+                    ASSERT_TRUE(ret.isOk());
                 }
-
-                free_camera_metadata(staticMeta);
-                ret = session->close();
-                ASSERT_TRUE(ret.isOk());
             }
+
+            free_camera_metadata(staticMeta);
+            ret = session->close();
+            ASSERT_TRUE(ret.isOk());
         }
     }
 }
@@ -2666,67 +2406,63 @@
 // Verify that all supported preview + still capture stream combinations
 // can be configured successfully.
 TEST_F(CameraHidlTest, configureStreamsPreviewStillOutputs) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
-        std::vector<AvailableStream> outputBlobStreams;
-        std::vector<AvailableStream> outputPreviewStreams;
-        AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
-                static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
-        AvailableStream blobThreshold = {INT32_MAX, INT32_MAX,
-                static_cast<int32_t>(PixelFormat::BLOB)};
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+    std::vector<AvailableStream> outputBlobStreams;
+    std::vector<AvailableStream> outputPreviewStreams;
+    AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
+                                        static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
+    AvailableStream blobThreshold = {INT32_MAX, INT32_MAX, static_cast<int32_t>(PixelFormat::BLOB)};
 
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_3_2) {
-                camera_metadata_t *staticMeta;
-                Return<void> ret;
-                sp<ICameraDeviceSession> session;
-                openEmptyDeviceSession(name, provider.second, &session /*out*/,
-                        &staticMeta /*out*/);
+    for (const auto& name : cameraDeviceNames) {
+        if (getCameraDeviceVersion(name, mProviderType) == CAMERA_DEVICE_API_VERSION_3_2) {
+            camera_metadata_t* staticMeta;
+            Return<void> ret;
+            sp<ICameraDeviceSession> session;
+            openEmptyDeviceSession(name, mProvider, &session /*out*/, &staticMeta /*out*/);
 
-                outputBlobStreams.clear();
-                ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta,
-                        outputBlobStreams, &blobThreshold));
-                ASSERT_NE(0u, outputBlobStreams.size());
+            outputBlobStreams.clear();
+            ASSERT_EQ(Status::OK,
+                      getAvailableOutputStreams(staticMeta, outputBlobStreams, &blobThreshold));
+            ASSERT_NE(0u, outputBlobStreams.size());
 
-                outputPreviewStreams.clear();
-                ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta,
-                        outputPreviewStreams, &previewThreshold));
-                ASSERT_NE(0u, outputPreviewStreams.size());
+            outputPreviewStreams.clear();
+            ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta, outputPreviewStreams,
+                                                            &previewThreshold));
+            ASSERT_NE(0u, outputPreviewStreams.size());
 
-                int32_t streamId = 0;
-                for (auto &blobIter : outputBlobStreams) {
-                    for (auto &previewIter : outputPreviewStreams) {
-                        Stream previewStream = {streamId++, StreamType::OUTPUT,
-                                static_cast<uint32_t> (previewIter.width),
-                                static_cast<uint32_t> (previewIter.height),
-                                static_cast<PixelFormat> (previewIter.format),
-                                GRALLOC1_CONSUMER_USAGE_HWCOMPOSER, 0,
-                                StreamRotation::ROTATION_0};
-                        Stream blobStream = {streamId++, StreamType::OUTPUT,
-                                static_cast<uint32_t> (blobIter.width),
-                                static_cast<uint32_t> (blobIter.height),
-                                static_cast<PixelFormat> (blobIter.format),
-                                GRALLOC1_CONSUMER_USAGE_CPU_READ, 0,
-                                StreamRotation::ROTATION_0};
-                        ::android::hardware::hidl_vec<Stream> streams = {
-                                previewStream, blobStream};
-                        StreamConfiguration config = {streams,
-                                StreamConfigurationMode::NORMAL_MODE};
-                        ret = session->configureStreams(config,
+            int32_t streamId = 0;
+            for (auto& blobIter : outputBlobStreams) {
+                for (auto& previewIter : outputPreviewStreams) {
+                    Stream previewStream = {streamId++,
+                                            StreamType::OUTPUT,
+                                            static_cast<uint32_t>(previewIter.width),
+                                            static_cast<uint32_t>(previewIter.height),
+                                            static_cast<PixelFormat>(previewIter.format),
+                                            GRALLOC1_CONSUMER_USAGE_HWCOMPOSER,
+                                            0,
+                                            StreamRotation::ROTATION_0};
+                    Stream blobStream = {streamId++,
+                                         StreamType::OUTPUT,
+                                         static_cast<uint32_t>(blobIter.width),
+                                         static_cast<uint32_t>(blobIter.height),
+                                         static_cast<PixelFormat>(blobIter.format),
+                                         GRALLOC1_CONSUMER_USAGE_CPU_READ,
+                                         0,
+                                         StreamRotation::ROTATION_0};
+                    ::android::hardware::hidl_vec<Stream> streams = {previewStream, blobStream};
+                    StreamConfiguration config = {streams, StreamConfigurationMode::NORMAL_MODE};
+                    ret = session->configureStreams(config,
                                                     [](Status s, HalStreamConfiguration halConfig) {
                                                         ASSERT_EQ(Status::OK, s);
                                                         ASSERT_EQ(2u, halConfig.streams.size());
                                                     });
-                        ASSERT_TRUE(ret.isOk());
-                    }
+                    ASSERT_TRUE(ret.isOk());
                 }
-
-                free_camera_metadata(staticMeta);
-                ret = session->close();
-                ASSERT_TRUE(ret.isOk());
             }
+
+            free_camera_metadata(staticMeta);
+            ret = session->close();
+            ASSERT_TRUE(ret.isOk());
         }
     }
 }
@@ -2735,99 +2471,95 @@
 // configured. Additionally check for common invalid inputs when
 // using this mode.
 TEST_F(CameraHidlTest, configureStreamsConstrainedOutputs) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
 
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_3_2) {
-                camera_metadata_t *staticMeta;
-                Return<void> ret;
-                sp<ICameraDeviceSession> session;
-                openEmptyDeviceSession(name, provider.second, &session /*out*/,
-                        &staticMeta /*out*/);
+    for (const auto& name : cameraDeviceNames) {
+        if (getCameraDeviceVersion(name, mProviderType) == CAMERA_DEVICE_API_VERSION_3_2) {
+            camera_metadata_t* staticMeta;
+            Return<void> ret;
+            sp<ICameraDeviceSession> session;
+            openEmptyDeviceSession(name, mProvider, &session /*out*/, &staticMeta /*out*/);
 
-                Status rc = isConstrainedModeAvailable(staticMeta);
-                if (Status::METHOD_NOT_SUPPORTED == rc) {
-                    ret = session->close();
-                    ASSERT_TRUE(ret.isOk());
-                    continue;
-                }
-                ASSERT_EQ(Status::OK, rc);
-
-                AvailableStream hfrStream;
-                rc = pickConstrainedModeSize(staticMeta, hfrStream);
-                ASSERT_EQ(Status::OK, rc);
-
-                int32_t streamId = 0;
-                Stream stream = {streamId, StreamType::OUTPUT,
-                        static_cast<uint32_t> (hfrStream.width),
-                        static_cast<uint32_t> (hfrStream.height),
-                        static_cast<PixelFormat> (hfrStream.format),
-                        GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER, 0,
-                        StreamRotation::ROTATION_0};
-                ::android::hardware::hidl_vec<Stream> streams = {stream};
-                StreamConfiguration config = {streams,
-                        StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE};
-                ret = session->configureStreams(config, [streamId] (Status s,
-                        HalStreamConfiguration halConfig) {
-                    ASSERT_EQ(Status::OK, s);
-                    ASSERT_EQ(1u, halConfig.streams.size());
-                    ASSERT_EQ(halConfig.streams[0].id, streamId);
-                });
-                ASSERT_TRUE(ret.isOk());
-
-                stream = {streamId++, StreamType::OUTPUT,
-                        static_cast<uint32_t> (0),
-                        static_cast<uint32_t> (0),
-                        static_cast<PixelFormat> (hfrStream.format),
-                        GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER, 0,
-                        StreamRotation::ROTATION_0};
-                streams[0] = stream;
-                config = {streams,
-                        StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE};
-                ret = session->configureStreams(config, [] (Status s,
-                        HalStreamConfiguration) {
-                    ASSERT_TRUE((Status::ILLEGAL_ARGUMENT == s) ||
-                                (Status::INTERNAL_ERROR == s));
-                });
-                ASSERT_TRUE(ret.isOk());
-
-                stream = {streamId++, StreamType::OUTPUT,
-                        static_cast<uint32_t> (UINT32_MAX),
-                        static_cast<uint32_t> (UINT32_MAX),
-                        static_cast<PixelFormat> (hfrStream.format),
-                        GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER, 0,
-                        StreamRotation::ROTATION_0};
-                streams[0] = stream;
-                config = {streams,
-                        StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE};
-                ret = session->configureStreams(config, [] (Status s,
-                        HalStreamConfiguration) {
-                    ASSERT_EQ(Status::ILLEGAL_ARGUMENT, s);
-                });
-                ASSERT_TRUE(ret.isOk());
-
-                stream = {streamId++, StreamType::OUTPUT,
-                        static_cast<uint32_t> (hfrStream.width),
-                        static_cast<uint32_t> (hfrStream.height),
-                        static_cast<PixelFormat> (UINT32_MAX),
-                        GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER, 0,
-                        StreamRotation::ROTATION_0};
-                streams[0] = stream;
-                config = {streams,
-                        StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE};
-                ret = session->configureStreams(config, [] (Status s,
-                        HalStreamConfiguration) {
-                    ASSERT_EQ(Status::ILLEGAL_ARGUMENT, s);
-                });
-                ASSERT_TRUE(ret.isOk());
-
-                free_camera_metadata(staticMeta);
+            Status rc = isConstrainedModeAvailable(staticMeta);
+            if (Status::METHOD_NOT_SUPPORTED == rc) {
                 ret = session->close();
                 ASSERT_TRUE(ret.isOk());
+                continue;
             }
+            ASSERT_EQ(Status::OK, rc);
+
+            AvailableStream hfrStream;
+            rc = pickConstrainedModeSize(staticMeta, hfrStream);
+            ASSERT_EQ(Status::OK, rc);
+
+            int32_t streamId = 0;
+            Stream stream = {streamId,
+                             StreamType::OUTPUT,
+                             static_cast<uint32_t>(hfrStream.width),
+                             static_cast<uint32_t>(hfrStream.height),
+                             static_cast<PixelFormat>(hfrStream.format),
+                             GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER,
+                             0,
+                             StreamRotation::ROTATION_0};
+            ::android::hardware::hidl_vec<Stream> streams = {stream};
+            StreamConfiguration config = {streams,
+                                          StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE};
+            ret = session->configureStreams(config,
+                                            [streamId](Status s, HalStreamConfiguration halConfig) {
+                                                ASSERT_EQ(Status::OK, s);
+                                                ASSERT_EQ(1u, halConfig.streams.size());
+                                                ASSERT_EQ(halConfig.streams[0].id, streamId);
+                                            });
+            ASSERT_TRUE(ret.isOk());
+
+            stream = {streamId++,
+                      StreamType::OUTPUT,
+                      static_cast<uint32_t>(0),
+                      static_cast<uint32_t>(0),
+                      static_cast<PixelFormat>(hfrStream.format),
+                      GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER,
+                      0,
+                      StreamRotation::ROTATION_0};
+            streams[0] = stream;
+            config = {streams, StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE};
+            ret = session->configureStreams(config, [](Status s, HalStreamConfiguration) {
+                ASSERT_TRUE((Status::ILLEGAL_ARGUMENT == s) || (Status::INTERNAL_ERROR == s));
+            });
+            ASSERT_TRUE(ret.isOk());
+
+            stream = {streamId++,
+                      StreamType::OUTPUT,
+                      static_cast<uint32_t>(UINT32_MAX),
+                      static_cast<uint32_t>(UINT32_MAX),
+                      static_cast<PixelFormat>(hfrStream.format),
+                      GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER,
+                      0,
+                      StreamRotation::ROTATION_0};
+            streams[0] = stream;
+            config = {streams, StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE};
+            ret = session->configureStreams(config, [](Status s, HalStreamConfiguration) {
+                ASSERT_EQ(Status::ILLEGAL_ARGUMENT, s);
+            });
+            ASSERT_TRUE(ret.isOk());
+
+            stream = {streamId++,
+                      StreamType::OUTPUT,
+                      static_cast<uint32_t>(hfrStream.width),
+                      static_cast<uint32_t>(hfrStream.height),
+                      static_cast<PixelFormat>(UINT32_MAX),
+                      GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER,
+                      0,
+                      StreamRotation::ROTATION_0};
+            streams[0] = stream;
+            config = {streams, StreamConfigurationMode::CONSTRAINED_HIGH_SPEED_MODE};
+            ret = session->configureStreams(config, [](Status s, HalStreamConfiguration) {
+                ASSERT_EQ(Status::ILLEGAL_ARGUMENT, s);
+            });
+            ASSERT_TRUE(ret.isOk());
+
+            free_camera_metadata(staticMeta);
+            ret = session->close();
+            ASSERT_TRUE(ret.isOk());
         }
     }
 }
@@ -2835,97 +2567,91 @@
 // Verify that all supported video + snapshot stream combinations can
 // be configured successfully.
 TEST_F(CameraHidlTest, configureStreamsVideoStillOutputs) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
-        std::vector<AvailableStream> outputBlobStreams;
-        std::vector<AvailableStream> outputVideoStreams;
-        AvailableStream videoThreshold = {kMaxVideoWidth, kMaxVideoHeight,
-                static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
-        AvailableStream blobThreshold = {kMaxVideoWidth, kMaxVideoHeight,
-                static_cast<int32_t>(PixelFormat::BLOB)};
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+    std::vector<AvailableStream> outputBlobStreams;
+    std::vector<AvailableStream> outputVideoStreams;
+    AvailableStream videoThreshold = {kMaxVideoWidth, kMaxVideoHeight,
+                                      static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
+    AvailableStream blobThreshold = {kMaxVideoWidth, kMaxVideoHeight,
+                                     static_cast<int32_t>(PixelFormat::BLOB)};
 
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_3_2) {
-                camera_metadata_t *staticMeta;
-                Return<void> ret;
-                sp<ICameraDeviceSession> session;
-                openEmptyDeviceSession(name, provider.second, &session /*out*/,
-                        &staticMeta /*out*/);
+    for (const auto& name : cameraDeviceNames) {
+        if (getCameraDeviceVersion(name, mProviderType) == CAMERA_DEVICE_API_VERSION_3_2) {
+            camera_metadata_t* staticMeta;
+            Return<void> ret;
+            sp<ICameraDeviceSession> session;
+            openEmptyDeviceSession(name, mProvider, &session /*out*/, &staticMeta /*out*/);
 
-                outputBlobStreams.clear();
-                ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta,
-                        outputBlobStreams, &blobThreshold));
-                ASSERT_NE(0u, outputBlobStreams.size());
+            outputBlobStreams.clear();
+            ASSERT_EQ(Status::OK,
+                      getAvailableOutputStreams(staticMeta, outputBlobStreams, &blobThreshold));
+            ASSERT_NE(0u, outputBlobStreams.size());
 
-                outputVideoStreams.clear();
-                ASSERT_EQ(Status::OK, getAvailableOutputStreams(staticMeta,
-                        outputVideoStreams, &videoThreshold));
-                ASSERT_NE(0u, outputVideoStreams.size());
+            outputVideoStreams.clear();
+            ASSERT_EQ(Status::OK,
+                      getAvailableOutputStreams(staticMeta, outputVideoStreams, &videoThreshold));
+            ASSERT_NE(0u, outputVideoStreams.size());
 
-                int32_t streamId = 0;
-                for (auto &blobIter : outputBlobStreams) {
-                    for (auto &videoIter : outputVideoStreams) {
-                        Stream videoStream = {streamId++, StreamType::OUTPUT,
-                                static_cast<uint32_t> (videoIter.width),
-                                static_cast<uint32_t> (videoIter.height),
-                                static_cast<PixelFormat> (videoIter.format),
-                                GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER, 0,
-                                StreamRotation::ROTATION_0};
-                        Stream blobStream = {streamId++, StreamType::OUTPUT,
-                                static_cast<uint32_t> (blobIter.width),
-                                static_cast<uint32_t> (blobIter.height),
-                                static_cast<PixelFormat> (blobIter.format),
-                                GRALLOC1_CONSUMER_USAGE_CPU_READ, 0,
-                                StreamRotation::ROTATION_0};
-                        ::android::hardware::hidl_vec<Stream> streams = {
-                                videoStream, blobStream};
-                        StreamConfiguration config = {streams,
-                                StreamConfigurationMode::NORMAL_MODE};
-                        ret = session->configureStreams(config,
+            int32_t streamId = 0;
+            for (auto& blobIter : outputBlobStreams) {
+                for (auto& videoIter : outputVideoStreams) {
+                    Stream videoStream = {streamId++,
+                                          StreamType::OUTPUT,
+                                          static_cast<uint32_t>(videoIter.width),
+                                          static_cast<uint32_t>(videoIter.height),
+                                          static_cast<PixelFormat>(videoIter.format),
+                                          GRALLOC1_CONSUMER_USAGE_VIDEO_ENCODER,
+                                          0,
+                                          StreamRotation::ROTATION_0};
+                    Stream blobStream = {streamId++,
+                                         StreamType::OUTPUT,
+                                         static_cast<uint32_t>(blobIter.width),
+                                         static_cast<uint32_t>(blobIter.height),
+                                         static_cast<PixelFormat>(blobIter.format),
+                                         GRALLOC1_CONSUMER_USAGE_CPU_READ,
+                                         0,
+                                         StreamRotation::ROTATION_0};
+                    ::android::hardware::hidl_vec<Stream> streams = {videoStream, blobStream};
+                    StreamConfiguration config = {streams, StreamConfigurationMode::NORMAL_MODE};
+                    ret = session->configureStreams(config,
                                                     [](Status s, HalStreamConfiguration halConfig) {
                                                         ASSERT_EQ(Status::OK, s);
                                                         ASSERT_EQ(2u, halConfig.streams.size());
                                                     });
-                        ASSERT_TRUE(ret.isOk());
-                    }
+                    ASSERT_TRUE(ret.isOk());
                 }
-
-                free_camera_metadata(staticMeta);
-                ret = session->close();
-                ASSERT_TRUE(ret.isOk());
             }
+
+            free_camera_metadata(staticMeta);
+            ret = session->close();
+            ASSERT_TRUE(ret.isOk());
         }
     }
 }
 
 // Generate and verify a camera capture request
 TEST_F(CameraHidlTest, processCaptureRequestPreview) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
-        AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
-                static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
-        uint64_t bufferId = 1;
-        uint32_t frameNumber = 1;
-        ::android::hardware::hidl_vec<uint8_t> settings;
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+    AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
+                                        static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
+    uint64_t bufferId = 1;
+    uint32_t frameNumber = 1;
+    ::android::hardware::hidl_vec<uint8_t> settings;
 
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_3_2) {
-                Stream previewStream;
-                HalStreamConfiguration halStreamConfig;
-                sp<ICameraDeviceSession> session;
-                bool supportsPartialResults = false;
-                uint32_t partialResultCount = 0;
-                configurePreviewStream(name, provider.second, &previewThreshold,
-                        &session /*out*/, &previewStream /*out*/,
-                        &halStreamConfig /*out*/, &supportsPartialResults /*out*/,
-                        &partialResultCount/*out*/);
+    for (const auto& name : cameraDeviceNames) {
+        if (getCameraDeviceVersion(name, mProviderType) == CAMERA_DEVICE_API_VERSION_3_2) {
+            Stream previewStream;
+            HalStreamConfiguration halStreamConfig;
+            sp<ICameraDeviceSession> session;
+            bool supportsPartialResults = false;
+            uint32_t partialResultCount = 0;
+            configurePreviewStream(name, mProvider, &previewThreshold, &session /*out*/,
+                                   &previewStream /*out*/, &halStreamConfig /*out*/,
+                                   &supportsPartialResults /*out*/, &partialResultCount /*out*/);
 
-                std::shared_ptr<ResultMetadataQueue> resultQueue;
-                auto resultQueueRet = session->getCaptureResultMetadataQueue(
+            std::shared_ptr<ResultMetadataQueue> resultQueue;
+            auto resultQueueRet =
+                session->getCaptureResultMetadataQueue(
                     [&resultQueue](const auto& descriptor) {
                         resultQueue = std::make_shared<ResultMetadataQueue>(
                                 descriptor);
@@ -2937,116 +2663,105 @@
                             // Don't use the queue onwards.
                         }
                     });
-                ASSERT_TRUE(resultQueueRet.isOk());
+            ASSERT_TRUE(resultQueueRet.isOk());
 
-                InFlightRequest inflightReq = {1, false, supportsPartialResults,
-                        partialResultCount, resultQueue};
+            InFlightRequest inflightReq = {1, false, supportsPartialResults, partialResultCount,
+                                           resultQueue};
 
-                RequestTemplate reqTemplate = RequestTemplate::PREVIEW;
-                Return<void> ret;
-                ret = session->constructDefaultRequestSettings(reqTemplate,
-                    [&](auto status, const auto& req) {
-                        ASSERT_EQ(Status::OK, status);
-                        settings = req; });
-                ASSERT_TRUE(ret.isOk());
+            RequestTemplate reqTemplate = RequestTemplate::PREVIEW;
+            Return<void> ret;
+            ret = session->constructDefaultRequestSettings(reqTemplate,
+                                                           [&](auto status, const auto& req) {
+                                                               ASSERT_EQ(Status::OK, status);
+                                                               settings = req;
+                                                           });
+            ASSERT_TRUE(ret.isOk());
 
-                sp<GraphicBuffer> gb = new GraphicBuffer(
-                    previewStream.width, previewStream.height,
-                    static_cast<int32_t>(halStreamConfig.streams[0].overrideFormat),
-                    1, android_convertGralloc1To0Usage(
-                           halStreamConfig.streams[0].producerUsage,
-                           halStreamConfig.streams[0].consumerUsage));
-                ASSERT_NE(nullptr, gb.get());
-                StreamBuffer outputBuffer = {halStreamConfig.streams[0].id,
-                        bufferId, hidl_handle(gb->getNativeBuffer()->handle),
-                        BufferStatus::OK, nullptr, nullptr};
-                ::android::hardware::hidl_vec<StreamBuffer> outputBuffers = {
-                        outputBuffer};
-                StreamBuffer emptyInputBuffer = {-1, 0, nullptr,
-                        BufferStatus::ERROR, nullptr, nullptr};
-                CaptureRequest request = {frameNumber, 0 /* fmqSettingsSize */,
-                        settings, emptyInputBuffer, outputBuffers};
+            sp<GraphicBuffer> gb = new GraphicBuffer(
+                previewStream.width, previewStream.height,
+                static_cast<int32_t>(halStreamConfig.streams[0].overrideFormat), 1,
+                android_convertGralloc1To0Usage(halStreamConfig.streams[0].producerUsage,
+                                                halStreamConfig.streams[0].consumerUsage));
+            ASSERT_NE(nullptr, gb.get());
+            StreamBuffer outputBuffer = {halStreamConfig.streams[0].id,
+                                         bufferId,
+                                         hidl_handle(gb->getNativeBuffer()->handle),
+                                         BufferStatus::OK,
+                                         nullptr,
+                                         nullptr};
+            ::android::hardware::hidl_vec<StreamBuffer> outputBuffers = {outputBuffer};
+            StreamBuffer emptyInputBuffer = {-1, 0, nullptr, BufferStatus::ERROR, nullptr, nullptr};
+            CaptureRequest request = {frameNumber, 0 /* fmqSettingsSize */, settings,
+                                      emptyInputBuffer, outputBuffers};
 
-                {
-                    std::unique_lock<std::mutex> l(mLock);
-                    mInflightMap.clear();
-                    mInflightMap.add(frameNumber, &inflightReq);
-                }
-
-                Status status = Status::INTERNAL_ERROR;
-                uint32_t numRequestProcessed = 0;
-                hidl_vec<BufferCache> cachesToRemove;
-                Return<void> returnStatus = session->processCaptureRequest(
-                        {request},
-                        cachesToRemove,
-                        [&status, &numRequestProcessed] (auto s, uint32_t n) {
-                            status = s;
-                            numRequestProcessed = n;
-                        });
-                ASSERT_TRUE(returnStatus.isOk());
-                ASSERT_EQ(Status::OK, status);
-                ASSERT_EQ(numRequestProcessed, 1u);
-
-                {
-                    std::unique_lock<std::mutex> l(mLock);
-                    while (!inflightReq.errorCodeValid &&
-                            ((0 < inflightReq.numBuffersLeft) ||
-                                    (!inflightReq.haveResultMetadata))) {
-                        auto timeout = std::chrono::system_clock::now() +
-                                std::chrono::seconds(kStreamBufferTimeoutSec);
-                        ASSERT_NE(std::cv_status::timeout,
-                                mResultCondition.wait_until(l, timeout));
-                    }
-
-                    ASSERT_FALSE(inflightReq.errorCodeValid);
-                    ASSERT_NE(inflightReq.resultOutputBuffers.size(), 0u);
-                    ASSERT_EQ(previewStream.id,
-                              inflightReq.resultOutputBuffers[0].streamId);
-
-                    request.frameNumber++;
-                    //Empty settings should be supported after the first call
-                    //for repeating requests.
-                    request.settings.setToExternal(nullptr, 0, true);
-                    // The buffer has been registered to HAL by bufferId, so per
-                    // API contract we should send a null handle for this buffer
-                    request.outputBuffers[0].buffer = nullptr;
-                    mInflightMap.clear();
-                    inflightReq = {1, false, supportsPartialResults,
-                                        partialResultCount, resultQueue};
-                    mInflightMap.add(request.frameNumber, &inflightReq);
-                }
-
-                returnStatus = session->processCaptureRequest(
-                        {request},
-                        cachesToRemove,
-                        [&status, &numRequestProcessed] (auto s, uint32_t n) {
-                            status = s;
-                            numRequestProcessed = n;
-                        });
-                ASSERT_TRUE(returnStatus.isOk());
-                ASSERT_EQ(Status::OK, status);
-                ASSERT_EQ(numRequestProcessed, 1u);
-
-                {
-                    std::unique_lock<std::mutex> l(mLock);
-                    while (!inflightReq.errorCodeValid &&
-                            ((0 < inflightReq.numBuffersLeft) ||
-                                    (!inflightReq.haveResultMetadata))) {
-                        auto timeout = std::chrono::system_clock::now() +
-                                std::chrono::seconds(kStreamBufferTimeoutSec);
-                        ASSERT_NE(std::cv_status::timeout,
-                                mResultCondition.wait_until(l, timeout));
-                    }
-
-                    ASSERT_FALSE(inflightReq.errorCodeValid);
-                    ASSERT_NE(inflightReq.resultOutputBuffers.size(), 0u);
-                    ASSERT_EQ(previewStream.id,
-                              inflightReq.resultOutputBuffers[0].streamId);
-                }
-
-                ret = session->close();
-                ASSERT_TRUE(ret.isOk());
+            {
+                std::unique_lock<std::mutex> l(mLock);
+                mInflightMap.clear();
+                mInflightMap.add(frameNumber, &inflightReq);
             }
+
+            Status status = Status::INTERNAL_ERROR;
+            uint32_t numRequestProcessed = 0;
+            hidl_vec<BufferCache> cachesToRemove;
+            Return<void> returnStatus = session->processCaptureRequest(
+                {request}, cachesToRemove, [&status, &numRequestProcessed](auto s, uint32_t n) {
+                    status = s;
+                    numRequestProcessed = n;
+                });
+            ASSERT_TRUE(returnStatus.isOk());
+            ASSERT_EQ(Status::OK, status);
+            ASSERT_EQ(numRequestProcessed, 1u);
+
+            {
+                std::unique_lock<std::mutex> l(mLock);
+                while (!inflightReq.errorCodeValid &&
+                       ((0 < inflightReq.numBuffersLeft) || (!inflightReq.haveResultMetadata))) {
+                    auto timeout = std::chrono::system_clock::now() +
+                                   std::chrono::seconds(kStreamBufferTimeoutSec);
+                    ASSERT_NE(std::cv_status::timeout, mResultCondition.wait_until(l, timeout));
+                }
+
+                ASSERT_FALSE(inflightReq.errorCodeValid);
+                ASSERT_NE(inflightReq.resultOutputBuffers.size(), 0u);
+                ASSERT_EQ(previewStream.id, inflightReq.resultOutputBuffers[0].streamId);
+
+                request.frameNumber++;
+                // Empty settings should be supported after the first call
+                // for repeating requests.
+                request.settings.setToExternal(nullptr, 0, true);
+                // The buffer has been registered to HAL by bufferId, so per
+                // API contract we should send a null handle for this buffer
+                request.outputBuffers[0].buffer = nullptr;
+                mInflightMap.clear();
+                inflightReq = {1, false, supportsPartialResults, partialResultCount, resultQueue};
+                mInflightMap.add(request.frameNumber, &inflightReq);
+            }
+
+            returnStatus = session->processCaptureRequest(
+                {request}, cachesToRemove, [&status, &numRequestProcessed](auto s, uint32_t n) {
+                    status = s;
+                    numRequestProcessed = n;
+                });
+            ASSERT_TRUE(returnStatus.isOk());
+            ASSERT_EQ(Status::OK, status);
+            ASSERT_EQ(numRequestProcessed, 1u);
+
+            {
+                std::unique_lock<std::mutex> l(mLock);
+                while (!inflightReq.errorCodeValid &&
+                       ((0 < inflightReq.numBuffersLeft) || (!inflightReq.haveResultMetadata))) {
+                    auto timeout = std::chrono::system_clock::now() +
+                                   std::chrono::seconds(kStreamBufferTimeoutSec);
+                    ASSERT_NE(std::cv_status::timeout, mResultCondition.wait_until(l, timeout));
+                }
+
+                ASSERT_FALSE(inflightReq.errorCodeValid);
+                ASSERT_NE(inflightReq.resultOutputBuffers.size(), 0u);
+                ASSERT_EQ(previewStream.id, inflightReq.resultOutputBuffers[0].streamId);
+            }
+
+            ret = session->close();
+            ASSERT_TRUE(ret.isOk());
         }
     }
 }
@@ -3054,64 +2769,57 @@
 // Test whether an incorrect capture request with missing settings will
 // be reported correctly.
 TEST_F(CameraHidlTest, processCaptureRequestInvalidSinglePreview) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
-        std::vector<AvailableStream> outputPreviewStreams;
-        AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
-                static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
-        uint64_t bufferId = 1;
-        uint32_t frameNumber = 1;
-        ::android::hardware::hidl_vec<uint8_t> settings;
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+    std::vector<AvailableStream> outputPreviewStreams;
+    AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
+                                        static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
+    uint64_t bufferId = 1;
+    uint32_t frameNumber = 1;
+    ::android::hardware::hidl_vec<uint8_t> settings;
 
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_3_2) {
-                Stream previewStream;
-                HalStreamConfiguration halStreamConfig;
-                sp<ICameraDeviceSession> session;
-                bool supportsPartialResults = false;
-                uint32_t partialResultCount = 0;
-                configurePreviewStream(name, provider.second, &previewThreshold,
-                        &session /*out*/, &previewStream /*out*/,
-                        &halStreamConfig /*out*/, &supportsPartialResults /*out*/,
-                        &partialResultCount /*out*/);
+    for (const auto& name : cameraDeviceNames) {
+        if (getCameraDeviceVersion(name, mProviderType) == CAMERA_DEVICE_API_VERSION_3_2) {
+            Stream previewStream;
+            HalStreamConfiguration halStreamConfig;
+            sp<ICameraDeviceSession> session;
+            bool supportsPartialResults = false;
+            uint32_t partialResultCount = 0;
+            configurePreviewStream(name, mProvider, &previewThreshold, &session /*out*/,
+                                   &previewStream /*out*/, &halStreamConfig /*out*/,
+                                   &supportsPartialResults /*out*/, &partialResultCount /*out*/);
 
-                sp<GraphicBuffer> gb = new GraphicBuffer(
-                    previewStream.width, previewStream.height,
-                    static_cast<int32_t>(halStreamConfig.streams[0].overrideFormat),
-                    1, android_convertGralloc1To0Usage(
-                           halStreamConfig.streams[0].producerUsage,
-                           halStreamConfig.streams[0].consumerUsage));
+            sp<GraphicBuffer> gb = new GraphicBuffer(
+                previewStream.width, previewStream.height,
+                static_cast<int32_t>(halStreamConfig.streams[0].overrideFormat), 1,
+                android_convertGralloc1To0Usage(halStreamConfig.streams[0].producerUsage,
+                                                halStreamConfig.streams[0].consumerUsage));
 
-                StreamBuffer outputBuffer = {halStreamConfig.streams[0].id,
-                        bufferId, hidl_handle(gb->getNativeBuffer()->handle),
-                        BufferStatus::OK, nullptr, nullptr};
-                ::android::hardware::hidl_vec<StreamBuffer> outputBuffers = {
-                        outputBuffer};
-                StreamBuffer emptyInputBuffer = {-1, 0, nullptr,
-                        BufferStatus::ERROR, nullptr, nullptr};
-                CaptureRequest request = {frameNumber, 0 /* fmqSettingsSize */, settings,
-                        emptyInputBuffer, outputBuffers};
+            StreamBuffer outputBuffer = {halStreamConfig.streams[0].id,
+                                         bufferId,
+                                         hidl_handle(gb->getNativeBuffer()->handle),
+                                         BufferStatus::OK,
+                                         nullptr,
+                                         nullptr};
+            ::android::hardware::hidl_vec<StreamBuffer> outputBuffers = {outputBuffer};
+            StreamBuffer emptyInputBuffer = {-1, 0, nullptr, BufferStatus::ERROR, nullptr, nullptr};
+            CaptureRequest request = {frameNumber, 0 /* fmqSettingsSize */, settings,
+                                      emptyInputBuffer, outputBuffers};
 
-                //Settings were not correctly initialized, we should fail here
-                Status status = Status::OK;
-                uint32_t numRequestProcessed = 0;
-                hidl_vec<BufferCache> cachesToRemove;
-                Return<void> ret = session->processCaptureRequest(
-                        {request},
-                        cachesToRemove,
-                        [&status, &numRequestProcessed] (auto s, uint32_t n) {
-                            status = s;
-                            numRequestProcessed = n;
-                        });
-                ASSERT_TRUE(ret.isOk());
-                ASSERT_EQ(Status::ILLEGAL_ARGUMENT, status);
-                ASSERT_EQ(numRequestProcessed, 0u);
+            // Settings were not correctly initialized, we should fail here
+            Status status = Status::OK;
+            uint32_t numRequestProcessed = 0;
+            hidl_vec<BufferCache> cachesToRemove;
+            Return<void> ret = session->processCaptureRequest(
+                {request}, cachesToRemove, [&status, &numRequestProcessed](auto s, uint32_t n) {
+                    status = s;
+                    numRequestProcessed = n;
+                });
+            ASSERT_TRUE(ret.isOk());
+            ASSERT_EQ(Status::ILLEGAL_ARGUMENT, status);
+            ASSERT_EQ(numRequestProcessed, 0u);
 
-                ret = session->close();
-                ASSERT_TRUE(ret.isOk());
-            }
+            ret = session->close();
+            ASSERT_TRUE(ret.isOk());
         }
     }
 }
@@ -3119,91 +2827,81 @@
 // Check whether an invalid capture request with missing output buffers
 // will be reported correctly.
 TEST_F(CameraHidlTest, processCaptureRequestInvalidBuffer) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
-        std::vector<AvailableStream> outputBlobStreams;
-        AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
-                static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
-        uint32_t frameNumber = 1;
-        ::android::hardware::hidl_vec<uint8_t> settings;
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+    std::vector<AvailableStream> outputBlobStreams;
+    AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
+                                        static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
+    uint32_t frameNumber = 1;
+    ::android::hardware::hidl_vec<uint8_t> settings;
 
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_3_2) {
-                Stream previewStream;
-                HalStreamConfiguration halStreamConfig;
-                sp<ICameraDeviceSession> session;
-                bool supportsPartialResults = false;
-                uint32_t partialResultCount = 0;
-                configurePreviewStream(name, provider.second, &previewThreshold,
-                        &session /*out*/, &previewStream /*out*/,
-                        &halStreamConfig /*out*/, &supportsPartialResults/*out*/,
-                        &partialResultCount /*out*/);
+    for (const auto& name : cameraDeviceNames) {
+        if (getCameraDeviceVersion(name, mProviderType) == CAMERA_DEVICE_API_VERSION_3_2) {
+            Stream previewStream;
+            HalStreamConfiguration halStreamConfig;
+            sp<ICameraDeviceSession> session;
+            bool supportsPartialResults = false;
+            uint32_t partialResultCount = 0;
+            configurePreviewStream(name, mProvider, &previewThreshold, &session /*out*/,
+                                   &previewStream /*out*/, &halStreamConfig /*out*/,
+                                   &supportsPartialResults /*out*/, &partialResultCount /*out*/);
 
-                RequestTemplate reqTemplate = RequestTemplate::PREVIEW;
-                Return<void> ret;
-                ret = session->constructDefaultRequestSettings(reqTemplate,
-                    [&](auto status, const auto& req) {
-                        ASSERT_EQ(Status::OK, status);
-                        settings = req; });
-                ASSERT_TRUE(ret.isOk());
+            RequestTemplate reqTemplate = RequestTemplate::PREVIEW;
+            Return<void> ret;
+            ret = session->constructDefaultRequestSettings(reqTemplate,
+                                                           [&](auto status, const auto& req) {
+                                                               ASSERT_EQ(Status::OK, status);
+                                                               settings = req;
+                                                           });
+            ASSERT_TRUE(ret.isOk());
 
-                ::android::hardware::hidl_vec<StreamBuffer> emptyOutputBuffers;
-                StreamBuffer emptyInputBuffer = {-1, 0, nullptr,
-                        BufferStatus::ERROR, nullptr, nullptr};
-                CaptureRequest request = {frameNumber, 0/* fmqSettingsSize */,
-                        settings, emptyInputBuffer, emptyOutputBuffers};
+            ::android::hardware::hidl_vec<StreamBuffer> emptyOutputBuffers;
+            StreamBuffer emptyInputBuffer = {-1, 0, nullptr, BufferStatus::ERROR, nullptr, nullptr};
+            CaptureRequest request = {frameNumber, 0 /* fmqSettingsSize */, settings,
+                                      emptyInputBuffer, emptyOutputBuffers};
 
-                //Output buffers are missing, we should fail here
-                Status status = Status::OK;
-                uint32_t numRequestProcessed = 0;
-                hidl_vec<BufferCache> cachesToRemove;
-                ret = session->processCaptureRequest(
-                        {request},
-                        cachesToRemove,
-                        [&status, &numRequestProcessed] (auto s, uint32_t n) {
-                            status = s;
-                            numRequestProcessed = n;
-                        });
-                ASSERT_TRUE(ret.isOk());
-                ASSERT_EQ(Status::ILLEGAL_ARGUMENT, status);
-                ASSERT_EQ(numRequestProcessed, 0u);
+            // Output buffers are missing, we should fail here
+            Status status = Status::OK;
+            uint32_t numRequestProcessed = 0;
+            hidl_vec<BufferCache> cachesToRemove;
+            ret = session->processCaptureRequest(
+                {request}, cachesToRemove, [&status, &numRequestProcessed](auto s, uint32_t n) {
+                    status = s;
+                    numRequestProcessed = n;
+                });
+            ASSERT_TRUE(ret.isOk());
+            ASSERT_EQ(Status::ILLEGAL_ARGUMENT, status);
+            ASSERT_EQ(numRequestProcessed, 0u);
 
-                ret = session->close();
-                ASSERT_TRUE(ret.isOk());
-            }
+            ret = session->close();
+            ASSERT_TRUE(ret.isOk());
         }
     }
 }
 
 // Generate, trigger and flush a preview request
 TEST_F(CameraHidlTest, flushPreviewRequest) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
-        std::vector<AvailableStream> outputPreviewStreams;
-        AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
-                static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
-        uint64_t bufferId = 1;
-        uint32_t frameNumber = 1;
-        ::android::hardware::hidl_vec<uint8_t> settings;
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+    std::vector<AvailableStream> outputPreviewStreams;
+    AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
+                                        static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
+    uint64_t bufferId = 1;
+    uint32_t frameNumber = 1;
+    ::android::hardware::hidl_vec<uint8_t> settings;
 
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_3_2) {
-                Stream previewStream;
-                HalStreamConfiguration halStreamConfig;
-                sp<ICameraDeviceSession> session;
-                bool supportsPartialResults = false;
-                uint32_t partialResultCount = 0;
-                configurePreviewStream(name, provider.second, &previewThreshold,
-                        &session /*out*/, &previewStream /*out*/,
-                        &halStreamConfig /*out*/, &supportsPartialResults /*out*/,
-                        &partialResultCount /*out*/);
+    for (const auto& name : cameraDeviceNames) {
+        if (getCameraDeviceVersion(name, mProviderType) == CAMERA_DEVICE_API_VERSION_3_2) {
+            Stream previewStream;
+            HalStreamConfiguration halStreamConfig;
+            sp<ICameraDeviceSession> session;
+            bool supportsPartialResults = false;
+            uint32_t partialResultCount = 0;
+            configurePreviewStream(name, mProvider, &previewThreshold, &session /*out*/,
+                                   &previewStream /*out*/, &halStreamConfig /*out*/,
+                                   &supportsPartialResults /*out*/, &partialResultCount /*out*/);
 
-                std::shared_ptr<ResultMetadataQueue> resultQueue;
-                auto resultQueueRet = session->getCaptureResultMetadataQueue(
+            std::shared_ptr<ResultMetadataQueue> resultQueue;
+            auto resultQueueRet =
+                session->getCaptureResultMetadataQueue(
                     [&resultQueue](const auto& descriptor) {
                         resultQueue = std::make_shared<ResultMetadataQueue>(
                                 descriptor);
@@ -3215,92 +2913,88 @@
                             // Don't use the queue onwards.
                         }
                     });
-                ASSERT_TRUE(resultQueueRet.isOk());
+            ASSERT_TRUE(resultQueueRet.isOk());
 
-                InFlightRequest inflightReq = {1, false, supportsPartialResults,
-                        partialResultCount, resultQueue};
-                RequestTemplate reqTemplate = RequestTemplate::PREVIEW;
-                Return<void> ret;
-                ret = session->constructDefaultRequestSettings(reqTemplate,
-                    [&](auto status, const auto& req) {
-                        ASSERT_EQ(Status::OK, status);
-                        settings = req; });
-                ASSERT_TRUE(ret.isOk());
+            InFlightRequest inflightReq = {1, false, supportsPartialResults, partialResultCount,
+                                           resultQueue};
+            RequestTemplate reqTemplate = RequestTemplate::PREVIEW;
+            Return<void> ret;
+            ret = session->constructDefaultRequestSettings(reqTemplate,
+                                                           [&](auto status, const auto& req) {
+                                                               ASSERT_EQ(Status::OK, status);
+                                                               settings = req;
+                                                           });
+            ASSERT_TRUE(ret.isOk());
 
-                sp<GraphicBuffer> gb = new GraphicBuffer(
-                    previewStream.width, previewStream.height,
-                    static_cast<int32_t>(halStreamConfig.streams[0].overrideFormat),
-                    1, android_convertGralloc1To0Usage(
-                           halStreamConfig.streams[0].producerUsage,
-                           halStreamConfig.streams[0].consumerUsage));
-                ASSERT_NE(nullptr, gb.get());
-                StreamBuffer outputBuffer = {halStreamConfig.streams[0].id,
-                        bufferId, hidl_handle(gb->getNativeBuffer()->handle),
-                        BufferStatus::OK, nullptr, nullptr};
-                ::android::hardware::hidl_vec<StreamBuffer> outputBuffers = {
-                        outputBuffer};
-                const StreamBuffer emptyInputBuffer = {-1, 0, nullptr,
-                        BufferStatus::ERROR, nullptr, nullptr};
-                CaptureRequest request = {frameNumber, 0 /* fmqSettingsSize */,
-                        settings, emptyInputBuffer, outputBuffers};
+            sp<GraphicBuffer> gb = new GraphicBuffer(
+                previewStream.width, previewStream.height,
+                static_cast<int32_t>(halStreamConfig.streams[0].overrideFormat), 1,
+                android_convertGralloc1To0Usage(halStreamConfig.streams[0].producerUsage,
+                                                halStreamConfig.streams[0].consumerUsage));
+            ASSERT_NE(nullptr, gb.get());
+            StreamBuffer outputBuffer = {halStreamConfig.streams[0].id,
+                                         bufferId,
+                                         hidl_handle(gb->getNativeBuffer()->handle),
+                                         BufferStatus::OK,
+                                         nullptr,
+                                         nullptr};
+            ::android::hardware::hidl_vec<StreamBuffer> outputBuffers = {outputBuffer};
+            const StreamBuffer emptyInputBuffer = {-1,      0,      nullptr, BufferStatus::ERROR,
+                                                   nullptr, nullptr};
+            CaptureRequest request = {frameNumber, 0 /* fmqSettingsSize */, settings,
+                                      emptyInputBuffer, outputBuffers};
 
-                {
-                    std::unique_lock<std::mutex> l(mLock);
-                    mInflightMap.clear();
-                    mInflightMap.add(frameNumber, &inflightReq);
+            {
+                std::unique_lock<std::mutex> l(mLock);
+                mInflightMap.clear();
+                mInflightMap.add(frameNumber, &inflightReq);
+            }
+
+            Status status = Status::INTERNAL_ERROR;
+            uint32_t numRequestProcessed = 0;
+            hidl_vec<BufferCache> cachesToRemove;
+            ret = session->processCaptureRequest(
+                {request}, cachesToRemove, [&status, &numRequestProcessed](auto s, uint32_t n) {
+                    status = s;
+                    numRequestProcessed = n;
+                });
+
+            ASSERT_TRUE(ret.isOk());
+            ASSERT_EQ(Status::OK, status);
+            ASSERT_EQ(numRequestProcessed, 1u);
+            // Flush before waiting for request to complete.
+            Return<Status> returnStatus = session->flush();
+            ASSERT_TRUE(returnStatus.isOk());
+            ASSERT_EQ(Status::OK, returnStatus);
+
+            {
+                std::unique_lock<std::mutex> l(mLock);
+                while (!inflightReq.errorCodeValid &&
+                       ((0 < inflightReq.numBuffersLeft) || (!inflightReq.haveResultMetadata))) {
+                    auto timeout = std::chrono::system_clock::now() +
+                                   std::chrono::seconds(kStreamBufferTimeoutSec);
+                    ASSERT_NE(std::cv_status::timeout, mResultCondition.wait_until(l, timeout));
                 }
 
-                Status status = Status::INTERNAL_ERROR;
-                uint32_t numRequestProcessed = 0;
-                hidl_vec<BufferCache> cachesToRemove;
-                ret = session->processCaptureRequest(
-                        {request},
-                        cachesToRemove,
-                        [&status, &numRequestProcessed] (auto s, uint32_t n) {
-                            status = s;
-                            numRequestProcessed = n;
-                        });
-
-                ASSERT_TRUE(ret.isOk());
-                ASSERT_EQ(Status::OK, status);
-                ASSERT_EQ(numRequestProcessed, 1u);
-                //Flush before waiting for request to complete.
-                Return<Status> returnStatus = session->flush();
-                ASSERT_TRUE(returnStatus.isOk());
-                ASSERT_EQ(Status::OK, returnStatus);
-
-                {
-                    std::unique_lock<std::mutex> l(mLock);
-                    while (!inflightReq.errorCodeValid &&
-                            ((0 < inflightReq.numBuffersLeft) ||
-                                    (!inflightReq.haveResultMetadata))) {
-                        auto timeout = std::chrono::system_clock::now() +
-                                std::chrono::seconds(kStreamBufferTimeoutSec);
-                        ASSERT_NE(std::cv_status::timeout,
-                                mResultCondition.wait_until(l, timeout));
+                if (!inflightReq.errorCodeValid) {
+                    ASSERT_NE(inflightReq.resultOutputBuffers.size(), 0u);
+                    ASSERT_EQ(previewStream.id, inflightReq.resultOutputBuffers[0].streamId);
+                } else {
+                    switch (inflightReq.errorCode) {
+                        case ErrorCode::ERROR_REQUEST:
+                        case ErrorCode::ERROR_RESULT:
+                        case ErrorCode::ERROR_BUFFER:
+                            // Expected
+                            break;
+                        case ErrorCode::ERROR_DEVICE:
+                        default:
+                            FAIL() << "Unexpected error:"
+                                   << static_cast<uint32_t>(inflightReq.errorCode);
                     }
-
-                    if (!inflightReq.errorCodeValid) {
-                        ASSERT_NE(inflightReq.resultOutputBuffers.size(), 0u);
-                        ASSERT_EQ(previewStream.id,
-                                  inflightReq.resultOutputBuffers[0].streamId);
-                    } else {
-                        switch (inflightReq.errorCode) {
-                            case ErrorCode::ERROR_REQUEST:
-                            case ErrorCode::ERROR_RESULT:
-                            case ErrorCode::ERROR_BUFFER:
-                                //Expected
-                                break;
-                            case ErrorCode::ERROR_DEVICE:
-                            default:
-                                FAIL() << "Unexpected error:" << static_cast<uint32_t> (
-                                        inflightReq.errorCode);
-                        }
-                    }
-
-                    ret = session->close();
-                    ASSERT_TRUE(ret.isOk());
                 }
+
+                ret = session->close();
+                ASSERT_TRUE(ret.isOk());
             }
         }
     }
@@ -3308,41 +3002,35 @@
 
 // Verify that camera flushes correctly without any pending requests.
 TEST_F(CameraHidlTest, flushEmpty) {
-    for (auto provider : CameraHidlEnvironment::Instance()->mProviders) {
-        hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(
-                provider.second);
-        std::vector<AvailableStream> outputPreviewStreams;
-        AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
-                static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+    std::vector<AvailableStream> outputPreviewStreams;
+    AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
+                                        static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
 
-        for (const auto& name : cameraDeviceNames) {
-            if (getCameraDeviceVersion(name, provider.first) ==
-                    CAMERA_DEVICE_API_VERSION_3_2) {
-                Stream previewStream;
-                HalStreamConfiguration halStreamConfig;
-                sp<ICameraDeviceSession> session;
-                bool supportsPartialResults = false;
-                uint32_t partialResultCount = 0;
-                configurePreviewStream(name, provider.second, &previewThreshold,
-                        &session /*out*/, &previewStream /*out*/,
-                        &halStreamConfig /*out*/, &supportsPartialResults /*out*/,
-                        &partialResultCount /*out*/);
+    for (const auto& name : cameraDeviceNames) {
+        if (getCameraDeviceVersion(name, mProviderType) == CAMERA_DEVICE_API_VERSION_3_2) {
+            Stream previewStream;
+            HalStreamConfiguration halStreamConfig;
+            sp<ICameraDeviceSession> session;
+            bool supportsPartialResults = false;
+            uint32_t partialResultCount = 0;
+            configurePreviewStream(name, mProvider, &previewThreshold, &session /*out*/,
+                                   &previewStream /*out*/, &halStreamConfig /*out*/,
+                                   &supportsPartialResults /*out*/, &partialResultCount /*out*/);
 
-                Return<Status> returnStatus = session->flush();
-                ASSERT_TRUE(returnStatus.isOk());
-                ASSERT_EQ(Status::OK, returnStatus);
+            Return<Status> returnStatus = session->flush();
+            ASSERT_TRUE(returnStatus.isOk());
+            ASSERT_EQ(Status::OK, returnStatus);
 
-                {
-                    std::unique_lock<std::mutex> l(mLock);
-                    auto timeout = std::chrono::system_clock::now() +
-                            std::chrono::milliseconds(kEmptyFlushTimeoutMSec);
-                    ASSERT_EQ(std::cv_status::timeout,
-                            mResultCondition.wait_until(l, timeout));
-                }
-
-                Return<void> ret = session->close();
-                ASSERT_TRUE(ret.isOk());
+            {
+                std::unique_lock<std::mutex> l(mLock);
+                auto timeout = std::chrono::system_clock::now() +
+                               std::chrono::milliseconds(kEmptyFlushTimeoutMSec);
+                ASSERT_EQ(std::cv_status::timeout, mResultCondition.wait_until(l, timeout));
             }
+
+            Return<void> ret = session->close();
+            ASSERT_TRUE(ret.isOk());
         }
     }
 }
@@ -3783,6 +3471,7 @@
 int main(int argc, char **argv) {
   ::testing::AddGlobalTestEnvironment(CameraHidlEnvironment::Instance());
   ::testing::InitGoogleTest(&argc, argv);
+  CameraHidlEnvironment::Instance()->init(&argc, argv);
   int status = RUN_ALL_TESTS();
   ALOGI("Test result = %d", status);
   return status;
diff --git a/cas/1.0/Android.bp b/cas/1.0/Android.bp
new file mode 100644
index 0000000..6d94793
--- /dev/null
+++ b/cas/1.0/Android.bp
@@ -0,0 +1,87 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+filegroup {
+    name: "android.hardware.cas@1.0_hal",
+    srcs: [
+        "types.hal",
+        "ICas.hal",
+        "ICasListener.hal",
+        "IDescramblerBase.hal",
+        "IMediaCasService.hal",
+    ],
+}
+
+genrule {
+    name: "android.hardware.cas@1.0_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++-sources -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.cas@1.0",
+    srcs: [
+        ":android.hardware.cas@1.0_hal",
+    ],
+    out: [
+        "android/hardware/cas/1.0/types.cpp",
+        "android/hardware/cas/1.0/CasAll.cpp",
+        "android/hardware/cas/1.0/CasListenerAll.cpp",
+        "android/hardware/cas/1.0/DescramblerBaseAll.cpp",
+        "android/hardware/cas/1.0/MediaCasServiceAll.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.cas@1.0_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++-headers -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.cas@1.0",
+    srcs: [
+        ":android.hardware.cas@1.0_hal",
+    ],
+    out: [
+        "android/hardware/cas/1.0/types.h",
+        "android/hardware/cas/1.0/hwtypes.h",
+        "android/hardware/cas/1.0/ICas.h",
+        "android/hardware/cas/1.0/IHwCas.h",
+        "android/hardware/cas/1.0/BnHwCas.h",
+        "android/hardware/cas/1.0/BpHwCas.h",
+        "android/hardware/cas/1.0/BsCas.h",
+        "android/hardware/cas/1.0/ICasListener.h",
+        "android/hardware/cas/1.0/IHwCasListener.h",
+        "android/hardware/cas/1.0/BnHwCasListener.h",
+        "android/hardware/cas/1.0/BpHwCasListener.h",
+        "android/hardware/cas/1.0/BsCasListener.h",
+        "android/hardware/cas/1.0/IDescramblerBase.h",
+        "android/hardware/cas/1.0/IHwDescramblerBase.h",
+        "android/hardware/cas/1.0/BnHwDescramblerBase.h",
+        "android/hardware/cas/1.0/BpHwDescramblerBase.h",
+        "android/hardware/cas/1.0/BsDescramblerBase.h",
+        "android/hardware/cas/1.0/IMediaCasService.h",
+        "android/hardware/cas/1.0/IHwMediaCasService.h",
+        "android/hardware/cas/1.0/BnHwMediaCasService.h",
+        "android/hardware/cas/1.0/BpHwMediaCasService.h",
+        "android/hardware/cas/1.0/BsMediaCasService.h",
+    ],
+}
+
+cc_library {
+    name: "android.hardware.cas@1.0",
+    defaults: ["hidl-module-defaults"],
+    generated_sources: ["android.hardware.cas@1.0_genc++"],
+    generated_headers: ["android.hardware.cas@1.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.cas@1.0_genc++_headers"],
+    vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+    ],
+}
diff --git a/cas/1.0/CasHal.mk b/cas/1.0/CasHal.mk
new file mode 100644
index 0000000..3cae6bf
--- /dev/null
+++ b/cas/1.0/CasHal.mk
@@ -0,0 +1,192 @@
+#
+# 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.
+
+
+########################################################################
+# Included by frameworks/base for MediaCas. Hidl HAL can't be linked as
+# Java lib from frameworks because it has dependency on frameworks itself.
+#
+
+intermediates := $(TARGET_OUT_COMMON_GEN)/JAVA_LIBRARIES/android.hardware.cas-V1.0-java_intermediates
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+HIDL_PATH := system/libhidl/transport/base/1.0
+
+#
+# Build types.hal (DebugInfo)
+#
+GEN := $(intermediates)/android/hidl/base/V1_0/DebugInfo.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(HIDL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hidl:system/libhidl/transport \
+        android.hidl.base@1.0::types.DebugInfo
+
+$(GEN): $(HIDL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IBase.hal
+#
+GEN := $(intermediates)/android/hidl/base/V1_0/IBase.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(HIDL_PATH)/IBase.hal
+$(GEN): PRIVATE_DEPS += $(HIDL_PATH)/types.hal
+$(GEN): $(HIDL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hidl:system/libhidl/transport \
+        android.hidl.base@1.0::IBase
+
+$(GEN): $(HIDL_PATH)/IBase.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+HIDL_PATH := hardware/interfaces/cas/1.0
+
+#
+# Build types.hal (HidlCasPluginDescriptor)
+#
+GEN := $(intermediates)/android/hardware/cas/V1_0/HidlCasPluginDescriptor.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(HIDL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.cas@1.0::types.HidlCasPluginDescriptor
+
+$(GEN): $(HIDL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build types.hal (Status)
+#
+GEN := $(intermediates)/android/hardware/cas/V1_0/Status.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(HIDL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.cas@1.0::types.Status
+
+$(GEN): $(HIDL_PATH)/types.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build ICas.hal
+#
+GEN := $(intermediates)/android/hardware/cas/V1_0/ICas.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(HIDL_PATH)/ICas.hal
+$(GEN): PRIVATE_DEPS += $(HIDL_PATH)/types.hal
+$(GEN): $(HIDL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.cas@1.0::ICas
+
+$(GEN): $(HIDL_PATH)/ICas.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build ICasListener.hal
+#
+GEN := $(intermediates)/android/hardware/cas/V1_0/ICasListener.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(HIDL_PATH)/ICasListener.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.cas@1.0::ICasListener
+
+$(GEN): $(HIDL_PATH)/ICasListener.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IDescramblerBase.hal
+#
+GEN := $(intermediates)/android/hardware/cas/V1_0/IDescramblerBase.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(HIDL_PATH)/IDescramblerBase.hal
+$(GEN): PRIVATE_DEPS += $(HIDL_PATH)/types.hal
+$(GEN): $(HIDL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.cas@1.0::IDescramblerBase
+
+$(GEN): $(HIDL_PATH)/IDescramblerBase.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IMediaCasService.hal
+#
+GEN := $(intermediates)/android/hardware/cas/V1_0/IMediaCasService.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(HIDL_PATH)/IMediaCasService.hal
+$(GEN): PRIVATE_DEPS += $(HIDL_PATH)/ICas.hal
+$(GEN): $(HIDL_PATH)/ICas.hal
+$(GEN): PRIVATE_DEPS += $(HIDL_PATH)/ICasListener.hal
+$(GEN): $(HIDL_PATH)/ICasListener.hal
+$(GEN): PRIVATE_DEPS += $(HIDL_PATH)/IDescramblerBase.hal
+$(GEN): $(HIDL_PATH)/IDescramblerBase.hal
+$(GEN): PRIVATE_DEPS += $(HIDL_PATH)/types.hal
+$(GEN): $(HIDL_PATH)/types.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.cas@1.0::IMediaCasService
+
+$(GEN): $(HIDL_PATH)/IMediaCasService.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
diff --git a/cas/1.0/ICas.hal b/cas/1.0/ICas.hal
new file mode 100644
index 0000000..08a92da
--- /dev/null
+++ b/cas/1.0/ICas.hal
@@ -0,0 +1,122 @@
+/*
+ * 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.
+ */
+package android.hardware.cas@1.0;
+
+import android.hardware.cas@1.0::types;
+
+/**
+  * ICas is the API to control the cas system and is accessible from both
+ * Java and native level. It is used to manage sessions, provision/refresh
+ * the cas system, and process the EMM/ECM messages. It also allows bi-directional,
+ * scheme-specific communications between the client and the cas system.
+ */
+
+interface ICas {
+    /**
+     * Provide the CA private data from a CA_descriptor in the conditional
+     * access table to a CasPlugin.
+     *
+     * @param pvtData a byte array containing the private data, the format of
+     * which is scheme-specific and opaque to the framework.
+     * @return status the status of the call.
+     */
+    setPrivateData(vec<uint8_t> pvtData) generates (Status status);
+
+    /**
+     * Open a session to descramble one or more streams scrambled by the
+     * conditional access system.
+     *
+     * @return status the status of the call.
+     * @return sessionId the id of the newly opened session.
+     */
+    openSession() generates(Status status, HidlCasSessionId sessionId);
+
+    /**
+     * Close a session.
+     *
+     * @param sessionId the id of the session to be closed.
+     * @return status the status of the call.
+     */
+    closeSession(HidlCasSessionId sessionId) generates (Status status);
+
+    /**
+     * Provide the CA private data from a CA_descriptor in the program map
+     * table to a session.
+     *
+     * @param sessionId the id of the session which the private data applies to.
+     * @param pvtData a byte array containing the private data, the format of
+     * which is scheme-specific and opaque to the framework.
+     * @return status the status of the call.
+     */
+    setSessionPrivateData(HidlCasSessionId sessionId, vec<uint8_t> pvtData)
+        generates (Status status);
+
+    /**
+     * Process an ECM from the ECM stream for this session’s elementary stream.
+     *
+     * @param sessionId the id of the session which the ecm data applies to.
+     * @param ecm a byte array containing the ecm data.
+     * @return status the status of the call.
+     */
+    processEcm(HidlCasSessionId sessionId, vec<uint8_t> ecm)
+        generates (Status status);
+
+    /**
+     * Process an in-band EMM from the EMM stream.
+     *
+     * @param emm a byte array containing the emm data.
+     * @return status the status of the call.
+     */
+    processEmm(vec<uint8_t> emm) generates (Status status);
+
+    /**
+     * Send an scheme-specific event to the CasPlugin.
+     *
+     * @param event an integer denoting a scheme-specific event to be sent.
+     * @param arg a scheme-specific integer argument for the event.
+     * @param data a byte array containing scheme-specific data for the event.
+     * @return status the status of the call.
+     */
+    sendEvent(int32_t event, int32_t arg, vec<uint8_t> eventData)
+        generates (Status status);
+
+    /**
+     * Initiate a provisioning operation for a CA system.
+     *
+     * @param provisionString string containing information needed for the
+     * provisioning operation, the format of which is scheme and implementation
+     * specific.
+     * @return status the status of the call.
+     */
+    provision(string provisionString) generates (Status status);
+
+    /**
+     * Notify the CA system to refresh entitlement keys.
+     *
+     * @param refreshType the type of the refreshment.
+     * @param refreshData private data associated with the refreshment.
+     * @return status the status of the call.
+     */
+    refreshEntitlements(int32_t refreshType, vec<uint8_t> refreshData)
+        generates (Status status);
+
+    /**
+     * Release the descrambler instance.
+     *
+     * @return status the status of the call.
+     */
+    release() generates (Status status);
+};
diff --git a/cas/1.0/ICasListener.hal b/cas/1.0/ICasListener.hal
new file mode 100644
index 0000000..8ae6014
--- /dev/null
+++ b/cas/1.0/ICasListener.hal
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+package android.hardware.cas@1.0;
+
+interface ICasListener {
+    /**
+      * Notify the listener of a scheme-specific event from the CA system.
+      *
+      * @param event an integer whose meaning is scheme-specific.
+      * @param arg an integer whose meaning is scheme-specific.
+      * @param data a byte array of data whose format and meaning are
+      * scheme-specific.
+      */
+    onEvent(int32_t event, int32_t arg, vec<uint8_t> data);
+};
diff --git a/cas/1.0/IDescramblerBase.hal b/cas/1.0/IDescramblerBase.hal
new file mode 100644
index 0000000..a126084
--- /dev/null
+++ b/cas/1.0/IDescramblerBase.hal
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+package android.hardware.cas@1.0;
+
+import android.hardware.cas@1.0::types;
+
+/**
+ * IDescramblerBase is the API to control the descrambler and is accessible
+ * from both Java and native level.
+ */
+
+interface IDescramblerBase {
+    /**
+     * Associate a MediaCas session with this MediaDescrambler instance.
+     *
+     * @param sessionId the id of the session to associate with this descrambler instance.
+     * @return status the status of the call.
+     */
+    setMediaCasSession(HidlCasSessionId sessionId) generates (Status status);
+
+    /**
+     * Query if the scrambling scheme requires the use of a secure decoder
+     * to decode data of the given mime type.
+     *
+     * @param mime the mime type of the media data.
+     * @return result whether the descrambler requires a secure decoder.
+     */
+    requiresSecureDecoderComponent(string mime) generates (bool result);
+
+    /**
+     * Release the descrambler instance.
+     *
+     * @return status the status of the call.
+     */
+    release() generates (Status status);
+};
diff --git a/cas/1.0/IMediaCasService.hal b/cas/1.0/IMediaCasService.hal
new file mode 100644
index 0000000..cfeafad
--- /dev/null
+++ b/cas/1.0/IMediaCasService.hal
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+package android.hardware.cas@1.0;
+
+import android.hardware.cas@1.0::ICas;
+import android.hardware.cas@1.0::ICasListener;
+import android.hardware.cas@1.0::IDescramblerBase;
+
+/**
+ * IMediaCasService is the main entry point for interacting with a vendor's
+ * cas HAL to create cas and descrambler plugin instances. A cas plugin instance
+ * opens cas sessions which are used to obtain keys for a descrambler session,
+ * which can in turn be used to descramble protected video content.
+ */
+interface IMediaCasService {
+    /**
+     * List all available CA systems on the device.
+     *
+     * @return descriptors an array of descriptors for the available CA systems.
+     */
+    enumeratePlugins() generates (vec<HidlCasPluginDescriptor> descriptors);
+
+    /**
+     * Query if a certain CA system is supported on this device.
+     *
+     * @param CA_system_id the id of the CA system.
+     * @return result whether the specified CA system is supported on this device.
+     */
+    isSystemIdSupported(int32_t CA_system_id) generates (bool result);
+
+    /**
+     * Construct a new instance of a CasPlugin given a CA_system_id.
+     *
+     * @param CA_system_id the id of the CA system.
+     * @param listener the event listener to receive events coming from the CasPlugin.
+     * @return cas the newly created CasPlugin interface.
+     */
+    createPlugin(int32_t CA_system_id, ICasListener listener) generates (ICas cas);
+
+    /**
+     * Query if the descrambling scheme for a CA system is supported on this device.
+     *
+     * @param CA_system_id the id of the CA system.
+     * @return result whether the specified descrambling scheme is supported on this device.
+     */
+    isDescramblerSupported(int32_t CA_system_id) generates (bool result);
+
+    /**
+     * Construct a new instance of a DescramblerPlugin given a CA_system_id.
+     *
+     * @param CA_system_id the id of the CA system.
+     * @return descrambler the newly created plugin interface.
+     */
+    createDescrambler(int32_t CA_system_id) generates (IDescramblerBase descrambler);
+};
diff --git a/cas/1.0/default/Android.bp b/cas/1.0/default/Android.bp
new file mode 100644
index 0000000..6da5cc4
--- /dev/null
+++ b/cas/1.0/default/Android.bp
@@ -0,0 +1,39 @@
+cc_binary {
+    name: "android.hardware.cas@1.0-service",
+    defaults: ["hidl_defaults"],
+    vendor: true,
+    relative_install_path: "hw",
+    srcs: [
+      "CasImpl.cpp",
+      "DescramblerImpl.cpp",
+      "MediaCasService.cpp",
+      "service.cpp",
+      "SharedLibrary.cpp",
+      "TypeConvert.cpp",
+    ],
+
+    product_variables: {
+        treble: {
+            cflags: ["-DUSE_VNDBINDER"],
+        },
+    },
+
+    compile_multilib: "32",
+    init_rc: ["android.hardware.cas@1.0-service.rc"],
+
+    shared_libs: [
+      "android.hardware.cas@1.0",
+      "android.hardware.cas.native@1.0",
+      "android.hidl.memory@1.0",
+      "libbinder",
+      "libhidlbase",
+      "libhidlmemory",
+      "libhidltransport",
+      "liblog",
+      "libutils",
+    ],
+    header_libs: [
+      "libstagefright_foundation_headers",
+      "media_plugin_headers",
+    ],
+}
diff --git a/cas/1.0/default/CasImpl.cpp b/cas/1.0/default/CasImpl.cpp
new file mode 100644
index 0000000..9d1f4a3
--- /dev/null
+++ b/cas/1.0/default/CasImpl.cpp
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "android.hardware.cas@1.0-CasImpl"
+
+#include <android/hardware/cas/1.0/ICasListener.h>
+#include <media/cas/CasAPI.h>
+#include <utils/Log.h>
+
+#include "CasImpl.h"
+#include "SharedLibrary.h"
+#include "TypeConvert.h"
+
+namespace android {
+namespace hardware {
+namespace cas {
+namespace V1_0 {
+namespace implementation {
+
+struct CasImpl::PluginHolder : public RefBase {
+public:
+    explicit PluginHolder(CasPlugin *plugin) : mPlugin(plugin) {}
+    ~PluginHolder() { if (mPlugin != NULL) delete mPlugin; }
+    CasPlugin* get() { return mPlugin; }
+
+private:
+    CasPlugin *mPlugin;
+    DISALLOW_EVIL_CONSTRUCTORS(PluginHolder);
+};
+
+CasImpl::CasImpl(const sp<ICasListener> &listener)
+    : mPluginHolder(NULL), mListener(listener) {
+    ALOGV("CTOR");
+}
+
+CasImpl::~CasImpl() {
+    ALOGV("DTOR");
+    release();
+}
+
+//static
+void CasImpl::OnEvent(
+        void *appData,
+        int32_t event,
+        int32_t arg,
+        uint8_t *data,
+        size_t size) {
+    if (appData == NULL) {
+        ALOGE("Invalid appData!");
+        return;
+    }
+    CasImpl *casImpl = static_cast<CasImpl *>(appData);
+    casImpl->onEvent(event, arg, data, size);
+}
+
+void CasImpl::init(const sp<SharedLibrary>& library, CasPlugin *plugin) {
+    mLibrary = library;
+    mPluginHolder = new PluginHolder(plugin);
+}
+
+void CasImpl::onEvent(
+        int32_t event, int32_t arg, uint8_t *data, size_t size) {
+    if (mListener == NULL) {
+        return;
+    }
+
+    HidlCasData eventData;
+    if (data != NULL) {
+        eventData.setToExternal(data, size);
+    }
+
+    mListener->onEvent(event, arg, eventData);
+}
+
+Return<Status> CasImpl::setPrivateData(const HidlCasData& pvtData) {
+    ALOGV("%s", __FUNCTION__);
+    sp<PluginHolder> holder = mPluginHolder;
+    if (holder == NULL) {
+        return toStatus(INVALID_OPERATION);
+    }
+    return toStatus(holder->get()->setPrivateData(pvtData));
+}
+
+Return<void> CasImpl::openSession(openSession_cb _hidl_cb) {
+    ALOGV("%s", __FUNCTION__);
+    CasSessionId sessionId;
+
+    sp<PluginHolder> holder = mPluginHolder;
+    status_t err = INVALID_OPERATION;
+    if (holder != NULL) {
+        err = holder->get()->openSession(&sessionId);
+    }
+
+    _hidl_cb(toStatus(err), sessionId);
+
+    return Void();
+}
+
+Return<Status> CasImpl::setSessionPrivateData(
+        const HidlCasSessionId &sessionId, const HidlCasData& pvtData) {
+    ALOGV("%s: sessionId=%s", __FUNCTION__,
+            sessionIdToString(sessionId).string());
+    sp<PluginHolder> holder = mPluginHolder;
+    if (holder == NULL) {
+        return toStatus(INVALID_OPERATION);
+    }
+    return toStatus(
+            holder->get()->setSessionPrivateData(
+                    sessionId, pvtData));
+}
+
+Return<Status> CasImpl::closeSession(const HidlCasSessionId &sessionId) {
+    ALOGV("%s: sessionId=%s", __FUNCTION__,
+            sessionIdToString(sessionId).string());
+    sp<PluginHolder> holder = mPluginHolder;
+    if (holder == NULL) {
+        return toStatus(INVALID_OPERATION);
+    }
+    return toStatus(holder->get()->closeSession(sessionId));
+}
+
+Return<Status> CasImpl::processEcm(
+        const HidlCasSessionId &sessionId, const HidlCasData& ecm) {
+    ALOGV("%s: sessionId=%s", __FUNCTION__,
+            sessionIdToString(sessionId).string());
+    sp<PluginHolder> holder = mPluginHolder;
+    if (holder == NULL) {
+        return toStatus(INVALID_OPERATION);
+    }
+
+    return toStatus(holder->get()->processEcm(sessionId, ecm));
+}
+
+Return<Status> CasImpl::processEmm(const HidlCasData& emm) {
+    ALOGV("%s", __FUNCTION__);
+    sp<PluginHolder> holder = mPluginHolder;
+    if (holder == NULL) {
+        return toStatus(INVALID_OPERATION);
+    }
+
+    return toStatus(holder->get()->processEmm(emm));
+}
+
+Return<Status> CasImpl::sendEvent(
+        int32_t event, int32_t arg,
+        const HidlCasData& eventData) {
+    ALOGV("%s", __FUNCTION__);
+    sp<PluginHolder> holder = mPluginHolder;
+    if (holder == NULL) {
+        return toStatus(INVALID_OPERATION);
+    }
+
+    status_t err = holder->get()->sendEvent(event, arg, eventData);
+    return toStatus(err);
+}
+
+Return<Status> CasImpl::provision(const hidl_string& provisionString) {
+    ALOGV("%s: provisionString=%s", __FUNCTION__, provisionString.c_str());
+    sp<PluginHolder> holder = mPluginHolder;
+    if (holder == NULL) {
+        return toStatus(INVALID_OPERATION);
+    }
+
+    return toStatus(holder->get()->provision(String8(provisionString.c_str())));
+}
+
+Return<Status> CasImpl::refreshEntitlements(
+        int32_t refreshType,
+        const HidlCasData& refreshData) {
+    ALOGV("%s", __FUNCTION__);
+    sp<PluginHolder> holder = mPluginHolder;
+    if (holder == NULL) {
+        return toStatus(INVALID_OPERATION);
+    }
+
+    status_t err = holder->get()->refreshEntitlements(refreshType, refreshData);
+    return toStatus(err);
+}
+
+Return<Status> CasImpl::release() {
+    ALOGV("%s: plugin=%p", __FUNCTION__,
+            mPluginHolder != NULL ? mPluginHolder->get() : NULL);
+    mPluginHolder.clear();
+    return Status::OK;
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace cas
+} // namespace hardware
+} // namespace android
diff --git a/cas/1.0/default/CasImpl.h b/cas/1.0/default/CasImpl.h
new file mode 100644
index 0000000..841d64e
--- /dev/null
+++ b/cas/1.0/default/CasImpl.h
@@ -0,0 +1,103 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HARDWARE_CAS_V1_0_CAS_IMPL_H_
+#define ANDROID_HARDWARE_CAS_V1_0_CAS_IMPL_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <android/hardware/cas/1.0/ICas.h>
+
+namespace android {
+struct CasPlugin;
+
+namespace hardware {
+namespace cas {
+namespace V1_0 {
+struct ICasListener;
+namespace implementation {
+
+class SharedLibrary;
+
+class CasImpl : public ICas {
+public:
+    CasImpl(const sp<ICasListener> &listener);
+    virtual ~CasImpl();
+
+    static void OnEvent(
+            void *appData,
+            int32_t event,
+            int32_t arg,
+            uint8_t *data,
+            size_t size);
+
+    void init(const sp<SharedLibrary>& library, CasPlugin *plugin);
+    void onEvent(
+            int32_t event,
+            int32_t arg,
+            uint8_t *data,
+            size_t size);
+
+    // ICas inherits
+
+    virtual Return<Status> setPrivateData(
+            const HidlCasData& pvtData) override;
+
+    virtual Return<void> openSession(
+            openSession_cb _hidl_cb) override;
+
+    virtual Return<Status> closeSession(
+            const HidlCasSessionId& sessionId) override;
+
+    virtual Return<Status> setSessionPrivateData(
+            const HidlCasSessionId& sessionId,
+            const HidlCasData& pvtData) override;
+
+    virtual Return<Status> processEcm(
+            const HidlCasSessionId& sessionId,
+            const HidlCasData& ecm) override;
+
+    virtual Return<Status> processEmm(
+            const HidlCasData& emm) override;
+
+    virtual Return<Status> sendEvent(
+            int32_t event, int32_t arg,
+            const HidlCasData& eventData) override;
+
+    virtual Return<Status> provision(
+            const hidl_string& provisionString) override;
+
+    virtual Return<Status> refreshEntitlements(
+            int32_t refreshType,
+            const HidlCasData& refreshData) override;
+
+    virtual Return<Status> release() override;
+
+private:
+    struct PluginHolder;
+    sp<SharedLibrary> mLibrary;
+    sp<PluginHolder> mPluginHolder;
+    sp<ICasListener> mListener;
+
+    DISALLOW_EVIL_CONSTRUCTORS(CasImpl);
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace cas
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_CAS_V1_0_CAS_IMPL_H_
diff --git a/cas/1.0/default/DescramblerImpl.cpp b/cas/1.0/default/DescramblerImpl.cpp
new file mode 100644
index 0000000..3d90809
--- /dev/null
+++ b/cas/1.0/default/DescramblerImpl.cpp
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "android.hardware.cas@1.0-DescramblerImpl"
+
+#include <hidlmemory/mapping.h>
+#include <media/hardware/CryptoAPI.h>
+#include <media/cas/DescramblerAPI.h>
+#include <utils/Log.h>
+
+#include "DescramblerImpl.h"
+#include "SharedLibrary.h"
+#include "TypeConvert.h"
+
+namespace android {
+using hidl::memory::V1_0::IMemory;
+
+namespace hardware {
+namespace cas {
+namespace V1_0 {
+namespace implementation {
+
+#define CHECK_SUBSAMPLE_DEF(type) \
+static_assert(sizeof(SubSample) == sizeof(type::SubSample), \
+        "SubSample: size doesn't match"); \
+static_assert(offsetof(SubSample, numBytesOfClearData) \
+        == offsetof(type::SubSample, mNumBytesOfClearData), \
+        "SubSample: numBytesOfClearData offset doesn't match"); \
+static_assert(offsetof(SubSample, numBytesOfEncryptedData) \
+        == offsetof(type::SubSample, mNumBytesOfEncryptedData), \
+        "SubSample: numBytesOfEncryptedData offset doesn't match")
+
+CHECK_SUBSAMPLE_DEF(DescramblerPlugin);
+CHECK_SUBSAMPLE_DEF(CryptoPlugin);
+
+DescramblerImpl::DescramblerImpl(
+        const sp<SharedLibrary>& library, DescramblerPlugin *plugin) :
+        mLibrary(library), mPlugin(plugin) {
+    ALOGV("CTOR: mPlugin=%p", mPlugin);
+}
+
+DescramblerImpl::~DescramblerImpl() {
+    ALOGV("DTOR: mPlugin=%p", mPlugin);
+    release();
+}
+
+Return<Status> DescramblerImpl::setMediaCasSession(const HidlCasSessionId& sessionId) {
+    ALOGV("%s: sessionId=%s", __FUNCTION__,
+            sessionIdToString(sessionId).string());
+
+    return toStatus(mPlugin->setMediaCasSession(sessionId));
+}
+
+Return<bool> DescramblerImpl::requiresSecureDecoderComponent(
+        const hidl_string& mime) {
+    return mPlugin->requiresSecureDecoderComponent(String8(mime.c_str()));
+}
+
+Return<void> DescramblerImpl::descramble(
+        ScramblingControl scramblingControl,
+        const hidl_vec<SubSample>& subSamples,
+        const SharedBuffer& srcBuffer,
+        uint64_t srcOffset,
+        const DestinationBuffer& dstBuffer,
+        uint64_t dstOffset,
+        descramble_cb _hidl_cb) {
+    ALOGV("%s", __FUNCTION__);
+
+    sp<IMemory> srcMem = mapMemory(srcBuffer.heapBase);
+    void *srcPtr = (uint8_t *)(void *)srcMem->getPointer() + srcBuffer.offset;
+    void *dstPtr = NULL;
+    if (dstBuffer.type == BufferType::SHARED_MEMORY) {
+        // When using shared memory, src buffer is also used as dst,
+        // we don't map it again here.
+        dstPtr = srcPtr;
+    } else {
+        native_handle_t *handle = const_cast<native_handle_t *>(
+                dstBuffer.secureMemory.getNativeHandle());
+        dstPtr = static_cast<void *>(handle);
+    }
+    // Casting hidl SubSample to DescramblerPlugin::SubSample, but need
+    // to ensure structs are actually idential
+
+    int32_t result = mPlugin->descramble(
+            dstBuffer.type != BufferType::SHARED_MEMORY,
+            (DescramblerPlugin::ScramblingControl)scramblingControl,
+            subSamples.size(),
+            (DescramblerPlugin::SubSample*)subSamples.data(),
+            srcPtr,
+            srcOffset,
+            dstPtr,
+            dstOffset,
+            NULL);
+
+    _hidl_cb(toStatus(result >= 0 ? OK : result), result, NULL);
+    return Void();
+}
+
+Return<Status> DescramblerImpl::release() {
+    ALOGV("%s: mPlugin=%p", __FUNCTION__, mPlugin);
+
+    if (mPlugin != NULL) {
+        delete mPlugin;
+        mPlugin = NULL;
+    }
+    return Status::OK;
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace cas
+} // namespace hardware
+} // namespace android
diff --git a/cas/1.0/default/DescramblerImpl.h b/cas/1.0/default/DescramblerImpl.h
new file mode 100644
index 0000000..d3b146e
--- /dev/null
+++ b/cas/1.0/default/DescramblerImpl.h
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HARDWARE_CAS_V1_0_DESCRAMBLER_IMPL_H_
+#define ANDROID_HARDWARE_CAS_V1_0_DESCRAMBLER_IMPL_H_
+
+#include <media/stagefright/foundation/ABase.h>
+#include <android/hardware/cas/native/1.0/IDescrambler.h>
+
+namespace android {
+struct DescramblerPlugin;
+using namespace hardware::cas::native::V1_0;
+
+namespace hardware {
+namespace cas {
+namespace V1_0 {
+namespace implementation {
+
+class SharedLibrary;
+
+class DescramblerImpl : public IDescrambler {
+public:
+    DescramblerImpl(const sp<SharedLibrary>& library, DescramblerPlugin *plugin);
+    virtual ~DescramblerImpl();
+
+    virtual Return<Status> setMediaCasSession(
+            const HidlCasSessionId& sessionId) override;
+
+    virtual Return<bool> requiresSecureDecoderComponent(
+            const hidl_string& mime) override;
+
+    virtual Return<void> descramble(
+            ScramblingControl scramblingControl,
+            const hidl_vec<SubSample>& subSamples,
+            const SharedBuffer& srcBuffer,
+            uint64_t srcOffset,
+            const DestinationBuffer& dstBuffer,
+            uint64_t dstOffset,
+            descramble_cb _hidl_cb) override;
+
+    virtual Return<Status> release() override;
+
+private:
+    sp<SharedLibrary> mLibrary;
+    DescramblerPlugin *mPlugin;
+
+    DISALLOW_EVIL_CONSTRUCTORS(DescramblerImpl);
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace cas
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_CAS_V1_0_DESCRAMBLER_IMPL_H_
diff --git a/cas/1.0/default/FactoryLoader.h b/cas/1.0/default/FactoryLoader.h
new file mode 100644
index 0000000..18c2186
--- /dev/null
+++ b/cas/1.0/default/FactoryLoader.h
@@ -0,0 +1,229 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HARDWARE_CAS_V1_0_FACTORY_LOADER_H_
+#define ANDROID_HARDWARE_CAS_V1_0_FACTORY_LOADER_H_
+
+#include <dirent.h>
+#include <dlfcn.h>
+#include "SharedLibrary.h"
+#include <utils/KeyedVector.h>
+#include <utils/Mutex.h>
+#include <media/cas/CasAPI.h>
+
+using namespace std;
+
+namespace android {
+namespace hardware {
+namespace cas {
+namespace V1_0 {
+namespace implementation {
+
+template <class T>
+class FactoryLoader {
+public:
+    FactoryLoader(const char *name) :
+        mFactory(NULL), mCreateFactoryFuncName(name) {}
+
+    virtual ~FactoryLoader() { closeFactory(); }
+
+    bool findFactoryForScheme(
+            int32_t CA_system_id,
+            sp<SharedLibrary> *library = NULL,
+            T** factory = NULL);
+
+    bool enumeratePlugins(vector<HidlCasPluginDescriptor>* results);
+
+private:
+    typedef T*(*CreateFactoryFunc)();
+
+    Mutex mMapLock;
+    T* mFactory;
+    const char *mCreateFactoryFuncName;
+    sp<SharedLibrary> mLibrary;
+    KeyedVector<int32_t, String8> mCASystemIdToLibraryPathMap;
+    KeyedVector<String8, wp<SharedLibrary> > mLibraryPathToOpenLibraryMap;
+
+    bool loadFactoryForSchemeFromPath(
+            const String8 &path,
+            int32_t CA_system_id,
+            sp<SharedLibrary> *library,
+            T** factory);
+
+    bool queryPluginsFromPath(
+            const String8 &path,
+            vector<HidlCasPluginDescriptor>* results);
+
+    bool openFactory(const String8 &path);
+    void closeFactory();
+};
+
+template <class T>
+bool FactoryLoader<T>::findFactoryForScheme(
+        int32_t CA_system_id, sp<SharedLibrary> *library, T** factory) {
+    if (library != NULL) {
+        library->clear();
+    }
+    if (factory != NULL) {
+        *factory = NULL;
+    }
+
+    Mutex::Autolock autoLock(mMapLock);
+
+    // first check cache
+    ssize_t index = mCASystemIdToLibraryPathMap.indexOfKey(CA_system_id);
+    if (index >= 0) {
+        return loadFactoryForSchemeFromPath(
+                mCASystemIdToLibraryPathMap[index],
+                CA_system_id, library, factory);
+    }
+
+    // no luck, have to search
+    String8 dirPath("/vendor/lib/mediacas");
+    DIR* pDir = opendir(dirPath.string());
+
+    if (pDir == NULL) {
+        ALOGE("Failed to open plugin directory %s", dirPath.string());
+        return false;
+    }
+
+    struct dirent* pEntry;
+    while ((pEntry = readdir(pDir))) {
+        String8 pluginPath = dirPath + "/" + pEntry->d_name;
+        if (pluginPath.getPathExtension() == ".so") {
+            if (loadFactoryForSchemeFromPath(
+                    pluginPath, CA_system_id, library, factory)) {
+                mCASystemIdToLibraryPathMap.add(CA_system_id, pluginPath);
+                closedir(pDir);
+
+                return true;
+            }
+        }
+    }
+
+    closedir(pDir);
+
+    ALOGE("Failed to find plugin");
+    return false;
+}
+
+template <class T>
+bool FactoryLoader<T>::enumeratePlugins(
+        vector<HidlCasPluginDescriptor>* results) {
+    ALOGI("enumeratePlugins");
+
+    results->clear();
+
+    String8 dirPath("/vendor/lib/mediacas");
+    DIR* pDir = opendir(dirPath.string());
+
+    if (pDir == NULL) {
+        ALOGE("Failed to open plugin directory %s", dirPath.string());
+        return false;
+    }
+
+    Mutex::Autolock autoLock(mMapLock);
+
+    struct dirent* pEntry;
+    while ((pEntry = readdir(pDir))) {
+        String8 pluginPath = dirPath + "/" + pEntry->d_name;
+        if (pluginPath.getPathExtension() == ".so") {
+            queryPluginsFromPath(pluginPath, results);
+        }
+    }
+    return true;
+}
+
+template <class T>
+bool FactoryLoader<T>::loadFactoryForSchemeFromPath(
+        const String8 &path, int32_t CA_system_id,
+        sp<SharedLibrary> *library, T** factory) {
+    closeFactory();
+
+    if (!openFactory(path) || !mFactory->isSystemIdSupported(CA_system_id)) {
+        closeFactory();
+        return false;
+    }
+
+    if (library != NULL) {
+        *library = mLibrary;
+    }
+    if (factory != NULL) {
+        *factory = mFactory;
+    }
+    return true;
+}
+
+template <class T>
+bool FactoryLoader<T>::queryPluginsFromPath(
+        const String8 &path, vector<HidlCasPluginDescriptor>* results) {
+    closeFactory();
+
+    vector<CasPluginDescriptor> descriptors;
+    if (!openFactory(path) || mFactory->queryPlugins(&descriptors) != OK) {
+        closeFactory();
+        return false;
+    }
+
+    for (auto it = descriptors.begin(); it != descriptors.end(); it++) {
+        results->push_back( HidlCasPluginDescriptor {
+                .caSystemId = it->CA_system_id,
+                .name = it->name.c_str()});
+    }
+    return true;
+}
+
+template <class T>
+bool FactoryLoader<T>::openFactory(const String8 &path) {
+    // get strong pointer to open shared library
+    ssize_t index = mLibraryPathToOpenLibraryMap.indexOfKey(path);
+    if (index >= 0) {
+        mLibrary = mLibraryPathToOpenLibraryMap[index].promote();
+    } else {
+        index = mLibraryPathToOpenLibraryMap.add(path, NULL);
+    }
+
+    if (!mLibrary.get()) {
+        mLibrary = new SharedLibrary(path);
+        if (!*mLibrary) {
+            return false;
+        }
+
+        mLibraryPathToOpenLibraryMap.replaceValueAt(index, mLibrary);
+    }
+
+    CreateFactoryFunc createFactory =
+        (CreateFactoryFunc)mLibrary->lookup(mCreateFactoryFuncName);
+    if (createFactory == NULL || (mFactory = createFactory()) == NULL) {
+        return false;
+    }
+    return true;
+}
+
+template <class T>
+void FactoryLoader<T>::closeFactory() {
+    delete mFactory;
+    mFactory = NULL;
+    mLibrary.clear();
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace cas
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_CAS_V1_0_FACTORY_LOADER_H_
diff --git a/cas/1.0/default/MediaCasService.cpp b/cas/1.0/default/MediaCasService.cpp
new file mode 100644
index 0000000..ca43224
--- /dev/null
+++ b/cas/1.0/default/MediaCasService.cpp
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "android.hardware.cas@1.0-MediaCasService"
+
+#include <android/hardware/cas/1.0/ICasListener.h>
+#include <media/cas/CasAPI.h>
+#include <media/cas/DescramblerAPI.h>
+#include <utils/Log.h>
+
+#include "CasImpl.h"
+#include "DescramblerImpl.h"
+#include "MediaCasService.h"
+
+namespace android {
+namespace hardware {
+namespace cas {
+namespace V1_0 {
+namespace implementation {
+
+MediaCasService::MediaCasService() :
+    mCasLoader("createCasFactory"),
+    mDescramblerLoader("createDescramblerFactory") {
+}
+
+MediaCasService::~MediaCasService() {
+}
+
+Return<void> MediaCasService::enumeratePlugins(enumeratePlugins_cb _hidl_cb) {
+
+    ALOGV("%s", __FUNCTION__);
+
+    vector<HidlCasPluginDescriptor> results;
+    mCasLoader.enumeratePlugins(&results);
+
+    _hidl_cb(results);
+    return Void();
+}
+
+Return<bool> MediaCasService::isSystemIdSupported(int32_t CA_system_id) {
+    ALOGV("isSystemIdSupported: CA_system_id=%d", CA_system_id);
+
+    return mCasLoader.findFactoryForScheme(CA_system_id);
+}
+
+Return<sp<ICas>> MediaCasService::createPlugin(
+        int32_t CA_system_id, const sp<ICasListener>& listener) {
+
+    ALOGV("%s: CA_system_id=%d", __FUNCTION__, CA_system_id);
+
+    sp<ICas> result;
+
+    CasFactory *factory;
+    sp<SharedLibrary> library;
+    if (mCasLoader.findFactoryForScheme(CA_system_id, &library, &factory)) {
+        CasPlugin *plugin = NULL;
+        sp<CasImpl> casImpl = new CasImpl(listener);
+        if (factory->createPlugin(CA_system_id, (uint64_t)casImpl.get(),
+                &CasImpl::OnEvent, &plugin) == OK && plugin != NULL) {
+            casImpl->init(library, plugin);
+            result = casImpl;
+        }
+    }
+
+    return result;
+}
+
+Return<bool> MediaCasService::isDescramblerSupported(int32_t CA_system_id) {
+    ALOGV("%s: CA_system_id=%d", __FUNCTION__, CA_system_id);
+
+    return mDescramblerLoader.findFactoryForScheme(CA_system_id);
+}
+
+Return<sp<IDescramblerBase>> MediaCasService::createDescrambler(int32_t CA_system_id) {
+
+    ALOGV("%s: CA_system_id=%d", __FUNCTION__, CA_system_id);
+
+    sp<IDescrambler> result;
+
+    DescramblerFactory *factory;
+    sp<SharedLibrary> library;
+    if (mDescramblerLoader.findFactoryForScheme(
+            CA_system_id, &library, &factory)) {
+        DescramblerPlugin *plugin = NULL;
+        if (factory->createPlugin(CA_system_id, &plugin) == OK
+                && plugin != NULL) {
+            result = new DescramblerImpl(library, plugin);
+        }
+    }
+
+    return result;
+}
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace cas
+} // namespace hardware
+} // namespace android
diff --git a/cas/1.0/default/MediaCasService.h b/cas/1.0/default/MediaCasService.h
new file mode 100644
index 0000000..77ddac6
--- /dev/null
+++ b/cas/1.0/default/MediaCasService.h
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HARDWARE_CAS_V1_0_MEDIA_CAS_SERVICE_H_
+#define ANDROID_HARDWARE_CAS_V1_0_MEDIA_CAS_SERVICE_H_
+
+#include <android/hardware/cas/1.0/IMediaCasService.h>
+
+#include "FactoryLoader.h"
+
+namespace android {
+struct CasFactory;
+struct DescramblerFactory;
+namespace hardware {
+namespace cas {
+namespace V1_0 {
+namespace implementation {
+
+class MediaCasService : public IMediaCasService {
+public:
+    MediaCasService();
+
+    virtual Return<void> enumeratePlugins(
+            enumeratePlugins_cb _hidl_cb) override;
+
+    virtual Return<bool> isSystemIdSupported(
+            int32_t CA_system_id) override;
+
+    virtual Return<sp<ICas>> createPlugin(
+            int32_t CA_system_id, const sp<ICasListener>& listener) override;
+
+    virtual Return<bool> isDescramblerSupported(
+            int32_t CA_system_id) override;
+
+    virtual Return<sp<IDescramblerBase>> createDescrambler(
+            int32_t CA_system_id) override;
+
+private:
+    FactoryLoader<CasFactory> mCasLoader;
+    FactoryLoader<DescramblerFactory> mDescramblerLoader;
+
+    virtual ~MediaCasService();
+};
+
+} // namespace implementation
+} // namespace V1_0
+} // namespace cas
+} // namespace hardware
+} // namespace android
+
+#endif // ANDROID_HARDWARE_CAS_V1_0_MEDIA_CAS_SERVICE_H_
diff --git a/cas/1.0/default/SharedLibrary.cpp b/cas/1.0/default/SharedLibrary.cpp
new file mode 100644
index 0000000..9c7f385
--- /dev/null
+++ b/cas/1.0/default/SharedLibrary.cpp
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "android.hardware.cas@1.0-SharedLibrary"
+
+#include <dlfcn.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include "SharedLibrary.h"
+#include <utils/Log.h>
+
+namespace android {
+namespace hardware {
+namespace cas {
+namespace V1_0 {
+namespace implementation {
+
+SharedLibrary::SharedLibrary(const String8 &path) {
+    mLibHandle = dlopen(path.string(), RTLD_NOW);
+}
+
+SharedLibrary::~SharedLibrary() {
+    if (mLibHandle != NULL) {
+        dlclose(mLibHandle);
+        mLibHandle = NULL;
+    }
+}
+
+bool SharedLibrary::operator!() const {
+    return mLibHandle == NULL;
+}
+
+void *SharedLibrary::lookup(const char *symbol) const {
+    if (!mLibHandle) {
+        return NULL;
+    }
+    // Clear last error before we load the symbol again,
+    // in case the caller didn't retrieve it.
+    (void)dlerror();
+    return dlsym(mLibHandle, symbol);
+}
+
+const char *SharedLibrary::lastError() const {
+    const char *error = dlerror();
+    return error ? error : "No errors or unknown error";
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace cas
+}  // namespace hardware
+}  // namespace android
diff --git a/cas/1.0/default/SharedLibrary.h b/cas/1.0/default/SharedLibrary.h
new file mode 100644
index 0000000..18130a5
--- /dev/null
+++ b/cas/1.0/default/SharedLibrary.h
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HARDWARE_CAS_V1_0_SHARED_LIBRARY_H_
+#define ANDROID_HARDWARE_CAS_V1_0_SHARED_LIBRARY_H_
+
+#include <utils/RefBase.h>
+#include <utils/String8.h>
+#include <media/stagefright/foundation/ABase.h>
+
+namespace android {
+namespace hardware {
+namespace cas {
+namespace V1_0 {
+namespace implementation {
+
+class SharedLibrary : public RefBase {
+public:
+    explicit SharedLibrary(const String8 &path);
+    ~SharedLibrary();
+
+    bool operator!() const;
+    void *lookup(const char *symbol) const;
+    const char *lastError() const;
+
+private:
+    void *mLibHandle;
+    DISALLOW_EVIL_CONSTRUCTORS(SharedLibrary);
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace cas
+}  // namespace hardware
+}  // namespace android
+
+#endif // ANDROID_HARDWARE_CAS_V1_0_SHARED_LIBRARY_H_
diff --git a/cas/1.0/default/TypeConvert.cpp b/cas/1.0/default/TypeConvert.cpp
new file mode 100644
index 0000000..cd0efdb
--- /dev/null
+++ b/cas/1.0/default/TypeConvert.cpp
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "android.hardware.cas@1.0-TypeConvert"
+
+#include <utils/Log.h>
+#include "TypeConvert.h"
+
+namespace android {
+namespace hardware {
+namespace cas {
+namespace V1_0 {
+namespace implementation {
+
+Status toStatus(status_t legacyStatus) {
+    Status status;
+    switch(legacyStatus) {
+    case android::OK:
+        status = Status::OK;
+        break;
+    case android::ERROR_CAS_NO_LICENSE:
+        status = Status::ERROR_CAS_NO_LICENSE;
+        break;
+    case android::ERROR_CAS_LICENSE_EXPIRED:
+        status = Status::ERROR_CAS_LICENSE_EXPIRED;
+        break;
+    case android::ERROR_CAS_SESSION_NOT_OPENED:
+        status = Status::ERROR_CAS_SESSION_NOT_OPENED;
+        break;
+    case android::ERROR_CAS_CANNOT_HANDLE:
+        status = Status::ERROR_CAS_CANNOT_HANDLE;
+        break;
+    case android::ERROR_CAS_TAMPER_DETECTED:
+        status = Status::ERROR_CAS_INVALID_STATE;
+        break;
+    case android::BAD_VALUE:
+        status = Status::BAD_VALUE;
+        break;
+    case android::ERROR_CAS_NOT_PROVISIONED:
+        status = Status::ERROR_CAS_NOT_PROVISIONED;
+        break;
+    case android::ERROR_CAS_RESOURCE_BUSY:
+        status = Status::ERROR_CAS_RESOURCE_BUSY;
+        break;
+    case android::ERROR_CAS_INSUFFICIENT_OUTPUT_PROTECTION:
+        status = Status::ERROR_CAS_INSUFFICIENT_OUTPUT_PROTECTION;
+        break;
+    case android::ERROR_CAS_DEVICE_REVOKED:
+        status = Status::ERROR_CAS_DEVICE_REVOKED;
+        break;
+    case android::ERROR_CAS_DECRYPT_UNIT_NOT_INITIALIZED:
+        status = Status::ERROR_CAS_DECRYPT_UNIT_NOT_INITIALIZED;
+        break;
+    case android::ERROR_CAS_DECRYPT:
+        status = Status::ERROR_CAS_DECRYPT;
+        break;
+    default:
+        ALOGW("Unable to convert legacy status: %d, defaulting to UNKNOWN",
+            legacyStatus);
+        status = Status::ERROR_CAS_UNKNOWN;
+        break;
+    }
+    return status;
+}
+
+String8 sessionIdToString(const CasSessionId &sessionId) {
+    String8 result;
+    for (size_t i = 0; i < sessionId.size(); i++) {
+        result.appendFormat("%02x ", sessionId[i]);
+    }
+    if (result.isEmpty()) {
+        result.append("(null)");
+    }
+    return result;
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace cas
+}  // namespace hardware
+}  // namespace android
diff --git a/cas/1.0/default/TypeConvert.h b/cas/1.0/default/TypeConvert.h
new file mode 100644
index 0000000..7c3dded
--- /dev/null
+++ b/cas/1.0/default/TypeConvert.h
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_HARDWARE_CAS_V1_0_TYPE_CONVERT_H
+#define ANDROID_HARDWARE_CAS_V1_0_TYPE_CONVERT_H
+
+#include <android/hardware/cas/1.0/types.h>
+#include <media/cas/CasAPI.h>
+#include <media/stagefright/MediaErrors.h>
+#include <utils/String8.h>
+
+namespace android {
+namespace hardware {
+namespace cas {
+namespace V1_0 {
+namespace implementation {
+
+Status toStatus(status_t legacyStatus);
+
+String8 sessionIdToString(const CasSessionId &sessionId);
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace cas
+}  // namespace hardware
+}  // namespace android
+
+#endif // ANDROID_HARDWARE_CAS_V1_0_TYPE_CONVERT_H
diff --git a/cas/1.0/default/android.hardware.cas@1.0-service.rc b/cas/1.0/default/android.hardware.cas@1.0-service.rc
new file mode 100644
index 0000000..93de794
--- /dev/null
+++ b/cas/1.0/default/android.hardware.cas@1.0-service.rc
@@ -0,0 +1,6 @@
+service cas-hal-1-0 /vendor/bin/hw/android.hardware.cas@1.0-service
+    class hal
+    user media
+    group mediadrm drmrpc
+    ioprio rt 4
+    writepid /dev/cpuset/foreground/tasks
diff --git a/cas/1.0/default/service.cpp b/cas/1.0/default/service.cpp
new file mode 100644
index 0000000..3f1df5a
--- /dev/null
+++ b/cas/1.0/default/service.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "android.hardware.cas@1.0-service"
+
+#include <binder/ProcessState.h>
+#include <hidl/HidlTransportSupport.h>
+#include <hidl/LegacySupport.h>
+
+#include "MediaCasService.h"
+
+using android::hardware::configureRpcThreadpool;
+using android::hardware::joinRpcThreadpool;
+using android::hardware::cas::V1_0::implementation::MediaCasService;
+using android::hardware::cas::V1_0::IMediaCasService;
+
+int main() {
+    ALOGD("android.hardware.cas@1.0-service starting...");
+
+#ifdef USE_VNDBINDER
+    // The CAS HAL may communicate to other vendor components via
+    // /dev/vndbinder
+    android::ProcessState::initWithDriver("/dev/vndbinder");
+#endif // USE_VNDBINDER
+
+    configureRpcThreadpool(8, true /* callerWillJoin */);
+
+    // Setup hwbinder service
+    android::sp<IMediaCasService> service = new MediaCasService();
+    android::status_t status = service->registerAsService();
+    LOG_ALWAYS_FATAL_IF(
+            status != android::OK,
+            "Error while registering cas service: %d", status);
+    joinRpcThreadpool();
+    return 0;
+}
diff --git a/cas/1.0/types.hal b/cas/1.0/types.hal
new file mode 100644
index 0000000..7337f00
--- /dev/null
+++ b/cas/1.0/types.hal
@@ -0,0 +1,124 @@
+/**
+ * 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.
+ */
+
+package android.hardware.cas@1.0;
+
+enum Status : uint32_t {
+    /**
+     * The CAS plugin must return OK when an operation completes without any
+     * errors.
+     */
+    OK,
+
+    /**
+     * The CAS plugin must return ERROR_CAS_NO_LICENSE, when descrambling is
+     * attempted and no license keys have been provided.
+     */
+    ERROR_CAS_NO_LICENSE,
+
+    /**
+     * ERROR_CAS_LICENSE_EXPIRED must be returned when an attempt is made
+     * to use a license and the keys in that license have expired.
+     */
+    ERROR_CAS_LICENSE_EXPIRED,
+
+    /**
+     * The CAS plugin must return ERROR_CAS_SESSION_NOT_OPENED when an
+     * attempt is made to use a session that has not been opened.
+     */
+    ERROR_CAS_SESSION_NOT_OPENED,
+
+    /**
+     * The CAS plugin must return ERROR_CAS_CANNOT_HANDLE when an unsupported
+     * data format or operation is attempted.
+     */
+    ERROR_CAS_CANNOT_HANDLE,
+
+    /**
+     * ERROR_CAS_INVALID_STATE must be returned when the device is in a state
+     * where it is not able to perform descrambling.
+     */
+    ERROR_CAS_INVALID_STATE,
+
+    /**
+     * The CAS plugin must return BAD_VALUE whenever an illegal parameter is
+     * passed to one of the interface functions.
+     */
+    BAD_VALUE,
+
+    /**
+     * The CAS plugin must return ERROR_CAS_NOT_PROVISIONED when the device
+     * has not yet been provisioned.
+     */
+    ERROR_CAS_NOT_PROVISIONED,
+
+    /**
+     * ERROR_CAS_RESOURCE_BUSY must be returned when resources, such as CAS
+     * sessions or secure buffers are not available to perform a requested
+     * operation because they are already in use.
+     */
+    ERROR_CAS_RESOURCE_BUSY,
+
+    /**
+     * The CAS Plugin must return ERROR_CAS_INSUFFICIENT_OUTPUT_PROTECTION
+     * when the output protection level enabled on the device is not
+     * sufficient to meet the requirements in the license policy. HDCP is an
+     * example of a form of output protection.
+     */
+    ERROR_CAS_INSUFFICIENT_OUTPUT_PROTECTION,
+
+    /**
+     * The CAS Plugin must return ERROR_CAS_TAMPER_DETECTED if an attempt to
+     * tamper with the CAS system is detected.
+     */
+    ERROR_CAS_TAMPER_DETECTED,
+
+    /**
+     * The CAS Plugin must return ERROR_CAS_DEVICE_REVOKED if the response
+     * indicates that the device has been revoked. Device revocation means
+     * that the device is no longer permitted to play content.
+     */
+    ERROR_CAS_DEVICE_REVOKED,
+
+    /**
+     * The CAS plugin must return ERROR_CAS_DECRYPT_UNIT_NOT_INITIALIZED when
+     * descrambling is failing because the session is not initialized properly.
+     */
+    ERROR_CAS_DECRYPT_UNIT_NOT_INITIALIZED,
+
+    /**
+     * The CAS Plugin must return ERROR_CAS_DECRYPT if the DescramblerPlugin's
+     * descramble operation fails.
+     */
+    ERROR_CAS_DECRYPT,
+
+    /**
+     * ERROR_CAS_UNKNOWN must be returned when a fatal failure occurs and no
+     * other defined error is appropriate.
+     */
+    ERROR_CAS_UNKNOWN,
+};
+
+typedef vec<uint8_t> HidlCasSessionId;
+typedef vec<uint8_t> HidlCasData;
+
+/**
+ * Describes a CAS plugin with its system id and name.
+ */
+struct HidlCasPluginDescriptor {
+    int32_t caSystemId;
+    string name;
+};
diff --git a/cas/Android.bp b/cas/Android.bp
new file mode 100644
index 0000000..57532a0
--- /dev/null
+++ b/cas/Android.bp
@@ -0,0 +1,6 @@
+// This is an autogenerated file, do not edit.
+subdirs = [
+    "1.0",
+    "1.0/default",
+    "native/1.0",
+]
diff --git a/cas/native/1.0/Android.bp b/cas/native/1.0/Android.bp
new file mode 100644
index 0000000..e39cab1
--- /dev/null
+++ b/cas/native/1.0/Android.bp
@@ -0,0 +1,68 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+filegroup {
+    name: "android.hardware.cas.native@1.0_hal",
+    srcs: [
+        "types.hal",
+        "IDescrambler.hal",
+    ],
+}
+
+genrule {
+    name: "android.hardware.cas.native@1.0_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++-sources -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.cas.native@1.0",
+    srcs: [
+        ":android.hardware.cas.native@1.0_hal",
+    ],
+    out: [
+        "android/hardware/cas/native/1.0/types.cpp",
+        "android/hardware/cas/native/1.0/DescramblerAll.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.cas.native@1.0_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++-headers -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.cas.native@1.0",
+    srcs: [
+        ":android.hardware.cas.native@1.0_hal",
+    ],
+    out: [
+        "android/hardware/cas/native/1.0/types.h",
+        "android/hardware/cas/native/1.0/hwtypes.h",
+        "android/hardware/cas/native/1.0/IDescrambler.h",
+        "android/hardware/cas/native/1.0/IHwDescrambler.h",
+        "android/hardware/cas/native/1.0/BnHwDescrambler.h",
+        "android/hardware/cas/native/1.0/BpHwDescrambler.h",
+        "android/hardware/cas/native/1.0/BsDescrambler.h",
+    ],
+}
+
+cc_library {
+    name: "android.hardware.cas.native@1.0",
+    defaults: ["hidl-module-defaults"],
+    generated_sources: ["android.hardware.cas.native@1.0_genc++"],
+    generated_headers: ["android.hardware.cas.native@1.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.cas.native@1.0_genc++_headers"],
+    vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "android.hardware.cas@1.0",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hardware.cas@1.0",
+    ],
+}
diff --git a/cas/native/1.0/IDescrambler.hal b/cas/native/1.0/IDescrambler.hal
new file mode 100644
index 0000000..4822111
--- /dev/null
+++ b/cas/native/1.0/IDescrambler.hal
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+package android.hardware.cas.native@1.0;
+
+import android.hardware.cas@1.0::IDescramblerBase;
+import android.hardware.cas@1.0::Status;
+
+/**
+ * IDescrambler is the native plugin API for descrambling operations.
+ */
+
+interface IDescrambler extends IDescramblerBase {
+    /**
+     * Descramble the data in a source SharedBuffer, described by an array of
+     * SubSample structures.
+     *
+     * @param scramblingControl an enumeration indicating the key that the subsamples
+     * were scrambled with.
+     * @param subSamples an array of SubSample structures describing the number of
+     * clear and scrambled bytes within each subsample.
+     * @param srcBuffer the SharedBuffer containing the source scrambled data.
+     * @param srcOffset the position where the source scrambled data starts at.
+     * @param dstBuffer the DestinationBuffer to hold the descrambled data.
+     * @param dstOffset the position where the descrambled data should start at.
+     *
+     * @return status the status of the call.
+     * @return bytesWritten number of bytes that have been successfully descrambled.
+     * @return detailedError a detailed message describing the error (if any).
+     */
+    descramble(ScramblingControl scramblingControl, vec<SubSample> subSamples,
+        SharedBuffer srcBuffer, uint64_t srcOffset, DestinationBuffer dstBuffer, uint64_t dstOffset)
+        generates(Status status, uint32_t bytesWritten, string detailedError);
+};
diff --git a/cas/native/1.0/types.hal b/cas/native/1.0/types.hal
new file mode 100644
index 0000000..d75338b
--- /dev/null
+++ b/cas/native/1.0/types.hal
@@ -0,0 +1,88 @@
+/**
+ * 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.
+ */
+
+package android.hardware.cas.native@1.0;
+
+/**
+ * Enumerates the keys used to scramble the content.
+ */
+enum ScramblingControl : uint32_t {
+    UNSCRAMBLED = 0,
+    RESERVED    = 1,
+    EVENKEY     = 2,
+    ODDKEY      = 3,
+};
+
+/**
+ * A subsample consists of some number of bytes of clear (unscrambled)
+ * data followed by a number of bytes of scrambled data.
+ */
+struct SubSample {
+    uint32_t numBytesOfClearData;
+    uint32_t numBytesOfEncryptedData;
+};
+
+/**
+ * SharedBuffer describes a shared buffer which is defined by a heapBase, an
+ * offset and a size. The offset is relative to the shared memory base for the
+ * memory region identified by heapBase.
+ */
+struct SharedBuffer {
+    /**
+     * The shared memory base handle
+     */
+    memory heapBase;
+
+    /**
+     * The offset from the shared memory base
+     */
+    uint64_t offset;
+
+    /**
+     * The size of the shared buffer in bytes
+     */
+    uint64_t size;
+};
+
+/**
+ * A descrambling destination buffer can be either normal user-space shared
+ * memory for the non-secure descrambling case, or it can be a secure buffer
+ * which is referenced by a native-handle. The native handle is allocated
+ * by the vendor's buffer allocator.
+ */
+enum BufferType : uint32_t {
+    SHARED_MEMORY = 0,
+    NATIVE_HANDLE = 1,
+};
+
+struct DestinationBuffer {
+    /**
+     * The type of the buffer
+     */
+    BufferType type;
+
+    /**
+     * If type == SHARED_MEMORY, the descrambled data must be written
+     * to user-space non-secure shared memory.
+     */
+    SharedBuffer nonsecureMemory;
+
+    /**
+     * If type == NATIVE_HANDLE, the descrambled data must be written
+     * to secure memory referenced by the vendor's buffer allocator.
+     */
+    handle secureMemory;
+};
diff --git a/compatibility_matrix.26.xml b/compatibility_matrix.26.xml
index 8c715dd..5c81f26 100644
--- a/compatibility_matrix.26.xml
+++ b/compatibility_matrix.26.xml
@@ -57,7 +57,7 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.broadcastradio</name>
-        <version>1.0</version>
+        <version>1.0-1</version>
         <interface>
             <name>IBroadcastRadioFactory</name>
             <instance>default</instance>
@@ -71,6 +71,14 @@
             <instance>legacy/0</instance>
         </interface>
     </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.cas</name>
+        <version>1.0</version>
+        <interface>
+            <name>IMediaCasService</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
     <hal format="hidl" optional="false">
         <name>android.hardware.configstore</name>
         <version>1.0</version>
@@ -204,16 +212,24 @@
         </interface>
     </hal>
     <hal format="hidl" optional="true">
-        <name>android.hardware.power</name>
+        <name>android.hardware.oemlock</name>
         <version>1.0</version>
         <interface>
+            <name>IOemLock</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.power</name>
+        <version>1.0-1</version>
+        <interface>
             <name>IPower</name>
             <instance>default</instance>
         </interface>
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.radio</name>
-        <version>1.0</version>
+        <version>1.0-1</version>
         <interface>
             <name>IRadio</name>
             <instance>slot1</instance>
@@ -256,9 +272,25 @@
         </interface>
     </hal>
     <hal format="hidl" optional="true">
-        <name>android.hardware.thermal</name>
+        <name>android.hardware.tetheroffload.config</name>
         <version>1.0</version>
         <interface>
+            <name>IOffloadConfig</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.tetheroffload.control</name>
+        <version>1.0</version>
+        <interface>
+            <name>IOffloadControl</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.thermal</name>
+        <version>1.0-1</version>
+        <interface>
             <name>IThermal</name>
             <instance>default</instance>
         </interface>
@@ -281,7 +313,7 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.usb</name>
-        <version>1.0</version>
+        <version>1.0-1</version>
         <interface>
             <name>IUsb</name>
             <instance>default</instance>
@@ -289,7 +321,7 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.vibrator</name>
-        <version>1.0</version>
+        <version>1.0-1</version>
         <interface>
             <name>IVibrator</name>
             <instance>default</instance>
@@ -304,14 +336,30 @@
         </interface>
     </hal>
     <hal format="hidl" optional="true">
-        <name>android.hardware.wifi</name>
+        <name>android.hardware.weaver</name>
         <version>1.0</version>
         <interface>
+            <name>IWeaver</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.wifi</name>
+        <version>1.0-1</version>
+        <interface>
             <name>IWifi</name>
             <instance>default</instance>
         </interface>
     </hal>
     <hal format="hidl" optional="true">
+        <name>android.hardware.wifi.offload</name>
+        <version>1.0</version>
+        <interface>
+            <name>IOffload</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
         <name>android.hardware.wifi.supplicant</name>
         <version>1.0</version>
         <interface>
@@ -319,7 +367,4 @@
             <instance>default</instance>
         </interface>
     </hal>
-    <kernel version="4.9.0" />
-    <kernel version="4.4.0" />
-    <kernel version="3.18.0" />
 </compatibility-matrix>
diff --git a/compatibility_matrix.27.xml b/compatibility_matrix.27.xml
new file mode 100644
index 0000000..5c81f26
--- /dev/null
+++ b/compatibility_matrix.27.xml
@@ -0,0 +1,370 @@
+<compatibility-matrix version="1.0" type="framework">
+    <hal format="hidl" optional="false">
+        <name>android.hardware.audio</name>
+        <version>2.0</version>
+        <interface>
+            <name>IDevicesFactory</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="false">
+        <name>android.hardware.audio.effect</name>
+        <version>2.0</version>
+        <interface>
+            <name>IEffectsFactory</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.automotive.evs</name>
+        <version>1.0</version>
+        <interface>
+            <name>IEvsEnumerator</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.automotive.vehicle</name>
+        <version>2.0</version>
+        <interface>
+            <name>IVehicle</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.biometrics.fingerprint</name>
+        <version>2.1</version>
+        <interface>
+            <name>IBiometricsFingerprint</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.bluetooth</name>
+        <version>1.0</version>
+        <interface>
+            <name>IBluetoothHci</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.boot</name>
+        <version>1.0</version>
+        <interface>
+            <name>IBootControl</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.broadcastradio</name>
+        <version>1.0-1</version>
+        <interface>
+            <name>IBroadcastRadioFactory</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.camera.provider</name>
+        <version>2.4</version>
+        <interface>
+            <name>ICameraProvider</name>
+            <instance>legacy/0</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.cas</name>
+        <version>1.0</version>
+        <interface>
+            <name>IMediaCasService</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="false">
+        <name>android.hardware.configstore</name>
+        <version>1.0</version>
+        <interface>
+            <name>ISurfaceFlingerConfigs</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.contexthub</name>
+        <version>1.0</version>
+        <interface>
+            <name>IContexthub</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="false">
+        <name>android.hardware.drm</name>
+        <version>1.0</version>
+        <interface>
+            <name>ICryptoFactory</name>
+            <instance>default</instance>
+        </interface>
+        <interface>
+            <name>IDrmFactory</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.dumpstate</name>
+        <version>1.0</version>
+        <interface>
+            <name>IDumpstateDevice</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="false">
+        <name>android.hardware.gatekeeper</name>
+        <version>1.0</version>
+        <interface>
+            <name>IGatekeeper</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.gnss</name>
+        <version>1.0</version>
+        <interface>
+            <name>IGnss</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="false">
+        <name>android.hardware.graphics.allocator</name>
+        <version>2.0</version>
+        <interface>
+            <name>IAllocator</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="false">
+        <name>android.hardware.graphics.composer</name>
+        <version>2.1</version>
+        <interface>
+            <name>IComposer</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="false">
+        <name>android.hardware.graphics.mapper</name>
+        <version>2.0</version>
+        <interface>
+            <name>IMapper</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.health</name>
+        <version>1.0</version>
+        <interface>
+            <name>IHealth</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.ir</name>
+        <version>1.0</version>
+    </hal>
+    <hal format="hidl" optional="false">
+        <name>android.hardware.keymaster</name>
+        <version>3.0</version>
+        <interface>
+            <name>IKeymasterDevice</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.light</name>
+        <version>2.0</version>
+        <interface>
+            <name>ILight</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="false">
+        <name>android.hardware.media.omx</name>
+        <version>1.0</version>
+        <interface>
+            <name>IOmx</name>
+            <instance>default</instance>
+        </interface>
+        <interface>
+            <name>IOmxStore</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.memtrack</name>
+        <version>1.0</version>
+        <interface>
+            <name>IMemtrack</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.nfc</name>
+        <version>1.0</version>
+        <interface>
+            <name>INfc</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.oemlock</name>
+        <version>1.0</version>
+        <interface>
+            <name>IOemLock</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.power</name>
+        <version>1.0-1</version>
+        <interface>
+            <name>IPower</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.radio</name>
+        <version>1.0-1</version>
+        <interface>
+            <name>IRadio</name>
+            <instance>slot1</instance>
+        </interface>
+        <interface>
+            <name>ISap</name>
+            <instance>slot1</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.radio.deprecated</name>
+        <version>1.0</version>
+        <interface>
+            <name>IOemHook</name>
+            <instance>slot1</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.renderscript</name>
+        <version>1.0</version>
+        <interface>
+            <name>IDevice</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.sensors</name>
+        <version>1.0</version>
+        <interface>
+            <name>ISensors</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.soundtrigger</name>
+        <version>2.0</version>
+        <interface>
+            <name>ISoundTriggerHw</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.tetheroffload.config</name>
+        <version>1.0</version>
+        <interface>
+            <name>IOffloadConfig</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.tetheroffload.control</name>
+        <version>1.0</version>
+        <interface>
+            <name>IOffloadControl</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.thermal</name>
+        <version>1.0-1</version>
+        <interface>
+            <name>IThermal</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.tv.cec</name>
+        <version>1.0</version>
+        <interface>
+            <name>IHdmiCec</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.tv.input</name>
+        <version>1.0</version>
+        <interface>
+            <name>ITvInput</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.usb</name>
+        <version>1.0-1</version>
+        <interface>
+            <name>IUsb</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.vibrator</name>
+        <version>1.0-1</version>
+        <interface>
+            <name>IVibrator</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.vr</name>
+        <version>1.0</version>
+        <interface>
+            <name>IVr</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.weaver</name>
+        <version>1.0</version>
+        <interface>
+            <name>IWeaver</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.wifi</name>
+        <version>1.0-1</version>
+        <interface>
+            <name>IWifi</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.wifi.offload</name>
+        <version>1.0</version>
+        <interface>
+            <name>IOffload</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.wifi.supplicant</name>
+        <version>1.0</version>
+        <interface>
+            <name>ISupplicant</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+</compatibility-matrix>
diff --git a/compatibility_matrix.current.xml b/compatibility_matrix.current.xml
index e3c4e15..5c81f26 100644
--- a/compatibility_matrix.current.xml
+++ b/compatibility_matrix.current.xml
@@ -57,7 +57,7 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.broadcastradio</name>
-        <version>1.0</version>
+        <version>1.0-1</version>
         <interface>
             <name>IBroadcastRadioFactory</name>
             <instance>default</instance>
@@ -71,6 +71,14 @@
             <instance>legacy/0</instance>
         </interface>
     </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.cas</name>
+        <version>1.0</version>
+        <interface>
+            <name>IMediaCasService</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
     <hal format="hidl" optional="false">
         <name>android.hardware.configstore</name>
         <version>1.0</version>
@@ -206,10 +214,14 @@
     <hal format="hidl" optional="true">
         <name>android.hardware.oemlock</name>
         <version>1.0</version>
+        <interface>
+            <name>IOemLock</name>
+            <instance>default</instance>
+        </interface>
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.power</name>
-        <version>1.0</version>
+        <version>1.0-1</version>
         <interface>
             <name>IPower</name>
             <instance>default</instance>
@@ -217,7 +229,7 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.radio</name>
-        <version>1.0</version>
+        <version>1.0-1</version>
         <interface>
             <name>IRadio</name>
             <instance>slot1</instance>
@@ -260,9 +272,25 @@
         </interface>
     </hal>
     <hal format="hidl" optional="true">
-        <name>android.hardware.thermal</name>
+        <name>android.hardware.tetheroffload.config</name>
         <version>1.0</version>
         <interface>
+            <name>IOffloadConfig</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.tetheroffload.control</name>
+        <version>1.0</version>
+        <interface>
+            <name>IOffloadControl</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.thermal</name>
+        <version>1.0-1</version>
+        <interface>
             <name>IThermal</name>
             <instance>default</instance>
         </interface>
@@ -285,7 +313,7 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.usb</name>
-        <version>1.0</version>
+        <version>1.0-1</version>
         <interface>
             <name>IUsb</name>
             <instance>default</instance>
@@ -293,7 +321,7 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.vibrator</name>
-        <version>1.0</version>
+        <version>1.0-1</version>
         <interface>
             <name>IVibrator</name>
             <instance>default</instance>
@@ -310,16 +338,28 @@
     <hal format="hidl" optional="true">
         <name>android.hardware.weaver</name>
         <version>1.0</version>
+        <interface>
+            <name>IWeaver</name>
+            <instance>default</instance>
+        </interface>
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.wifi</name>
-        <version>1.0</version>
+        <version>1.0-1</version>
         <interface>
             <name>IWifi</name>
             <instance>default</instance>
         </interface>
     </hal>
     <hal format="hidl" optional="true">
+        <name>android.hardware.wifi.offload</name>
+        <version>1.0</version>
+        <interface>
+            <name>IOffload</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
         <name>android.hardware.wifi.supplicant</name>
         <version>1.0</version>
         <interface>
@@ -327,7 +367,4 @@
             <instance>default</instance>
         </interface>
     </hal>
-    <kernel version="4.9.0" />
-    <kernel version="4.4.0" />
-    <kernel version="3.18.0" />
 </compatibility-matrix>
diff --git a/compatibility_matrix.legacy.xml b/compatibility_matrix.legacy.xml
index 1dbbb05..5655fb9 100644
--- a/compatibility_matrix.legacy.xml
+++ b/compatibility_matrix.legacy.xml
@@ -57,7 +57,7 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.broadcastradio</name>
-        <version>1.0</version>
+        <version>1.0-1</version>
         <interface>
             <name>IBroadcastRadioFactory</name>
             <instance>default</instance>
@@ -71,6 +71,14 @@
             <instance>legacy/0</instance>
         </interface>
     </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.cas</name>
+        <version>1.0</version>
+        <interface>
+            <name>IMediaCasService</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
     <hal format="hidl" optional="false">
         <name>android.hardware.configstore</name>
         <version>1.0</version>
@@ -204,16 +212,24 @@
         </interface>
     </hal>
     <hal format="hidl" optional="true">
-        <name>android.hardware.power</name>
+        <name>android.hardware.oemlock</name>
         <version>1.0</version>
         <interface>
+            <name>IOemLock</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.power</name>
+        <version>1.0-1</version>
+        <interface>
             <name>IPower</name>
             <instance>default</instance>
         </interface>
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.radio</name>
-        <version>1.0</version>
+        <version>1.0-1</version>
         <interface>
             <name>IRadio</name>
             <instance>slot1</instance>
@@ -256,9 +272,25 @@
         </interface>
     </hal>
     <hal format="hidl" optional="true">
-        <name>android.hardware.thermal</name>
+        <name>android.hardware.tetheroffload.config</name>
         <version>1.0</version>
         <interface>
+            <name>IOffloadConfig</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.tetheroffload.control</name>
+        <version>1.0</version>
+        <interface>
+            <name>IOffloadControl</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.thermal</name>
+        <version>1.0-1</version>
+        <interface>
             <name>IThermal</name>
             <instance>default</instance>
         </interface>
@@ -281,7 +313,7 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.usb</name>
-        <version>1.0</version>
+        <version>1.0-1</version>
         <interface>
             <name>IUsb</name>
             <instance>default</instance>
@@ -289,7 +321,7 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.vibrator</name>
-        <version>1.0</version>
+        <version>1.0-1</version>
         <interface>
             <name>IVibrator</name>
             <instance>default</instance>
@@ -304,14 +336,30 @@
         </interface>
     </hal>
     <hal format="hidl" optional="true">
-        <name>android.hardware.wifi</name>
+        <name>android.hardware.weaver</name>
         <version>1.0</version>
         <interface>
+            <name>IWeaver</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.wifi</name>
+        <version>1.0-1</version>
+        <interface>
             <name>IWifi</name>
             <instance>default</instance>
         </interface>
     </hal>
     <hal format="hidl" optional="true">
+        <name>android.hardware.wifi.offload</name>
+        <version>1.0</version>
+        <interface>
+            <name>IOffload</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
         <name>android.hardware.wifi.supplicant</name>
         <version>1.0</version>
         <interface>
@@ -319,7 +367,4 @@
             <instance>default</instance>
         </interface>
     </hal>
-    <kernel version="4.9.0" />
-    <kernel version="4.4.0" />
-    <kernel version="3.18.0" />
 </compatibility-matrix>
diff --git a/configstore/1.0/Android.bp b/configstore/1.0/Android.bp
index 89f99f2..96ef00a 100644
--- a/configstore/1.0/Android.bp
+++ b/configstore/1.0/Android.bp
@@ -39,13 +39,16 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.configstore@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.configstore@1.0_genc++"],
     generated_headers: ["android.hardware.configstore@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.configstore@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/configstore/1.0/default/Android.mk b/configstore/1.0/default/Android.mk
index e017cfd..8b24031 100644
--- a/configstore/1.0/default/Android.mk
+++ b/configstore/1.0/default/Android.mk
@@ -3,6 +3,7 @@
 ################################################################################
 include $(CLEAR_VARS)
 LOCAL_MODULE := android.hardware.configstore@1.0-service
+LOCAL_REQUIRED_MODULES_arm64 := configstore@1.0.policy
 LOCAL_PROPRIETARY_MODULE := true
 LOCAL_MODULE_CLASS := EXECUTABLES
 LOCAL_MODULE_RELATIVE_PATH := hw
@@ -16,7 +17,18 @@
     libhidlbase \
     libhidltransport \
     libbase \
+    libhwminijail \
     liblog \
     libutils \
 
 include $(BUILD_EXECUTABLE)
+
+# seccomp filter for configstore
+ifeq ($(TARGET_ARCH), $(filter $(TARGET_ARCH), arm64))
+include $(CLEAR_VARS)
+LOCAL_MODULE := configstore@1.0.policy
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/etc/seccomp_policy
+LOCAL_SRC_FILES := seccomp_policy/configstore@1.0-$(TARGET_ARCH).policy
+include $(BUILD_PREBUILT)
+endif
diff --git a/configstore/1.0/default/seccomp_policy/configstore@1.0-arm64.policy b/configstore/1.0/default/seccomp_policy/configstore@1.0-arm64.policy
new file mode 100644
index 0000000..43bf1fa
--- /dev/null
+++ b/configstore/1.0/default/seccomp_policy/configstore@1.0-arm64.policy
@@ -0,0 +1,51 @@
+# 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.
+
+futex: 1
+# ioctl: arg1 == BINDER_WRITE_READ
+ioctl: arg1 == 0xc0306201
+# prctl: arg0 == PR_SET_NAME || arg0 == PR_SET_VMA || arg0 == PR_SET_TIMERSLACK
+# || arg0 == PR_GET_NO_NEW_PRIVS # used by crash_dump
+prctl: arg0 == 15 || arg0 == 0x53564d41 || arg0 == 29 || arg0 == 39
+openat: 1
+mmap: 1
+mprotect: 1
+close: 1
+getuid: 1
+read: 1
+faccessat: 1
+write: 1
+fstat: 1
+clone: 1
+munmap: 1
+lseek: 1
+sigaltstack: 1
+writev: 1
+setpriority: 1
+restart_syscall: 1
+exit: 1
+exit_group: 1
+rt_sigreturn: 1
+getrlimit: 1
+madvise: 1
+clock_gettime: 1
+
+# used during process crash by crash_dump to dump process info
+rt_sigprocmask: 1
+rt_sigaction: 1
+# socket: arg0 == AF_LOCAL
+socket: arg0 == 1
+connect: 1
+recvmsg: 1
+rt_tgsigqueueinfo: 1
diff --git a/configstore/1.0/default/service.cpp b/configstore/1.0/default/service.cpp
index 3dca739..c9c81a0 100644
--- a/configstore/1.0/default/service.cpp
+++ b/configstore/1.0/default/service.cpp
@@ -18,6 +18,7 @@
 
 #include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
 #include <hidl/HidlTransportSupport.h>
+#include <hwminijail/HardwareMinijail.h>
 
 #include "SurfaceFlingerConfigs.h"
 
@@ -25,14 +26,16 @@
 using android::hardware::joinRpcThreadpool;
 using android::hardware::configstore::V1_0::ISurfaceFlingerConfigs;
 using android::hardware::configstore::V1_0::implementation::SurfaceFlingerConfigs;
+using android::hardware::SetupMinijail;
 using android::sp;
 using android::status_t;
 using android::OK;
 
 int main() {
-    // TODO(b/34857894): tune the max thread count.
     configureRpcThreadpool(10, true);
 
+    SetupMinijail("/vendor/etc/seccomp_policy/configstore@1.0.policy");
+
     sp<ISurfaceFlingerConfigs> surfaceFlingerConfigs = new SurfaceFlingerConfigs;
     status_t status = surfaceFlingerConfigs->registerAsService();
     LOG_ALWAYS_FATAL_IF(status != OK, "Could not register ISurfaceFlingerConfigs");
diff --git a/configstore/1.0/vts/functional/Android.bp b/configstore/1.0/vts/functional/Android.bp
index 1775538..1b8a591 100644
--- a/configstore/1.0/vts/functional/Android.bp
+++ b/configstore/1.0/vts/functional/Android.bp
@@ -16,19 +16,8 @@
 
 cc_test {
     name: "VtsHalConfigstoreV1_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalConfigstoreV1_0TargetTest.cpp"],
-    shared_libs: [
-        "libbase",
-        "libhidlbase",
-        "liblog",
-        "libutils",
-        "android.hardware.configstore@1.0",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ]
+    static_libs: ["android.hardware.configstore@1.0"],
 }
 
diff --git a/configstore/utils/Android.bp b/configstore/utils/Android.bp
index a4cad66..93e52f1 100644
--- a/configstore/utils/Android.bp
+++ b/configstore/utils/Android.bp
@@ -17,6 +17,9 @@
 cc_library_shared {
     name: "android.hardware.configstore-utils",
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     defaults: ["hidl_defaults"],
 
     srcs: [ "ConfigStoreUtils.cpp" ],
diff --git a/contexthub/1.0/Android.bp b/contexthub/1.0/Android.bp
index 45d2e5c..ae1bd08 100644
--- a/contexthub/1.0/Android.bp
+++ b/contexthub/1.0/Android.bp
@@ -46,13 +46,16 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.contexthub@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.contexthub@1.0_genc++"],
     generated_headers: ["android.hardware.contexthub@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.contexthub@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/contexthub/1.0/default/Contexthub.cpp b/contexthub/1.0/default/Contexthub.cpp
index bf45900..3626a09 100644
--- a/contexthub/1.0/default/Contexthub.cpp
+++ b/contexthub/1.0/default/Contexthub.cpp
@@ -440,18 +440,15 @@
     // Data from the nanoapp header is passed through HIDL as explicit fields,
     // but the legacy HAL expects it prepended to the binary, therefore we must
     // reconstruct it here prior to passing to the legacy HAL.
-    uint32_t targetChreApiVersion =
-        (appBinary.targetChreApiMajorVersion << 24) |
-        (appBinary.targetChreApiMinorVersion << 16);
     const struct nano_app_binary_t header = {
         .header_version = htole32(1),
-        .magic          = htole32(NANOAPP_MAGIC),
-        .app_id.id      = htole64(appBinary.appId),
-        .app_version    = htole32(appBinary.appVersion),
-        .flags          = htole32(appBinary.flags),
-        .hw_hub_type    = htole64(0),
-        .reserved[0]    = htole32(targetChreApiVersion),
-        .reserved[1]    = 0,
+        .magic = htole32(NANOAPP_MAGIC),
+        .app_id.id = htole64(appBinary.appId),
+        .app_version = htole32(appBinary.appVersion),
+        .flags = htole32(appBinary.flags),
+        .hw_hub_type = htole64(0),
+        .target_chre_api_major_version = appBinary.targetChreApiMajorVersion,
+        .target_chre_api_minor_version = appBinary.targetChreApiMinorVersion,
     };
     const uint8_t *headerBytes = reinterpret_cast<const uint8_t *>(&header);
 
diff --git a/contexthub/1.0/vts/functional/Android.bp b/contexthub/1.0/vts/functional/Android.bp
index c35386d..7c6e8c7 100644
--- a/contexthub/1.0/vts/functional/Android.bp
+++ b/contexthub/1.0/vts/functional/Android.bp
@@ -16,19 +16,8 @@
 
 cc_test {
     name: "VtsHalContexthubV1_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalContexthubV1_0TargetTest.cpp"],
-    shared_libs: [
-        "liblog",
-        "libhidlbase",
-        "libhidltransport",
-        "libutils",
-        "android.hardware.contexthub@1.0",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ]
+    static_libs: ["android.hardware.contexthub@1.0"],
 }
 
diff --git a/current.txt b/current.txt
index 2ad1e09..5207c6a 100644
--- a/current.txt
+++ b/current.txt
@@ -187,13 +187,18 @@
 d8f0877ae1d321c1d884c7631dfe36cab0ec8a4b2863d4b687f85d3549a63bcc android.hardware.wifi.supplicant@1.0::ISupplicantStaNetworkCallback
 fe3c3c2f572b72f15f8594c538b0577bd5c28722c31879cfe6231330cddb6747 android.hardware.wifi.supplicant@1.0::types
 
-# ABI preserving changes to HALs released in Android O
+# ABI preserving changes to HALs during Android O MR1 (Initial Set)
 
+26a4dd19a71f3a28249100af29be470f80e08355165fe6a7173aaa1ef264640d android.hardware.automotive.vehicle@2.0::types
+150a338ce11fcec70757c9675d83cf6a5d7b40d0c812741b91671fecce59eac9 android.hardware.broadcastradio@1.0::types
+dc7e6d4f537b9943e27edc4f86c5a03bb643b18f18f866f8c3c71c0ac4ea8cbc android.hardware.broadcastradio@1.0::types
 760485232f6cce07f8bb05e3475509956996b702f77415ee5bff05e2ec5a5bcc android.hardware.dumpstate@1.0::IDumpstateDevice
 e822cb7f4a1bdd45689c5e92ccd19a2201c20b771bd4b2ec1ae627e324591f9d android.hardware.radio@1.0::IRadioResponse
+6e69adb24d7c0b0ca3a54a38c49a5625b161b3f5d5f7d6fda0befdbbfc8e9e06 android.hardware.radio@1.0::IRadioResponse
 28e929b453df3d9f5060af2764e6cdb123ddb893e3e86923c877f6ff7e5f02c9 android.hardware.wifi@1.0::types
+df1d7b27e644bfed0a4f606a8c44d35d45cafce82c7c648494c8a25c7cd4a949 android.hardware.wifi@1.0::types
 
-# HALs released in Android O MR1
+# HALs released in Android O MR1 (Initial Set)
 
 4b65763663a94a3920134011691f8fbb42ccb7b7795589efddc049a9106047d6 android.hardware.oemlock@1.0::IOemLock
 e02cd3722cb5e8fa51179f5defacb4f7866f903c9c7c51dc01a3148473a71525 android.hardware.oemlock@1.0::types
@@ -220,3 +225,25 @@
 b18caefefcc765092412285d776234fcf213b73bdf07ae1b67a5f71b2d2464e3 android.hardware.wifi.offload@1.0::types
 c26473e2e4a00af43e28a0ddf9002e5062a7d0940429e5efb6e5513a8abcb75c android.hardware.wifi@1.1::IWifi
 b056e1defab4071584214584057d0bc73a613081bf1152590549649d4582c13c android.hardware.wifi@1.1::IWifiChip
+
+# ABI preserving changes to HALs during Android O MR1 (Final Set)
+05aa3de6130a9788fdb6f4d3cc57c3ea90f067e77a5e09d6a772ec7f6bca33d2 android.hardware.radio@1.1::IRadioResponse
+
+# HALs released in Android O MR1 (Final Set)
+044cb039378b8a0e36f40ff1e6ce04dc0d339da02095f968d5062a051e99d108 android.hardware.broadcastradio@1.1::types
+c9699483f8cefe4f9b39b4b9609b76cab2dd1659a06188056b45797d337d4256 android.hardware.broadcastradio@1.1::IBroadcastRadio
+b5d62dcd663fc4fcc977b252af59b333043bdfe73de2f11fe6d6a8bf438a0f92 android.hardware.broadcastradio@1.1::IBroadcastRadioFactory
+bc7e054a6e93adebedff345aeed44549be89e6b1b6ffe071ff47a61de764b232 android.hardware.broadcastradio@1.1::ITuner
+e9139fc755be578693f17c8cd1e27c75f412cfc722157bab5bf03ee68896e31d android.hardware.broadcastradio@1.1::ITunerCallback
+63929c99e5755d9e09d9e0fd2527391fbb1609dda0508f5933b7943b92ae0fbc android.hardware.camera.device@3.3::types
+bbcfc3f748b078f6a66c4e228084a679d30bd61bfde8bb7a91efd507b91c1bfd android.hardware.camera.device@3.3::ICameraDeviceSession
+4a6998cd6793a3f9f03989c29d662589b1bc9d38826c6698c6c17864f7a814f5 android.hardware.cas@1.0::types
+0e656ba1bac11461a17096ef752b69d24b000d820ef5652f0150a0f9731d54c2 android.hardware.cas@1.0::ICas
+b80e1456b81f80032d0de7cb45652ac15af11e7474d520d757481ecaad796dff android.hardware.cas@1.0::ICasListener
+a432d6d9200248dc2126827bcd6cdea31dd65eff39b939f64585d27d915a5857 android.hardware.cas@1.0::IDescramblerBase
+86ba9c03978b79a742e990420bc5ced0673d25a939f82572996bef92621e2014 android.hardware.cas@1.0::IMediaCasService
+503da837d1a67cbdb7c08a033e927e5430ae1b159d98bf72c6336b4dcc5e76f5 android.hardware.cas.native@1.0::types
+619600109232ed64b827c8a11beed8070b1827ae464547d7aa146cf0473b4bca android.hardware.cas.native@1.0::IDescrambler
+0a159f81359cd4f71bbe00972ee8403ea79351fb7c0cd48be72ebb3e424dbaef android.hardware.radio@1.0::types
+f4945e397b5dea41bb64518dfde59be71245d8a125fd1e0acffeb57ac7b08fed android.hardware.thermal@1.1::IThermal
+c8bc853546dd55584611def2a9fa1d99f657e3366c976d2f60fe6b8aa6d2cb87 android.hardware.thermal@1.1::IThermalCallback
diff --git a/drm/1.0/Android.bp b/drm/1.0/Android.bp
index 731f58f..d004b82 100644
--- a/drm/1.0/Android.bp
+++ b/drm/1.0/Android.bp
@@ -67,13 +67,16 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.drm@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.drm@1.0_genc++"],
     generated_headers: ["android.hardware.drm@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.drm@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
@@ -89,5 +92,3 @@
         "libutils",
     ],
 }
-
-subdirs = ["default"]
diff --git a/drm/1.0/default/Android.mk b/drm/1.0/default/Android.mk
index 0cc6e71..99773be 100644
--- a/drm/1.0/default/Android.mk
+++ b/drm/1.0/default/Android.mk
@@ -42,6 +42,9 @@
 LOCAL_C_INCLUDES := \
   hardware/interfaces/drm
 
+LOCAL_HEADER_LIBRARIES := \
+  media_plugin_headers
+
 # TODO(b/18948909) Some legacy DRM plugins only support 32-bit. They need to be
 # migrated to 64-bit. Once all of a device's legacy DRM plugins support 64-bit,
 # that device can turn on TARGET_ENABLE_MEDIADRM_64 to build this service as
diff --git a/drm/1.0/default/CryptoFactory.h b/drm/1.0/default/CryptoFactory.h
index 6b1d1ff..86130dc 100644
--- a/drm/1.0/default/CryptoFactory.h
+++ b/drm/1.0/default/CryptoFactory.h
@@ -20,7 +20,6 @@
 #include <hidl/Status.h>
 #include <media/hardware/CryptoAPI.h>
 #include <PluginLoader.h>
-#include <media/SharedLibrary.h>
 
 namespace android {
 namespace hardware {
diff --git a/drm/1.0/default/CryptoPlugin.cpp b/drm/1.0/default/CryptoPlugin.cpp
index 591861a..fd75dbd 100644
--- a/drm/1.0/default/CryptoPlugin.cpp
+++ b/drm/1.0/default/CryptoPlugin.cpp
@@ -51,7 +51,11 @@
 
     Return<void> CryptoPlugin::setSharedBufferBase(const hidl_memory& base,
             uint32_t bufferId) {
-        mSharedBufferMap[bufferId] = mapMemory(base);
+        sp<IMemory> hidlMemory = mapMemory(base);
+        ALOGE_IF(hidlMemory == nullptr, "mapMemory returns nullptr");
+
+        // allow mapMemory to return nullptr
+        mSharedBufferMap[bufferId] = hidlMemory;
         return Void();
     }
 
@@ -107,6 +111,10 @@
 
         AString detailMessage;
         sp<IMemory> sourceBase = mSharedBufferMap[source.bufferId];
+        if (sourceBase == nullptr) {
+            _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "source is a nullptr");
+            return Void();
+        }
 
         if (source.offset + offset + source.size > sourceBase->getSize()) {
             _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "invalid buffer size");
@@ -121,6 +129,11 @@
         if (destination.type == BufferType::SHARED_MEMORY) {
             const SharedBuffer& destBuffer = destination.nonsecureMemory;
             sp<IMemory> destBase = mSharedBufferMap[destBuffer.bufferId];
+            if (destBase == nullptr) {
+                _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "destination is a nullptr");
+                return Void();
+            }
+
             if (destBuffer.offset + destBuffer.size > destBase->getSize()) {
                 _hidl_cb(Status::ERROR_DRM_CANNOT_HANDLE, 0, "invalid buffer size");
                 return Void();
diff --git a/drm/1.0/default/DrmFactory.h b/drm/1.0/default/DrmFactory.h
index 726bf97..32e192d 100644
--- a/drm/1.0/default/DrmFactory.h
+++ b/drm/1.0/default/DrmFactory.h
@@ -20,7 +20,6 @@
 #include <hidl/Status.h>
 #include <media/drm/DrmAPI.h>
 #include <PluginLoader.h>
-#include <media/SharedLibrary.h>
 
 namespace android {
 namespace hardware {
diff --git a/drm/1.0/vts/functional/Android.bp b/drm/1.0/vts/functional/Android.bp
index b45ce84..57678fb 100644
--- a/drm/1.0/vts/functional/Android.bp
+++ b/drm/1.0/vts/functional/Android.bp
@@ -16,33 +16,20 @@
 
 cc_test {
     name: "VtsHalDrmV1_0TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: [
         "drm_hal_clearkey_test.cpp",
         "drm_hal_vendor_test.cpp",
         "vendor_modules.cpp"
-        ],
-    shared_libs: [
+    ],
+    static_libs: [
         "android.hardware.drm@1.0",
+        "android.hardware.drm@1.0-helper",
         "android.hidl.allocator@1.0",
         "android.hidl.memory@1.0",
-        "libbase",
-        "libcutils",
-        "libhidlbase",
         "libhidlmemory",
-        "libhidltransport",
-        "libhwbinder",
-        "liblog",
         "libnativehelper",
         "libssl",
         "libcrypto",
-        "libutils",
-    ],
-    static_libs: [
-        "VtsHalHidlTargetTestBase",
-        "android.hardware.drm@1.0-helper",
-    ],
-    cflags: [
-        "-O0",
-        "-g",
     ],
 }
diff --git a/drm/1.0/vts/functional/drm_hal_clearkey_test.cpp b/drm/1.0/vts/functional/drm_hal_clearkey_test.cpp
index 26641e8..3966eac 100644
--- a/drm/1.0/vts/functional/drm_hal_clearkey_test.cpp
+++ b/drm/1.0/vts/functional/drm_hal_clearkey_test.cpp
@@ -76,9 +76,12 @@
 #define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
 #define EXPECT_OK(ret) EXPECT_TRUE(ret.isOk())
 
-static const uint8_t kClearKeyUUID[16] = {
-    0x10, 0x77, 0xEF, 0xEC, 0xC0, 0xB2, 0x4D, 0x02,
-    0xAC, 0xE3, 0x3C, 0x1E, 0x52, 0xE2, 0xFB, 0x4B};
+static const uint8_t kCommonPsshBoxUUID[16] = {0x10, 0x77, 0xEF, 0xEC, 0xC0, 0xB2, 0x4D, 0x02,
+                                               0xAC, 0xE3, 0x3C, 0x1E, 0x52, 0xE2, 0xFB, 0x4B};
+
+// To be used in mpd to specify drm scheme for players
+static const uint8_t kClearKeyUUID[16] = {0xE2, 0x71, 0x9D, 0x58, 0xA9, 0x85, 0xB3, 0xC9,
+                                          0x78, 0x1A, 0xB0, 0x30, 0xAF, 0x78, 0xD3, 0x0E};
 
 static const uint8_t kInvalidUUID[16] = {
     0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80,
@@ -94,10 +97,10 @@
 
         drmFactory =
                 ::testing::VtsHalHidlTargetTestBase::getService<IDrmFactory>();
-        ASSERT_NE(drmFactory, nullptr);
+        ASSERT_NE(nullptr, drmFactory.get());
         cryptoFactory =
                 ::testing::VtsHalHidlTargetTestBase::getService<ICryptoFactory>();
-        ASSERT_NE(cryptoFactory, nullptr);
+        ASSERT_NE(nullptr, cryptoFactory.get());
     }
 
     virtual void TearDown() override {}
@@ -111,6 +114,9 @@
  * Ensure the factory supports the clearkey scheme UUID
  */
 TEST_F(DrmHalClearkeyFactoryTest, ClearKeyPluginSupported) {
+    EXPECT_TRUE(drmFactory->isCryptoSchemeSupported(kCommonPsshBoxUUID));
+    EXPECT_TRUE(cryptoFactory->isCryptoSchemeSupported(kCommonPsshBoxUUID));
+
     EXPECT_TRUE(drmFactory->isCryptoSchemeSupported(kClearKeyUUID));
     EXPECT_TRUE(cryptoFactory->isCryptoSchemeSupported(kClearKeyUUID));
 }
@@ -166,7 +172,7 @@
             kClearKeyUUID, packageName,
             [&](Status status, const sp<IDrmPlugin>& plugin) {
                 EXPECT_EQ(Status::OK, status);
-                EXPECT_NE(plugin, nullptr);
+                EXPECT_NE(nullptr, plugin.get());
             });
     EXPECT_OK(res);
 }
@@ -180,7 +186,7 @@
             kClearKeyUUID, initVec,
             [&](Status status, const sp<ICryptoPlugin>& plugin) {
                 EXPECT_EQ(Status::OK, status);
-                EXPECT_NE(plugin, nullptr);
+                EXPECT_NE(nullptr, plugin.get());
             });
     EXPECT_OK(res);
 }
@@ -194,7 +200,7 @@
             kInvalidUUID, packageName,
             [&](Status status, const sp<IDrmPlugin>& plugin) {
                 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
-                EXPECT_EQ(plugin, nullptr);
+                EXPECT_EQ(nullptr, plugin.get());
             });
     EXPECT_OK(res);
 }
@@ -208,7 +214,7 @@
             kInvalidUUID, initVec,
             [&](Status status, const sp<ICryptoPlugin>& plugin) {
                 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
-                EXPECT_EQ(plugin, nullptr);
+                EXPECT_EQ(nullptr, plugin.get());
             });
     EXPECT_OK(res);
 }
@@ -219,13 +225,13 @@
         // Create factories
         DrmHalClearkeyFactoryTest::SetUp();
 
-        ASSERT_NE(drmFactory, nullptr);
+        ASSERT_NE(nullptr, drmFactory.get());
         hidl_string packageName("android.hardware.drm.test");
         auto res = drmFactory->createPlugin(
                 kClearKeyUUID, packageName,
                 [this](Status status, const sp<IDrmPlugin>& plugin) {
                     EXPECT_EQ(Status::OK, status);
-                    ASSERT_NE(plugin, nullptr);
+                    ASSERT_NE(nullptr, plugin.get());
                     drmPlugin = plugin;
                 });
         ASSERT_OK(res);
@@ -235,7 +241,7 @@
                 kClearKeyUUID, initVec,
                 [this](Status status, const sp<ICryptoPlugin>& plugin) {
                     EXPECT_EQ(Status::OK, status);
-                    ASSERT_NE(plugin, nullptr);
+                    ASSERT_NE(nullptr, plugin.get());
                     cryptoPlugin = plugin;
                 });
         ASSERT_OK(res);
@@ -866,7 +872,7 @@
 sp<IMemory> DrmHalClearkeyPluginTest::getDecryptMemory(size_t size,
                                                        size_t index) {
     sp<IAllocator> ashmemAllocator = IAllocator::getService("ashmem");
-    EXPECT_NE(ashmemAllocator, nullptr);
+    EXPECT_NE(nullptr, ashmemAllocator.get());
 
     hidl_memory hidlMemory;
     auto res = ashmemAllocator->allocate(
@@ -878,6 +884,7 @@
     EXPECT_OK(res);
 
     sp<IMemory> mappedMemory = mapMemory(hidlMemory);
+    EXPECT_NE(nullptr, mappedMemory.get());
     EXPECT_OK(cryptoPlugin->setSharedBufferBase(hidlMemory, index));
     return mappedMemory;
 }
@@ -1063,8 +1070,6 @@
     AES_set_encrypt_key(&key[0], 128, &decryptionKey);
 
     size_t offset = 0;
-    size_t num = 0;
-    size_t ecount_buf = 0;
     for (size_t i = 0; i < subSamples.size(); i++) {
         memcpy(dest + offset, src + offset, subSamples[i].numBytesOfClearData);
         offset += subSamples[i].numBytesOfClearData;
@@ -1105,7 +1110,6 @@
     Status status = cryptoPlugin->setMediaDrmSession(sessionId);
     EXPECT_EQ(Status::OK, status);
 
-    const bool kNotSecure = false;
     uint32_t byteCount = decrypt(Mode::UNENCRYPTED, &iv[0], subSamples,
             noPattern, Status::OK);
     EXPECT_EQ(kByteCount, byteCount);
@@ -1132,7 +1136,6 @@
     Status status = cryptoPlugin->setMediaDrmSession(sessionId);
     EXPECT_EQ(Status::OK, status);
 
-    const bool kNotSecure = false;
     uint32_t byteCount = decrypt(Mode::AES_CTR, &iv[0], subSamples,
             noPattern, Status::OK);
     EXPECT_EQ(kClearBytes + kEncryptedBytes, byteCount);
@@ -1153,7 +1156,6 @@
     Status status = cryptoPlugin->setMediaDrmSession(sessionId);
     EXPECT_EQ(Status::OK, status);
 
-    const bool kNotSecure = false;
     uint32_t byteCount = decrypt(Mode::AES_CTR, &iv[0], subSamples,
             noPattern, Status::ERROR_DRM_NO_LICENSE);
     EXPECT_EQ(0u, byteCount);
diff --git a/drm/1.0/vts/functional/drm_hal_vendor_test.cpp b/drm/1.0/vts/functional/drm_hal_vendor_test.cpp
index e651e19..47c6950 100644
--- a/drm/1.0/vts/functional/drm_hal_vendor_test.cpp
+++ b/drm/1.0/vts/functional/drm_hal_vendor_test.cpp
@@ -113,7 +113,7 @@
               test_info->test_case_name(), test_info->name(),
               GetParam().c_str());
 
-        ASSERT_NE(vendorModule, nullptr);
+        ASSERT_NE(nullptr, vendorModule.get());
 
         // First try the binderized service name provided by the vendor module.
         // If that fails, which it can on non-binderized devices, try the default
@@ -123,14 +123,14 @@
         if (drmFactory == nullptr) {
             drmFactory = VtsTestBase::getService<IDrmFactory>();
         }
-        ASSERT_NE(drmFactory, nullptr);
+        ASSERT_NE(nullptr, drmFactory.get());
 
         // Do the same for the crypto factory
         cryptoFactory = VtsTestBase::getService<ICryptoFactory>(name);
         if (cryptoFactory == nullptr) {
             cryptoFactory = VtsTestBase::getService<ICryptoFactory>();
         }
-        ASSERT_NE(cryptoFactory, nullptr);
+        ASSERT_NE(nullptr, cryptoFactory.get());
 
         // If drm scheme not installed skip subsequent tests
         if (!drmFactory->isCryptoSchemeSupported(getVendorUUID())) {
@@ -239,7 +239,7 @@
             getVendorUUID(), packageName,
             [&](Status status, const sp<IDrmPlugin>& plugin) {
                 EXPECT_EQ(Status::OK, status);
-                EXPECT_NE(plugin, nullptr);
+                EXPECT_NE(nullptr, plugin.get());
             });
     EXPECT_OK(res);
 }
@@ -254,7 +254,7 @@
             getVendorUUID(), initVec,
             [&](Status status, const sp<ICryptoPlugin>& plugin) {
                 EXPECT_EQ(Status::OK, status);
-                EXPECT_NE(plugin, nullptr);
+                EXPECT_NE(nullptr, plugin.get());
             });
     EXPECT_OK(res);
 }
@@ -269,7 +269,7 @@
             kInvalidUUID, packageName,
             [&](Status status, const sp<IDrmPlugin>& plugin) {
                 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
-                EXPECT_EQ(plugin, nullptr);
+                EXPECT_EQ(nullptr, plugin.get());
             });
     EXPECT_OK(res);
 }
@@ -284,7 +284,7 @@
             kInvalidUUID, initVec,
             [&](Status status, const sp<ICryptoPlugin>& plugin) {
                 EXPECT_EQ(Status::ERROR_DRM_CANNOT_HANDLE, status);
-                EXPECT_EQ(plugin, nullptr);
+                EXPECT_EQ(nullptr, plugin.get());
             });
     EXPECT_OK(res);
 }
@@ -302,7 +302,7 @@
                 getVendorUUID(), packageName,
                 [this](Status status, const sp<IDrmPlugin>& plugin) {
                     EXPECT_EQ(Status::OK, status);
-                    ASSERT_NE(plugin, nullptr);
+                    ASSERT_NE(nullptr, plugin.get());
                     drmPlugin = plugin;
                 });
         ASSERT_OK(res);
@@ -312,7 +312,7 @@
                 getVendorUUID(), initVec,
                 [this](Status status, const sp<ICryptoPlugin>& plugin) {
                     EXPECT_EQ(Status::OK, status);
-                    ASSERT_NE(plugin, nullptr);
+                    ASSERT_NE(nullptr, plugin.get());
                     cryptoPlugin = plugin;
                 });
         ASSERT_OK(res);
@@ -1185,7 +1185,7 @@
 sp<IMemory> DrmHalVendorPluginTest::getDecryptMemory(size_t size,
                                                      size_t index) {
     sp<IAllocator> ashmemAllocator = IAllocator::getService("ashmem");
-    EXPECT_NE(ashmemAllocator, nullptr);
+    EXPECT_NE(nullptr, ashmemAllocator.get());
 
     hidl_memory hidlMemory;
     auto res = ashmemAllocator->allocate(
@@ -1198,7 +1198,7 @@
     EXPECT_OK(res);
 
     sp<IMemory> mappedMemory = mapMemory(hidlMemory);
-    EXPECT_NE(mappedMemory, nullptr);
+    EXPECT_NE(nullptr, mappedMemory.get());
     res = cryptoPlugin->setSharedBufferBase(hidlMemory, index);
     EXPECT_OK(res);
     return mappedMemory;
@@ -1406,8 +1406,6 @@
     AES_set_encrypt_key(&key[0], 128, &decryptionKey);
 
     size_t offset = 0;
-    size_t num = 0;
-    size_t ecount_buf = 0;
     for (size_t i = 0; i < subSamples.size(); i++) {
         const SubSample& subSample = subSamples[i];
 
diff --git a/drm/Android.bp b/drm/Android.bp
index 33f70eb..ed19a37 100644
--- a/drm/Android.bp
+++ b/drm/Android.bp
@@ -1,5 +1,6 @@
 // This is an autogenerated file, do not edit.
 subdirs = [
     "1.0",
+    "1.0/default",
     "1.0/vts/functional",
 ]
diff --git a/dumpstate/1.0/Android.bp b/dumpstate/1.0/Android.bp
index 2424c33..b135e00 100644
--- a/dumpstate/1.0/Android.bp
+++ b/dumpstate/1.0/Android.bp
@@ -35,13 +35,16 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.dumpstate@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.dumpstate@1.0_genc++"],
     generated_headers: ["android.hardware.dumpstate@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.dumpstate@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/dumpstate/1.0/vts/functional/Android.bp b/dumpstate/1.0/vts/functional/Android.bp
index a1c735b..1ab530f 100644
--- a/dumpstate/1.0/vts/functional/Android.bp
+++ b/dumpstate/1.0/vts/functional/Android.bp
@@ -15,18 +15,7 @@
 
 cc_test {
     name: "VtsHalDumpstateV1_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalDumpstateV1_0TargetTest.cpp"],
-    shared_libs: [
-        "android.hardware.dumpstate@1.0",
-        "libcutils",
-        "libhidlbase",
-        "liblog",
-        "libutils",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ]
+    static_libs: ["android.hardware.dumpstate@1.0"],
 }
diff --git a/gatekeeper/1.0/Android.bp b/gatekeeper/1.0/Android.bp
index eb70c09..f12f38f 100644
--- a/gatekeeper/1.0/Android.bp
+++ b/gatekeeper/1.0/Android.bp
@@ -39,13 +39,16 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.gatekeeper@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.gatekeeper@1.0_genc++"],
     generated_headers: ["android.hardware.gatekeeper@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.gatekeeper@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/gatekeeper/1.0/vts/functional/Android.bp b/gatekeeper/1.0/vts/functional/Android.bp
index 70cb615..aa1da7b 100644
--- a/gatekeeper/1.0/vts/functional/Android.bp
+++ b/gatekeeper/1.0/vts/functional/Android.bp
@@ -16,21 +16,7 @@
 
 cc_test {
     name: "VtsHalGatekeeperV1_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalGatekeeperV1_0TargetTest.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libnativehelper",
-        "libutils",
-        "android.hardware.gatekeeper@1.0",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ]
+    static_libs: ["android.hardware.gatekeeper@1.0"],
 }
diff --git a/gnss/1.0/Android.bp b/gnss/1.0/Android.bp
index c2988de..6db98f6 100644
--- a/gnss/1.0/Android.bp
+++ b/gnss/1.0/Android.bp
@@ -172,13 +172,16 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.gnss@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.gnss@1.0_genc++"],
     generated_headers: ["android.hardware.gnss@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.gnss@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/gnss/1.0/default/GnssMeasurement.cpp b/gnss/1.0/default/GnssMeasurement.cpp
index 6c9b838..d81f829 100644
--- a/gnss/1.0/default/GnssMeasurement.cpp
+++ b/gnss/1.0/default/GnssMeasurement.cpp
@@ -182,7 +182,6 @@
 
     auto clockVal = gpsData->clock;
     static uint32_t discontinuity_count_to_handle_old_clock_type = 0;
-    auto flags = clockVal.flags;
 
     gnssData.clock.leapSecond = clockVal.leap_second;
     /*
@@ -205,7 +204,7 @@
             break;
         case GPS_CLOCK_TYPE_GPS_TIME:
             // GPS time, need to convert.
-            flags |= GPS_CLOCK_HAS_FULL_BIAS;
+            clockVal.flags |= GPS_CLOCK_HAS_FULL_BIAS;
             clockVal.full_bias_ns = clockVal.time_ns;
             clockVal.time_ns = 0;
             gnssData.clock.hwClockDiscontinuityCount =
diff --git a/gnss/1.0/default/OWNERS b/gnss/1.0/default/OWNERS
new file mode 100644
index 0000000..6c25bd7
--- /dev/null
+++ b/gnss/1.0/default/OWNERS
@@ -0,0 +1,3 @@
+wyattriley@google.com
+gomo@google.com
+smalkos@google.com
diff --git a/gnss/1.0/vts/OWNERS b/gnss/1.0/vts/OWNERS
new file mode 100644
index 0000000..937d70a
--- /dev/null
+++ b/gnss/1.0/vts/OWNERS
@@ -0,0 +1,7 @@
+wyattriley@google.com
+gomo@google.com
+smalkos@google.com
+
+# VTS team
+yim@google.com
+trong@google.com
\ No newline at end of file
diff --git a/gnss/1.0/vts/functional/Android.bp b/gnss/1.0/vts/functional/Android.bp
index 6d96059..d7713db 100644
--- a/gnss/1.0/vts/functional/Android.bp
+++ b/gnss/1.0/vts/functional/Android.bp
@@ -16,21 +16,7 @@
 
 cc_test {
     name: "VtsHalGnssV1_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalGnssV1_0TargetTest.cpp"],
-    shared_libs: [
-        "android.hardware.gnss@1.0",
-        "libbase",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "liblog",
-        "libnativehelper",
-        "libutils",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ],
-}
\ No newline at end of file
+    static_libs: ["android.hardware.gnss@1.0"],
+}
diff --git a/graphics/allocator/2.0/Android.bp b/graphics/allocator/2.0/Android.bp
index 2c2a3da..46faa17 100644
--- a/graphics/allocator/2.0/Android.bp
+++ b/graphics/allocator/2.0/Android.bp
@@ -35,13 +35,17 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.graphics.allocator@2.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.graphics.allocator@2.0_genc++"],
     generated_headers: ["android.hardware.graphics.allocator@2.0_genc++_headers"],
     export_generated_headers: ["android.hardware.graphics.allocator@2.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+        support_system_process: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/graphics/bufferqueue/1.0/Android.bp b/graphics/bufferqueue/1.0/Android.bp
index 4773963..2d36fc7 100644
--- a/graphics/bufferqueue/1.0/Android.bp
+++ b/graphics/bufferqueue/1.0/Android.bp
@@ -42,13 +42,16 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.graphics.bufferqueue@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.graphics.bufferqueue@1.0_genc++"],
     generated_headers: ["android.hardware.graphics.bufferqueue@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.graphics.bufferqueue@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/graphics/common/1.0/Android.bp b/graphics/common/1.0/Android.bp
index 3d9aa90..86438c1 100644
--- a/graphics/common/1.0/Android.bp
+++ b/graphics/common/1.0/Android.bp
@@ -32,13 +32,17 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.graphics.common@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.graphics.common@1.0_genc++"],
     generated_headers: ["android.hardware.graphics.common@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.graphics.common@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+        support_system_process: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/graphics/composer/2.1/Android.bp b/graphics/composer/2.1/Android.bp
index 299570d..e875708 100644
--- a/graphics/composer/2.1/Android.bp
+++ b/graphics/composer/2.1/Android.bp
@@ -53,13 +53,16 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.graphics.composer@2.1",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.graphics.composer@2.1_genc++"],
     generated_headers: ["android.hardware.graphics.composer@2.1_genc++_headers"],
     export_generated_headers: ["android.hardware.graphics.composer@2.1_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/graphics/composer/2.1/default/Hwc.cpp b/graphics/composer/2.1/default/Hwc.cpp
index 8ca0eb3..862dff1 100644
--- a/graphics/composer/2.1/default/Hwc.cpp
+++ b/graphics/composer/2.1/default/Hwc.cpp
@@ -18,6 +18,7 @@
 
 #include "Hwc.h"
 
+#include <chrono>
 #include <type_traits>
 #include <log/log.h>
 
@@ -25,6 +26,8 @@
 #include "hardware/hwcomposer.h"
 #include "hwc2on1adapter/HWC2On1Adapter.h"
 
+using namespace std::chrono_literals;
+
 namespace android {
 namespace hardware {
 namespace graphics {
@@ -218,7 +221,24 @@
     sp<ComposerClient> client;
 
     {
-        std::lock_guard<std::mutex> lock(mClientMutex);
+        std::unique_lock<std::mutex> lock(mClientMutex);
+
+        if (mClient != nullptr) {
+            // In surface flinger we delete a composer client on one thread and
+            // then create a new client on another thread. Although surface
+            // flinger ensures the calls are made in that sequence (destroy and
+            // then create), sometimes the calls land in the composer service
+            // inverted (create and then destroy). Wait for a brief period to
+            // see if the existing client is destroyed.
+            ALOGI("HwcHal::createClient: Client already exists. Waiting for"
+                    " it to be destroyed.");
+            mClientDestroyedWait.wait_for(lock, 1s,
+                    [this] { return mClient == nullptr; });
+            std::string doneMsg = mClient == nullptr ?
+                    "Existing client was destroyed." :
+                    "Existing client was never destroyed!";
+            ALOGI("HwcHal::createClient: Done waiting. %s", doneMsg.c_str());
+        }
 
         // only one client is allowed
         if (mClient == nullptr) {
@@ -245,6 +265,7 @@
 {
     std::lock_guard<std::mutex> lock(mClientMutex);
     mClient = nullptr;
+    mClientDestroyedWait.notify_all();
 }
 
 void HwcHal::hotplugHook(hwc2_callback_data_t callbackData,
diff --git a/graphics/composer/2.1/default/Hwc.h b/graphics/composer/2.1/default/Hwc.h
index b45389a..7561327 100644
--- a/graphics/composer/2.1/default/Hwc.h
+++ b/graphics/composer/2.1/default/Hwc.h
@@ -17,8 +17,9 @@
 #ifndef ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_HWC_H
 #define ANDROID_HARDWARE_GRAPHICS_COMPOSER_V2_1_HWC_H
 
-#include <mutex>
+#include <condition_variable>
 #include <memory>
+#include <mutex>
 #include <unordered_set>
 #include <vector>
 
@@ -211,6 +212,7 @@
     } mDispatch;
 
     std::mutex mClientMutex;
+    std::condition_variable mClientDestroyedWait;
     wp<ComposerClient> mClient;
 
     // If the HWC implementation version is < 2.0, use an adapter to interface
diff --git a/graphics/composer/2.1/default/IComposerCommandBuffer.h b/graphics/composer/2.1/default/IComposerCommandBuffer.h
index 9ee5f4f..058709c 100644
--- a/graphics/composer/2.1/default/IComposerCommandBuffer.h
+++ b/graphics/composer/2.1/default/IComposerCommandBuffer.h
@@ -92,6 +92,23 @@
     bool writeQueue(bool* outQueueChanged, uint32_t* outCommandLength,
             hidl_vec<hidl_handle>* outCommandHandles)
     {
+        // After data are written to the queue, it may not be read by the
+        // remote reader when
+        //
+        //  - the writer does not send them (because of other errors)
+        //  - the hwbinder transaction fails
+        //  - the reader does not read them (because of other errors)
+        //
+        // Discard the stale data here.
+        size_t staleDataSize = mQueue ? mQueue->availableToRead() : 0;
+        if (staleDataSize > 0) {
+            ALOGW("discarding stale data from message queue");
+            CommandQueueType::MemTransaction tx;
+            if (mQueue->beginRead(staleDataSize, &tx)) {
+                mQueue->commitRead(staleDataSize);
+            }
+        }
+
         // write data to queue, optionally resizing it
         if (mQueue && (mDataMaxSize <= mQueue->getQuantumCount())) {
             if (!mQueue->write(mData.get(), mDataWritten)) {
diff --git a/graphics/composer/2.1/vts/functional/Android.bp b/graphics/composer/2.1/vts/functional/Android.bp
index 2e87144..1ba7c9a 100644
--- a/graphics/composer/2.1/vts/functional/Android.bp
+++ b/graphics/composer/2.1/vts/functional/Android.bp
@@ -44,33 +44,21 @@
 
 cc_test {
     name: "VtsHalGraphicsComposerV2_1TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalGraphicsComposerV2_1TargetTest.cpp"],
+
+    // TODO(b/64437680): Assume these libs are always available on the device.
     shared_libs: [
+        "libfmq",
+        "libsync",
+    ],
+    static_libs: [
         "android.hardware.graphics.allocator@2.0",
         "android.hardware.graphics.composer@2.1",
         "android.hardware.graphics.mapper@2.0",
-        "libbase",
-        "libcutils",
-        "libfmq",
-        "libhidlbase",
-        "libhidltransport",
-        "liblog",
-        "libnativehelper",
-        "libsync",
-        "libutils",
-    ],
-    static_libs: [
-        "libhwcomposer-command-buffer",
         "libVtsHalGraphicsComposerTestUtils",
         "libVtsHalGraphicsMapperTestUtils",
-        "VtsHalHidlTargetTestBase",
+        "libhwcomposer-command-buffer",
+        "libnativehelper",
     ],
-    cflags: [
-        "-Wall",
-        "-Wextra",
-        "-Werror",
-        "-O0",
-        "-g",
-    ]
 }
diff --git a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
index 0f03546..9a749d7 100644
--- a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
+++ b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
@@ -23,6 +23,7 @@
 #include "VtsHalGraphicsMapperTestUtils.h"
 
 #include <VtsHalHidlTargetTestBase.h>
+#include <VtsHalHidlTargetTestEnvBase.h>
 #include <unistd.h>
 
 #include <algorithm>
@@ -50,21 +51,40 @@
 using android::hardware::graphics::mapper::V2_0::tests::Gralloc;
 using GrallocError = android::hardware::graphics::mapper::V2_0::Error;
 
+// Test environment for graphics.composer
+class GraphicsComposerHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
+   public:
+    // get the test environment singleton
+    static GraphicsComposerHidlEnvironment* Instance() {
+        static GraphicsComposerHidlEnvironment* instance = new GraphicsComposerHidlEnvironment;
+        return instance;
+    }
+
+    virtual void registerTestServices() override { registerTestService<IComposer>(); }
+
+   private:
+    GraphicsComposerHidlEnvironment() {}
+
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(GraphicsComposerHidlEnvironment);
+};
+
 class GraphicsComposerHidlTest : public ::testing::VtsHalHidlTargetTestBase {
  protected:
   void SetUp() override {
-    ASSERT_NO_FATAL_FAILURE(mComposer = std::make_unique<Composer>());
-    ASSERT_NO_FATAL_FAILURE(mComposerClient = mComposer->createClient());
+      ASSERT_NO_FATAL_FAILURE(
+          mComposer = std::make_unique<Composer>(
+              GraphicsComposerHidlEnvironment::Instance()->getServiceName<IComposer>()));
+      ASSERT_NO_FATAL_FAILURE(mComposerClient = mComposer->createClient());
 
-    mComposerCallback = new GraphicsComposerCallback;
-    mComposerClient->registerCallback(mComposerCallback);
+      mComposerCallback = new GraphicsComposerCallback;
+      mComposerClient->registerCallback(mComposerCallback);
 
-    // assume the first display is primary and is never removed
-    mPrimaryDisplay = waitForFirstDisplay();
+      // assume the first display is primary and is never removed
+      mPrimaryDisplay = waitForFirstDisplay();
 
-    // explicitly disable vsync
-    mComposerClient->setVsyncEnabled(mPrimaryDisplay, false);
-    mComposerCallback->setVsyncAllowed(false);
+      // explicitly disable vsync
+      mComposerClient->setVsyncEnabled(mPrimaryDisplay, false);
+      mComposerCallback->setVsyncAllowed(false);
   }
 
   void TearDown() override {
@@ -684,10 +704,11 @@
 }  // namespace android
 
 int main(int argc, char** argv) {
-  ::testing::InitGoogleTest(&argc, argv);
-
-  int status = RUN_ALL_TESTS();
-  LOG(INFO) << "Test result = " << status;
-
-  return status;
+    using android::hardware::graphics::composer::V2_1::tests::GraphicsComposerHidlEnvironment;
+    ::testing::AddGlobalTestEnvironment(GraphicsComposerHidlEnvironment::Instance());
+    ::testing::InitGoogleTest(&argc, argv);
+    GraphicsComposerHidlEnvironment::Instance()->init(&argc, argv);
+    int status = RUN_ALL_TESTS();
+    ALOGI("Test result = %d", status);
+    return status;
 }
diff --git a/graphics/mapper/2.0/Android.bp b/graphics/mapper/2.0/Android.bp
index 408d58f..f5913af 100644
--- a/graphics/mapper/2.0/Android.bp
+++ b/graphics/mapper/2.0/Android.bp
@@ -39,13 +39,17 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.graphics.mapper@2.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.graphics.mapper@2.0_genc++"],
     generated_headers: ["android.hardware.graphics.mapper@2.0_genc++_headers"],
     export_generated_headers: ["android.hardware.graphics.mapper@2.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+        support_system_process: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/graphics/mapper/2.0/vts/functional/Android.bp b/graphics/mapper/2.0/vts/functional/Android.bp
index 1c0e4c5..ac6cb47 100644
--- a/graphics/mapper/2.0/vts/functional/Android.bp
+++ b/graphics/mapper/2.0/vts/functional/Android.bp
@@ -37,30 +37,16 @@
 
 cc_test {
     name: "VtsHalGraphicsMapperV2_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalGraphicsMapperV2_0TargetTest.cpp"],
     shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libnativehelper",
         "libsync",
-        "libutils",
+    ],
+    static_libs: [
         "android.hardware.graphics.allocator@2.0",
         "android.hardware.graphics.mapper@2.0",
         "android.hardware.graphics.common@1.0",
-    ],
-    static_libs: [
         "libVtsHalGraphicsMapperTestUtils",
-        "VtsHalHidlTargetTestBase",
+        "libnativehelper",
     ],
-    cflags: [
-        "-Wall",
-        "-Wextra",
-        "-Werror",
-        "-O0",
-        "-g",
-    ]
 }
diff --git a/health/1.0/Android.bp b/health/1.0/Android.bp
index 4fb2d7b..d8ebc20 100644
--- a/health/1.0/Android.bp
+++ b/health/1.0/Android.bp
@@ -39,13 +39,16 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.health@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.health@1.0_genc++"],
     generated_headers: ["android.hardware.health@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.health@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/health/1.0/default/Android.bp b/health/1.0/default/Android.bp
new file mode 100644
index 0000000..cb2e87d
--- /dev/null
+++ b/health/1.0/default/Android.bp
@@ -0,0 +1,20 @@
+cc_library_static {
+    name: "android.hardware.health@1.0-convert",
+    vendor_available: true,
+    srcs: ["convert.cpp"],
+    include_dirs: [
+        "system/core/base/include",
+    ],
+    header_libs: ["libhealthd_headers"],
+    export_header_lib_headers: ["libhealthd_headers"],
+    export_include_dirs: ["include"],
+    shared_libs: [
+        "libcutils",
+        "libhidlbase",
+        "libhidltransport",
+        "libutils",
+        "android.hardware.health@1.0",
+    ],
+
+}
+
diff --git a/health/1.0/default/Android.mk b/health/1.0/default/Android.mk
index 96ff91f..199ab41 100644
--- a/health/1.0/default/Android.mk
+++ b/health/1.0/default/Android.mk
@@ -4,10 +4,12 @@
 LOCAL_MODULE := android.hardware.health@1.0-impl
 LOCAL_PROPRIETARY_MODULE := true
 LOCAL_MODULE_RELATIVE_PATH := hw
-LOCAL_C_INCLUDES := system/core/healthd/include system/core/base/include
+LOCAL_C_INCLUDES := system/core/base/include
 LOCAL_SRC_FILES := \
     Health.cpp \
 
+LOCAL_HEADER_LIBRARIES := libhealthd_headers
+
 LOCAL_SHARED_LIBRARIES := \
     libcutils \
     libhidlbase \
@@ -23,20 +25,6 @@
 include $(BUILD_SHARED_LIBRARY)
 
 include $(CLEAR_VARS)
-LOCAL_MODULE := android.hardware.health@1.0-convert
-LOCAL_SRC_FILES := convert.cpp
-LOCAL_C_INCLUDES := system/core/healthd/include system/core/base/include
-LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
-LOCAL_SHARED_LIBRARIES := \
-    libcutils \
-    libhidlbase \
-    libhidltransport \
-    libutils \
-    android.hardware.health@1.0 \
-
-include $(BUILD_STATIC_LIBRARY)
-
-include $(CLEAR_VARS)
 LOCAL_PROPRIETARY_MODULE := true
 LOCAL_MODULE_RELATIVE_PATH := hw
 LOCAL_MODULE := android.hardware.health@1.0-service
diff --git a/health/1.0/default/libhealthd/Android.bp b/health/1.0/default/libhealthd/Android.bp
new file mode 100644
index 0000000..ce02e28
--- /dev/null
+++ b/health/1.0/default/libhealthd/Android.bp
@@ -0,0 +1,10 @@
+// Copyright 2016 The Android Open Source Project
+
+cc_library_static {
+    srcs: ["healthd_board_default.cpp"],
+    name: "libhealthd.default",
+    vendor_available: true,
+    cflags: ["-Werror"],
+    include_dirs: ["system/core/base/include"],
+    header_libs: ["libhealthd_headers"],
+}
diff --git a/health/1.0/default/libhealthd/Android.mk b/health/1.0/default/libhealthd/Android.mk
deleted file mode 100644
index a5f4445..0000000
--- a/health/1.0/default/libhealthd/Android.mk
+++ /dev/null
@@ -1,10 +0,0 @@
-# Copyright 2016 The Android Open Source Project
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_SRC_FILES := healthd_board_default.cpp
-LOCAL_MODULE := libhealthd.default
-LOCAL_CFLAGS := -Werror
-LOCAL_C_INCLUDES := system/core/healthd/include system/core/base/include
-include $(BUILD_STATIC_LIBRARY)
diff --git a/health/1.0/vts/functional/Android.bp b/health/1.0/vts/functional/Android.bp
index 1a4c8c8..8742651 100644
--- a/health/1.0/vts/functional/Android.bp
+++ b/health/1.0/vts/functional/Android.bp
@@ -16,17 +16,7 @@
 
 cc_test {
     name: "VtsHalHealthV1_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalHealthV1_0TargetTest.cpp"],
-    shared_libs: [
-        "libhidlbase",
-        "liblog",
-        "libutils",
-        "android.hardware.health@1.0",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ]
+    static_libs: ["android.hardware.health@1.0"],
 }
diff --git a/health/Android.bp b/health/Android.bp
index 33f70eb..a6f6017 100644
--- a/health/Android.bp
+++ b/health/Android.bp
@@ -1,5 +1,7 @@
 // This is an autogenerated file, do not edit.
 subdirs = [
     "1.0",
+    "1.0/default",
+    "1.0/default/libhealthd",
     "1.0/vts/functional",
 ]
diff --git a/ir/1.0/Android.bp b/ir/1.0/Android.bp
index a059da5..489f61f 100644
--- a/ir/1.0/Android.bp
+++ b/ir/1.0/Android.bp
@@ -39,13 +39,16 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.ir@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.ir@1.0_genc++"],
     generated_headers: ["android.hardware.ir@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.ir@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/ir/1.0/vts/functional/Android.bp b/ir/1.0/vts/functional/Android.bp
index 4aac297..2a86f8e 100644
--- a/ir/1.0/vts/functional/Android.bp
+++ b/ir/1.0/vts/functional/Android.bp
@@ -16,20 +16,9 @@
 
 cc_test {
     name: "VtsHalIrV1_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalIrV1_0TargetTest.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libutils",
+    static_libs: [
         "android.hardware.ir@1.0",
     ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ],
 }
diff --git a/keymaster/3.0/Android.bp b/keymaster/3.0/Android.bp
index 1846200..14cfab2 100644
--- a/keymaster/3.0/Android.bp
+++ b/keymaster/3.0/Android.bp
@@ -39,13 +39,16 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.keymaster@3.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.keymaster@3.0_genc++"],
     generated_headers: ["android.hardware.keymaster@3.0_genc++_headers"],
     export_generated_headers: ["android.hardware.keymaster@3.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/keymaster/3.0/vts/functional/Android.bp b/keymaster/3.0/vts/functional/Android.bp
new file mode 100644
index 0000000..7d96704
--- /dev/null
+++ b/keymaster/3.0/vts/functional/Android.bp
@@ -0,0 +1,32 @@
+//
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_test {
+    name: "VtsHalKeymasterV3_0TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: [
+        "authorization_set.cpp",
+        "attestation_record.cpp",
+        "key_param_output.cpp",
+        "keymaster_hidl_hal_test.cpp",
+        "keystore_tags_utils.cpp",
+    ],
+    static_libs: [
+        "android.hardware.keymaster@3.0",
+        "libcrypto",
+        "libsoftkeymasterdevice",
+    ],
+}
diff --git a/keymaster/3.0/vts/functional/Android.mk b/keymaster/3.0/vts/functional/Android.mk
deleted file mode 100644
index 4098664..0000000
--- a/keymaster/3.0/vts/functional/Android.mk
+++ /dev/null
@@ -1,39 +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.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := VtsHalKeymasterV3_0TargetTest
-LOCAL_SRC_FILES := \
-        authorization_set.cpp \
-        attestation_record.cpp \
-        key_param_output.cpp \
-        keymaster_hidl_hal_test.cpp \
-        keystore_tags_utils.cpp \
-
-LOCAL_SHARED_LIBRARIES := \
-        android.hardware.keymaster@3.0 \
-        libcrypto \
-        libhidlbase \
-        liblog \
-        libsoftkeymasterdevice \
-        libutils \
-
-LOCAL_STATIC_LIBRARIES := \
-        VtsHalHidlTargetTestBase \
-
-LOCAL_CFLAGS := -Wall -Werror
-
-include $(BUILD_NATIVE_TEST)
diff --git a/keymaster/Android.bp b/keymaster/Android.bp
index 09b8cb2..90a0195 100644
--- a/keymaster/Android.bp
+++ b/keymaster/Android.bp
@@ -1,4 +1,5 @@
 // This is an autogenerated file, do not edit.
 subdirs = [
     "3.0",
+    "3.0/vts/functional",
 ]
diff --git a/light/2.0/Android.bp b/light/2.0/Android.bp
index cffdbe0..7cc7f84 100644
--- a/light/2.0/Android.bp
+++ b/light/2.0/Android.bp
@@ -39,13 +39,16 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.light@2.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.light@2.0_genc++"],
     generated_headers: ["android.hardware.light@2.0_genc++_headers"],
     export_generated_headers: ["android.hardware.light@2.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/light/2.0/vts/functional/Android.bp b/light/2.0/vts/functional/Android.bp
index 0558ff2..e0ec4cf 100644
--- a/light/2.0/vts/functional/Android.bp
+++ b/light/2.0/vts/functional/Android.bp
@@ -16,19 +16,8 @@
 
 cc_test {
     name: "VtsHalLightV2_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalLightV2_0TargetTest.cpp"],
-    shared_libs: [
-        "libbase",
-        "libhidlbase",
-        "liblog",
-        "libutils",
-        "android.hardware.light@2.0",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ]
+    static_libs: ["android.hardware.light@2.0"],
 }
 
diff --git a/media/1.0/Android.bp b/media/1.0/Android.bp
index 61eeb3f..de2187e 100644
--- a/media/1.0/Android.bp
+++ b/media/1.0/Android.bp
@@ -32,13 +32,16 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.media@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.media@1.0_genc++"],
     generated_headers: ["android.hardware.media@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.media@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/media/omx/1.0/Android.bp b/media/omx/1.0/Android.bp
index 8e5527e..f8bed6e 100644
--- a/media/omx/1.0/Android.bp
+++ b/media/omx/1.0/Android.bp
@@ -74,13 +74,16 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.media.omx@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.media.omx@1.0_genc++"],
     generated_headers: ["android.hardware.media.omx@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.media.omx@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/media/omx/1.0/vts/functional/audio/Android.bp b/media/omx/1.0/vts/functional/audio/Android.bp
index 66fd20b..f517fa1 100644
--- a/media/omx/1.0/vts/functional/audio/Android.bp
+++ b/media/omx/1.0/vts/functional/audio/Android.bp
@@ -16,65 +16,19 @@
 
 cc_test {
     name: "VtsHalMediaOmxV1_0TargetAudioEncTest",
-    defaults: ["hidl_defaults"],
-    srcs: ["VtsHalMediaOmxV1_0TargetAudioEncTest.cpp",
-           "media_audio_hidl_test_common.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidlmemory",
-        "libhidltransport",
-        "libhwbinder",
-        "libnativehelper",
-        "libutils",
-        "libstagefright_foundation",
-        "android.hidl.allocator@1.0",
-        "android.hidl.memory@1.0",
-        "android.hardware.media.omx@1.0",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase",
-                  "VtsHalMediaOmxV1_0CommonUtil"],
-    cflags: [
-        "-O0",
-        "-g",
-    ],
-    include_dirs: [
-        "frameworks/native/include/media/openmax/",
-        "hardware/interfaces/media/omx/1.0/vts/functional/common",
+    defaults: ["VtsHalMediaOmxV1_0Defaults"],
+    srcs: [
+        "VtsHalMediaOmxV1_0TargetAudioEncTest.cpp",
+        "media_audio_hidl_test_common.cpp"
     ],
 }
 
 cc_test {
     name: "VtsHalMediaOmxV1_0TargetAudioDecTest",
-    defaults: ["hidl_defaults"],
-    srcs: ["VtsHalMediaOmxV1_0TargetAudioDecTest.cpp",
-           "media_audio_hidl_test_common.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidlmemory",
-        "libhidltransport",
-        "libhwbinder",
-        "libnativehelper",
-        "libutils",
-        "libstagefright_foundation",
-        "android.hidl.allocator@1.0",
-        "android.hidl.memory@1.0",
-        "android.hardware.media.omx@1.0",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase",
-                  "VtsHalMediaOmxV1_0CommonUtil"],
-    cflags: [
-        "-O0",
-        "-g",
-    ],
-    include_dirs: [
-        "frameworks/native/include/media/openmax/",
-        "hardware/interfaces/media/omx/1.0/vts/functional/common",
+    defaults: ["VtsHalMediaOmxV1_0Defaults"],
+    srcs: [
+        "VtsHalMediaOmxV1_0TargetAudioDecTest.cpp",
+        "media_audio_hidl_test_common.cpp"
     ],
 }
 
diff --git a/media/omx/1.0/vts/functional/audio/VtsHalMediaOmxV1_0TargetAudioDecTest.cpp b/media/omx/1.0/vts/functional/audio/VtsHalMediaOmxV1_0TargetAudioDecTest.cpp
index 1aae7bc..8520757 100644
--- a/media/omx/1.0/vts/functional/audio/VtsHalMediaOmxV1_0TargetAudioDecTest.cpp
+++ b/media/omx/1.0/vts/functional/audio/VtsHalMediaOmxV1_0TargetAudioDecTest.cpp
@@ -588,12 +588,12 @@
                             AudioDecHidlTest::standardComp comp) {
     android::hardware::media::omx::V1_0::Status status;
     Message msg;
-    int timeOut = TIMEOUT_COUNTER;
+    int timeOut = TIMEOUT_COUNTER_Q;
 
     while (timeOut--) {
         size_t i = 0;
         status =
-            observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
+            observer->dequeueMessage(&msg, DEFAULT_TIMEOUT_Q, iBuffer, oBuffer);
         if (status == android::hardware::media::omx::V1_0::Status::OK) {
             EXPECT_EQ(msg.type, Message::Type::EVENT);
             packedArgs audioArgs = {eEncoding, comp};
@@ -613,8 +613,8 @@
         size_t index;
         if ((index = getEmptyBufferID(oBuffer)) < oBuffer->size()) {
             dispatchOutputBuffer(omxNode, oBuffer, index);
+            timeOut = TIMEOUT_COUNTER_Q;
         }
-        timeOut--;
     }
 }
 
@@ -654,11 +654,12 @@
         frameID++;
     }
 
-    int timeOut = TIMEOUT_COUNTER;
-    bool stall = false;
+    int timeOut = TIMEOUT_COUNTER_Q;
+    bool iQueued, oQueued;
     while (1) {
+        iQueued = oQueued = false;
         status =
-            observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
+            observer->dequeueMessage(&msg, DEFAULT_TIMEOUT_Q, iBuffer, oBuffer);
 
         // Port Reconfiguration
         if (status == android::hardware::media::omx::V1_0::Status::OK &&
@@ -688,18 +689,16 @@
                                 (*Info)[frameID].bytesCount, flags,
                                 (*Info)[frameID].timestamp);
             frameID++;
-            stall = false;
-        } else
-            stall = true;
+            iQueued = true;
+        }
         if ((index = getEmptyBufferID(oBuffer)) < oBuffer->size()) {
             dispatchOutputBuffer(omxNode, oBuffer, index);
-            stall = false;
-        } else
-            stall = true;
-        if (stall)
-            timeOut--;
+            oQueued = true;
+        }
+        if (iQueued || oQueued)
+            timeOut = TIMEOUT_COUNTER_Q;
         else
-            timeOut = TIMEOUT_COUNTER;
+            timeOut--;
         if (timeOut == 0) {
             EXPECT_TRUE(false) << "Wait on Input/Output is found indefinite";
             break;
@@ -1149,9 +1148,8 @@
     decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, eEncoding,
                   kPortIndexInput, kPortIndexOutput, eleStream, &Info, 0,
                   nFrames, compName, false);
-    // Note: Assumes 200 ms is enough to end any decode call that started
     flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
-               kPortIndexOutput, 200000);
+               kPortIndexOutput);
     framesReceived = 0;
 
     // Seek to next key frame and start decoding till the end
@@ -1172,9 +1170,8 @@
                       kPortIndexInput, kPortIndexOutput, eleStream, &Info,
                       index, Info.size() - index, compName, false);
     }
-    // Note: Assumes 200 ms is enough to end any decode call that started
     flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
-               kPortIndexOutput, 200000);
+               kPortIndexOutput);
     framesReceived = 0;
 
     // set state to idle
diff --git a/media/omx/1.0/vts/functional/audio/VtsHalMediaOmxV1_0TargetAudioEncTest.cpp b/media/omx/1.0/vts/functional/audio/VtsHalMediaOmxV1_0TargetAudioEncTest.cpp
index ae79e82..038830d 100644
--- a/media/omx/1.0/vts/functional/audio/VtsHalMediaOmxV1_0TargetAudioEncTest.cpp
+++ b/media/omx/1.0/vts/functional/audio/VtsHalMediaOmxV1_0TargetAudioEncTest.cpp
@@ -342,12 +342,12 @@
                             android::Vector<BufferInfo>* oBuffer) {
     android::hardware::media::omx::V1_0::Status status;
     Message msg;
-    int timeOut = TIMEOUT_COUNTER;
+    int timeOut = TIMEOUT_COUNTER_Q;
 
     while (timeOut--) {
         size_t i = 0;
         status =
-            observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
+            observer->dequeueMessage(&msg, DEFAULT_TIMEOUT_Q, iBuffer, oBuffer);
         EXPECT_EQ(status,
                   android::hardware::media::omx::V1_0::Status::TIMED_OUT);
         // status == TIMED_OUT, it could be due to process time being large
@@ -362,8 +362,8 @@
         size_t index;
         if ((index = getEmptyBufferID(oBuffer)) < oBuffer->size()) {
             dispatchOutputBuffer(omxNode, oBuffer, index);
+            timeOut = TIMEOUT_COUNTER_Q;
         }
-        timeOut--;
     }
 }
 
@@ -400,11 +400,12 @@
         nFrames--;
     }
 
-    int timeOut = TIMEOUT_COUNTER;
-    bool stall = false;
+    int timeOut = TIMEOUT_COUNTER_Q;
+    bool iQueued, oQueued;
     while (1) {
+        iQueued = oQueued = false;
         status =
-            observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
+            observer->dequeueMessage(&msg, DEFAULT_TIMEOUT_Q, iBuffer, oBuffer);
 
         if (status == android::hardware::media::omx::V1_0::Status::OK)
             ASSERT_TRUE(false);
@@ -425,19 +426,17 @@
                                 timestamp);
             timestamp += timestampIncr;
             nFrames--;
-            stall = false;
-        } else
-            stall = true;
+            iQueued = true;
+        }
         // Dispatch output buffer
         if ((index = getEmptyBufferID(oBuffer)) < oBuffer->size()) {
             dispatchOutputBuffer(omxNode, oBuffer, index);
-            stall = false;
-        } else
-            stall = true;
-        if (stall)
-            timeOut--;
+            oQueued = true;
+        }
+        if (iQueued || oQueued)
+            timeOut = TIMEOUT_COUNTER_Q;
         else
-            timeOut = TIMEOUT_COUNTER;
+            timeOut--;
         if (timeOut == 0) {
             EXPECT_TRUE(false) << "Wait on Input/Output is found indefinite";
             break;
diff --git a/media/omx/1.0/vts/functional/audio/media_audio_hidl_test_common.h b/media/omx/1.0/vts/functional/audio/media_audio_hidl_test_common.h
index 08b3d9c..b187d28 100644
--- a/media/omx/1.0/vts/functional/audio/media_audio_hidl_test_common.h
+++ b/media/omx/1.0/vts/functional/audio/media_audio_hidl_test_common.h
@@ -20,11 +20,6 @@
 #include <media_hidl_test_common.h>
 
 /*
- * Random Index used for monkey testing while get/set parameters
- */
-#define RANDOM_INDEX 1729
-
-/*
  * Common audio utils
  */
 void enumerateProfile(sp<IOmxNode> omxNode, OMX_U32 portIndex,
diff --git a/media/omx/1.0/vts/functional/common/Android.bp b/media/omx/1.0/vts/functional/common/Android.bp
index 93251fe..af55e3a 100644
--- a/media/omx/1.0/vts/functional/common/Android.bp
+++ b/media/omx/1.0/vts/functional/common/Android.bp
@@ -16,18 +16,40 @@
 
 cc_library_static {
     name: "VtsHalMediaOmxV1_0CommonUtil",
-    defaults: ["hidl_defaults"],
     srcs: ["media_hidl_test_common.cpp"],
-    shared_libs: [
-        "liblog",
+
+    header_libs: ["media_plugin_headers"],
+    export_header_lib_headers: ["media_plugin_headers"],
+    export_include_dirs: ["."],
+
+    static_libs: [
+        "VtsHalHidlTargetTestBase",
         "libhidlmemory",
         "android.hidl.allocator@1.0",
         "android.hidl.memory@1.0",
         "android.hardware.media.omx@1.0",
     ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [ "-O0", "-g", ],
-    include_dirs: [
-        "frameworks/native/include/media/openmax/",
+}
+
+cc_defaults {
+    name: "VtsHalMediaOmxV1_0Defaults",
+    defaults: ["VtsHalTargetTestDefaults"],
+
+    // Link to these statically as they are not guaranteed to be on the device.
+    static_libs: [
+        "VtsHalMediaOmxV1_0CommonUtil",
+        "android.hardware.graphics.bufferqueue@1.0",
+        "android.hardware.graphics.common@1.0",
+        "android.hardware.media.omx@1.0",
+        "android.hardware.media@1.0",
+        "android.hidl.allocator@1.0",
+        "android.hidl.memory@1.0",
+        "libhidlmemory",
+        "libnativehelper",
+    ],
+
+    // TODO(b/64437680): Assume these libs are always available on the device.
+    shared_libs: [
+        "libstagefright_foundation",
     ],
 }
diff --git a/media/omx/1.0/vts/functional/common/media_hidl_test_common.cpp b/media/omx/1.0/vts/functional/common/media_hidl_test_common.cpp
index 1f67e2b..1ef645c 100644
--- a/media/omx/1.0/vts/functional/common/media_hidl_test_common.cpp
+++ b/media/omx/1.0/vts/functional/common/media_hidl_test_common.cpp
@@ -187,6 +187,66 @@
 }
 
 // allocate buffers needed on a component port
+void allocateBuffer(sp<IOmxNode> omxNode, BufferInfo* buffer, OMX_U32 portIndex,
+                    OMX_U32 nBufferSize, PortMode portMode) {
+    android::hardware::media::omx::V1_0::Status status;
+
+    if (portMode == PortMode::PRESET_SECURE_BUFFER) {
+        buffer->owner = client;
+        buffer->omxBuffer.type = CodecBuffer::Type::NATIVE_HANDLE;
+        omxNode->allocateSecureBuffer(
+            portIndex, nBufferSize,
+            [&status, &buffer](
+                android::hardware::media::omx::V1_0::Status _s, uint32_t id,
+                ::android::hardware::hidl_handle const& nativeHandle) {
+                status = _s;
+                buffer->id = id;
+                buffer->omxBuffer.nativeHandle = nativeHandle;
+            });
+        ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
+    } else if (portMode == PortMode::PRESET_BYTE_BUFFER ||
+               portMode == PortMode::DYNAMIC_ANW_BUFFER) {
+        sp<IAllocator> allocator = IAllocator::getService("ashmem");
+        EXPECT_NE(allocator.get(), nullptr);
+
+        buffer->owner = client;
+        buffer->omxBuffer.type = CodecBuffer::Type::SHARED_MEM;
+        buffer->omxBuffer.attr.preset.rangeOffset = 0;
+        buffer->omxBuffer.attr.preset.rangeLength = 0;
+        bool success = false;
+        if (portMode != PortMode::PRESET_BYTE_BUFFER) {
+            nBufferSize = sizeof(android::VideoNativeMetadata);
+        }
+        allocator->allocate(
+            nBufferSize,
+            [&success, &buffer](bool _s,
+                                ::android::hardware::hidl_memory const& mem) {
+                success = _s;
+                buffer->omxBuffer.sharedMemory = mem;
+            });
+        ASSERT_EQ(success, true);
+        ASSERT_EQ(buffer->omxBuffer.sharedMemory.size(), nBufferSize);
+        buffer->mMemory = mapMemory(buffer->omxBuffer.sharedMemory);
+        ASSERT_NE(buffer->mMemory, nullptr);
+        if (portMode == PortMode::DYNAMIC_ANW_BUFFER) {
+            android::VideoNativeMetadata* metaData =
+                static_cast<android::VideoNativeMetadata*>(
+                    static_cast<void*>(buffer->mMemory->getPointer()));
+            metaData->nFenceFd = -1;
+            buffer->slot = -1;
+        }
+        omxNode->useBuffer(
+            portIndex, buffer->omxBuffer,
+            [&status, &buffer](android::hardware::media::omx::V1_0::Status _s,
+                               uint32_t id) {
+                status = _s;
+                buffer->id = id;
+            });
+        ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
+    }
+}
+
+// allocate buffers needed on a component port
 void allocatePortBuffers(sp<IOmxNode> omxNode,
                          android::Vector<BufferInfo>* buffArray,
                          OMX_U32 portIndex, PortMode portMode) {
@@ -199,70 +259,11 @@
                           &portDef);
     ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
 
-    if (portMode == PortMode::PRESET_SECURE_BUFFER) {
-        for (size_t i = 0; i < portDef.nBufferCountActual; i++) {
-            BufferInfo buffer;
-            buffer.owner = client;
-            buffer.omxBuffer.type = CodecBuffer::Type::NATIVE_HANDLE;
-            omxNode->allocateSecureBuffer(
-                portIndex, portDef.nBufferSize,
-                [&status, &buffer](
-                    android::hardware::media::omx::V1_0::Status _s, uint32_t id,
-                    ::android::hardware::hidl_handle const& nativeHandle) {
-                    status = _s;
-                    buffer.id = id;
-                    buffer.omxBuffer.nativeHandle = nativeHandle;
-                });
-            buffArray->push(buffer);
-            ASSERT_EQ(status,
-                      ::android::hardware::media::omx::V1_0::Status::OK);
-        }
-    } else if (portMode == PortMode::PRESET_BYTE_BUFFER ||
-               portMode == PortMode::DYNAMIC_ANW_BUFFER) {
-        sp<IAllocator> allocator = IAllocator::getService("ashmem");
-        EXPECT_NE(allocator.get(), nullptr);
-
-        for (size_t i = 0; i < portDef.nBufferCountActual; i++) {
-            BufferInfo buffer;
-            buffer.owner = client;
-            buffer.omxBuffer.type = CodecBuffer::Type::SHARED_MEM;
-            buffer.omxBuffer.attr.preset.rangeOffset = 0;
-            buffer.omxBuffer.attr.preset.rangeLength = 0;
-            bool success = false;
-            if (portMode != PortMode::PRESET_BYTE_BUFFER) {
-                portDef.nBufferSize = sizeof(android::VideoNativeMetadata);
-            }
-            allocator->allocate(
-                portDef.nBufferSize,
-                [&success, &buffer](
-                    bool _s, ::android::hardware::hidl_memory const& mem) {
-                    success = _s;
-                    buffer.omxBuffer.sharedMemory = mem;
-                });
-            ASSERT_EQ(success, true);
-            ASSERT_EQ(buffer.omxBuffer.sharedMemory.size(),
-                      portDef.nBufferSize);
-            buffer.mMemory = mapMemory(buffer.omxBuffer.sharedMemory);
-            ASSERT_NE(buffer.mMemory, nullptr);
-            if (portMode == PortMode::DYNAMIC_ANW_BUFFER) {
-                android::VideoNativeMetadata* metaData =
-                    static_cast<android::VideoNativeMetadata*>(
-                        static_cast<void*>(buffer.mMemory->getPointer()));
-                metaData->nFenceFd = -1;
-                buffer.slot = -1;
-            }
-            omxNode->useBuffer(
-                portIndex, buffer.omxBuffer,
-                [&status, &buffer](
-                    android::hardware::media::omx::V1_0::Status _s,
-                    uint32_t id) {
-                    status = _s;
-                    buffer.id = id;
-                });
-            buffArray->push(buffer);
-            ASSERT_EQ(status,
-                      ::android::hardware::media::omx::V1_0::Status::OK);
-        }
+    for (size_t i = 0; i < portDef.nBufferCountActual; i++) {
+        BufferInfo buffer;
+        allocateBuffer(omxNode, &buffer, portIndex, portDef.nBufferSize,
+                       portMode);
+        buffArray->push(buffer);
     }
 }
 
@@ -551,7 +552,7 @@
         }
     }
 
-    int timeOut = TIMEOUT_COUNTER;
+    int timeOut = TIMEOUT_COUNTER_PE;
     while (timeOut--) {
         // Dispatch all client owned output buffers to recover remaining frames
         while (1) {
@@ -560,15 +561,15 @@
                 // if dispatch is successful, perhaps there is a latency
                 // in the component. Dont be in a haste to leave. reset timeout
                 // counter
-                timeOut = TIMEOUT_COUNTER;
+                timeOut = TIMEOUT_COUNTER_PE;
             } else {
                 break;
             }
         }
 
         Message msg;
-        status =
-            observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
+        status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT_PE, iBuffer,
+                                          oBuffer);
         if (status == android::hardware::media::omx::V1_0::Status::OK) {
             if (msg.data.eventData.event == OMX_EventPortSettingsChanged) {
                 if (fptr) {
diff --git a/media/omx/1.0/vts/functional/common/media_hidl_test_common.h b/media/omx/1.0/vts/functional/common/media_hidl_test_common.h
index 0adea14..94a0194 100644
--- a/media/omx/1.0/vts/functional/common/media_hidl_test_common.h
+++ b/media/omx/1.0/vts/functional/common/media_hidl_test_common.h
@@ -33,8 +33,21 @@
 #include <media/openmax/OMX_AudioExt.h>
 #include <media/openmax/OMX_VideoExt.h>
 
+/* TIME OUTS (Wait time in dequeueMessage()) */
+
+/* As component is switching states (loaded<->idle<->execute), dequeueMessage()
+ * expects the events to be received within this duration */
 #define DEFAULT_TIMEOUT 100000
-#define TIMEOUT_COUNTER (10000000 / DEFAULT_TIMEOUT)
+/* Time interval between successive Input/Output enqueues */
+#define DEFAULT_TIMEOUT_Q 2000
+/* While the component is amidst a process call, asynchronous commands like
+ * flush, change states can get delayed (at max by process call time). Instead
+ * of waiting on DEFAULT_TIMEOUT, we give an additional leeway. */
+#define DEFAULT_TIMEOUT_PE 500000
+
+/* Breakout Timeout :: 5 sec*/
+#define TIMEOUT_COUNTER_Q (5000000 / DEFAULT_TIMEOUT_Q)
+#define TIMEOUT_COUNTER_PE (5000000 / DEFAULT_TIMEOUT_PE)
 
 /*
  * Random Index used for monkey testing while get/set parameters
@@ -113,20 +126,21 @@
         android::Vector<BufferInfo>* iBuffers = nullptr,
         android::Vector<BufferInfo>* oBuffers = nullptr) {
         int64_t finishBy = android::ALooper::GetNowUs() + timeoutUs;
+        android::Mutex::Autolock autoLock(msgLock);
         for (;;) {
-            android::Mutex::Autolock autoLock(msgLock);
             android::List<Message>::iterator it = msgQueue.begin();
             while (it != msgQueue.end()) {
                 if (it->type ==
                     android::hardware::media::omx::V1_0::Message::Type::EVENT) {
                     *msg = *it;
-                    msgQueue.erase(it);
+                    it = msgQueue.erase(it);
                     // OMX_EventBufferFlag event is sent when the component has
                     // processed a buffer with its EOS flag set. This event is
                     // not sent by soft omx components. Vendor components can
                     // send this. From IOMX point of view, we will ignore this
                     // event.
-                    if (msg->data.eventData.event == OMX_EventBufferFlag) break;
+                    if (msg->data.eventData.event == OMX_EventBufferFlag)
+                        continue;
                     return ::android::hardware::media::omx::V1_0::Status::OK;
                 } else if (it->type == android::hardware::media::omx::V1_0::
                                            Message::Type::FILL_BUFFER_DONE) {
@@ -137,7 +151,7 @@
                                 it->data.bufferData.buffer) {
                                 if (callBack) callBack(*it, &(*oBuffers)[i]);
                                 oBuffers->editItemAt(i).owner = client;
-                                msgQueue.erase(it);
+                                it = msgQueue.erase(it);
                                 break;
                             }
                         }
@@ -152,24 +166,22 @@
                                 it->data.bufferData.buffer) {
                                 if (callBack) callBack(*it, &(*iBuffers)[i]);
                                 iBuffers->editItemAt(i).owner = client;
-                                msgQueue.erase(it);
+                                it = msgQueue.erase(it);
                                 break;
                             }
                         }
                         EXPECT_LE(i, iBuffers->size());
                     }
+                } else {
+                    EXPECT_TRUE(false) << "Received unexpected message";
+                    ++it;
                 }
-                ++it;
             }
-            if (finishBy - android::ALooper::GetNowUs() < 0)
-                return toStatus(android::TIMED_OUT);
-            android::status_t err =
-                (timeoutUs < 0)
-                    ? msgCondition.wait(msgLock)
-                    : msgCondition.waitRelative(
-                          msgLock,
-                          (finishBy - android::ALooper::GetNowUs()) * 1000ll);
-            if (err == android::TIMED_OUT) return toStatus(err);
+            int64_t delayUs = finishBy - android::ALooper::GetNowUs();
+            if (delayUs < 0) return toStatus(android::TIMED_OUT);
+            (timeoutUs < 0)
+                ? msgCondition.wait(msgLock)
+                : msgCondition.waitRelative(msgLock, delayUs * 1000ll);
         }
     }
 
@@ -284,6 +296,9 @@
 Return<android::hardware::media::omx::V1_0::Status> setAudioPortFormat(
     sp<IOmxNode> omxNode, OMX_U32 portIndex, OMX_AUDIO_CODINGTYPE eEncoding);
 
+void allocateBuffer(sp<IOmxNode> omxNode, BufferInfo* buffer, OMX_U32 portIndex,
+                    OMX_U32 nBufferSize, PortMode portMode);
+
 void allocatePortBuffers(sp<IOmxNode> omxNode,
                          android::Vector<BufferInfo>* buffArray,
                          OMX_U32 portIndex,
@@ -322,7 +337,8 @@
 void flushPorts(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
                 android::Vector<BufferInfo>* iBuffer,
                 android::Vector<BufferInfo>* oBuffer, OMX_U32 kPortIndexInput,
-                OMX_U32 kPortIndexOutput, int64_t timeoutUs = DEFAULT_TIMEOUT);
+                OMX_U32 kPortIndexOutput,
+                int64_t timeoutUs = DEFAULT_TIMEOUT_PE);
 
 typedef void (*portreconfig)(sp<IOmxNode> omxNode, sp<CodecObserver> observer,
                              android::Vector<BufferInfo>* iBuffer,
diff --git a/media/omx/1.0/vts/functional/component/Android.bp b/media/omx/1.0/vts/functional/component/Android.bp
index fd3210f..f76b6e9 100644
--- a/media/omx/1.0/vts/functional/component/Android.bp
+++ b/media/omx/1.0/vts/functional/component/Android.bp
@@ -16,32 +16,7 @@
 
 cc_test {
     name: "VtsHalMediaOmxV1_0TargetComponentTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalMediaOmxV1_0Defaults"],
     srcs: ["VtsHalMediaOmxV1_0TargetComponentTest.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidlmemory",
-        "libhidltransport",
-        "libhwbinder",
-        "libnativehelper",
-        "libutils",
-        "libstagefright_foundation",
-        "android.hidl.allocator@1.0",
-        "android.hidl.memory@1.0",
-        "android.hardware.media.omx@1.0",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase",
-                  "VtsHalMediaOmxV1_0CommonUtil"],
-    cflags: [
-        "-O0",
-        "-g",
-    ],
-    include_dirs: [
-        "frameworks/native/include/media/openmax/",
-        "hardware/interfaces/media/omx/1.0/vts/functional/common",
-    ],
 }
 
diff --git a/media/omx/1.0/vts/functional/component/VtsHalMediaOmxV1_0TargetComponentTest.cpp b/media/omx/1.0/vts/functional/component/VtsHalMediaOmxV1_0TargetComponentTest.cpp
index 2d91e82..2ec86b2 100644
--- a/media/omx/1.0/vts/functional/component/VtsHalMediaOmxV1_0TargetComponentTest.cpp
+++ b/media/omx/1.0/vts/functional/component/VtsHalMediaOmxV1_0TargetComponentTest.cpp
@@ -213,9 +213,6 @@
     }
 };
 
-// Random Index used for monkey testing while get/set parameters
-#define RANDOM_INDEX 1729
-
 void initPortMode(PortMode* pm, bool isSecure,
                   ComponentHidlTest::standardCompClass compClass) {
     pm[0] = PortMode::PRESET_BYTE_BUFFER;
@@ -374,7 +371,7 @@
         kPortIndexOutput = kPortIndexInput + 1;
     }
 
-    for (size_t i = kPortIndexInput; i < kPortIndexOutput; i++) {
+    for (size_t i = kPortIndexInput; i <= kPortIndexOutput; i++) {
         OMX_PARAM_PORTDEFINITIONTYPE portDef;
         status =
             getPortParam(omxNode, OMX_IndexParamPortDefinition, i, &portDef);
@@ -409,10 +406,32 @@
             setPortParam(omxNode, OMX_IndexParamPortDefinition, i, &mirror);
 
             portDef = mirror;
-            portDef.nBufferSize >>= 1;
+            OMX_U32 nBufferSize = portDef.nBufferSize >> 1;
+            if (nBufferSize != 0) {
+                if (!strncmp(gEnv->getComponent().c_str(), "OMX.google.", 11)) {
+                    portDef.nBufferSize = nBufferSize;
+                } else {
+                    // Probable alignment requirements of vendor component
+                    portDef.nBufferSize = ALIGN_POWER_OF_TWO(nBufferSize, 12);
+                    nBufferSize = portDef.nBufferSize;
+                }
+            } else {
+                ASSERT_TRUE(false) << "Unexpected buffer size";
+            }
             setPortParam(omxNode, OMX_IndexParamPortDefinition, i, &portDef);
             getPortParam(omxNode, OMX_IndexParamPortDefinition, i, &portDef);
-            EXPECT_EQ(portDef.nBufferSize, mirror.nBufferSize);
+            // SPECIAL CASE: For video decoder, allow configuration of input
+            // buffer size even if it is less than minimum requirement and
+            // similarly for encoder allow configuration of output port buffer
+            // size.
+            if ((compClass == video_encoder && i == kPortIndexOutput) ||
+                (compClass == video_decoder && i == kPortIndexInput)) {
+                double dev = (portDef.nBufferSize / (double)nBufferSize);
+                dev -= 1;
+                if (dev < 0 || dev > 0.1) EXPECT_TRUE(false);
+            } else {
+                EXPECT_EQ(portDef.nBufferSize, mirror.nBufferSize);
+            }
             setPortParam(omxNode, OMX_IndexParamPortDefinition, i, &mirror);
 
             portDef = mirror;
@@ -470,8 +489,10 @@
         portBase = params.nStartPortNumber;
     }
 
-    sp<IAllocator> allocator = IAllocator::getService("ashmem");
-    EXPECT_NE(allocator.get(), nullptr);
+    // set state to idle
+    status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet),
+                                  OMX_StateIdle);
+    ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
 
     OMX_PARAM_PORTDEFINITIONTYPE portDef;
     status =
@@ -485,30 +506,9 @@
 
     for (size_t i = 0; i < portDef.nBufferCountActual; i++) {
         BufferInfo buffer;
-        buffer.owner = client;
-        buffer.omxBuffer.type = CodecBuffer::Type::SHARED_MEM;
-        buffer.omxBuffer.attr.preset.rangeOffset = 0;
-        buffer.omxBuffer.attr.preset.rangeLength = 0;
-        bool success = false;
-        allocator->allocate(
-            nBufferSize,
-            [&success, &buffer](bool _s,
-                                ::android::hardware::hidl_memory const& mem) {
-                success = _s;
-                buffer.omxBuffer.sharedMemory = mem;
-            });
-        ASSERT_EQ(success, true);
-        ASSERT_EQ(buffer.omxBuffer.sharedMemory.size(), nBufferSize);
-
-        omxNode->useBuffer(
-            portBase, buffer.omxBuffer,
-            [&status, &buffer](android::hardware::media::omx::V1_0::Status _s,
-                               uint32_t id) {
-                status = _s;
-                buffer.id = id;
-            });
+        allocateBuffer(omxNode, &buffer, portBase, nBufferSize,
+                       PortMode::PRESET_BYTE_BUFFER);
         pBuffer.push(buffer);
-        ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
     }
 
     status =
@@ -583,9 +583,9 @@
                             kPortIndexInput, kPortIndexOutput);
 }
 
-// state transitions test
-TEST_F(ComponentHidlTest, StateTransitions) {
-    description("Test State Transitions Loaded<->Idle<->Execute");
+// test port mode configuration when the component is in various states
+TEST_F(ComponentHidlTest, PortModeConfig) {
+    description("Test Port Mode Configuration");
     if (disableTest) return;
     android::hardware::media::omx::V1_0::Status status;
     uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
@@ -618,26 +618,144 @@
     // set state to idle
     changeStateLoadedtoIdle(omxNode, observer, &iBuffer, &oBuffer,
                             kPortIndexInput, kPortIndexOutput, portMode);
+    // Only Allow Port Mode configuration in loaded state
+    status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
+    EXPECT_NE(status, ::android::hardware::media::omx::V1_0::Status::OK);
+    status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
+    EXPECT_NE(status, ::android::hardware::media::omx::V1_0::Status::OK);
+
+    // set state to executing
+    changeStateIdletoExecute(omxNode, observer);
+    // Only Allow Port Mode configuration in loaded state
+    status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
+    EXPECT_NE(status, ::android::hardware::media::omx::V1_0::Status::OK);
+    status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
+    EXPECT_NE(status, ::android::hardware::media::omx::V1_0::Status::OK);
+
+    // set state to idle
+    changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
+    // set state to loaded
+    changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
+                            kPortIndexInput, kPortIndexOutput);
+
+    status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
+    EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
+    status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
+    EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
+}
+
+// state transitions test
+TEST_F(ComponentHidlTest, StateTransitions) {
+    description("Test State Transitions Loaded<->Idle<->Execute");
+    if (disableTest) return;
+    android::hardware::media::omx::V1_0::Status status;
+    uint32_t kPortIndexInput = 0, kPortIndexOutput = 1;
+    OMX_U32 portBase = 0;
+    Message msg;
+    status = setRole(omxNode, gEnv->getRole().c_str());
+    ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
+    OMX_PORT_PARAM_TYPE params;
+    if (compClass == audio_decoder || compClass == audio_encoder) {
+        status = getParam(omxNode, OMX_IndexParamAudioInit, &params);
+    } else {
+        status = getParam(omxNode, OMX_IndexParamVideoInit, &params);
+    }
+    if (status == ::android::hardware::media::omx::V1_0::Status::OK) {
+        ASSERT_EQ(params.nPorts, 2U);
+        portBase = params.nStartPortNumber;
+    }
+    kPortIndexInput = portBase;
+    kPortIndexOutput = portBase + 1;
+
+    android::Vector<BufferInfo> pBuffer[2];
+
+    // set port mode
+    PortMode portMode[2];
+    initPortMode(portMode, isSecure, compClass);
+    status = omxNode->setPortMode(kPortIndexInput, portMode[0]);
+    EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
+    status = omxNode->setPortMode(kPortIndexOutput, portMode[1]);
+    EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
+
+    // set state to idle
+    status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet),
+                                  OMX_StateIdle);
+    ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
+
+    for (size_t j = portBase; j < portBase + 2; j++) {
+        pBuffer[j - portBase].clear();
+
+        OMX_PARAM_PORTDEFINITIONTYPE def;
+        status = getPortParam(omxNode, OMX_IndexParamPortDefinition, j, &def);
+        ASSERT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
+
+        for (size_t i = 0; i < def.nBufferCountActual; i++) {
+            // Dont switch states until the ports are populated
+            status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT,
+                                              &pBuffer[0], &pBuffer[1]);
+            ASSERT_EQ(status,
+                      android::hardware::media::omx::V1_0::Status::TIMED_OUT);
+
+            BufferInfo buffer;
+            allocateBuffer(omxNode, &buffer, j, def.nBufferSize,
+                           portMode[j - portBase]);
+            pBuffer[j - portBase].push(buffer);
+        }
+    }
+
+    // As the ports are populated, check if the state transition is complete
+    status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, &pBuffer[0],
+                                      &pBuffer[1]);
+    ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
+    ASSERT_EQ(msg.type, Message::Type::EVENT);
+    ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete);
+    ASSERT_EQ(msg.data.eventData.data1, OMX_CommandStateSet);
+    ASSERT_EQ(msg.data.eventData.data2, OMX_StateIdle);
+
     // set state to executing
     changeStateIdletoExecute(omxNode, observer);
     // dispatch buffers
-    for (size_t i = 0; i < oBuffer.size(); i++) {
-        dispatchOutputBuffer(omxNode, &oBuffer, i, portMode[1]);
+    for (size_t i = 0; i < pBuffer[1].size(); i++) {
+        dispatchOutputBuffer(omxNode, &pBuffer[1], i, portMode[1]);
     }
     // set state to idle
-    changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
+    changeStateExecutetoIdle(omxNode, observer, &pBuffer[0], &pBuffer[1]);
     //    // set state to executing
     //    changeStateIdletoExecute(omxNode, observer);
     //    // TODO: Sending empty input buffers is slightly tricky.
     //    // dispatch buffers
-    //    for (size_t i = 0; i < iBuffer.size(); i++) {
-    //        dispatchInputBuffer(omxNode, &iBuffer, i, 0, 0, 0, portMode[0]);
+    //    for (size_t i = 0; i < pBuffer[0].size(); i++) {
+    //        dispatchInputBuffer(omxNode, &pBuffer[0], i, 0, 0, 0,
+    //        portMode[0]);
     //    }
     //    // set state to idle
-    //    changeStateExecutetoIdle(omxNode, observer, &iBuffer, &oBuffer);
+    //    changeStateExecutetoIdle(omxNode, observer, &pBuffer[0], &pBuffer[1]);
+
     // set state to loaded
-    changeStateIdletoLoaded(omxNode, observer, &iBuffer, &oBuffer,
-                            kPortIndexInput, kPortIndexOutput);
+    status = omxNode->sendCommand(toRawCommandType(OMX_CommandStateSet),
+                                  OMX_StateLoaded);
+    ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
+
+    for (size_t j = portBase; j < portBase + 2; j++) {
+        for (size_t i = 0; i < pBuffer[j].size(); ++i) {
+            // Dont switch states until the ports are populated
+            status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT,
+                                              &pBuffer[0], &pBuffer[1]);
+            ASSERT_EQ(status,
+                      android::hardware::media::omx::V1_0::Status::TIMED_OUT);
+
+            status = omxNode->freeBuffer(j, pBuffer[j][i].id);
+            ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
+        }
+    }
+
+    status = observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, &pBuffer[0],
+                                      &pBuffer[1]);
+    ASSERT_EQ(status, android::hardware::media::omx::V1_0::Status::OK);
+    ASSERT_EQ(msg.type, Message::Type::EVENT);
+    ASSERT_EQ(msg.data.eventData.event, OMX_EventCmdComplete);
+    ASSERT_EQ(msg.data.eventData.data1, OMX_CommandStateSet);
+    ASSERT_EQ(msg.data.eventData.data2, OMX_StateLoaded);
 }
 
 // state transitions test - monkeying
diff --git a/media/omx/1.0/vts/functional/master/Android.bp b/media/omx/1.0/vts/functional/master/Android.bp
index e24b79b..4a45e69 100644
--- a/media/omx/1.0/vts/functional/master/Android.bp
+++ b/media/omx/1.0/vts/functional/master/Android.bp
@@ -16,29 +16,7 @@
 
 cc_test {
     name: "VtsHalMediaOmxV1_0TargetMasterTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalMediaOmxV1_0Defaults"],
     srcs: ["VtsHalMediaOmxV1_0TargetMasterTest.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
-        "libnativehelper",
-        "libutils",
-        "android.hidl.allocator@1.0",
-        "android.hidl.memory@1.0",
-        "android.hardware.media.omx@1.0",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ],
-    include_dirs: [
-        "frameworks/native/include/media/openmax/",
-        "hardware/interfaces/media/omx/1.0/vts/functional/common",
-    ],
 }
 
diff --git a/media/omx/1.0/vts/functional/video/Android.bp b/media/omx/1.0/vts/functional/video/Android.bp
index 4e94f3b..e251a15 100644
--- a/media/omx/1.0/vts/functional/video/Android.bp
+++ b/media/omx/1.0/vts/functional/video/Android.bp
@@ -16,70 +16,26 @@
 
 cc_test {
     name: "VtsHalMediaOmxV1_0TargetVideoDecTest",
-    defaults: ["hidl_defaults"],
-    srcs: ["VtsHalMediaOmxV1_0TargetVideoDecTest.cpp",
-           "media_video_hidl_test_common.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidlmemory",
-        "libhidltransport",
-        "libhwbinder",
-        "libnativehelper",
-        "libutils",
-        "libstagefright_foundation",
-        "android.hidl.allocator@1.0",
-        "android.hidl.memory@1.0",
-        "android.hardware.media.omx@1.0",
+    defaults: ["VtsHalMediaOmxV1_0Defaults"],
+    srcs: [
+        "VtsHalMediaOmxV1_0TargetVideoDecTest.cpp",
+        "media_video_hidl_test_common.cpp"
+    ],
+    static_libs: [
         "android.hardware.graphics.allocator@2.0",
         "android.hardware.graphics.mapper@2.0",
-        "android.hardware.graphics.common@1.0",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase",
-                  "VtsHalMediaOmxV1_0CommonUtil"],
-    cflags: [
-        "-O0",
-        "-g",
-    ],
-    include_dirs: [
-        "frameworks/native/include/media/openmax/",
-        "hardware/interfaces/media/omx/1.0/vts/functional/common",
     ],
 }
 
 cc_test {
     name: "VtsHalMediaOmxV1_0TargetVideoEncTest",
-    defaults: ["hidl_defaults"],
-    srcs: ["VtsHalMediaOmxV1_0TargetVideoEncTest.cpp",
-           "media_video_hidl_test_common.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidlmemory",
-        "libhidltransport",
-        "libhwbinder",
-        "libnativehelper",
+    defaults: ["VtsHalMediaOmxV1_0Defaults"],
+    srcs: [
+        "VtsHalMediaOmxV1_0TargetVideoEncTest.cpp",
+        "media_video_hidl_test_common.cpp"
+    ],
+    static_libs: [
         "libnativewindow",
-        "libutils",
-        "libstagefright_foundation",
-        "android.hidl.allocator@1.0",
-        "android.hidl.memory@1.0",
-        "android.hardware.media.omx@1.0",
-        "android.hardware.graphics.bufferqueue@1.0",
         "android.hardware.graphics.mapper@2.0",
     ],
-    static_libs: ["VtsHalHidlTargetTestBase",
-                  "VtsHalMediaOmxV1_0CommonUtil"],
-    cflags: [
-        "-O0",
-        "-g",
-    ],
-    include_dirs: [
-        "frameworks/native/include/media/openmax/",
-        "hardware/interfaces/media/omx/1.0/vts/functional/common",
-    ],
 }
diff --git a/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoDecTest.cpp b/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoDecTest.cpp
index ff031dd..a5b5524 100644
--- a/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoDecTest.cpp
+++ b/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoDecTest.cpp
@@ -635,12 +635,12 @@
                             PortMode oPortMode) {
     android::hardware::media::omx::V1_0::Status status;
     Message msg;
-    int timeOut = TIMEOUT_COUNTER;
+    int timeOut = TIMEOUT_COUNTER_Q;
 
     while (timeOut--) {
         size_t i = 0;
         status =
-            observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
+            observer->dequeueMessage(&msg, DEFAULT_TIMEOUT_Q, iBuffer, oBuffer);
         if (status == android::hardware::media::omx::V1_0::Status::OK) {
             EXPECT_EQ(msg.type, Message::Type::EVENT);
             portReconfiguration(omxNode, observer, iBuffer, oBuffer,
@@ -659,8 +659,8 @@
         size_t index;
         if ((index = getEmptyBufferID(oBuffer)) < oBuffer->size()) {
             dispatchOutputBuffer(omxNode, oBuffer, index, oPortMode);
+            timeOut = TIMEOUT_COUNTER_Q;
         }
-        timeOut--;
     }
 }
 
@@ -700,11 +700,12 @@
         frameID++;
     }
 
-    int timeOut = TIMEOUT_COUNTER;
-    bool stall = false;
+    int timeOut = TIMEOUT_COUNTER_Q;
+    bool iQueued, oQueued;
     while (1) {
+        iQueued = oQueued = false;
         status =
-            observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
+            observer->dequeueMessage(&msg, DEFAULT_TIMEOUT_Q, iBuffer, oBuffer);
 
         // Port Reconfiguration
         if (status == android::hardware::media::omx::V1_0::Status::OK &&
@@ -733,18 +734,16 @@
                                 (*Info)[frameID].bytesCount, flags,
                                 (*Info)[frameID].timestamp);
             frameID++;
-            stall = false;
-        } else
-            stall = true;
+            iQueued = true;
+        }
         if ((index = getEmptyBufferID(oBuffer)) < oBuffer->size()) {
             dispatchOutputBuffer(omxNode, oBuffer, index, oPortMode);
-            stall = false;
-        } else
-            stall = true;
-        if (stall)
-            timeOut--;
+            oQueued = true;
+        }
+        if (iQueued || oQueued)
+            timeOut = TIMEOUT_COUNTER_Q;
         else
-            timeOut = TIMEOUT_COUNTER;
+            timeOut--;
         if (timeOut == 0) {
             EXPECT_TRUE(false) << "Wait on Input/Output is found indefinite";
             break;
@@ -840,7 +839,7 @@
     OMX_VIDEO_PARAM_PORTFORMATTYPE portFormat;
     *eColorFormat = OMX_COLOR_FormatUnused;
     portFormat.nIndex = 0;
-    while (1) {
+    while (portFormat.nIndex < 512) {
         status = getPortParam(omxNode, OMX_IndexParamVideoPortFormat,
                               kPortIndexOutput, &portFormat);
         if (status != ::android::hardware::media::omx::V1_0::Status::OK) break;
@@ -854,7 +853,9 @@
             break;
         }
         if (OMX_COLOR_FormatYUV420SemiPlanar == portFormat.eColorFormat ||
-            OMX_COLOR_FormatYUV420Planar == portFormat.eColorFormat) {
+            OMX_COLOR_FormatYUV420Planar == portFormat.eColorFormat ||
+            OMX_COLOR_FormatYUV420PackedPlanar == portFormat.eColorFormat ||
+            OMX_COLOR_FormatYUV420PackedSemiPlanar == portFormat.eColorFormat) {
             *eColorFormat = portFormat.eColorFormat;
             break;
         }
@@ -1365,9 +1366,8 @@
     decodeNFrames(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
                   kPortIndexOutput, eleStream, &Info, 0, nFrames, portMode[1],
                   false);
-    // Note: Assumes 200 ms is enough to end any decode call that started
     flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
-               kPortIndexOutput, 200000);
+               kPortIndexOutput);
     framesReceived = 0;
 
     // Seek to next key frame and start decoding till the end
@@ -1388,10 +1388,9 @@
                       kPortIndexOutput, eleStream, &Info, index,
                       Info.size() - index, portMode[1], false);
     }
-    // Note: Assumes 200 ms is enough to end any decode call that started
     eleStream.close();
     flushPorts(omxNode, observer, &iBuffer, &oBuffer, kPortIndexInput,
-               kPortIndexOutput, 200000);
+               kPortIndexOutput);
     framesReceived = 0;
 
     // set state to idle
diff --git a/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoEncTest.cpp b/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoEncTest.cpp
index c6d688f..23f051d 100644
--- a/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoEncTest.cpp
+++ b/media/omx/1.0/vts/functional/video/VtsHalMediaOmxV1_0TargetVideoEncTest.cpp
@@ -532,12 +532,15 @@
 // Set Default port param.
 void setDefaultPortParam(sp<IOmxNode> omxNode, OMX_U32 portIndex,
                          OMX_VIDEO_CODINGTYPE eCompressionFormat,
+                         OMX_U32 nFrameWidth, OMX_U32 nFrameHeight,
                          OMX_U32 nBitrate, OMX_U32 xFramerate) {
     android::hardware::media::omx::V1_0::Status status;
     OMX_PARAM_PORTDEFINITIONTYPE portDef;
     status = getPortParam(omxNode, OMX_IndexParamPortDefinition, portIndex,
                           &portDef);
     EXPECT_EQ(status, ::android::hardware::media::omx::V1_0::Status::OK);
+    portDef.format.video.nFrameWidth = nFrameWidth;
+    portDef.format.video.nFrameHeight = nFrameHeight;
     portDef.format.video.nBitrate = nBitrate;
     portDef.format.video.xFramerate = xFramerate;
     portDef.format.video.bFlagErrorConcealment = OMX_TRUE;
@@ -609,12 +612,12 @@
                             sp<CodecProducerListener> listener = nullptr) {
     android::hardware::media::omx::V1_0::Status status;
     Message msg;
-    int timeOut = TIMEOUT_COUNTER;
+    int timeOut = TIMEOUT_COUNTER_Q;
 
     while (timeOut--) {
         size_t i = 0;
         status =
-            observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
+            observer->dequeueMessage(&msg, DEFAULT_TIMEOUT_Q, iBuffer, oBuffer);
         EXPECT_EQ(status,
                   android::hardware::media::omx::V1_0::Status::TIMED_OUT);
         // status == TIMED_OUT, it could be due to process time being large
@@ -633,6 +636,7 @@
         size_t index;
         if ((index = getEmptyBufferID(oBuffer)) < oBuffer->size()) {
             dispatchOutputBuffer(omxNode, oBuffer, index);
+            timeOut = TIMEOUT_COUNTER_Q;
         }
     }
 }
@@ -1024,11 +1028,12 @@
         }
     }
 
-    int timeOut = TIMEOUT_COUNTER;
-    bool stall = false;
+    int timeOut = TIMEOUT_COUNTER_Q;
+    bool iQueued, oQueued;
     while (1) {
+        iQueued = oQueued = false;
         status =
-            observer->dequeueMessage(&msg, DEFAULT_TIMEOUT, iBuffer, oBuffer);
+            observer->dequeueMessage(&msg, DEFAULT_TIMEOUT_Q, iBuffer, oBuffer);
 
         if (status == android::hardware::media::omx::V1_0::Status::OK) {
             ASSERT_EQ(msg.type, Message::Type::EVENT);
@@ -1039,6 +1044,9 @@
             } else if (msg.data.eventData.event == OMX_EventError) {
                 EXPECT_TRUE(false) << "Received OMX_EventError, not sure why";
                 break;
+            } else if (msg.data.eventData.event == OMX_EventDataSpaceChanged) {
+                // TODO: how am i supposed to respond now?
+                std::cout << "[          ] Info ! OMX_EventDataSpaceChanged \n";
             } else {
                 ASSERT_TRUE(false);
             }
@@ -1056,9 +1064,7 @@
                 timestamp += timestampIncr;
                 nFrames--;
                 ipCount++;
-                stall = false;
-            } else {
-                stall = true;
+                iQueued = true;
             }
         } else {
             if ((index = getEmptyBufferID(iBuffer)) < iBuffer->size()) {
@@ -1077,20 +1083,17 @@
                 timestamp += timestampIncr;
                 nFrames--;
                 ipCount++;
-                stall = false;
-            } else {
-                stall = true;
+                iQueued = true;
             }
         }
         if ((index = getEmptyBufferID(oBuffer)) < oBuffer->size()) {
             dispatchOutputBuffer(omxNode, oBuffer, index);
-            stall = false;
-        } else
-            stall = true;
-        if (stall)
-            timeOut--;
+            oQueued = true;
+        }
+        if (iQueued || oQueued)
+            timeOut = TIMEOUT_COUNTER_Q;
         else
-            timeOut = TIMEOUT_COUNTER;
+            timeOut--;
         if (timeOut == 0) {
             EXPECT_TRUE(false) << "Wait on Input/Output is found indefinite";
             break;
@@ -1245,8 +1248,8 @@
 
     // Configure output port
     uint32_t nBitRate = 512000;
-    setDefaultPortParam(omxNode, kPortIndexOutput, eCompressionFormat, nBitRate,
-                        xFramerate);
+    setDefaultPortParam(omxNode, kPortIndexOutput, eCompressionFormat,
+                        nFrameWidth, nFrameHeight, nBitRate, xFramerate);
     setRefreshPeriod(omxNode, kPortIndexOutput, 0);
 
     unsigned int index;
@@ -1330,6 +1333,11 @@
     setupRAWPort(omxNode, kPortIndexInput, nFrameWidth, nFrameHeight, 0,
                  xFramerate, eColorFormat);
 
+    // Configure output port
+    uint32_t nBitRate = 512000;
+    setDefaultPortParam(omxNode, kPortIndexOutput, eCompressionFormat,
+                        nFrameWidth, nFrameHeight, nBitRate, xFramerate);
+
     // CreateInputSurface
     EXPECT_TRUE(omx->createInputSurface(
                        [&](android::hardware::media::omx::V1_0::Status _s,
diff --git a/media/omx/1.0/vts/functional/video/media_video_hidl_test_common.h b/media/omx/1.0/vts/functional/video/media_video_hidl_test_common.h
index c1d7aea..55de125 100644
--- a/media/omx/1.0/vts/functional/video/media_video_hidl_test_common.h
+++ b/media/omx/1.0/vts/functional/video/media_video_hidl_test_common.h
@@ -18,14 +18,8 @@
 #define MEDIA_VIDEO_HIDL_TEST_COMMON_H
 
 /*
- * Random Index used for monkey testing while get/set parameters
- */
-#define RANDOM_INDEX 1729
-
-/*
  * Common video utils
  */
-
 void enumerateProfileAndLevel(sp<IOmxNode> omxNode, OMX_U32 portIndex,
                               std::vector<int32_t>* arrProfile,
                               std::vector<int32_t>* arrLevel);
diff --git a/media/res/bbb_aac_stereo_128kbps_48000hz.aac b/media/res/bbb_aac_stereo_128kbps_48000hz.aac
old mode 100755
new mode 100644
Binary files differ
diff --git a/media/res/bbb_aac_stereo_128kbps_48000hz.info b/media/res/bbb_aac_stereo_128kbps_48000hz.info
old mode 100755
new mode 100644
diff --git a/media/res/bbb_amrwb_1ch_14kbps_16000hz.amrwb b/media/res/bbb_amrwb_1ch_14kbps_16000hz.amrwb
old mode 100755
new mode 100644
Binary files differ
diff --git a/media/res/bbb_amrwb_1ch_14kbps_16000hz.info b/media/res/bbb_amrwb_1ch_14kbps_16000hz.info
old mode 100755
new mode 100644
diff --git a/media/res/bbb_g711alaw_1ch_8khz.info b/media/res/bbb_g711alaw_1ch_8khz.info
old mode 100755
new mode 100644
diff --git a/media/res/bbb_g711alaw_1ch_8khz.raw b/media/res/bbb_g711alaw_1ch_8khz.raw
old mode 100755
new mode 100644
diff --git a/media/res/bbb_g711mulaw_1ch_8khz.info b/media/res/bbb_g711mulaw_1ch_8khz.info
old mode 100755
new mode 100644
diff --git a/media/res/bbb_g711mulaw_1ch_8khz.raw b/media/res/bbb_g711mulaw_1ch_8khz.raw
old mode 100755
new mode 100644
diff --git a/media/res/bbb_gsm_1ch_8khz_13kbps.info b/media/res/bbb_gsm_1ch_8khz_13kbps.info
old mode 100755
new mode 100644
diff --git a/media/res/bbb_gsm_1ch_8khz_13kbps.raw b/media/res/bbb_gsm_1ch_8khz_13kbps.raw
old mode 100755
new mode 100644
Binary files differ
diff --git a/media/res/bbb_opus_stereo_128kbps_48000hz.info b/media/res/bbb_opus_stereo_128kbps_48000hz.info
old mode 100755
new mode 100644
diff --git a/media/res/bbb_opus_stereo_128kbps_48000hz.opus b/media/res/bbb_opus_stereo_128kbps_48000hz.opus
old mode 100755
new mode 100644
Binary files differ
diff --git a/media/res/bbb_raw_1ch_8khz_s32le.info b/media/res/bbb_raw_1ch_8khz_s32le.info
old mode 100755
new mode 100644
diff --git a/media/res/bbb_raw_1ch_8khz_s32le.raw b/media/res/bbb_raw_1ch_8khz_s32le.raw
old mode 100755
new mode 100644
Binary files differ
diff --git a/media/res/bbb_vorbis_stereo_128kbps_48000hz.info b/media/res/bbb_vorbis_stereo_128kbps_48000hz.info
old mode 100755
new mode 100644
diff --git a/media/res/bbb_vorbis_stereo_128kbps_48000hz.vorbis b/media/res/bbb_vorbis_stereo_128kbps_48000hz.vorbis
old mode 100755
new mode 100644
Binary files differ
diff --git a/memtrack/1.0/Android.bp b/memtrack/1.0/Android.bp
index 6f6e16d..4df2c1d 100644
--- a/memtrack/1.0/Android.bp
+++ b/memtrack/1.0/Android.bp
@@ -39,13 +39,16 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.memtrack@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.memtrack@1.0_genc++"],
     generated_headers: ["android.hardware.memtrack@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.memtrack@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/memtrack/1.0/vts/functional/Android.bp b/memtrack/1.0/vts/functional/Android.bp
index 71e6111..2d833e7 100644
--- a/memtrack/1.0/vts/functional/Android.bp
+++ b/memtrack/1.0/vts/functional/Android.bp
@@ -16,20 +16,7 @@
 
 cc_test {
     name: "VtsHalMemtrackV1_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalMemtrackV1_0TargetTest.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhardware",
-        "libhidlbase",
-        "libutils",
-        "android.hardware.memtrack@1.0",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ]
+    static_libs: ["android.hardware.memtrack@1.0"],
 }
diff --git a/minijail/Android.mk b/minijail/Android.mk
new file mode 100644
index 0000000..272bb0e
--- /dev/null
+++ b/minijail/Android.mk
@@ -0,0 +1,14 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := libhwminijail
+LOCAL_PROPRIETARY_MODULE := true
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
+LOCAL_SRC_FILES := HardwareMinijail.cpp
+
+LOCAL_SHARED_LIBRARIES := \
+    libbase \
+    libminijail_vendor
+
+include $(BUILD_SHARED_LIBRARY)
diff --git a/minijail/HardwareMinijail.cpp b/minijail/HardwareMinijail.cpp
new file mode 100644
index 0000000..e6b1144
--- /dev/null
+++ b/minijail/HardwareMinijail.cpp
@@ -0,0 +1,45 @@
+//
+// 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.
+//
+
+#include <android-base/logging.h>
+#include <libminijail.h>
+
+#include <hwminijail/HardwareMinijail.h>
+
+namespace android {
+namespace hardware {
+
+void SetupMinijail(const std::string& seccomp_policy_path) {
+    if (access(seccomp_policy_path.c_str(), R_OK) == -1) {
+        LOG(WARNING) << "Could not find seccomp policy file at: " << seccomp_policy_path;
+        return;
+    }
+
+    struct minijail* jail = minijail_new();
+    if (jail == NULL) {
+        LOG(FATAL) << "Failed to create minijail.";
+    }
+
+    minijail_no_new_privs(jail);
+    minijail_log_seccomp_filter_failures(jail);
+    minijail_use_seccomp_filter(jail);
+    minijail_parse_seccomp_filters(jail, seccomp_policy_path.c_str());
+    minijail_enter(jail);
+    minijail_destroy(jail);
+}
+
+}  // namespace hardware
+}  // namespace android
diff --git a/minijail/include/hwminijail/HardwareMinijail.h b/minijail/include/hwminijail/HardwareMinijail.h
new file mode 100644
index 0000000..8fcf007
--- /dev/null
+++ b/minijail/include/hwminijail/HardwareMinijail.h
@@ -0,0 +1,30 @@
+//
+// 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.
+//
+
+#ifndef ANDROID_HARDWARE_CONFIGSTORE_MINIJAIL_H
+#define ANDROID_HARDWARE_CONFIGSTORE_MINIJAIL_H
+
+#include <string>
+
+namespace android {
+namespace hardware {
+
+void SetupMinijail(const std::string& seccomp_policy_path);
+
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_CONFIGSTORE_UTILS_H
diff --git a/neuralnetworks/1.0/Android.bp b/neuralnetworks/1.0/Android.bp
new file mode 100644
index 0000000..d7c3bbb
--- /dev/null
+++ b/neuralnetworks/1.0/Android.bp
@@ -0,0 +1,80 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+filegroup {
+    name: "android.hardware.neuralnetworks@1.0_hal",
+    srcs: [
+        "types.hal",
+        "IDevice.hal",
+        "IEvent.hal",
+        "IPreparedModel.hal",
+    ],
+}
+
+genrule {
+    name: "android.hardware.neuralnetworks@1.0_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++-sources -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.neuralnetworks@1.0",
+    srcs: [
+        ":android.hardware.neuralnetworks@1.0_hal",
+    ],
+    out: [
+        "android/hardware/neuralnetworks/1.0/types.cpp",
+        "android/hardware/neuralnetworks/1.0/DeviceAll.cpp",
+        "android/hardware/neuralnetworks/1.0/EventAll.cpp",
+        "android/hardware/neuralnetworks/1.0/PreparedModelAll.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.neuralnetworks@1.0_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++-headers -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.neuralnetworks@1.0",
+    srcs: [
+        ":android.hardware.neuralnetworks@1.0_hal",
+    ],
+    out: [
+        "android/hardware/neuralnetworks/1.0/types.h",
+        "android/hardware/neuralnetworks/1.0/hwtypes.h",
+        "android/hardware/neuralnetworks/1.0/IDevice.h",
+        "android/hardware/neuralnetworks/1.0/IHwDevice.h",
+        "android/hardware/neuralnetworks/1.0/BnHwDevice.h",
+        "android/hardware/neuralnetworks/1.0/BpHwDevice.h",
+        "android/hardware/neuralnetworks/1.0/BsDevice.h",
+        "android/hardware/neuralnetworks/1.0/IEvent.h",
+        "android/hardware/neuralnetworks/1.0/IHwEvent.h",
+        "android/hardware/neuralnetworks/1.0/BnHwEvent.h",
+        "android/hardware/neuralnetworks/1.0/BpHwEvent.h",
+        "android/hardware/neuralnetworks/1.0/BsEvent.h",
+        "android/hardware/neuralnetworks/1.0/IPreparedModel.h",
+        "android/hardware/neuralnetworks/1.0/IHwPreparedModel.h",
+        "android/hardware/neuralnetworks/1.0/BnHwPreparedModel.h",
+        "android/hardware/neuralnetworks/1.0/BpHwPreparedModel.h",
+        "android/hardware/neuralnetworks/1.0/BsPreparedModel.h",
+    ],
+}
+
+cc_library {
+    name: "android.hardware.neuralnetworks@1.0",
+    defaults: ["hidl-module-defaults"],
+    generated_sources: ["android.hardware.neuralnetworks@1.0_genc++"],
+    generated_headers: ["android.hardware.neuralnetworks@1.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.neuralnetworks@1.0_genc++_headers"],
+    vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+    ],
+}
diff --git a/neuralnetworks/1.0/IDevice.hal b/neuralnetworks/1.0/IDevice.hal
new file mode 100644
index 0000000..b6f9433
--- /dev/null
+++ b/neuralnetworks/1.0/IDevice.hal
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ */
+
+/* This HAL is a work in progress */
+
+package android.hardware.neuralnetworks@1.0;
+
+import IEvent;
+import IPreparedModel;
+
+/**
+ * This interface represents a device driver.
+ */
+interface IDevice {
+    /**
+     * Gets the capabilities of a driver.
+     *
+     * @return status ErrorStatus::NONE if successful.
+     * @return capabilities Capabilities of the driver.
+     */
+    getCapabilities() generates (ErrorStatus status, Capabilities capabilities);
+
+    /**
+     * Gets the supported operations in a model.
+     *
+     * getSupportedSubgraph provides a more nuanced indication on whether a
+     * model is able to be compiled by the driver. Having the entire model
+     * allows for additional information such as tensor shapes to inputs or
+     * tensor strides, information which is not known in "initialize".
+     *
+     * @param model A model whose operations--and their corresponding
+     *              operands--are to be verified by the driver.
+     * @return status ErrorStatus::NONE if successful.
+     * @return supportedOperations A list of supported operations, where true
+     *                             indicates the operation is supported and
+     *                             false indicates the operation is not
+     *                             supported. The index of "supported"
+     *                             corresponds with the index of the operation
+     *                             it is describing.
+     */
+    getSupportedOperations(Model model)
+            generates (ErrorStatus status, vec<bool> supportedOperations);
+
+    /**
+     * Prepares a model for execution.
+     *
+     * prepareModel is used to make any necessary transformations or alternative
+     * representations to a model for execution, possible including
+     * transformations on the constant data, optimization on the model's graph,
+     * or compilation into the device's native binary.
+     *
+     * The only information that may be unknown to the model at this stage is
+     * the shape of the tensors, which may only be known at execution time.
+     *
+     * @param model The model to be prepared for execution.
+     * @param event A synchronization callback that must be signaled once the
+     *              execution has finished.
+     * @return status ErrorStatus::NONE if successful.
+     * @return preparedModel A handle to the resultant prepared model.
+     */
+    prepareModel(Model model, IEvent event)
+            generates (ErrorStatus status, IPreparedModel preparedModel);
+
+    /**
+     * Returns the current status of a driver.
+     *
+     * @return status Status of the driver.
+     */
+    getStatus() generates (DeviceStatus status);
+};
diff --git a/neuralnetworks/1.0/IEvent.hal b/neuralnetworks/1.0/IEvent.hal
new file mode 100644
index 0000000..2ebda58
--- /dev/null
+++ b/neuralnetworks/1.0/IEvent.hal
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+
+/* This HAL is a work in progress */
+
+package android.hardware.neuralnetworks@1.0;
+
+/**
+ * The IEvent interface is a callback object passed by the
+ * Neuralnetworks runtime to the vendor service. It is used as a
+ * synchronization primitive between one or more runtime threads and a
+ * single asynchronous vendor thread.  An event object is passed as an
+ * argument to a HIDL call that is expected to take a non-trivial
+ * amount of time. When the asynchronous execution thread has
+ * completed its computation, it must call "notify" on the event to
+ * indicate to the Neuralnetworks runtime whether the computation was
+ * successful or not, and that the corresponding output is ready to be
+ * consumed if the execution was successful.
+ */
+interface IEvent {
+
+    /**
+     * IEvent::notify is called by the server thread (i.e., the thread doing
+     * the work) to mark the event as completed so that any threads requiring
+     * the corresponding output can continue executing.
+     *
+     * @param status ErrorStatus::NONE if successful.
+     */
+    oneway notify(ErrorStatus status);
+};
diff --git a/neuralnetworks/1.0/IPreparedModel.hal b/neuralnetworks/1.0/IPreparedModel.hal
new file mode 100644
index 0000000..a7c3342
--- /dev/null
+++ b/neuralnetworks/1.0/IPreparedModel.hal
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+package android.hardware.neuralnetworks@1.0;
+
+import IEvent;
+
+/**
+ * IPreparedModel describes a model that has been prepared for execution and
+ * is used to launch executions.
+ */
+interface IPreparedModel {
+    /**
+     * Spawns an asynchronous execution on a prepared model.
+     *
+     * Executions are asynchronous with respect to the Neuralnetworks runtime.
+     * To support this, IPreparedModel::execute must spawn a new task and return
+     * whether the task was successfully launched. The asynchronous task which
+     * performs the execution must call event's IEvent::notify with the status
+     * of the execution immediately after the execution has finished.
+     *
+     * Multiple threads can call this execute function concurrently.
+     *
+     * @param request The input and output information on which the prepared
+     *                model is to be executed.
+     *                prepared model.
+     * @param event A callback used for synchronization that must be signaled
+     *              once the execution has finished.
+     * @return status ErrorStatus::NONE if the asynchronous task was
+     *                successfully launched.
+     */
+    execute(Request request, IEvent event) generates (ErrorStatus status);
+};
diff --git a/neuralnetworks/1.0/types.hal b/neuralnetworks/1.0/types.hal
new file mode 100644
index 0000000..39e3d34
--- /dev/null
+++ b/neuralnetworks/1.0/types.hal
@@ -0,0 +1,1272 @@
+/*
+ * 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.
+ */
+
+package android.hardware.neuralnetworks@1.0;
+
+/**
+ * Operand types.
+ *
+ * The type of an operand in a model.
+ *
+ * Types prefaced with TENSOR_* must be used for tensor data (i.e., tensors
+ * with at least one dimension). Types not prefaced by TENSOR_* represent
+ * scalar values and must have no dimensions.
+ */
+enum OperandType : int32_t {
+    /**
+     * The following entries are used to declare scalars.
+     */
+    FLOAT32             = 0,
+    INT32               = 1,
+    UINT32              = 2,
+
+    /**
+     * The following entries are used to declare tensors.
+     */
+    TENSOR_FLOAT32      = 3,
+    TENSOR_INT32        = 4,
+
+    /**
+     * A tensor of 8 bit integers that represent real numbers.
+     *
+     * Attached to this tensor are two numbers that can be used to convert the
+     * 8 bit integer to the real value and vice versa. These two numbers are:
+     * - scale: a 32 bit floating point value
+     * - zero_value: a 32 bit integer
+     *
+     * The formula is:
+     * real_value = (integer_value - zero_value) * scale.
+     */
+    TENSOR_QUANT8_ASYMM = 5,
+
+    /**
+     * The following entries are OEM specific operand types.
+     */
+    OEM                 = 10000,
+    TENSOR_OEM_BYTE     = 10001,
+};
+
+/**
+ * Operation types.
+ *
+ * The type of an operation in a model.
+ */
+enum OperationType : int32_t {
+    /**
+     * Adds two tensors, elment-wise.
+     *
+     * Takes two input tensors of identical type and compatible dimensions.  The output
+     * is the sum of both input tensors, optionally modified by an activation function.
+     *
+     * Two dimensions are compatible when:
+     *     1. they are equal, or
+     *     2. one of them is 1
+     *
+     * The size of the output is the maximum size along each dimension of the input operands.
+     * It starts with the trailing dimensions, and works its way forward.
+     *
+     * Example:
+     *     input1.dimension =    {4, 1, 2}
+     *     input2.dimension = {5, 4, 3, 1}
+     *     output.dimension = {5, 4, 3, 2}
+     *
+     * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+     * Supported tensor rank: up to 4
+     *
+     * Inputs:
+     * 0: A tensor.
+     * 1: A tensor of the same type, and compatible dimensions as input0.
+     * 2: An INT32 value, and has to be one of the {@link FusedActivationFunc} values.
+     *    Specifies the activation to invoke on the result of each addition.
+     *
+     * Ouputs:
+     * 0: The sum, a tensor of the same type as input0.
+     */
+    ADD = 0,
+
+    /**
+     * Performs a 2-D average pooling operation.
+     *
+     * The output dimensions are functions of the filter dimensions, stride, and padding.
+     *
+     * The values in output Tensor is computed as:
+     *     output[batch, row, col, channel] =
+     *         sum_{i, j}(input[batch, row + i, col + j, channel]) / sum(1)
+     *
+     * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+     *                         {@link OperandType::TENSOR_QUANT8_ASYMM}
+     * Supported tensor rank: 4, with "NHWC" data layout.
+     *
+     * Inputs:
+     * 0: A 4-D tensor, of shape [batches, height, width, depth], specifying the input.
+     * 1: An INT32 value, specifying the padding on the left, in the ‘width’ dimension.
+     * 2: An INT32 value, specifying the padding on the right,in the ‘width’ dimension.
+     * 3: An INT32 value, specifying the padding on the top, in the ‘height’ dimension.
+     * 4: An INT32 value, specifying the padding on the bottom, in the ‘height’ dimension.
+     * 5: An INT32 value, specifying the output stride in the ‘width’ dimension.
+     * 6: An INT32 value, specifying the output stride in the ‘height’ dimension.
+     * 7: An INT32 value, specifying the filter width.
+     * 8: An INT32 value, specifying the filter height.
+     * 9: An INT32 value, and has to be one of the {@link FusedActivationFunc} values.
+     *    Specifies the activation to invoke on the result of each addition.
+     *
+     * Ouputs:
+     * 0: The output 4-D tensor, of shape [batches, out_height, out_width, depth].
+     */
+    AVERAGE_POOL_2D = 1,
+
+    /**
+     * Concatenates the input tensors along the given dimension.
+     *
+     * The input tensors must have identical type and the same dimensions except the
+     * dimension along the concatenation axis.
+     *
+     * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+     *                         {@link OperandType::TENSOR_QUANT8_ASYMM}
+     * Supported tensor rank: up to 4
+     *
+     * Inputs:
+     * 0 ~ n: The list on n input tensors, of shape [D0, D1, ..., Daxis(i), ..., Dm]
+     * n+1: An INT32 value, specifying the concatenation axis.
+     * n+2: An INT32 value, and has to be one of the {@link FusedActivationFunc} values.
+     *    Specifies the activation to invoke on the result of each addition.
+     *
+     * Ouputs:
+     * 0: The output, a tensor of the same type as the input tensors.
+          The output shape is [D0, D1, ..., sum(Daxis(i)), ..., Dm].
+     */
+    CONCATENATION = 2,
+
+    /**
+     * Performs an 2-D convolution operation.
+     *
+     * The CONV_2D op sweeps a 2-D filter that can mix channels together over a batch of
+     * images, applying the filter to each window of each image of the appropriate size.
+     *
+     * The output dimensions are functions of the filter dimensions, stride, and padding.
+     *
+     * The values in output Tensor is computed as:
+     *     output[batch, row, col, channel] =
+     *         sum_{i, j} (
+     *             input[batch, row + i, col + j, k] *
+     *             filter[channel, row + i, col + j, k] +
+     *             bias[channel]
+     *         )
+     *
+     * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+     *                         {@link OperandType::TENSOR_QUANT8_ASYMM}
+     * Supported tensor rank: 4, with "NHWC" data layout.
+     *
+     * Inputs:
+     * 0: A 4-D tensor, of shape [batches, height, width, depth_in], specifying the input.
+     * 1: A 4-D tensor, of shape [depth_out, filter_height, filter_width, depth_in],
+     *    specifying the filter.
+     * 2: A 1-D tensor, of shape [depth_out], specifying the bias.
+     *    For input tensor of {@link OperandType::TENSOR_FLOAT32} type, the bias should
+     *    also be of {@link OperandType::TENSOR_FLOAT32}.
+     *    For input tensor of {@link OperandType::TENSOR_QUANT8_ASYMM} type, the bias
+     *    should be of {@link OperandType::TENSOR_INT32}.
+     * 3: An INT32 value, specifying the padding on the left, in the ‘width’ dimension.
+     * 4: An INT32 value, specifying the padding on the right,in the ‘width’ dimension.
+     * 5: An INT32 value, specifying the padding on the top, in the ‘height’ dimension.
+     * 6: An INT32 value, specifying the padding on the bottom, in the ‘height’ dimension.
+     * 7: An INT32 value, specifying the output stride in the ‘width’ dimension.
+     * 8: An INT32 value, specifying the output stride in the ‘height’ dimension.
+     * 9: An INT32 value, and has to be one of the {@link FusedActivationFunc} values.
+     *    Specifies the activation to invoke on the result of each addition.
+     *
+     * Ouputs:
+     * 0: The output 4-D tensor, of shape [batches, out_height, out_width, depth_out].
+     */
+    CONV_2D = 3,
+
+    /**
+     * Performs an depthwise 2-D convolution operation.
+     *
+     * Given an input tensor of shape [batches, height, width, depth_in] and a filter
+     * tensor of shape [depth_out, filter_height, filter_width, depth_in] containing
+     * in_channels convolutional filters of depth 1, DEPTHWISE_CONV applies a different
+     * filter to each input channel (expanding from 1 channel to channel_multiplier channels
+     * for each), then concatenates the results together.
+     *
+     * The output has depth_out = depth_in * depth_multiplier channels.
+     * The output dimensions are functions of the filter dimensions, stride, and padding.
+     *
+     * The values in output Tensor is computed as:
+     *     output[b, i, j, k * channel_multiplier + q] =
+     *         sum_{di, dj} (
+     *             input[b, strides[1] * i + di, strides[2] * j + dj, k] *
+     *             filter[di, dj, k, q]
+     *         )
+     *
+     * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+     *                         {@link OperandType::TENSOR_QUANT8_ASYMM}
+     * Supported tensor rank: 4, with "NHWC" data layout.
+     *
+     * Inputs:
+     * 0: A 4-D tensor, of shape [batches, height, width, depth_in], specifying the input.
+     * 1: A 4-D tensor, of shape [depth_out, filter_height, filter_width, depth_in],
+     *    specifying the filter.
+     * 2: A 1-D tensor, of shape [depth_out], specifying the bias.
+     *    For input tensor of {@link OperandType::TENSOR_FLOAT32} type, the bias should
+     *    also be of {@link OperandType::TENSOR_FLOAT32}.
+     *    For input tensor of {@link OperandType::TENSOR_QUANT8_ASYMM} type, the bias
+     *    should be of {@link OperandType::TENSOR_INT32}.
+     * 3: An INT32 value, specifying the padding on the left, in the ‘width’ dimension.
+     * 4: An INT32 value, specifying the padding on the right,in the ‘width’ dimension.
+     * 5: An INT32 value, specifying the padding on the top, in the ‘height’ dimension.
+     * 6: An INT32 value, specifying the padding on the bottom, in the ‘height’ dimension.
+     * 7: An INT32 value, specifying the output stride in the ‘width’ dimension.
+     * 8: An INT32 value, specifying the output stride in the ‘height’ dimension.
+     * 9: An INT32 value, specifying the depthwise multiplier.
+     * 10: An INT32 value, and has to be one of the {@link FusedActivationFunc} values.
+     *    Specifies the activation to invoke on the result of each addition.
+     *
+     * Ouputs:
+     * 0: The output 4-D tensor, of shape [batches, out_height, out_width, depth_out].
+     */
+    DEPTHWISE_CONV_2D = 4,
+
+    /**
+     * Rearranges data from depth into blocks of spatial data.
+     *
+     * More specifically, this op outputs a copy of the input tensor where values from
+     * the depth dimension are moved in spatial blocks to the height and width dimensions.
+     * The value block_size indicates the input block size and how the data is moved.
+     *
+     * Chunks of data of size block_size * block_size from depth are rearranged into
+     * non-overlapping blocks of size block_size x block_size.
+     *
+     * The width of the output tensor is input_depth * block_size, whereas the height is
+     * input_height * block_size.
+     * The depth of the input tensor must be divisible by block_size * block_size
+     *
+     * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+     *                         {@link OperandType::TENSOR_QUANT8_ASYMM}
+     * Supported tensor rank: 4, with "NHWC" data layout.
+     *
+     * Inputs:
+     * 0: A 4-D tensor, of shape [batches, height, width, depth_in], specifying the input.
+     * 1: An INT32 value, specifying the block_size. block_size must be >=1 and
+     *    block_size * block_size must be a divisor of the input depth.
+     *
+     * Ouputs:
+     * 0: The output 4-D tensor, of shape [batch, height*block_size, width*block_size,
+     *    depth/(block_size*block_size)].
+     */
+    DEPTH_TO_SPACE = 5,
+
+    /**
+     * Dequantizes the input tensor.
+     *
+     * The formula is:
+     *     output = (input - zero_value) * scale.
+     *
+     * Supported tensor types: {@link OperandType::TENSOR_QUANT8_ASYMM}
+     * Supported tensor rank: up to 4
+     *
+     * Inputs:
+     * 0: A tensor of type {@link OperandType::TENSOR_QUANT8_ASYMM}.
+     *
+     * Ouputs:
+     * 0: The output tensor of same shape as input0, but with type
+          {@link OperandType::TENSOR_FLOAT32}.
+     */
+    DEQUANTIZE = 6,
+
+    /**
+     * Looks up items from a given tensor.
+     *
+     * Each item in the output is a raw copy of the corresponding item in
+     * the input “values”. If the the given “lookup” indices are out of bounds,
+     * the op will fail and an error will be reported.
+     *
+     * Inputs:
+     * * 0: Values. An n-D tensor of any type X (where n >= 2). E.g., if n is 2,
+     *      then the shape would be [lookup_dimension, values_dimension], where
+     *      “lookup_dimension” corresponds to the indexing dimension in the lookup
+     *      table, and “values_dimension” to the contents.
+     * * 1: Lookups. An 1-D tensor of type T, of shape [lookup_size], where
+     *      “lookup_size” is the number of elements to look for, and each entry
+     *      corresponds to the first dimension of the “values” tensor.
+     *
+     * Output:
+     * * 0: A n-D tensor of type X and the same rank and shape as the “values”
+     *      tensor, except for the first dimension which has size “lookup_size”.
+     */
+    EMBEDDING_LOOKUP = 7,
+
+    /**
+     * Computes element-wise floor() on the input tensor.
+     *
+     * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+     * Supported tensor rank: up to 4
+     *
+     * Inputs:
+     * 0: A tensor.
+     *
+     * Ouputs:
+     * 0: The output, a tensor of the same type and dimensions as input0.
+     */
+    FLOOR = 8,
+
+    /**
+     * Denotes a fully (densely) connected layer, which connects all elements in the input
+     * tensor with each element in the output tensor.
+     *
+     * This layer implements the operation:
+     *     outputs = activation(inputs * weights’ + bias)
+     *
+     * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+     *                         {@link OperandType::TENSOR_QUANT8_ASYMM}
+     * Supported tensor rank: up to 4.
+     *
+     * Inputs:
+     * 0: A tensor, specifying the input. If rank is greater than 2, then it gets flattened to
+     *    a 2-D Tensor. The 2-D Tensor is handled as if dimensions corresponded to shape
+     *    [batch_size, input_size], where “batch_size” corresponds to the batching dimension,
+     *    and “input_size” is the size of the input.
+     * 1: A 2-D tensor, specifying the weights, of shape [num_units, input_size], where “num_units”
+     *    corresponds to the number of output nodes.
+     * 2: A 1-D tensor, of shape [num_units], specifying the bias.
+     *    For input tensor of {@link OperandType::TENSOR_FLOAT32} type, the bias should
+     *    also be of {@link OperandType::TENSOR_FLOAT32}.
+     *    For input tensor of {@link OperandType::TENSOR_QUANT8_ASYMM} type, the bias
+     *    should be of {@link OperandType::TENSOR_INT32}.
+     * 3: An INT32 value, and has to be one of the {@link FusedActivationFunc} values.
+     *    Specifies the activation to invoke on the result of each addition.
+     *
+     * Ouputs:
+     * 0: The output tensor, of shape [batch_size, num_units].
+     */
+    FULLY_CONNECTED = 9,
+
+    /**
+     * Looks up values of a hash table with given keys.
+     *
+     * Inputs:
+     * * 0: Lookups. A 1-D int32 tensor with shape [ k ].
+     * * 1: Keys. A 1-D int32 tensor with shape [ n ], *MUST* be sorted in
+     *      ascending order.
+     * * 2: Values. A tensor with shape [ n … ].
+     *
+     * Outputs:
+     * * 0: Output. A tensor with shape [ k …].
+     * * 1: Hits. A uint8 tensor with shape [ k ] indicates whether the lookup
+     *      hits or not.
+     */
+    HASHTABLE_LOOKUP = 10,
+
+    /**
+     * Applies L2 normalization along a the depth dimension.
+     *
+     * The values in output Tensor is computed as:
+     *     output[batch, row, col, channel] =
+     *         input[batch, row, col, channel] /
+     *         sqrt(sum_{c} pow(input[batch, row, col, c], 2))
+     *
+     * For x with more dimensions, independently normalizes each 1-D slice along dimension dim.
+     *
+     * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+     * Supported tensor rank: 4, with "NHWC" data layout.
+     *
+     * Inputs:
+     * 0: A 4-D tensor, of shape [batches, height, width, depth], specifying the input.
+     *
+     * Ouputs:
+     * 0: The output 4-D tensor, of shape [batches, out_height, out_width, depth].
+     */
+    L2_NORMALIZATION = 11,
+
+    /**
+     * Performs an 2-D L2 pooling operation.
+     *
+     * The output dimensions are functions of the filter dimensions, stride, and padding.
+     *
+     * The values in output Tensor is computed as:
+     *     output[batch, row, col, channel] =
+     *         sqrt(sum_{i, j} pow(input[batch, row + i, col + j, channel], 2) / sum(1))
+     *
+     * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+     * Supported tensor rank: 4, with "NHWC" data layout.
+     *
+     * Inputs:
+     * 0: A 4-D tensor, of shape [batches, height, width, depth], specifying the input.
+     * 1: An INT32 value, specifying the padding on the left, in the ‘width’ dimension.
+     * 2: An INT32 value, specifying the padding on the right,in the ‘width’ dimension.
+     * 3: An INT32 value, specifying the padding on the top, in the ‘height’ dimension.
+     * 4: An INT32 value, specifying the padding on the bottom, in the ‘height’ dimension.
+     * 5: An INT32 value, specifying the output stride in the ‘width’ dimension.
+     * 6: An INT32 value, specifying the output stride in the ‘height’ dimension.
+     * 7: An INT32 value, specifying the filter width.
+     * 8: An INT32 value, specifying the filter height.
+     * 9: An INT32 value, and has to be one of the {@link FusedActivationFunc} values.
+     *    Specifies the activation to invoke on the result of each addition.
+     *
+     * Ouputs:
+     * 0: The output 4-D tensor, of shape [batches, out_height, out_width, depth].
+     */
+    L2_POOL_2D = 12,
+
+    /**
+     * Applies Local Response Normalization along the depth dimension.
+     *
+     * The 4-D input tensor is treated as a 3-D array of 1-D vectors (along the last
+     * dimension), and each vector is normalized independently. Within a given vector,
+     * each component is divided by the weighted, squared sum of inputs within depth_radius.
+     *
+     * In details:
+     *     sqr_sum[a, b, c, d] =
+     *         sum(pow(input[a, b, c, d - depth_radius : d + depth_radius + 1], 2)
+     *     output = input / pow((bias + alpha * sqr_sum), beta)
+     *
+     * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+     * Supported tensor rank: 4, with "NHWC" data layout.
+     *
+     * Inputs:
+     * 0: A 4-D tensor, of shape [batches, height, width, depth], specifying the input.
+     * 1: An INT32 value, specifying the radius of the normalization window.
+     * 2: A FLOAT32 value, specifying the bias, must not be zero.
+     * 3: A FLOAT32 value, specifying the scale factor, alpha.
+     * 4: A FLOAT32 value, specifying the exponent, beta.
+     *
+     * Ouputs:
+     * 0: The output tensor of same shape as input0.
+     */
+    LOCAL_RESPONSE_NORMALIZATION = 13,
+
+    /**
+     * Computes sigmoid activation on the input tensor element-wise.
+     *
+     * In details:
+     *     output = 1 / (1 + exp(-input))
+     *
+     * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+     *                         {@link OperandType::TENSOR_QUANT8_ASYMM}
+     * Supported tensor rank: up to 4.
+     *
+     * Inputs:
+     * 0: A tensor, specifying the input.
+     *
+     * Ouputs:
+     * 0: The output tensor of same shape as input0.
+     */
+    LOGISTIC = 14,
+
+    /**
+     * Projects an input to a bit vector via locality senstive hashing.
+     *
+     * Inputs:
+     * * 0: Hash functions. Dim.size == 2, DataType: Float.
+     *            Tensor[0].Dim[0]: Number of hash functions.
+     *            Tensor[0].Dim[1]: Number of seeds per hash functions.
+     *            Tensor[0].Dim[1] <= 32 in sparse case.
+     *
+     * * 1: Input. Dim.size >= 1, no restriction on DataType.
+     * * 2: Weight. Optional. Dim.size == 1, DataType: Float.
+     *     If not set, each input element is considered to have the same weight of
+     *     1.0.
+     *     Tensor[1].Dim[0] == Tensor[2].Dim[0]
+     * * 3: Type:
+     *        Sparse: Value LSHProjectionType_SPARSE(=1).
+     *          Computed bit vector is considered to be sparse.
+     *          Each output element is an int32 made up of multiple bits computed from
+     *          hash functions.
+     *
+     *        Dense: Value LSHProjectionType_DENSE(=2).
+     *          Computed bit vector is considered to be dense. Each output element
+     *          represents a bit and can take the value of either 0 or 1.
+     *
+     * Outputs:
+     * * 0: If the projection type is sparse:
+     *        Output.Dim == { Tensor[0].Dim[0] }
+     *        A tensor of int32 that represents hash signatures.
+     *      If the projection type is Dense:
+     *        Output.Dim == { Tensor[0].Dim[0] * Tensor[0].Dim[1] }
+     *        A flattened tensor that represents projected bit vectors.
+     */
+    LSH_PROJECTION = 15,
+
+    /**
+     * Long short-term memory unit (LSTM) recurrent network layer.
+     *
+     * The default non-peephole implementation is based on:
+     * http://deeplearning.cs.cmu.edu/pdfs/Hochreiter97_lstm.pdf
+     * S. Hochreiter and J. Schmidhuber. "Long Short-Term Memory". Neural
+     * Computation, 9(8):1735-1780, 1997.
+     *
+     * The peephole implementation is based on:
+     * https://research.google.com/pubs/archive/43905.pdf
+     * Hasim Sak, Andrew Senior, and Francoise Beaufays. "Long short-term memory
+     * recurrent neural network architectures for large scale acoustic modeling."
+     * INTERSPEECH, 2014.
+     *
+     * The coupling of input and forget gate (CIFG) is based on:
+     * http://arxiv.org/pdf/1503.04069.pdf
+     * Greff et al. "LSTM: A Search Space Odyssey"
+     *
+     * The class has the following independently optional inputs:
+     * * If input gate (if CIFG): “input_to_forget_weights”,
+     *   “recurrent_to_input_weights”, “cell_to_input_weights”, “input_gate_bias”.
+     * * If no peephole connections: “cell_to_input_weights”,
+     *   “cell_to_forget_weights”, “cell_to_output_weights”.
+     * * If no projection layer: “projection_weights” and “projection_bias”.
+     * * If no projection bias: “projection_bias”.
+     *
+     * Supported tensor types:
+     * * {@link OperandType::TENSOR_FLOAT32}
+     *
+     * Inputs:
+     * * 0: Input.
+     *      A 2-D tensor of type T, of shape [batch_size, input_size], where
+     *      “batch_size” corresponds to the batching dimension, and “input_size”
+     *      is the size of the input.
+     * * 1: input_to_input_weights.
+     *      A 2-D tensor of type T, of shape [num_units, input_size], where
+     *      “num_units” corresponds to the number of cell units.
+     * * 2: input_to_forget_weights.
+     *      A 2-D tensor of type T, of shape [num_units, input_size].
+     * * 3: input_to_cell_weights.
+     *      A 2-D tensor of type T, of shape [num_units, input_size].
+     * * 4: input_to_output_weights.
+     *      A 2-D tensor of type T, of shape [num_units, input_size].
+     * * 5: recurrent_to_input_weights.
+     *      A 2-D tensor of type T, of shape [num_units, output_size], where
+     *      “output_size” corresponds to either the number of cell units (i.e.,
+     *      “num_units”), or the second dimension of the “projection_weights”, if
+     *      defined.
+     * * 6: recurrent_to_forget_weights.
+     *      A 2-D tensor of type T, of shape [num_units, output_size].
+     * * 7: recurrent_to_cell_weights.
+     *      A 2-D tensor of type T, of shape [num_units, output_size].
+     * * 8: recurrent_to_output_weights.
+     *      A 2-D tensor of type T, of shape [num_units, output_size].
+     * * 9: cell_to_input_weights.
+     *      A 1-D tensor of type T, of shape [num_units].
+     * * 10:cell_to_forget_weights.
+     *      A 1-D tensor of type T, of shape [num_units].
+     * * 11:cell_to_output_weights.
+     *      A 1-D tensor of type T, of shape [num_units].
+     * * 12:input_gate_bias.
+     *      A 1-D tensor of type T, of shape [num_units].
+     * * 13:forget_gate_bias.
+     *      A 1-D tensor of type T, of shape [num_units].
+     * * 14:cell_bias.
+     *      A 1-D tensor of type T, of shape [num_units].
+     * * 15:output_gate_bias.
+     *      A 1-D tensor of type T, of shape [num_units].
+     * * 16:projection_weights.
+     *      A 2-D tensor of type T, of shape [output_size, num_units].
+     * * 17:projection_bias.
+     *      A 1-D tensor of type T, of shape [output_size].
+     *
+     * Parameters:
+     * * 18:fused_activation_function.
+     *      An (optional) ActivationFunctionType indicating the activation
+     *      function.
+     *      If “NONE” is specified then it results in a linear activation.
+     * * 19:cell_clip.
+     *      A clipping threshold for the cell state, such that values are bound
+     *      within [-cell_clip, cell_clip]. If set to 0.0 then clipping is
+     *      disabled.
+     * * 20:proj_clip.
+     *      A clipping threshold for the output from the projection layer, such
+     *      that values are bound within [-proj_clip, proj_clip]. If set to 0.0
+     *      then clipping is disabled.
+     *
+     * Outputs:
+     * * 0: scratch_buffer.
+     *      A 3-D tensor of type T, of shape [batch_size, num_cell, 4].
+     * * 1: output_state.
+     *      A 2-D tensor of type T, of shape [batch_size, output_size].
+     * * 2: cell_state.
+     *      A 2-D tensor of type T, of shape [batch_size, num_units].
+     * * 3: output.
+     *      A 2-D tensor of type T, of shape [batch_size, output_size]. This is
+     *      effectively the same as the current “output_state” value.
+     */
+    LSTM = 16,
+
+    /**
+     * Performs an 2-D max pooling operation.
+     *
+     * The output dimensions are functions of the filter dimensions, stride, and padding.
+     *
+     * The values in output Tensor is computed as:
+     *     output[batch, row, col, channel] =
+     *         max_{i, j} (input[batch, row + i, col + j, channel])
+     *
+     * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+     *                         {@link OperandType::TENSOR_QUANT8_ASYMM}
+     * Supported tensor rank: 4, with "NHWC" data layout.
+     *
+     * Inputs:
+     * 0: A 4-D tensor, of shape [batches, height, width, depth], specifying the input.
+     * 1: An INT32 value, specifying the padding on the left, in the ‘width’ dimension.
+     * 2: An INT32 value, specifying the padding on the right,in the ‘width’ dimension.
+     * 3: An INT32 value, specifying the padding on the top, in the ‘height’ dimension.
+     * 4: An INT32 value, specifying the padding on the bottom, in the ‘height’ dimension.
+     * 5: An INT32 value, specifying the output stride in the ‘width’ dimension.
+     * 6: An INT32 value, specifying the output stride in the ‘height’ dimension.
+     * 7: An INT32 value, specifying the filter width.
+     * 8: An INT32 value, specifying the filter height.
+     * 9: An INT32 value, and has to be one of the {@link FusedActivationFunc} values.
+     *    Specifies the activation to invoke on the result of each addition.
+     *
+     * Ouputs:
+     * 0: The output 4-D tensor, of shape [batches, out_height, out_width, depth].
+     */
+    MAX_POOL_2D = 17,
+
+    /**
+     * Multiplies two tensors, elment-wise.
+     *
+     * Takes two input tensors of identical type and compatible dimensions.  The output
+     * is the product of both input tensors, optionally modified by an activation function.
+     *
+     * Two dimensions are compatible when:
+     *     1. they are equal, or
+     *     2. one of them is 1
+     *
+     * The size of the resulting output is the maximum size along each dimension of the
+     * input operands. It starts with the trailing dimensions, and works its way forward.
+     *
+     * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+     * Supported tensor rank: up to 4
+     *
+     * Inputs:
+     * 0: A tensor.
+     * 1: A tensor of the same type, and compatible dimensions as input0.
+     * 2: An INT32 value, and has to be one of the {@link FusedActivationFunc} values.
+     *    Specifies the activation to invoke on the result of each addition.
+     *
+     * Ouputs:
+     * 0: The product, a tensor of the same type as input0.
+     */
+    MUL = 18,
+
+    /**
+     * Computes rectified linear activation on the input tensor element-wise.
+     *
+     * In details:
+     *     output = max(0, input)
+     *
+     * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+     *                         {@link OperandType::TENSOR_QUANT8_ASYMM}
+     * Supported tensor rank: up to 4.
+     *
+     * Inputs:
+     * 0: A tensor, specifying the input.
+     *
+     * Ouputs:
+     * 0: The output tensor of same shape as input0.
+     */
+    RELU = 19,
+
+    /**
+     * Computes rectified linear 1 activation on the input tensor element-wise.
+     *
+     * In details:
+     *     output = min(1.f, max(-1.f, input))
+     *
+     * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+     *                         {@link OperandType::TENSOR_QUANT8_ASYMM}
+     * Supported tensor rank: up to 4.
+     *
+     * Inputs:
+     * 0: A tensor, specifying the input.
+     *
+     * Ouputs:
+     * 0: The output tensor of same shape as input0.
+     */
+    RELU1 = 20,
+
+    /**
+     * Computes rectified linear 6 activation on the input tensor element-wise.
+     *
+     * In details:
+     *     output = min(6, max(0, input))
+     *
+     * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+     *                         {@link OperandType::TENSOR_QUANT8_ASYMM}
+     * Supported tensor rank: up to 4.
+     *
+     * Inputs:
+     * 0: A tensor, specifying the input.
+     *
+     * Ouputs:
+     * 0: The output tensor of same shape as input0.
+     */
+    RELU6 = 21,
+
+    /**
+     * Reshapes a tensor.
+     *
+     * Given tensor, this operation returns a tensor that has the same values as tensor,
+     * but with a newly specified shape.
+     *
+     * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+     *                         {@link OperandType::TENSOR_QUANT8_ASYMM}
+     * Supported tensor rank: up to 4.
+     *
+     * Inputs:
+     * 0: A tensor, specifying the tensor to be reshaped.
+     * 1: A 1-D tensor of type {@link OperandType::TENSOR_INT32}, defining the shape
+     *    of the output tensor. The number of elements implied by shape must be the same
+     *    as the number of elements in the input tensor.
+     *
+     * Ouputs:
+     * 0: The output tensor, of shape specified by the input shape.
+     */
+    RESHAPE = 22,
+
+    /**
+     * Resizes images to given size using the bilinear interpretation.
+     *
+     * Resized images will be distorted if their original aspect ratio is not the same as input.
+     *
+     * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+     * Supported tensor rank: 4, with "NHWC" data layout.
+     *
+     * Inputs:
+     * 0: A 4-D tensor, of shape [batches, height, width, depth], specifying the input.
+     * 1: An INT32 value, specifying the output width of the output tensor.
+     * 2: An INT32 value, specifying the output height of the output tensor.
+     *
+     * Ouputs:
+     * 0: The output 4-D tensor, of shape [batches, new_height, new_width, depth].
+     */
+    RESIZE_BILINEAR = 23,
+
+    /**
+     * A basic recurrent neural network layer.
+     *
+     * This layer implements the operation:
+     * outputs = state = activation(inputs * input_weights + state * recurrent_weights + bias)
+     *
+     * Where:
+     * * “input_weights” is a weight matrix that multiplies the inputs;
+     * * “recurrent_weights” is a weight matrix that multiplies the current
+     *    “state” which itself is the output from the previous time step
+     *    computation;
+     * * “bias” is a bias vector (added to each output vector in the batch);
+     * * “activation” is the function passed as the “fused_activation_function”
+     *   argument (if not “NONE”).
+     *
+     * Supported tensor types:
+     * * {@link OperandType::TENSOR_FLOAT32}
+     *
+     * Inputs:
+     * * 0: input.
+     *      A 2-D tensor of type T, of shape [batch_size, input_size], where
+     *      “batch_size” corresponds to the batching dimension, and “input_size” is
+     *      the size of the input.
+     * * 1: weights.
+     *      A 2-D tensor of type T, of shape [num_units, input_size], where
+     *      “num_units” corresponds to the number of units.
+     * * 2: recurrent_weights.
+     *      A 2-D tensor of type T, of shape [num_units, num_units], with columns
+     *      corresponding to the weights from each unit.
+     * * 3: bias.
+     *      A 1-D tensor of type T, of shape [num_units].
+     *
+     *    For FLOAT32 input tensor, bias must also be FLOAT32.
+     *    For UINT8 input tensor, bias must be INT32.
+     *
+     * Parameters
+     * * 4: fused_activation_function.
+     *      An (optional) ActivationFunctionType indicating the activation
+     *      function. If “NONE” is specified then it results in a linear
+     *      activation.
+     *
+     * * 5: Hidden state.
+     *      A 2-D tensor of type T, of shape [batch_size, num_units].
+     *
+     * Outputs:
+     * * 0: output.
+     *      A 2-D tensor of type T, of shape [batch_size, num_units]. This is
+     *      effectively the same as the current state value.
+     */
+    RNN = 24,
+
+    /**
+     * Computes the softmax activation on the input tensor element-wise, per batch, by
+     * normalizing the input vector so the maximum coefficient is zero.
+     *
+     * In details:
+     *     output[batch, i] =
+     *         exp((input[batch, i] - max(input[batch, :])) * beta) /
+     *         sum_{k}{exp((input[batch, k] - max(input[batch, :])) * beta)}
+     *
+     * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+     *                         {@link OperandType::TENSOR_QUANT8_ASYMM}
+     * Supported tensor rank: 2 or 4.
+     *
+     * Inputs:
+     * 0: A 2-D or 4-D tensor, specifying the tensor to be reshaped.
+     * 1: A FLOAT32 value, specifying the scaling factor for the exponent, beta.
+     *
+     * Ouputs:
+     * 0: The output tensor of same shape as input0.
+     */
+    SOFTMAX = 25,
+
+    /**
+     * Rearranges blocks of spatial data, into depth.
+     *
+     * More specifically, this op outputs a copy of the input tensor where values from
+     * the height and width dimensions are moved to the depth dimension.
+     * The value block_size indicates the input block size and how the data is moved.
+     *
+     * Chunks of data of size block_size * block_size from depth are rearranged into
+     * non-overlapping blocks of size block_size x block_size.
+     *
+     * The depth of the output tensor is input_depth * block_size * block_size.
+     * The input tensor's height and width must be divisible by block_size.
+     *
+     * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+     *                         {@link OperandType::TENSOR_QUANT8_ASYMM}
+     * Supported tensor rank: 4, with "NHWC" data layout.
+     *
+     * Inputs:
+     * 0: A 4-D tensor, of shape [batches, height, width, depth_in], specifying the input.
+     * 1: An INT32 value, specifying the block_size. block_size must be >=1 and
+     *    block_size must be a divisor of both the input height and width.
+     *
+     * Ouputs:
+     * 0: The output 4-D tensor, of shape [batch, height/block_size, width/block_size,
+     *    depth*block_size*block_size].
+     */
+    SPACE_TO_DEPTH = 26,
+
+    /**
+     * SVDF op is a kind of stateful layer derived from the notion that a
+     * densely connected layer that's processing a sequence of input frames can
+     * be approximated by using a singular value decomposition of each of its
+     * nodes. The implementation is based on:
+     *
+     * https://research.google.com/pubs/archive/43813.pdf
+     *
+     * P. Nakkiran, R. Alvarez, R. Prabhavalkar, C. Parada.
+     * “Compressing Deep Neural Networks using a Rank-Constrained Topology”.
+     * INTERSPEECH, 2015.
+     *
+     * It processes the incoming input using a 2-stage filtering mechanism:
+     * * stage 1 performs filtering on the "features" dimension, whose outputs get
+     *   pushed into a memory of fixed-size memory_size.
+     * * stage 2 performs filtering on the "time" dimension of the memory_size
+     *   memoized outputs of stage 1.
+     *
+     * Specifically, for rank 1, this layer implements the operation:
+     *
+     *    memory = push(conv1d(inputs, weights_feature, feature_dim, "VALID"));
+     *    outputs = activation(memory * weights_time + bias);
+     *
+     * Where:
+     * * “weights_feature” is a weights matrix that processes the inputs (by
+     *   convolving the input with every “feature filter”), and whose outputs get
+     *   pushed, stacked in order, into the fixed-size “memory” (the oldest entry
+     *   gets dropped);
+     * * “weights_time” is a weights matrix that processes the “memory” (by a
+     *   batched matrix multiplication on the num_units);
+     * * “bias” is an optional bias vector (added to each output vector in the
+     *   batch); and
+     * * “activation” is the function passed as the “fused_activation_function”
+     *   argument (if not “NONE”).
+     *
+     * Each rank adds a dimension to the weights matrices by means of stacking
+     * the filters.
+     *
+     * Supported tensor types:
+     * * {@link OperandType::TENSOR_FLOAT32}
+     *
+     * Inputs:
+     * * 0: input.
+     *      A 2-D tensor of type T, of shape [batch_size, input_size], where
+     *      “batch_size” corresponds to the batching dimension, and “input_size” is
+     *      the size of the input.
+     * * 1: weights_feature.
+     *      A 2-D tensor of type T, of shape [num_units, input_size], where
+     *      “num_units” corresponds to the number of units.
+     * * 2: weights_time.
+     *      A 2-D tensor of type T, of shape [num_units, memory_size], where
+     *      “memory_size” corresponds to the fixed-size of the memory.
+     * * 3: bias.
+     *      A optional 1-D tensor of type T, of shape [num_units].
+     *
+     *    For FLOAT32 input tensor, bias must also be FLOAT32.
+     *    For UINT8 input tensor, bias must be INT32.
+     *
+     * Parameters:
+     * * 4: rank.
+     *      The rank of the SVD approximation.
+     * * 5: fused_activation_function.
+     *      An (optional) ActivationFunctionType indicating the activation function.
+     *      If “NONE” is specified then it results in a linear activation.
+     *
+     * Outputs:
+     * * 0: state.
+     *      A 2-D tensor of type T, of shape [batch_size, (memory_size - 1) * num_units * rank].
+     * * 1: output.
+     *      A 2-D tensor of type T, of shape [batch_size, num_units].
+     */
+    SVDF = 27,
+
+    /**
+     * Computes hyperbolic tangent of input tensor element-wise.
+     *
+     * In details:
+     *     output = tanh(input)
+     *
+     * Supported tensor types: {@link OperandType::TENSOR_FLOAT32}
+     * Supported tensor rank: up to 4.
+     *
+     * Inputs:
+     * 0: A tensor, specifying the input.
+     *
+     * Ouputs:
+     * 0: The output tensor of same shape as input0.
+     */
+    TANH = 28,
+
+    /**
+     * OEM specific operation.
+     *
+     * This operation is OEM specific. It should only be used for OEM applications.
+     */
+    OEM_OPERATION = 10000,
+};
+
+/**
+ * Fused activation function types.
+ */
+enum FusedActivationFunc : int32_t {
+    NONE  = 0,
+    RELU  = 1,
+    RELU1 = 2,
+    RELU6 = 3,
+};
+
+/**
+ * How an operand is used.
+ */
+enum OperandLifeTime : int32_t {
+    /**
+     * The operand is internal to the model.  It's created by an operation
+     * and consumed by other operations.
+     */
+    TEMPORARY_VARIABLE,
+
+    /**
+     * The operand is an input of the model. An operand can't be both
+     * input and output of a model.
+     */
+    MODEL_INPUT,
+
+    /**
+     * The operand is an output of the model.
+     */
+    MODEL_OUTPUT,
+
+    /**
+     * The operand is a constant found in Model.operandValues.
+     */
+    CONSTANT_COPY,
+
+    /**
+     * The operand is a constant that was specified via a Memory object.
+     */
+    CONSTANT_REFERENCE,
+};
+
+/**
+ * Status of a device.
+ */
+enum DeviceStatus : int32_t {
+    AVAILABLE,
+    BUSY,
+    OFFLINE,
+    UNKNOWN,
+};
+
+/**
+ * A typed operation.
+ */
+struct OperationTuple {
+    /**
+     * The type of operation.
+     */
+    OperationType operationType;
+
+    /**
+     * The input data type of operation.
+     */
+    OperandType operandType;
+};
+
+/**
+ * Performance information for the reference workload.
+ *
+ * Used by a driver to report its performance characteristics.
+ */
+struct PerformanceInfo {
+    /**
+     * Execution time in nanoseconds.
+     */
+    float execTime;
+
+    /**
+     * Power usage in picoJoules.
+     */
+    float powerUsage;
+};
+
+/**
+ * The capabilities of a driver.
+ */
+struct Capabilities {
+    /**
+     * A collection of typed operations supported by the driver.
+     */
+    vec<OperationTuple> supportedOperationTuples;
+
+    /**
+     * Indicates whether a driver caches its prepared model for reuse the next
+     * time the application begins. This is useful because the model may have
+     * been prepared in a previous run.
+     *
+     * True if caching is supported, false otherwise.
+     */
+    bool cachesCompilation;
+
+    /**
+     * Driver performance when operating on float32 data.
+     */
+    PerformanceInfo float32Performance;
+
+    /**
+     * Driver performance when operating on asymmetric 8-bit quantized data.
+     */
+    PerformanceInfo quantized8Performance;
+};
+
+/**
+ * Describes the location of a data object.
+ */
+struct DataLocation {
+    /**
+     * The index of the memory pool where this location is found.
+     */
+    uint32_t poolIndex;
+
+    /**
+     * Offset in bytes from the start of the pool.
+     */
+    uint32_t offset;
+
+    /**
+     * The length of the data in bytes.
+     */
+    uint32_t length;
+};
+
+/**
+ * Describes one operand of the model's graph.
+ */
+struct Operand {
+    /**
+     * Data type of the operand.
+     */
+    OperandType type;
+
+    /**
+     * Dimensions of the operand.
+     */
+    vec<uint32_t> dimensions;
+
+    /**
+     * The number of operations that use this operand as input.
+     */
+    uint32_t numberOfConsumers;
+
+    /**
+     * Quantized scale of the operand.
+     *
+     * Only applicable if the operand is of type TENSOR_QUANT8_ASYMM.
+     */
+    float scale;
+
+    /**
+     * Quantized zero-point offset of the operand.
+     *
+     * Only applicable if the operand is of type TENSOR_QUANT8_ASYMM.
+     */
+    int32_t zeroPoint;
+
+    /**
+     * How the operand is used.
+     */
+    OperandLifeTime lifetime;
+
+    /**
+     * Where to find the data for this operand.
+     * If the lifetime is TEMPORARY_VARIABLE, MODEL_INPUT, or MODEL_OUTPUT:
+     * - All the fields will be 0.
+     * If the lifetime is CONSTANT_COPY:
+     * - location.poolIndex is 0.
+     * - location.offset is the offset in bytes into Model.operandValues.
+     * - location.length is set.
+     * If the lifetime is CONSTANT_REFERENCE:
+     * - location.poolIndex is set.
+     * - location.offset is the offset in bytes into the specified pool.
+     * - location.length is set.
+     */
+    DataLocation location;
+};
+
+/**
+ * Describes one operation of the model's graph.
+ */
+struct Operation {
+    /**
+     * The tuple describing the operation type and input type.
+     */
+    OperationTuple opTuple;
+
+    /**
+     * Describes the table that contains the indexes of the inputs of the
+     * operation. The offset is the index in the operandIndexes table.
+     */
+    vec<uint32_t> inputs;
+
+    /**
+     * Describes the table that contains the indexes of the outputs of the
+     * operation. The offset is the index in the operandIndexes table.
+     */
+    vec<uint32_t> outputs;
+};
+
+/**
+ * A Neural Network Model.
+ *
+ * This includes not only the execution graph, but also constant data such as
+ * weights or scalars added at construction time. The only information that
+ * might not be known is the shape of the input tensors.
+ */
+struct Model {
+    /**
+     * All operands included in the model.
+     */
+    vec<Operand> operands;
+
+    /**
+     * All operations included in the model.
+     *
+     * The operations are sorted into execution order.
+     */
+    vec<Operation> operations;
+
+    /**
+     * Input indexes of the model.
+     *
+     * Each value corresponds to the index of the operand in "operands".
+     */
+    vec<uint32_t> inputIndexes;
+
+    /**
+     * Output indexes of the model.
+     *
+     * Each value corresponds to the index of the operand in "operands".
+     */
+    vec<uint32_t> outputIndexes;
+
+    /**
+     * A byte buffer containing operand data that were copied into the model.
+     */
+    vec<uint8_t> operandValues;
+
+    /**
+     * A collection of shared memory pools containing operand data that were
+     * registered by the model.
+     */
+    vec<memory> pools;
+};
+
+/**
+ * Metadata information specifying the location of the input or output data and
+ * any updates to the input or output operand.
+ */
+struct RequestArgument {
+    /**
+     * The location within one of the memory pools passed in the Request.
+     */
+    DataLocation location;
+
+    /**
+     * Updated dimension information.
+     *
+     * If dimensions.size() > 0, dimension information was provided along with the
+     * argument.  This can be the case for models that accept inputs of varying size.
+     * This can't change the rank, just the value of the dimensions that were
+     * unspecified in the model.
+     */
+    vec<uint32_t> dimensions;
+};
+
+/**
+ * Inputs to be sent to and outputs to be retrieved from a prepared model.
+ *
+ * A Request serves two primary tasks:
+ * 1) Provides the input and output data to be used when executing the model.
+ * 2) Specifies any updates to the input operand metadata that were left
+ *    unspecified at model preparation time.
+ */
+struct Request {
+    /**
+     * Input data and information to be used in the execution of a prepared
+     * model.
+     *
+     * The index of the input corresponds to the index in Model.inputIndexes.
+     *   E.g., input[i] corresponds to Model.inputIndexes[i].
+     */
+    vec<RequestArgument> inputs;
+
+    /**
+     * Output data and information to be used in the execution of a prepared
+     * model.
+     *
+     * The index of the output corresponds to the index in Model.outputIndexes.
+     *   E.g., output[i] corresponds to Model.outputIndexes[i].
+     */
+    vec<RequestArgument> outputs;
+
+    /**
+     * A collection of shared memory pools containing operand data for both the
+     * inputs and the outputs to a model.
+     */
+    vec<memory> pools;
+};
+
+/**
+ * Return status of a function.
+ */
+enum ErrorStatus : int32_t {
+    NONE,
+    DEVICE_UNAVAILABLE,
+    GENERAL_FAILURE,
+    OUTPUT_INSUFFICIENT_SIZE,
+    INVALID_ARGUMENT,
+};
diff --git a/neuralnetworks/1.0/vts/OWNERS b/neuralnetworks/1.0/vts/OWNERS
new file mode 100644
index 0000000..59e7c28
--- /dev/null
+++ b/neuralnetworks/1.0/vts/OWNERS
@@ -0,0 +1,11 @@
+# Neuralnetworks team
+butlermichael@google.com
+dgross@google.com
+ijsung@google.com
+jeanluc@google.com
+miaowang@google.com
+yangni@google.com
+
+# VTS team
+yim@google.com
+yuexima@google.com
diff --git a/neuralnetworks/1.0/vts/functional/Android.bp b/neuralnetworks/1.0/vts/functional/Android.bp
new file mode 100644
index 0000000..2318430
--- /dev/null
+++ b/neuralnetworks/1.0/vts/functional/Android.bp
@@ -0,0 +1,35 @@
+//
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_test {
+    name: "VtsHalNeuralnetworksV1_0TargetTest",
+    srcs: [
+        "Event.cpp",
+        "GeneratedTestHarness.cpp",
+        "VtsHalNeuralnetworksV1_0TargetTest.cpp",
+    ],
+    defaults: ["VtsHalTargetTestDefaults"],
+    static_libs: [
+        "android.hardware.neuralnetworks@1.0",
+        "android.hidl.allocator@1.0",
+        "android.hidl.memory@1.0",
+        "libhidlmemory",
+    ],
+    header_libs: [
+        "libneuralnetworks_generated_test_harness_headers",
+        "libneuralnetworks_generated_tests",
+    ],
+}
diff --git a/neuralnetworks/1.0/vts/functional/Event.cpp b/neuralnetworks/1.0/vts/functional/Event.cpp
new file mode 100644
index 0000000..efaacb3
--- /dev/null
+++ b/neuralnetworks/1.0/vts/functional/Event.cpp
@@ -0,0 +1,94 @@
+#include "Event.h"
+#include <android-base/logging.h>
+
+namespace android {
+namespace hardware {
+namespace neuralnetworks {
+namespace V1_0 {
+namespace implementation {
+
+Event::Event() : mStatus(Status::WAITING) {}
+
+Event::~Event() {
+    // Note that we cannot call Event::join_thread from here: Event is
+    // intended to be reference counted, and it is possible that the
+    // reference count drops to zero in the bound thread, causing the
+    // bound thread to call this destructor. If a thread tries to join
+    // itself, it throws an exception, producing a message like the
+    // following:
+    //
+    //     terminating with uncaught exception of type std::__1::system_error:
+    //     thread::join failed: Resource deadlock would occur
+}
+
+Return<void> Event::notify(ErrorStatus status) {
+    {
+        std::lock_guard<std::mutex> lock(mMutex);
+        mStatus = status == ErrorStatus::NONE ? Status::SUCCESS : Status::ERROR;
+        if (mStatus == Status::SUCCESS && mCallback != nullptr) {
+            bool success = mCallback();
+            if (!success) {
+                LOG(ERROR) << "Event::notify -- callback failed";
+            }
+        }
+    }
+    mCondition.notify_all();
+    return Void();
+}
+
+Event::Status Event::poll() {
+    std::lock_guard<std::mutex> lock(mMutex);
+    return mStatus;
+}
+
+Event::Status Event::wait() {
+    std::unique_lock<std::mutex> lock(mMutex);
+    mCondition.wait(lock, [this]{return mStatus != Status::WAITING;});
+    join_thread_locked();
+    return mStatus;
+}
+
+bool Event::on_finish(std::function<bool(void)> callback) {
+    std::lock_guard<std::mutex> lock(mMutex);
+    if (mCallback != nullptr) {
+        LOG(ERROR) << "Event::on_finish -- a callback has already been bound to this event";
+        return false;
+    }
+    if (callback == nullptr) {
+        LOG(ERROR) << "Event::on_finish -- the new callback is invalid";
+        return false;
+    }
+    mCallback = std::move(callback);
+    return true;
+}
+
+bool Event::bind_thread(std::thread&& asyncThread) {
+    std::lock_guard<std::mutex> lock(mMutex);
+    if (mThread.joinable()) {
+        LOG(ERROR) << "Event::bind_thread -- a thread has already been bound to this event";
+        return false;
+    }
+    if (!asyncThread.joinable()) {
+        LOG(ERROR) << "Event::bind_thread -- the new thread is not joinable";
+        return false;
+    }
+    mThread = std::move(asyncThread);
+    return true;
+}
+
+void Event::join_thread() {
+    std::lock_guard<std::mutex> lock(mMutex);
+    join_thread_locked();
+}
+
+void Event::join_thread_locked() {
+    if (mThread.joinable()) {
+        mThread.join();
+    }
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace neuralnetworks
+}  // namespace hardware
+}  // namespace android
diff --git a/neuralnetworks/1.0/vts/functional/Event.h b/neuralnetworks/1.0/vts/functional/Event.h
new file mode 100644
index 0000000..7dd4070
--- /dev/null
+++ b/neuralnetworks/1.0/vts/functional/Event.h
@@ -0,0 +1,216 @@
+#ifndef ANDROID_HARDWARE_NEURALNETWORKS_V1_0_EVENT_H
+#define ANDROID_HARDWARE_NEURALNETWORKS_V1_0_EVENT_H
+
+#include <android/hardware/neuralnetworks/1.0/IEvent.h>
+#include <chrono>
+#include <condition_variable>
+#include <functional>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+#include <mutex>
+#include <thread>
+
+namespace android {
+namespace hardware {
+namespace neuralnetworks {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+/**
+ * The Event class is used internally by the Neuralnetworks runtime to
+ * synchronize between different threads. An asynchronous task is launched
+ * paired with an event object. When a client thread requires the output being
+ * processed by the asynchronous task, the client thread can wait for the result
+ * and be blocked until it has completed or a timeout condition has been
+ * reached, or poll the result periodically. Both poll and wait* may safely be
+ * called concurrently, even on the same event. When the server thread has
+ * completed, it should immediately call "notify" to indicate the corresponding
+ * output has been produced and awaken any client threads waiting on the event.
+ *
+ * This class exists to enable synchronization across HIDL. When synchronization
+ * is only required in the same process, consider using std::future, std::mutex,
+ * std::condition_variable, or std::experimental::latch instead.
+ */
+struct Event : public IEvent {
+    Event();
+    ~Event() override;
+
+    /**
+     * Event::Status::WAITING -- The corresponding asynchronous execution has
+     *                           not yet finished.
+     * Event::Status::SUCCESS -- The corresponding asynchronous execution has
+     *                           succeeded and the output is ready to be
+     *                           consumed.
+     * Event::Status::TIMEOUT -- The calling thread has waited longer than the
+     *                           user has specified. This only applies to the
+     *                           methods Event::wait_for and Event::wait_until.
+     * Event::Status::ERROR   -- The corresponding asynchronous execution has
+     *                           failed to properly execute.
+     */
+    enum class Status : uint32_t {
+        WAITING,
+        SUCCESS,
+        TIMEOUT,
+        ERROR,
+    };
+
+    /**
+     * IEvent::notify marks the event with the return status of the
+     * asynchronous call the event is paired with and enables all
+     * prior and future wait calls on the Event object to proceed. The
+     * call to IEvent::notify happens before any wait* calls on
+     * this event return (except in the case of TIMEOUT) and before
+     * any poll calls that see the resulting status. The asynchronous
+     * call the event is paired with must ensure that any update to
+     * state that should be visible to the caller of wait* or poll
+     * happens before the call to IEvent::notify.
+     *
+     * IEvent::notify can be called at most once on a given event.
+     *
+     * @param neuralnetworks::V1_0::ErrorStatus ErrorStatus::NONE on success
+     */
+    Return<void> notify(ErrorStatus status) override;
+
+    /**
+     * Event::poll returns the current status of the event.
+     *
+     * @return Status SUCCESS, ERROR, or WAITING
+     */
+    Event::Status poll();
+
+    /**
+     * Event::wait blocks until the event has been signaled.
+     *
+     * @return Status SUCCESS or ERROR
+     */
+    Event::Status wait();
+
+    /**
+     * Event::wait_for blocks until the event has been signaled or the time
+     * duration from the time the wait_for function was called has expired,
+     * whichever comes first.
+     *
+     * @return Status SUCCESS, ERROR, or TIMEOUT
+     */
+    template<class Rep, class Period>
+    Event::Status wait_for(const std::chrono::duration<Rep,Period>& timeout_duration);
+
+    /**
+     * Event::wait_until blocks until the event has been signaled or a certain
+     * time has been reached, whichever comes first.
+     *
+     * @return Status SUCCESS, ERROR, or TIMEOUT
+     */
+    template<class Clock, class Duration>
+    Event::Status wait_until(const std::chrono::time_point<Clock,Duration>& timeout_duration);
+
+    /**
+     * Event::on_finish binds a callback function to the event. The
+     * callback will be executed when IEvent::notify is called, before
+     * any calls to wait* return. (Note that wait_for or wait_until
+     * can return TIMEOUT before IEvent::notify is called for the
+     * first time, and hence before the callback is executed.)
+     *
+     * The callback function must not synchronize with or otherwise
+     * access the event object it is bound to.
+     *
+     * Event::on_finish can be called at most once on a given event.
+     *
+     * @param callback Function to be invoked the first time IEvent::notify is
+     *                 called. Must have a target -- i.e., must not compare equal
+     *                 to nullptr. Callback returns true if it successfully
+     *                 completes, false if it fails.
+     * @return bool True if the callback was successfully bound, false if
+     *              unsuccessful.
+     *
+     * TODO: What if notify has already been called before on_finish?
+     * TODO: Why does the return value of the callback matter?
+     */
+    bool on_finish(std::function<bool(void)> callback);
+
+    /**
+     * Event::bind_thread binds a thread to the event for later use by
+     * Event::join_thread.
+     *
+     * The thread must be passed using std::move.
+     *
+     * Once a thread is bound with Event::bind_thread, the client code
+     * should ensure that one of the following occurs before the event is
+     * destroyed:
+     * - Event::join_thread has been called.
+     * - Event::wait has been called.
+     * - Event::wait_for has been called and returned other than TIMEOUT.
+     * - Event::wait_until has been called and returned other than TIMEOUT.
+     *
+     * The bound thread shall not call any Event method with the exception of
+     * IEvent::notify, which it will call when the thread has finished its
+     * computation.
+     *
+     * Event::bind_thread can be called at most once on a given event.
+     *
+     * @param asyncThread Thread to be bound to the event. The thread object
+     *                    must represent a thread of execution -- i.e.,
+     *                    asyncThread.joinable() must be true.
+     * @return bool True if successful, false if thread was not properly bound.
+     */
+    bool bind_thread(std::thread&& asyncThread);
+
+    /**
+     * Event::join_thread ensures that the thread (if any) bound to
+     * this event with Event::bind_thread has fully finished and
+     * cleaned its resources. It is legal to call this function
+     * multiple times, concurrently or sequentially.
+     */
+    void join_thread();
+
+ private:
+    // Same as Event::join_thread but assumes we already hold a lock on mMutex.
+    void join_thread_locked();
+
+    Status                    mStatus;
+    std::mutex                mMutex;
+    std::condition_variable   mCondition;
+    std::function<bool(void)> mCallback;
+    std::thread               mThread;
+};
+
+
+// template function implementations
+
+template<class Rep, class Period>
+Event::Status Event::wait_for(const std::chrono::duration<Rep,Period>& timeout_duration) {
+    std::unique_lock<std::mutex> lock(mMutex);
+    std::cv_status status = mCondition.wait_for(lock, timeout_duration,
+                                                [this]{return mStatus != Status::WAITING;});
+    if (status != std::cv_status::timeout) {
+        join_thread_locked();
+    }
+    return status != std::cv_status::timeout ? mStatus : Status::TIMEOUT;
+}
+
+template<class Clock, class Duration>
+Event::Status Event::wait_until(const std::chrono::time_point<Clock,Duration>& timeout_time) {
+    std::unique_lock<std::mutex> lock(mMutex);
+    std::cv_status status = mCondition.wait_until(lock, timeout_time,
+                                                  [this]{return mStatus != Status::WAITING;});
+    if (status != std::cv_status::timeout) {
+        join_thread_locked();
+    }
+    return status != std::cv_status::timeout ? mStatus : Status::TIMEOUT;
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace neuralnetworks
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_NEURALNETWORKS_V1_0_EVENT_H
diff --git a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
new file mode 100644
index 0000000..db90ac2
--- /dev/null
+++ b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
@@ -0,0 +1,203 @@
+/*
+ * 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.
+ */
+
+#include "Event.h"
+#include "TestHarness.h"
+#include "VtsHalNeuralnetworksV1_0TargetTest.h"
+
+#include <android-base/logging.h>
+#include <android/hidl/memory/1.0/IMemory.h>
+#include <hidlmemory/mapping.h>
+
+namespace android {
+namespace hardware {
+namespace neuralnetworks {
+namespace V1_0 {
+namespace vts {
+namespace functional {
+// allocator helper
+hidl_memory allocateSharedMemory(int64_t size, const std::string& type = "ashmem");
+
+namespace generated_tests {
+using ::android::hardware::neuralnetworks::V1_0::implementation::Event;
+using ::generated_tests::filter;
+using ::generated_tests::for_all;
+using ::generated_tests::for_each;
+using ::generated_tests::resize_accordingly;
+using ::generated_tests::MixedTyped;
+using ::generated_tests::MixedTypedExampleType;
+using ::generated_tests::Float32Operands;
+using ::generated_tests::Int32Operands;
+using ::generated_tests::Quant8Operands;
+// Top level driver for models and examples generated by test_generator.py
+// Test driver for those generated from ml/nn/runtime/test/spec
+void Execute(const sp<IDevice>& device, std::function<Model(void)> create_model,
+             std::function<bool(int)> is_ignored,
+             const std::vector<MixedTypedExampleType>& examples) {
+    Model model = create_model();
+    sp<IPreparedModel> preparedModel;
+    sp<Event> preparationEvent = new Event();
+    ASSERT_NE(nullptr, preparationEvent.get());
+    Return<void> prepareRet = device->prepareModel(
+        model, preparationEvent, [&](ErrorStatus status, const sp<IPreparedModel>& prepared) {
+            EXPECT_EQ(ErrorStatus::NONE, status);
+            preparedModel = prepared;
+        });
+    ASSERT_TRUE(prepareRet.isOk());
+    ASSERT_NE(nullptr, preparedModel.get());
+    Event::Status preparationStatus = preparationEvent->wait();
+    EXPECT_EQ(Event::Status::SUCCESS, preparationStatus);
+
+    const uint32_t INPUT = 0;
+    const uint32_t OUTPUT = 1;
+
+    int example_no = 1;
+    for (auto& example : examples) {
+        SCOPED_TRACE(example_no++);
+
+        const MixedTyped& inputs = example.first;
+        const MixedTyped& golden = example.second;
+
+        std::vector<RequestArgument> inputs_info, outputs_info;
+        uint32_t inputSize = 0, outputSize = 0;
+
+        // This function only partially specifies the metadata (vector of RequestArguments).
+        // The contents are copied over below.
+        for_all(inputs, [&inputs_info, &inputSize](int index, auto, auto s) {
+            if (inputs_info.size() <= static_cast<size_t>(index)) inputs_info.resize(index + 1);
+            RequestArgument arg = {
+                .location = {.poolIndex = INPUT, .offset = 0, .length = static_cast<uint32_t>(s)},
+                .dimensions = {},
+            };
+            inputs_info[index] = arg;
+            inputSize += s;
+        });
+        // Compute offset for inputs 1 and so on
+        {
+            size_t offset = 0;
+            for (auto& i : inputs_info) {
+                i.location.offset = offset;
+                offset += i.location.length;
+            }
+        }
+
+        MixedTyped test;  // holding test results
+
+        // Go through all outputs, initialize RequestArgument descriptors
+        resize_accordingly<float>(golden, test);
+        resize_accordingly<int32_t>(golden, test);
+        resize_accordingly<uint8_t>(golden, test);
+        for_all(golden, [&outputs_info, &outputSize](int index, auto, auto s) {
+            if (outputs_info.size() <= static_cast<size_t>(index)) outputs_info.resize(index + 1);
+            RequestArgument arg = {
+                .location = {.poolIndex = OUTPUT, .offset = 0, .length = static_cast<uint32_t>(s)},
+                .dimensions = {},
+            };
+            outputs_info[index] = arg;
+            outputSize += s;
+        });
+        // Compute offset for outputs 1 and so on
+        {
+            size_t offset = 0;
+            for (auto& i : outputs_info) {
+                i.location.offset = offset;
+                offset += i.location.length;
+            }
+        }
+        std::vector<hidl_memory> pools = {allocateSharedMemory(inputSize),
+                                          allocateSharedMemory(outputSize)};
+        ASSERT_NE(0ull, pools[INPUT].size());
+        ASSERT_NE(0ull, pools[OUTPUT].size());
+
+        // load data
+        sp<IMemory> inputMemory = mapMemory(pools[INPUT]);
+        sp<IMemory> outputMemory = mapMemory(pools[OUTPUT]);
+        ASSERT_NE(nullptr, inputMemory.get());
+        ASSERT_NE(nullptr, outputMemory.get());
+        char* inputPtr = reinterpret_cast<char*>(static_cast<void*>(inputMemory->getPointer()));
+        char* outputPtr = reinterpret_cast<char*>(static_cast<void*>(outputMemory->getPointer()));
+        ASSERT_NE(nullptr, inputPtr);
+        ASSERT_NE(nullptr, outputPtr);
+        inputMemory->update();
+        outputMemory->update();
+
+        // Go through all inputs, copy the values
+        for_all(inputs, [&inputs_info, inputPtr](int index, auto p, auto s) {
+            char* begin = (char*)p;
+            char* end = begin + s;
+            // TODO: handle more than one input
+            std::copy(begin, end, inputPtr + inputs_info[index].location.offset);
+        });
+
+        inputMemory->commit();
+        outputMemory->commit();
+        // execute request
+        sp<Event> executionEvent = new Event();
+        ASSERT_NE(nullptr, executionEvent.get());
+        Return<ErrorStatus> executeStatus = preparedModel->execute(
+            {.inputs = inputs_info, .outputs = outputs_info, .pools = pools}, executionEvent);
+        ASSERT_TRUE(executeStatus.isOk());
+        EXPECT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(executeStatus));
+        Event::Status eventStatus = executionEvent->wait();
+        EXPECT_EQ(Event::Status::SUCCESS, eventStatus);
+
+        // validate results
+        outputMemory->read();
+#define COPY_BACK(ty)                                                              \
+    for_each<ty>(test, [&outputs_info, outputPtr](int index, std::vector<ty>& m) { \
+        RequestArgument& i = outputs_info[index];                                  \
+        ASSERT_EQ(m.size(), i.location.length / sizeof(ty));                       \
+        char* begin = outputPtr + i.location.offset;                               \
+        memcpy(m.data(), begin, i.location.length);                                \
+    });
+        COPY_BACK(float);
+        COPY_BACK(int32_t);
+        COPY_BACK(uint8_t);
+#undef COPY_BACK
+        outputMemory->commit();
+        // Filter out don't cares
+        MixedTyped filtered_golden;
+        MixedTyped filtered_test;
+        filter<float>(golden, &filtered_golden, is_ignored);
+        filter<float>(test, &filtered_test, is_ignored);
+        filter<int32_t>(golden, &filtered_golden, is_ignored);
+        filter<int32_t>(test, &filtered_test, is_ignored);
+        filter<uint8_t>(golden, &filtered_golden, is_ignored);
+        filter<uint8_t>(test, &filtered_test, is_ignored);
+
+        // We want "close-enough" results for float
+        for_each<float>(filtered_golden, [&filtered_test](int index, auto& golden_float) {
+            auto& test_float_operands = std::get<Float32Operands>(filtered_test);
+            auto& test_float = test_float_operands[index];
+            for (unsigned int i = 0; i < golden_float.size(); i++) {
+                SCOPED_TRACE(i);
+                EXPECT_NEAR(golden_float[i], test_float[i], 1.e-5);
+            }
+        });
+        EXPECT_EQ(std::get<Int32Operands>(filtered_golden), std::get<Int32Operands>(filtered_test));
+        EXPECT_EQ(std::get<Quant8Operands>(filtered_golden),
+                  std::get<Quant8Operands>(filtered_test));
+    }
+}
+
+}  // namespace generated_tests
+
+}  // namespace functional
+}  // namespace vts
+}  // namespace V1_0
+}  // namespace neuralnetworks
+}  // namespace hardware
+}  // namespace android
diff --git a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0TargetTest.cpp b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0TargetTest.cpp
new file mode 100644
index 0000000..453e3e5
--- /dev/null
+++ b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0TargetTest.cpp
@@ -0,0 +1,299 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "neuralnetworks_hidl_hal_test"
+
+#include "VtsHalNeuralnetworksV1_0TargetTest.h"
+#include "Event.h"
+#include "TestHarness.h"
+
+#include <android-base/logging.h>
+#include <android/hidl/memory/1.0/IMemory.h>
+#include <hidlmemory/mapping.h>
+
+namespace android {
+namespace hardware {
+namespace neuralnetworks {
+namespace V1_0 {
+namespace vts {
+namespace functional {
+
+using ::android::hardware::neuralnetworks::V1_0::implementation::Event;
+using ::generated_tests::MixedTypedExampleType;
+namespace generated_tests {
+extern void Execute(const sp<IDevice>&, std::function<Model(void)>, std::function<bool(int)>,
+                    const std::vector<MixedTypedExampleType>&);
+}
+
+// A class for test environment setup
+NeuralnetworksHidlEnvironment::NeuralnetworksHidlEnvironment() {}
+
+NeuralnetworksHidlEnvironment::~NeuralnetworksHidlEnvironment() {}
+
+NeuralnetworksHidlEnvironment* NeuralnetworksHidlEnvironment::getInstance() {
+    // This has to return a "new" object because it is freed inside
+    // ::testing::AddGlobalTestEnvironment when the gtest is being torn down
+    static NeuralnetworksHidlEnvironment* instance = new NeuralnetworksHidlEnvironment();
+    return instance;
+}
+
+void NeuralnetworksHidlEnvironment::registerTestServices() {
+    registerTestService<IDevice>();
+}
+
+// The main test class for NEURALNETWORK HIDL HAL.
+NeuralnetworksHidlTest::~NeuralnetworksHidlTest() {}
+
+void NeuralnetworksHidlTest::SetUp() {
+    device = ::testing::VtsHalHidlTargetTestBase::getService<IDevice>(
+        NeuralnetworksHidlEnvironment::getInstance());
+    ASSERT_NE(nullptr, device.get());
+}
+
+void NeuralnetworksHidlTest::TearDown() {}
+
+// create device test
+TEST_F(NeuralnetworksHidlTest, CreateDevice) {}
+
+// status test
+TEST_F(NeuralnetworksHidlTest, StatusTest) {
+    Return<DeviceStatus> status = device->getStatus();
+    ASSERT_TRUE(status.isOk());
+    EXPECT_EQ(DeviceStatus::AVAILABLE, static_cast<DeviceStatus>(status));
+}
+
+// initialization
+TEST_F(NeuralnetworksHidlTest, GetCapabilitiesTest) {
+    Return<void> ret =
+        device->getCapabilities([](ErrorStatus status, const Capabilities& capabilities) {
+            EXPECT_EQ(ErrorStatus::NONE, status);
+            EXPECT_NE(nullptr, capabilities.supportedOperationTuples.data());
+            EXPECT_NE(0ull, capabilities.supportedOperationTuples.size());
+            EXPECT_EQ(0u, static_cast<uint32_t>(capabilities.cachesCompilation) & ~0x1);
+            EXPECT_LT(0.0f, capabilities.float32Performance.execTime);
+            EXPECT_LT(0.0f, capabilities.float32Performance.powerUsage);
+            EXPECT_LT(0.0f, capabilities.quantized8Performance.execTime);
+            EXPECT_LT(0.0f, capabilities.quantized8Performance.powerUsage);
+        });
+    EXPECT_TRUE(ret.isOk());
+}
+
+namespace {
+// create the model
+Model createTestModel() {
+    const std::vector<float> operand2Data = {5.0f, 6.0f, 7.0f, 8.0f};
+    const uint32_t size = operand2Data.size() * sizeof(float);
+
+    const uint32_t operand1 = 0;
+    const uint32_t operand2 = 1;
+    const uint32_t operand3 = 2;
+    const uint32_t operand4 = 3;
+
+    const std::vector<Operand> operands = {
+        {
+            .type = OperandType::TENSOR_FLOAT32,
+            .dimensions = {1, 2, 2, 1},
+            .numberOfConsumers = 1,
+            .scale = 0.0f,
+            .zeroPoint = 0,
+            .lifetime = OperandLifeTime::MODEL_INPUT,
+            .location = {.poolIndex = 0, .offset = 0, .length = 0},
+        },
+        {
+            .type = OperandType::TENSOR_FLOAT32,
+            .dimensions = {1, 2, 2, 1},
+            .numberOfConsumers = 1,
+            .scale = 0.0f,
+            .zeroPoint = 0,
+            .lifetime = OperandLifeTime::CONSTANT_COPY,
+            .location = {.poolIndex = 0, .offset = 0, .length = size},
+        },
+        {
+            .type = OperandType::INT32,
+            .dimensions = {},
+            .numberOfConsumers = 1,
+            .scale = 0.0f,
+            .zeroPoint = 0,
+            .lifetime = OperandLifeTime::CONSTANT_COPY,
+            .location = {.poolIndex = 0, .offset = size, .length = sizeof(int32_t)},
+        },
+        {
+            .type = OperandType::TENSOR_FLOAT32,
+            .dimensions = {1, 2, 2, 1},
+            .numberOfConsumers = 0,
+            .scale = 0.0f,
+            .zeroPoint = 0,
+            .lifetime = OperandLifeTime::MODEL_OUTPUT,
+            .location = {.poolIndex = 0, .offset = 0, .length = 0},
+        },
+    };
+
+    const std::vector<Operation> operations = {{
+        .opTuple = {OperationType::ADD, OperandType::TENSOR_FLOAT32},
+        .inputs = {operand1, operand2, operand3},
+        .outputs = {operand4},
+    }};
+
+    const std::vector<uint32_t> inputIndexes = {operand1};
+    const std::vector<uint32_t> outputIndexes = {operand4};
+    std::vector<uint8_t> operandValues(
+        reinterpret_cast<const uint8_t*>(operand2Data.data()),
+        reinterpret_cast<const uint8_t*>(operand2Data.data()) + size);
+    int32_t activation[1] = {static_cast<int32_t>(FusedActivationFunc::NONE)};
+    operandValues.insert(operandValues.end(), reinterpret_cast<const uint8_t*>(&activation[0]),
+                         reinterpret_cast<const uint8_t*>(&activation[1]));
+
+    const std::vector<hidl_memory> pools = {};
+
+    return {
+        .operands = operands,
+        .operations = operations,
+        .inputIndexes = inputIndexes,
+        .outputIndexes = outputIndexes,
+        .operandValues = operandValues,
+        .pools = pools,
+    };
+}
+}  // anonymous namespace
+
+// allocator helper
+hidl_memory allocateSharedMemory(int64_t size, const std::string& type = "ashmem") {
+    hidl_memory memory;
+
+    sp<IAllocator> allocator = IAllocator::getService(type);
+    if (!allocator.get()) {
+        return {};
+    }
+
+    Return<void> ret = allocator->allocate(size, [&](bool success, const hidl_memory& mem) {
+        ASSERT_TRUE(success);
+        memory = mem;
+    });
+    if (!ret.isOk()) {
+        return {};
+    }
+
+    return memory;
+}
+
+// supported subgraph test
+TEST_F(NeuralnetworksHidlTest, SupportedOperationsTest) {
+    Model model = createTestModel();
+    Return<void> ret = device->getSupportedOperations(
+        model, [&](ErrorStatus status, const hidl_vec<bool>& supported) {
+            EXPECT_EQ(ErrorStatus::NONE, status);
+            EXPECT_EQ(model.operations.size(), supported.size());
+        });
+    EXPECT_TRUE(ret.isOk());
+}
+
+// execute simple graph
+TEST_F(NeuralnetworksHidlTest, SimpleExecuteGraphTest) {
+    std::vector<float> inputData = {1.0f, 2.0f, 3.0f, 4.0f};
+    std::vector<float> outputData = {-1.0f, -1.0f, -1.0f, -1.0f};
+    std::vector<float> expectedData = {6.0f, 8.0f, 10.0f, 12.0f};
+    const uint32_t INPUT = 0;
+    const uint32_t OUTPUT = 1;
+
+    // prepare request
+    Model model = createTestModel();
+    sp<IPreparedModel> preparedModel;
+    sp<Event> preparationEvent = new Event();
+    ASSERT_NE(nullptr, preparationEvent.get());
+    Return<void> prepareRet = device->prepareModel(
+        model, preparationEvent, [&](ErrorStatus status, const sp<IPreparedModel>& prepared) {
+            EXPECT_EQ(ErrorStatus::NONE, status);
+            preparedModel = prepared;
+        });
+    ASSERT_TRUE(prepareRet.isOk());
+    ASSERT_NE(nullptr, preparedModel.get());
+    Event::Status preparationStatus = preparationEvent->wait();
+    EXPECT_EQ(Event::Status::SUCCESS, preparationStatus);
+
+    // prepare inputs
+    uint32_t inputSize = static_cast<uint32_t>(inputData.size() * sizeof(float));
+    uint32_t outputSize = static_cast<uint32_t>(outputData.size() * sizeof(float));
+    std::vector<RequestArgument> inputs = {{
+        .location = {.poolIndex = INPUT, .offset = 0, .length = inputSize}, .dimensions = {},
+    }};
+    std::vector<RequestArgument> outputs = {{
+        .location = {.poolIndex = OUTPUT, .offset = 0, .length = outputSize}, .dimensions = {},
+    }};
+    std::vector<hidl_memory> pools = {allocateSharedMemory(inputSize),
+                                      allocateSharedMemory(outputSize)};
+    ASSERT_NE(0ull, pools[INPUT].size());
+    ASSERT_NE(0ull, pools[OUTPUT].size());
+
+    // load data
+    sp<IMemory> inputMemory = mapMemory(pools[INPUT]);
+    sp<IMemory> outputMemory = mapMemory(pools[OUTPUT]);
+    ASSERT_NE(nullptr, inputMemory.get());
+    ASSERT_NE(nullptr, outputMemory.get());
+    float* inputPtr = reinterpret_cast<float*>(static_cast<void*>(inputMemory->getPointer()));
+    float* outputPtr = reinterpret_cast<float*>(static_cast<void*>(outputMemory->getPointer()));
+    ASSERT_NE(nullptr, inputPtr);
+    ASSERT_NE(nullptr, outputPtr);
+    inputMemory->update();
+    outputMemory->update();
+    std::copy(inputData.begin(), inputData.end(), inputPtr);
+    std::copy(outputData.begin(), outputData.end(), outputPtr);
+    inputMemory->commit();
+    outputMemory->commit();
+
+    // execute request
+    sp<Event> executionEvent = new Event();
+    ASSERT_NE(nullptr, executionEvent.get());
+    Return<ErrorStatus> executeStatus = preparedModel->execute(
+        {.inputs = inputs, .outputs = outputs, .pools = pools}, executionEvent);
+    ASSERT_TRUE(executeStatus.isOk());
+    EXPECT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(executeStatus));
+    Event::Status eventStatus = executionEvent->wait();
+    EXPECT_EQ(Event::Status::SUCCESS, eventStatus);
+
+    // validate results { 1+5, 2+6, 3+7, 4+8 }
+    outputMemory->read();
+    std::copy(outputPtr, outputPtr + outputData.size(), outputData.begin());
+    outputMemory->commit();
+    EXPECT_EQ(expectedData, outputData);
+}
+
+// Mixed-typed examples
+typedef MixedTypedExampleType MixedTypedExample;
+
+// in frameworks/ml/nn/runtime/tests/generated/
+#include "all_generated_vts_tests.cpp"
+
+// TODO: Add tests for execution failure, or wait_for/wait_until timeout.
+//       Discussion:
+//       https://googleplex-android-review.git.corp.google.com/#/c/platform/hardware/interfaces/+/2654636/5/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0TargetTest.cpp@222
+
+}  // namespace functional
+}  // namespace vts
+}  // namespace V1_0
+}  // namespace neuralnetworks
+}  // namespace hardware
+}  // namespace android
+
+using android::hardware::neuralnetworks::V1_0::vts::functional::NeuralnetworksHidlEnvironment;
+
+int main(int argc, char** argv) {
+    ::testing::AddGlobalTestEnvironment(NeuralnetworksHidlEnvironment::getInstance());
+    ::testing::InitGoogleTest(&argc, argv);
+    NeuralnetworksHidlEnvironment::getInstance()->init(&argc, argv);
+
+    int status = RUN_ALL_TESTS();
+    return status;
+}
diff --git a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0TargetTest.h b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0TargetTest.h
new file mode 100644
index 0000000..9c56e6a
--- /dev/null
+++ b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworksV1_0TargetTest.h
@@ -0,0 +1,85 @@
+/*
+ * 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.
+ */
+
+#ifndef VTS_HAL_NEURALNETWORKS_V1_0_TARGET_TESTS_H
+#define VTS_HAL_NEURALNETWORKS_V1_0_TARGET_TESTS_H
+
+#include <android/hardware/neuralnetworks/1.0/IDevice.h>
+#include <android/hardware/neuralnetworks/1.0/IPreparedModel.h>
+#include <android/hardware/neuralnetworks/1.0/types.h>
+#include <android/hidl/allocator/1.0/IAllocator.h>
+
+#include <VtsHalHidlTargetTestBase.h>
+#include <VtsHalHidlTargetTestEnvBase.h>
+#include <gtest/gtest.h>
+#include <string>
+
+using ::android::hardware::neuralnetworks::V1_0::IDevice;
+using ::android::hardware::neuralnetworks::V1_0::IPreparedModel;
+using ::android::hardware::neuralnetworks::V1_0::Capabilities;
+using ::android::hardware::neuralnetworks::V1_0::DeviceStatus;
+using ::android::hardware::neuralnetworks::V1_0::FusedActivationFunc;
+using ::android::hardware::neuralnetworks::V1_0::Model;
+using ::android::hardware::neuralnetworks::V1_0::OperationType;
+using ::android::hardware::neuralnetworks::V1_0::PerformanceInfo;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hidl::allocator::V1_0::IAllocator;
+using ::android::hidl::memory::V1_0::IMemory;
+using ::android::sp;
+
+namespace android {
+namespace hardware {
+namespace neuralnetworks {
+namespace V1_0 {
+namespace vts {
+namespace functional {
+
+// A class for test environment setup
+class NeuralnetworksHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
+    NeuralnetworksHidlEnvironment();
+    NeuralnetworksHidlEnvironment(const NeuralnetworksHidlEnvironment&) = delete;
+    NeuralnetworksHidlEnvironment(NeuralnetworksHidlEnvironment&&) = delete;
+    NeuralnetworksHidlEnvironment& operator=(const NeuralnetworksHidlEnvironment&) = delete;
+    NeuralnetworksHidlEnvironment& operator=(NeuralnetworksHidlEnvironment&&) = delete;
+
+   public:
+    ~NeuralnetworksHidlEnvironment() override;
+    static NeuralnetworksHidlEnvironment* getInstance();
+    void registerTestServices() override;
+};
+
+// The main test class for NEURALNETWORKS HIDL HAL.
+class NeuralnetworksHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+   public:
+    ~NeuralnetworksHidlTest() override;
+    void SetUp() override;
+    void TearDown() override;
+
+    sp<IDevice> device;
+};
+
+}  // namespace functional
+}  // namespace vts
+}  // namespace V1_0
+}  // namespace neuralnetworks
+}  // namespace hardware
+}  // namespace android
+
+#endif  // VTS_HAL_NEURALNETWORKS_V1_0_TARGET_TESTS_H
diff --git a/neuralnetworks/Android.bp b/neuralnetworks/Android.bp
new file mode 100644
index 0000000..33f70eb
--- /dev/null
+++ b/neuralnetworks/Android.bp
@@ -0,0 +1,5 @@
+// This is an autogenerated file, do not edit.
+subdirs = [
+    "1.0",
+    "1.0/vts/functional",
+]
diff --git a/nfc/1.0/Android.bp b/nfc/1.0/Android.bp
index 7c9a66e..4adb32c 100644
--- a/nfc/1.0/Android.bp
+++ b/nfc/1.0/Android.bp
@@ -46,13 +46,16 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.nfc@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.nfc@1.0_genc++"],
     generated_headers: ["android.hardware.nfc@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.nfc@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/nfc/1.0/vts/functional/Android.bp b/nfc/1.0/vts/functional/Android.bp
index d9ba702..3861bd4 100644
--- a/nfc/1.0/vts/functional/Android.bp
+++ b/nfc/1.0/vts/functional/Android.bp
@@ -16,21 +16,9 @@
 
 cc_test {
     name: "VtsHalNfcV1_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalNfcV1_0TargetTest.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libnativehelper",
-        "libutils",
+    static_libs: [
         "android.hardware.nfc@1.0",
     ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ],
 }
diff --git a/oemlock/1.0/Android.bp b/oemlock/1.0/Android.bp
index 21e7271..742061d 100644
--- a/oemlock/1.0/Android.bp
+++ b/oemlock/1.0/Android.bp
@@ -39,13 +39,16 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.oemlock@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.oemlock@1.0_genc++"],
     generated_headers: ["android.hardware.oemlock@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.oemlock@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/oemlock/1.0/vts/functional/Android.bp b/oemlock/1.0/vts/functional/Android.bp
index a13b3dc..20737a1 100644
--- a/oemlock/1.0/vts/functional/Android.bp
+++ b/oemlock/1.0/vts/functional/Android.bp
@@ -16,21 +16,7 @@
 
 cc_test {
     name: "VtsHalOemLockV1_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalOemLockV1_0TargetTest.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libnativehelper",
-        "libutils",
-        "android.hardware.oemlock@1.0",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ],
+    static_libs: ["android.hardware.oemlock@1.0"],
 }
diff --git a/power/1.0/Android.bp b/power/1.0/Android.bp
index 1d967fd..bc886cb 100644
--- a/power/1.0/Android.bp
+++ b/power/1.0/Android.bp
@@ -39,13 +39,16 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.power@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.power@1.0_genc++"],
     generated_headers: ["android.hardware.power@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.power@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/power/1.0/vts/functional/Android.bp b/power/1.0/vts/functional/Android.bp
index 5ab1eb4..45f74fc 100644
--- a/power/1.0/vts/functional/Android.bp
+++ b/power/1.0/vts/functional/Android.bp
@@ -16,21 +16,7 @@
 
 cc_test {
     name: "VtsHalPowerV1_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalPowerV1_0TargetTest.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libnativehelper",
-        "libutils",
-        "android.hardware.power@1.0",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ]
+    static_libs: ["android.hardware.power@1.0"],
 }
diff --git a/power/1.1/Android.bp b/power/1.1/Android.bp
index bfc140f..fb10aba 100644
--- a/power/1.1/Android.bp
+++ b/power/1.1/Android.bp
@@ -39,13 +39,16 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.power@1.1",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.power@1.1_genc++"],
     generated_headers: ["android.hardware.power@1.1_genc++_headers"],
     export_generated_headers: ["android.hardware.power@1.1_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/power/1.1/default/Android.bp b/power/1.1/default/Android.bp
deleted file mode 100644
index 0b3598b..0000000
--- a/power/1.1/default/Android.bp
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (C) 2016 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-cc_binary {
-    proprietary: true,
-    defaults: ["hidl_defaults"],
-    relative_install_path: "hw",
-    name: "android.hardware.power@1.1-service",
-    init_rc: ["android.hardware.power@1.1-service.rc"],
-    srcs: ["service.cpp" , "Power.cpp"],
-
-    shared_libs: [
-        "liblog",
-        "libdl",
-        "libutils",
-        "libhardware",
-        "libhidlbase",
-        "libhidltransport",
-        "android.hardware.power@1.0",
-        "android.hardware.power@1.1",
-    ],
-}
diff --git a/power/1.1/default/Power.cpp b/power/1.1/default/Power.cpp
deleted file mode 100644
index b5d0c84..0000000
--- a/power/1.1/default/Power.cpp
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "android.hardware.power@1.1-impl"
-
-#include <log/log.h>
-
-#include <hardware/hardware.h>
-#include <hardware/power.h>
-
-#include "Power.h"
-
-namespace android {
-namespace hardware {
-namespace power {
-namespace V1_1 {
-namespace implementation {
-
-using ::android::hardware::power::V1_0::Feature;
-using ::android::hardware::power::V1_0::PowerHint;
-using ::android::hardware::power::V1_0::PowerStatePlatformSleepState;
-using ::android::hardware::power::V1_0::Status;
-using ::android::hardware::power::V1_1::PowerStateSubsystem;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-
-Power::Power(power_module_t *module) : mModule(module) {
-    if (mModule)
-        mModule->init(mModule);
-}
-
-Power::~Power() {
-    delete(mModule);
-}
-
-// Methods from ::android::hardware::power::V1_0::IPower follow.
-Return<void> Power::setInteractive(bool interactive)  {
-    if (mModule->setInteractive)
-        mModule->setInteractive(mModule, interactive ? 1 : 0);
-    return Void();
-}
-
-Return<void> Power::powerHint(PowerHint hint, int32_t data)  {
-    int32_t param = data;
-    if (mModule->powerHint) {
-        if (data)
-            mModule->powerHint(mModule, static_cast<power_hint_t>(hint), &param);
-        else
-            mModule->powerHint(mModule, static_cast<power_hint_t>(hint), NULL);
-    }
-    return Void();
-}
-
-Return<void> Power::setFeature(Feature feature, bool activate)  {
-    if (mModule->setFeature)
-        mModule->setFeature(mModule, static_cast<feature_t>(feature),
-                activate ? 1 : 0);
-    return Void();
-}
-
-Return<void> Power::getPlatformLowPowerStats(getPlatformLowPowerStats_cb _hidl_cb)  {
-    hidl_vec<PowerStatePlatformSleepState> states;
-    ssize_t number_platform_modes;
-    size_t *voters = nullptr;
-    power_state_platform_sleep_state_t *legacy_states = nullptr;
-    int ret;
-
-    if (mModule->get_number_of_platform_modes == nullptr ||
-            mModule->get_voter_list == nullptr ||
-            mModule->get_platform_low_power_stats == nullptr)
-    {
-        _hidl_cb(states, Status::SUCCESS);
-        return Void();
-    }
-
-    number_platform_modes = mModule->get_number_of_platform_modes(mModule);
-    if (number_platform_modes)
-    {
-       if ((ssize_t) (SIZE_MAX / sizeof(size_t)) <= number_platform_modes)  // overflow
-           goto done;
-       voters = new (std::nothrow) size_t [number_platform_modes];
-       if (voters == nullptr)
-           goto done;
-
-       ret = mModule->get_voter_list(mModule, voters);
-       if (ret != 0)
-           goto done;
-
-       if ((ssize_t) (SIZE_MAX / sizeof(power_state_platform_sleep_state_t))
-           <= number_platform_modes)  // overflow
-           goto done;
-       legacy_states = new (std::nothrow)
-           power_state_platform_sleep_state_t [number_platform_modes];
-       if (legacy_states == nullptr)
-           goto done;
-
-       for (int i = 0; i < number_platform_modes; i++)
-       {
-          legacy_states[i].voters = nullptr;
-          legacy_states[i].voters = new power_state_voter_t [voters[i]];
-          if (legacy_states[i].voters == nullptr)
-              goto done;
-       }
-
-       ret = mModule->get_platform_low_power_stats(mModule, legacy_states);
-       if (ret != 0)
-           goto done;
-
-       states.resize(number_platform_modes);
-       for (int i = 0; i < number_platform_modes; i++)
-       {
-          power_state_platform_sleep_state_t& legacy_state = legacy_states[i];
-          PowerStatePlatformSleepState& state = states[i];
-          state.name = legacy_state.name;
-          state.residencyInMsecSinceBoot = legacy_state.residency_in_msec_since_boot;
-          state.totalTransitions = legacy_state.total_transitions;
-          state.supportedOnlyInSuspend = legacy_state.supported_only_in_suspend;
-          state.voters.resize(voters[i]);
-          for(size_t j = 0; j < voters[i]; j++)
-          {
-              state.voters[j].name = legacy_state.voters[j].name;
-              state.voters[j].totalTimeInMsecVotedForSinceBoot = legacy_state.voters[j].total_time_in_msec_voted_for_since_boot;
-              state.voters[j].totalNumberOfTimesVotedSinceBoot = legacy_state.voters[j].total_number_of_times_voted_since_boot;
-          }
-       }
-    }
-done:
-    if (legacy_states)
-    {
-        for (int i = 0; i < number_platform_modes; i++)
-        {
-            if(legacy_states[i].voters)
-                delete(legacy_states[i].voters);
-        }
-    }
-    delete[] legacy_states;
-    delete[] voters;
-    _hidl_cb(states, Status::SUCCESS);
-    return Void();
-}
-
-// Methods from ::android::hardware::power::V1_1::IPower follow.
-Return<void> Power::getSubsystemLowPowerStats(getSubsystemLowPowerStats_cb _hidl_cb) {
-    hidl_vec<PowerStateSubsystem> subsystems;
-    ssize_t number_subsystems = 0;
-
-    //This API will report zero subsystems to support older devices
-    //For devices that support this API, they will have their own implementation
-    subsystems.resize(number_subsystems);
-    _hidl_cb(subsystems, Status::SUCCESS);
-    return Void();
-}
-
-Return<void> Power::powerHintAsync(PowerHint hint, int32_t data) {
-    // just call the normal power hint in this oneway function
-    return powerHint(hint, data);
-}
-
-} // namespace implementation
-}  // namespace V1_1
-}  // namespace power
-}  // namespace hardware
-}  // namespace android
diff --git a/power/1.1/default/Power.h b/power/1.1/default/Power.h
deleted file mode 100644
index e779d64..0000000
--- a/power/1.1/default/Power.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_HARDWARE_POWER_V1_1_POWER_H
-#define ANDROID_HARDWARE_POWER_V1_1_POWER_H
-
-#include <android/hardware/power/1.1/IPower.h>
-#include <hidl/MQDescriptor.h>
-#include <hidl/Status.h>
-#include <hardware/power.h>
-
-namespace android {
-namespace hardware {
-namespace power {
-namespace V1_1 {
-namespace implementation {
-
-using ::android::hardware::power::V1_0::Feature;
-using ::android::hardware::power::V1_0::PowerHint;
-using ::android::hardware::power::V1_1::IPower;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-
-struct Power : public IPower {
-    Power(power_module_t* module);
-    ~Power();
-
-    // Methods from ::android::hardware::power::V1_0::IPower follow
-    Return<void> setInteractive(bool interactive) override;
-    Return<void> powerHint(PowerHint hint, int32_t data) override;
-    Return<void> setFeature(Feature feature, bool activate) override;
-    Return<void> getPlatformLowPowerStats(getPlatformLowPowerStats_cb _hidl_cb) override;
-
-    // Methods from ::android::hardware::power::V1_1::IPower follow.
-    Return<void> getSubsystemLowPowerStats(getSubsystemLowPowerStats_cb _hidl_cb) override;
-    Return<void> powerHintAsync(PowerHint hint, int32_t data) override;
-
-    // Methods from ::android::hidl::base::V1_0::IBase follow.
-
-  private:
-    power_module_t* mModule;
-};
-
-}  // namespace implementation
-}  // namespace V1_1
-}  // namespace power
-}  // namespace hardware
-}  // namespace android
-
-#endif  // ANDROID_HARDWARE_POWER_V1_1_POWER_H
diff --git a/power/1.1/default/android.hardware.power@1.1-service.rc b/power/1.1/default/android.hardware.power@1.1-service.rc
deleted file mode 100644
index f2512f1..0000000
--- a/power/1.1/default/android.hardware.power@1.1-service.rc
+++ /dev/null
@@ -1,4 +0,0 @@
-service power-hal-1-1 /vendor/bin/hw/android.hardware.power@1.1-service
-    class hal
-    user system
-    group system
diff --git a/power/1.1/default/service.cpp b/power/1.1/default/service.cpp
deleted file mode 100644
index 571db2f..0000000
--- a/power/1.1/default/service.cpp
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "android.hardware.power@1.1-service"
-
-#include <android/log.h>
-#include <hidl/HidlTransportSupport.h>
-#include <android/hardware/power/1.1/IPower.h>
-#include <hardware/power.h>
-#include "Power.h"
-
-using android::sp;
-using android::status_t;
-using android::OK;
-
-// libhwbinder:
-using android::hardware::configureRpcThreadpool;
-using android::hardware::joinRpcThreadpool;
-
-// Generated HIDL files
-using android::hardware::power::V1_1::IPower;
-using android::hardware::power::V1_1::implementation::Power;
-
-int main() {
-
-    status_t status;
-    android::sp<IPower> service = nullptr;
-    const hw_module_t* hw_module = nullptr;
-    power_module_t* power_module = nullptr;
-    int err;
-
-    ALOGI("Power HAL Service 1.1 (Default) is starting.");
-
-    err = hw_get_module(POWER_HARDWARE_MODULE_ID, &hw_module);
-    if (err) {
-        ALOGE("hw_get_module %s failed: %d", POWER_HARDWARE_MODULE_ID, err);
-        goto shutdown;
-    }
-
-    if (!hw_module->methods || !hw_module->methods->open) {
-        power_module = reinterpret_cast<power_module_t*>(
-            const_cast<hw_module_t*>(hw_module));
-    } else {
-        err = hw_module->methods->open(hw_module, POWER_HARDWARE_MODULE_ID,
-                                           reinterpret_cast<hw_device_t**>(&power_module));
-        if (err) {
-            ALOGE("Passthrough failed to load legacy HAL.");
-            goto shutdown;
-        }
-    }
-
-    service = new Power(power_module);
-    if (service == nullptr) {
-        ALOGE("Can not create an instance of Power HAL Iface, exiting.");
-
-        goto shutdown;
-    }
-
-    configureRpcThreadpool(1, true /*callerWillJoin*/);
-
-    status = service->registerAsService();
-    if (status != OK) {
-        ALOGE("Could not register service for Power HAL Iface (%d).", status);
-        goto shutdown;
-    }
-
-    ALOGI("Power Service is ready");
-    joinRpcThreadpool();
-    //Should not pass this line
-
-shutdown:
-    // In normal operation, we don't expect the thread pool to exit
-
-    ALOGE("Power Service is shutting down");
-    return 1;
-}
diff --git a/power/1.1/vts/functional/Android.bp b/power/1.1/vts/functional/Android.bp
index f886bd2..604cd36 100644
--- a/power/1.1/vts/functional/Android.bp
+++ b/power/1.1/vts/functional/Android.bp
@@ -16,19 +16,10 @@
 
 cc_test {
     name: "VtsHalPowerV1_1TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalPowerV1_1TargetTest.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libhidlbase",
-        "libhidltransport",
-        "libutils",
+    static_libs: [
+        "android.hardware.power@1.0",
         "android.hardware.power@1.1",
     ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ]
 }
diff --git a/power/Android.bp b/power/Android.bp
index 7a315fa..a5415df 100644
--- a/power/Android.bp
+++ b/power/Android.bp
@@ -4,6 +4,5 @@
     "1.0/default",
     "1.0/vts/functional",
     "1.1",
-    "1.1/default",
     "1.1/vts/functional",
 ]
diff --git a/radio/1.0/Android.bp b/radio/1.0/Android.bp
index 988f5d2..093ceac 100644
--- a/radio/1.0/Android.bp
+++ b/radio/1.0/Android.bp
@@ -67,13 +67,16 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.radio@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.radio@1.0_genc++"],
     generated_headers: ["android.hardware.radio@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.radio@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/radio/1.0/IRadioResponse.hal b/radio/1.0/IRadioResponse.hal
index a94aac3..94b304a 100644
--- a/radio/1.0/IRadioResponse.hal
+++ b/radio/1.0/IRadioResponse.hal
@@ -161,6 +161,7 @@
      *   RadioError:NO_RESOURCES
      *   RadioError:CANCELLED
      *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:SIM_ABSENT
      */
     oneway supplyNetworkDepersonalizationResponse(RadioResponseInfo info, int32_t remainingRetries);
 
@@ -544,6 +545,7 @@
      *   RadioError:OPERATION_NOT_ALLOWED
      *   RadioError:NO_RESOURCES
      *   RadioError:CANCELLED
+     *   RadioError:SIM_ABSENT
      */
     oneway sendSmsResponse(RadioResponseInfo info, SendSmsResult sms);
 
@@ -574,6 +576,7 @@
      *   RadioError:OPERATION_NOT_ALLOWED
      *   RadioError:NO_RESOURCES
      *   RadioError:CANCELLED
+     *   RadioError:SIM_ABSENT
      */
     oneway sendSMSExpectMoreResponse(RadioResponseInfo info, SendSmsResult sms);
 
@@ -594,6 +597,7 @@
      *   RadioError:NO_MEMORY
      *   RadioError:NO_RESOURCES
      *   RadioError:CANCELLED
+     *   RadioError:SIM_ABSENT
      */
     oneway setupDataCallResponse(RadioResponseInfo info, SetupDataCallResult dcResponse);
 
@@ -860,6 +864,7 @@
      *   RadioError:NO_MEMORY
      *   RadioError:NO_RESOURCES
      *   RadioError:CANCELLED
+     *   RadioError:SIM_ABSENT
      */
     oneway deactivateDataCallResponse(RadioResponseInfo info);
 
@@ -1166,6 +1171,7 @@
      *   RadioError:NO_RESOURCES
      *   RadioError:CANCELLED
      *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:SIM_ABSENT
      */
     oneway getDataCallListResponse(RadioResponseInfo info, vec<SetupDataCallResult> dcResponse);
 
@@ -1210,6 +1216,7 @@
      *   RadioError:REQUEST_NOT_SUPPORTED
      *   RadioError:CANCELLED
      *   RadioError:INVALID_MODEM_STATE
+     *   RadioError:SIM_ABSENT
      */
     oneway writeSmsToSimResponse(RadioResponseInfo info, int32_t index);
 
@@ -1231,6 +1238,7 @@
      *   RadioError:NO_RESOURCES
      *   RadioError:CANCELLED
      *   RadioError:INVALID_MODEM_STATE
+     *   RadioError:SIM_ABSENT
      */
     oneway deleteSmsOnSimResponse(RadioResponseInfo info);
 
@@ -1615,6 +1623,7 @@
      *   RadioError:ENCODING_ERR
      *   RadioError:NO_RESOURCES
      *   RadioError:CANCELLED
+     *   RadioError:SIM_ABSENT
      */
     oneway sendCdmaSmsResponse(RadioResponseInfo info, SendSmsResult sms);
 
@@ -1819,6 +1828,7 @@
      *   RadioError:NO_RESOURCES
      *   RadioError:CANCELLED
      *   RadioError:INVALID_MODEM_STATE
+     *   RadioError:SIM_ABSENT
      */
     oneway writeSmsToRuimResponse(RadioResponseInfo info, uint32_t index);
 
@@ -1839,6 +1849,8 @@
      *   RadioError:NO_RESOURCES
      *   RadioError:CANCELLED
      *   RadioError:INVALID_MODEM_STATE
+     *   RadioError:OPERATION_NOT_ALLOWED
+     *   RadioError:SIM_ABSENT
      */
     oneway deleteSmsOnRuimResponse(RadioResponseInfo info);
 
@@ -1906,6 +1918,7 @@
      *   RadioError:OPERATION_NOT_ALLOWED
      *   RadioError:NO_RESOURCES
      *   RadioError:CANCELLED
+     *   RadioError:SIM_ABSENT
      */
     oneway getSmscAddressResponse(RadioResponseInfo info, string smsc);
 
@@ -1927,6 +1940,7 @@
      *   RadioError:OPERATION_NOT_ALLOWED
      *   RadioError:NO_RESOURCES
      *   RadioError:CANCELLED
+     *   RadioError:SIM_ABSENT
      */
     oneway setSmscAddressResponse(RadioResponseInfo info);
 
@@ -1946,6 +1960,7 @@
      *   RadioError:REQUEST_NOT_SUPPORTED
      *   RadioError:NO_RESOURCES
      *   RadioError:CANCELLED
+     *   RadioError:SIM_ABSENT
      */
     oneway reportSmsMemoryStatusResponse(RadioResponseInfo info);
 
@@ -2024,6 +2039,7 @@
      *   RadioError:NO_RESOURCES
      *   RadioError:CANCELLED
      *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:SIM_ABSENT
      */
     oneway sendEnvelopeWithStatusResponse(RadioResponseInfo info, IccIoResult iccIo);
 
@@ -2328,6 +2344,7 @@
      *   RadioError:NO_RESOURCES
      *   RadioError:CANCELLED
      *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:SIM_ABSENT
      */
     oneway setDataProfileResponse(RadioResponseInfo info);
 
@@ -2414,6 +2431,7 @@
      *   RadioError:NO_RESOURCES
      *   RadioError:CANCELLED
      *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:SIM_ABSENT
      */
     oneway stopLceServiceResponse(RadioResponseInfo info, LceStatusInfo statusInfo);
 
@@ -2430,6 +2448,7 @@
      *   RadioError:NO_RESOURCES
      *   RadioError:CANCELLED
      *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:SIM_ABSENT
      */
     oneway pullLceDataResponse(RadioResponseInfo info, LceDataInfo lceInfo);
 
diff --git a/radio/1.0/types.hal b/radio/1.0/types.hal
index c5d7f8a..4d22bc0 100644
--- a/radio/1.0/types.hal
+++ b/radio/1.0/types.hal
@@ -1507,8 +1507,8 @@
     int32_t lac;                          // 16-bit Location Area Code, 0..65535, INT_MAX if unknown
     int32_t cid;                          // 16-bit GSM Cell Identity described in
                                           // TS 27.007, 0..65535, INT_MAX if unknown
-    int32_t arfcn;                        // 16-bit GSM Absolute RF channel number, INT_MAX if
-                                          // unknown
+    int32_t arfcn;                        // 16-bit GSM Absolute RF channel number; this value must
+                                          // be valid
     uint8_t bsic;                         // 6-bit Base Station Identity Code, 0xFF if unknown
 };
 
@@ -1520,9 +1520,9 @@
     int32_t cid;                          // 28-bit UMTS Cell Identity described in
                                           // TS 25.331, 0..268435455, INT_MAX if unknown
     int32_t psc;                          // 9-bit UMTS Primary Scrambling Code described in
-                                          // TS 25.331, 0..511, INT_MAX if unknown
-    int32_t uarfcn;                       // 16-bit UMTS Absolute RF Channel Number, INT_MAX if
-                                          // unknown
+                                          // TS 25.331, 0..511; this value must be valid
+    int32_t uarfcn;                       // 16-bit UMTS Absolute RF Channel Number; this value must
+                                          // be valid
 };
 
 struct CellIdentityCdma {
@@ -1547,10 +1547,10 @@
                                           // unknown
     int32_t ci;                           // 28-bit Cell Identity described in TS TS 27.007, INT_MAX
                                           // if unknown
-    int32_t pci;                          // physical cell id 0..503, INT_MAX if unknown
+    int32_t pci;                          // physical cell id 0..503; this value must be valid
     int32_t tac;                          // 16-bit tracking area code, INT_MAX if unknown
-    int32_t earfcn;                       // 18-bit LTE Absolute RC Channel Number, INT_MAX if
-                                          // unknown
+    int32_t earfcn;                       // 18-bit LTE Absolute RF Channel Number; this value must
+                                          // be valid
 };
 
 struct CellIdentityTdscdma {
diff --git a/radio/1.0/vts/OWNERS b/radio/1.0/vts/OWNERS
new file mode 100644
index 0000000..2384317
--- /dev/null
+++ b/radio/1.0/vts/OWNERS
@@ -0,0 +1,8 @@
+# Telephony team
+amitmahajan@google.com
+sanketpadawe@google.com
+shuoq@google.com
+
+# VTS team
+yuexima@google.com
+yim@google.com
diff --git a/radio/1.0/vts/functional/Android.bp b/radio/1.0/vts/functional/Android.bp
index eb11b54..82a8a72 100644
--- a/radio/1.0/vts/functional/Android.bp
+++ b/radio/1.0/vts/functional/Android.bp
@@ -16,7 +16,7 @@
 
 cc_test {
     name: "VtsHalRadioV1_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["radio_hidl_hal_cell_broadcast.cpp",
            "radio_hidl_hal_data.cpp",
            "radio_hidl_hal_icc.cpp",
@@ -30,46 +30,22 @@
            "radio_response.cpp",
            "VtsHalRadioV1_0TargetTest.cpp",
            "vts_test_util.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libnativehelper",
-        "libutils",
+    static_libs: [
         "android.hardware.radio@1.0",
     ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ],
 }
 
 cc_test {
     name: "VtsHalSapV1_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["sap_callback.cpp",
            "sap_hidl_hal_api.cpp",
            "sap_hidl_hal_test.cpp",
            "VtsHalSapV1_0TargetTest.cpp",
            "vts_test_util.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libnativehelper",
-        "libutils",
+    static_libs: [
         "android.hardware.radio@1.0",
     ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ],
 }
 
 cc_library_static {
@@ -82,4 +58,4 @@
 cc_library_headers {
     name: "radio.util.header@1.0",
     export_include_dirs: ["."],
-}
\ No newline at end of file
+}
diff --git a/radio/1.0/vts/functional/radio_hidl_hal_misc.cpp b/radio/1.0/vts/functional/radio_hidl_hal_misc.cpp
index d93b176..795af86 100644
--- a/radio/1.0/vts/functional/radio_hidl_hal_misc.cpp
+++ b/radio/1.0/vts/functional/radio_hidl_hal_misc.cpp
@@ -70,7 +70,7 @@
 TEST_F(RadioHidlTest, setRadioPower) {
     int serial = GetRandomSerialNumber();
 
-    radio->setRadioPower(serial, 0);
+    radio->setRadioPower(serial, 1);
     EXPECT_EQ(std::cv_status::no_timeout, wait());
     EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp->rspInfo.type);
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
diff --git a/radio/1.0/vts/functional/radio_hidl_hal_voice.cpp b/radio/1.0/vts/functional/radio_hidl_hal_voice.cpp
index 8d6e200..1d2f199 100644
--- a/radio/1.0/vts/functional/radio_hidl_hal_voice.cpp
+++ b/radio/1.0/vts/functional/radio_hidl_hal_voice.cpp
@@ -366,6 +366,7 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
+        std::cout << static_cast<int>(radioRsp->rspInfo.error) << std::endl;
         ASSERT_TRUE(CheckGeneralError() ||
                     radioRsp->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
                     radioRsp->rspInfo.error == RadioError::NONE ||
diff --git a/radio/1.1/Android.bp b/radio/1.1/Android.bp
index 3a3f639..156cf99 100644
--- a/radio/1.1/Android.bp
+++ b/radio/1.1/Android.bp
@@ -60,13 +60,16 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.radio@1.1",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.radio@1.1_genc++"],
     generated_headers: ["android.hardware.radio@1.1_genc++_headers"],
     export_generated_headers: ["android.hardware.radio@1.1_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/radio/1.1/IRadioResponse.hal b/radio/1.1/IRadioResponse.hal
index 4e7bf43..759602b 100644
--- a/radio/1.1/IRadioResponse.hal
+++ b/radio/1.1/IRadioResponse.hal
@@ -16,6 +16,7 @@
 
 package android.hardware.radio@1.1;
 
+import @1.0::RadioResponseInfo;
 import @1.0::IRadioResponse;
 
 /**
diff --git a/radio/1.1/vts/OWNERS b/radio/1.1/vts/OWNERS
new file mode 100644
index 0000000..2384317
--- /dev/null
+++ b/radio/1.1/vts/OWNERS
@@ -0,0 +1,8 @@
+# Telephony team
+amitmahajan@google.com
+sanketpadawe@google.com
+shuoq@google.com
+
+# VTS team
+yuexima@google.com
+yim@google.com
diff --git a/radio/1.1/vts/functional/Android.bp b/radio/1.1/vts/functional/Android.bp
index 9000eb2..e7195ee 100644
--- a/radio/1.1/vts/functional/Android.bp
+++ b/radio/1.1/vts/functional/Android.bp
@@ -16,30 +16,18 @@
 
 cc_test {
     name: "VtsHalRadioV1_1TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["radio_hidl_hal_api.cpp",
            "radio_hidl_hal_test.cpp",
            "radio_indication.cpp",
            "radio_response.cpp",
            "VtsHalRadioV1_1TargetTest.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libnativehelper",
-        "libutils",
+    static_libs: [
+        "RadioVtsTestUtilBase",
         "android.hardware.radio@1.1",
         "android.hardware.radio@1.0",
     ],
-    static_libs: ["VtsHalHidlTargetTestBase",
-                  "RadioVtsTestUtilBase"],
     header_libs: [
         "radio.util.header@1.0",
     ],
-    cflags: [
-        "-O0",
-        "-g",
-    ],
 }
diff --git a/radio/deprecated/1.0/Android.bp b/radio/deprecated/1.0/Android.bp
index e45ecc3..e63ed28 100644
--- a/radio/deprecated/1.0/Android.bp
+++ b/radio/deprecated/1.0/Android.bp
@@ -49,13 +49,16 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.radio.deprecated@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.radio.deprecated@1.0_genc++"],
     generated_headers: ["android.hardware.radio.deprecated@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.radio.deprecated@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/renderscript/1.0/Android.bp b/renderscript/1.0/Android.bp
index d599315..0f62652 100644
--- a/renderscript/1.0/Android.bp
+++ b/renderscript/1.0/Android.bp
@@ -46,13 +46,17 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.renderscript@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.renderscript@1.0_genc++"],
     generated_headers: ["android.hardware.renderscript@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.renderscript@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+        support_system_process: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/renderscript/1.0/default/Device.cpp b/renderscript/1.0/default/Device.cpp
index 3aae060..4831a8b 100644
--- a/renderscript/1.0/default/Device.cpp
+++ b/renderscript/1.0/default/Device.cpp
@@ -1,6 +1,9 @@
 #include "Context.h"
 #include "Device.h"
 
+#include <android/dlext.h>
+#include <dlfcn.h>
+
 namespace android {
 namespace hardware {
 namespace renderscript {
@@ -39,7 +42,25 @@
     static_assert(sizeof(size_t) <= sizeof(uint64_t), "RenderScript HIDL Error: sizeof(size_t) > sizeof(uint64_t)");
 
     const char* filename = "libRS_internal.so";
-    void* handle = dlopen(filename, RTLD_LAZY | RTLD_LOCAL);
+    // Try to load libRS_internal.so from the "rs" namespace directly.
+    typedef struct android_namespace_t* (*GetExportedNamespaceFnPtr)(const char*);
+    GetExportedNamespaceFnPtr getExportedNamespace =
+        (GetExportedNamespaceFnPtr)dlsym(RTLD_DEFAULT, "android_get_exported_namespace");
+    void* handle = nullptr;
+    if (getExportedNamespace != nullptr) {
+        android_namespace_t* rs_namespace = getExportedNamespace("rs");
+        if (rs_namespace != nullptr) {
+            const android_dlextinfo dlextinfo = {
+                .flags = ANDROID_DLEXT_USE_NAMESPACE, .library_namespace = rs_namespace,
+            };
+            handle = android_dlopen_ext(filename, RTLD_LAZY | RTLD_LOCAL, &dlextinfo);
+        }
+    }
+    if (handle == nullptr) {
+        // if there is no "rs" namespace (in case when this HAL impl is loaded
+        // into a vendor process), then use the plain dlopen.
+        handle = dlopen(filename, RTLD_LAZY | RTLD_LOCAL);
+    }
 
     dispatchTable dispatchHal = {
         .SetNativeLibDir = (SetNativeLibDirFnPtr) nullptr,
diff --git a/renderscript/1.0/vts/functional/Android.bp b/renderscript/1.0/vts/functional/Android.bp
index 5256c1f..bf011e6 100644
--- a/renderscript/1.0/vts/functional/Android.bp
+++ b/renderscript/1.0/vts/functional/Android.bp
@@ -23,21 +23,9 @@
         "VtsScriptTests.cpp",
         "bitcode.cpp",
     ],
-    defaults: ["hidl_defaults"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libnativehelper",
-        "libutils",
-        "libnativewindow",
+    defaults: ["VtsHalTargetTestDefaults"],
+    static_libs: [
         "android.hardware.renderscript@1.0",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
+        "libnativewindow",
     ],
 }
diff --git a/renderscript/1.0/vts/functional/VtsHalRenderscriptV1_0TargetTest.cpp b/renderscript/1.0/vts/functional/VtsHalRenderscriptV1_0TargetTest.cpp
index 2670b8d..c6eecd6 100644
--- a/renderscript/1.0/vts/functional/VtsHalRenderscriptV1_0TargetTest.cpp
+++ b/renderscript/1.0/vts/functional/VtsHalRenderscriptV1_0TargetTest.cpp
@@ -28,8 +28,10 @@
 }
 
 void RenderscriptHidlTest::TearDown() {
-    context->contextFinish();
-    context->contextDestroy();
+    if (context.get() != nullptr) {
+        context->contextFinish();
+        context->contextDestroy();
+    }
 }
 
 // A class for test environment setup (kept since this file is a template).
diff --git a/sensors/1.0/Android.bp b/sensors/1.0/Android.bp
index f6cf4a7..b2cda05 100644
--- a/sensors/1.0/Android.bp
+++ b/sensors/1.0/Android.bp
@@ -39,13 +39,16 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.sensors@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.sensors@1.0_genc++"],
     generated_headers: ["android.hardware.sensors@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.sensors@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/sensors/1.0/default/Android.bp b/sensors/1.0/default/Android.bp
index 8144590..4bbafa6 100644
--- a/sensors/1.0/default/Android.bp
+++ b/sensors/1.0/default/Android.bp
@@ -38,6 +38,9 @@
         "android.hardware.sensors@1.0",
     ],
     local_include_dirs: ["include/sensors"],
+    export_shared_lib_headers: [
+        "libhardware",
+    ],
 }
 
 
diff --git a/sensors/1.0/vts/functional/Android.bp b/sensors/1.0/vts/functional/Android.bp
index af149ba..a49307d 100644
--- a/sensors/1.0/vts/functional/Android.bp
+++ b/sensors/1.0/vts/functional/Android.bp
@@ -16,19 +16,8 @@
 
 cc_test {
     name: "VtsHalSensorsV1_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalSensorsV1_0TargetTest.cpp"],
-    shared_libs: [
-        "android.hardware.sensors@1.0",
-        "libcutils",
-        "libhidlbase",
-        "liblog",
-        "libutils",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ],
+    static_libs: ["android.hardware.sensors@1.0"],
 }
 
diff --git a/soundtrigger/2.0/Android.bp b/soundtrigger/2.0/Android.bp
index 8259776..f45c4e2 100644
--- a/soundtrigger/2.0/Android.bp
+++ b/soundtrigger/2.0/Android.bp
@@ -46,13 +46,16 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.soundtrigger@2.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.soundtrigger@2.0_genc++"],
     generated_headers: ["android.hardware.soundtrigger@2.0_genc++_headers"],
     export_generated_headers: ["android.hardware.soundtrigger@2.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/soundtrigger/2.0/default/OWNERS b/soundtrigger/2.0/default/OWNERS
new file mode 100644
index 0000000..6fdc97c
--- /dev/null
+++ b/soundtrigger/2.0/default/OWNERS
@@ -0,0 +1,3 @@
+elaurent@google.com
+krocard@google.com
+mnaganov@google.com
diff --git a/soundtrigger/2.0/vts/functional/Android.bp b/soundtrigger/2.0/vts/functional/Android.bp
index 8f0cc4e..be6b3a8 100644
--- a/soundtrigger/2.0/vts/functional/Android.bp
+++ b/soundtrigger/2.0/vts/functional/Android.bp
@@ -16,21 +16,7 @@
 
 cc_test {
     name: "VtsHalSoundtriggerV2_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalSoundtriggerV2_0TargetTest.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libnativehelper",
-        "libutils",
-        "android.hardware.soundtrigger@2.0",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ],
+    static_libs: ["android.hardware.soundtrigger@2.0"],
 }
diff --git a/tests/Android.bp b/tests/Android.bp
index ddf300b..9583bfd 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -20,6 +20,8 @@
     "memory/1.0/default",
     "msgq/1.0",
     "msgq/1.0/default",
+    "multithread/1.0",
+    "multithread/1.0/default",
     "pointer/1.0",
     "pointer/1.0/default",
     "pointer/1.0/default/lib",
diff --git a/tests/bar/1.0/.hidl_for_test b/tests/bar/1.0/.hidl_for_test
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/bar/1.0/.hidl_for_test
diff --git a/tests/bar/1.0/Android.bp b/tests/bar/1.0/Android.bp
index 4c76014..44ae7a5 100644
--- a/tests/bar/1.0/Android.bp
+++ b/tests/bar/1.0/Android.bp
@@ -67,13 +67,16 @@
     ],
 }
 
-cc_library_shared {
+cc_test_library {
     name: "android.hardware.tests.bar@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.tests.bar@1.0_genc++"],
     generated_headers: ["android.hardware.tests.bar@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.tests.bar@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/tests/baz/1.0/.hidl_for_test b/tests/baz/1.0/.hidl_for_test
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/baz/1.0/.hidl_for_test
diff --git a/tests/baz/1.0/Android.bp b/tests/baz/1.0/Android.bp
index 1445b11..7fa8b27 100644
--- a/tests/baz/1.0/Android.bp
+++ b/tests/baz/1.0/Android.bp
@@ -60,13 +60,16 @@
     ],
 }
 
-cc_library_shared {
+cc_test_library {
     name: "android.hardware.tests.baz@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.tests.baz@1.0_genc++"],
     generated_headers: ["android.hardware.tests.baz@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.tests.baz@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/tests/expression/1.0/.hidl_for_test b/tests/expression/1.0/.hidl_for_test
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/expression/1.0/.hidl_for_test
diff --git a/tests/expression/1.0/Android.bp b/tests/expression/1.0/Android.bp
index 0cfe47d..0ea0acf 100644
--- a/tests/expression/1.0/Android.bp
+++ b/tests/expression/1.0/Android.bp
@@ -42,13 +42,16 @@
     ],
 }
 
-cc_library_shared {
+cc_test_library {
     name: "android.hardware.tests.expression@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.tests.expression@1.0_genc++"],
     generated_headers: ["android.hardware.tests.expression@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.tests.expression@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/tests/extension/light/2.0/.hidl_for_test b/tests/extension/light/2.0/.hidl_for_test
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/extension/light/2.0/.hidl_for_test
diff --git a/tests/extension/light/2.0/Android.bp b/tests/extension/light/2.0/Android.bp
index 6469b45..e8a5017 100644
--- a/tests/extension/light/2.0/Android.bp
+++ b/tests/extension/light/2.0/Android.bp
@@ -39,13 +39,16 @@
     ],
 }
 
-cc_library_shared {
+cc_test_library {
     name: "android.hardware.tests.extension.light@2.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.tests.extension.light@2.0_genc++"],
     generated_headers: ["android.hardware.tests.extension.light@2.0_genc++_headers"],
     export_generated_headers: ["android.hardware.tests.extension.light@2.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/tests/foo/1.0/.hidl_for_test b/tests/foo/1.0/.hidl_for_test
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/foo/1.0/.hidl_for_test
diff --git a/tests/foo/1.0/Android.bp b/tests/foo/1.0/Android.bp
index b698847..b5de12e 100644
--- a/tests/foo/1.0/Android.bp
+++ b/tests/foo/1.0/Android.bp
@@ -67,13 +67,16 @@
     ],
 }
 
-cc_library_shared {
+cc_test_library {
     name: "android.hardware.tests.foo@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.tests.foo@1.0_genc++"],
     generated_headers: ["android.hardware.tests.foo@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.tests.foo@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/tests/hash/1.0/.hidl_for_test b/tests/hash/1.0/.hidl_for_test
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/hash/1.0/.hidl_for_test
diff --git a/tests/hash/1.0/Android.bp b/tests/hash/1.0/Android.bp
index 617ddec..d4d1d1a 100644
--- a/tests/hash/1.0/Android.bp
+++ b/tests/hash/1.0/Android.bp
@@ -35,13 +35,16 @@
     ],
 }
 
-cc_library_shared {
+cc_test_library {
     name: "android.hardware.tests.hash@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.tests.hash@1.0_genc++"],
     generated_headers: ["android.hardware.tests.hash@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.tests.hash@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/tests/inheritance/1.0/.hidl_for_test b/tests/inheritance/1.0/.hidl_for_test
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/inheritance/1.0/.hidl_for_test
diff --git a/tests/inheritance/1.0/Android.bp b/tests/inheritance/1.0/Android.bp
index 4dbcf4b..93a8ad5 100644
--- a/tests/inheritance/1.0/Android.bp
+++ b/tests/inheritance/1.0/Android.bp
@@ -56,13 +56,16 @@
     ],
 }
 
-cc_library_shared {
+cc_test_library {
     name: "android.hardware.tests.inheritance@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.tests.inheritance@1.0_genc++"],
     generated_headers: ["android.hardware.tests.inheritance@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.tests.inheritance@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/tests/libhwbinder/1.0/.hidl_for_test b/tests/libhwbinder/1.0/.hidl_for_test
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/libhwbinder/1.0/.hidl_for_test
diff --git a/tests/libhwbinder/1.0/Android.bp b/tests/libhwbinder/1.0/Android.bp
index f254bad..4f3beb0 100644
--- a/tests/libhwbinder/1.0/Android.bp
+++ b/tests/libhwbinder/1.0/Android.bp
@@ -42,13 +42,16 @@
     ],
 }
 
-cc_library_shared {
+cc_test_library {
     name: "android.hardware.tests.libhwbinder@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.tests.libhwbinder@1.0_genc++"],
     generated_headers: ["android.hardware.tests.libhwbinder@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.tests.libhwbinder@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/tests/libhwbinder/aidl/.hidl_for_test b/tests/libhwbinder/aidl/.hidl_for_test
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/libhwbinder/aidl/.hidl_for_test
diff --git a/tests/memory/1.0/.hidl_for_test b/tests/memory/1.0/.hidl_for_test
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/memory/1.0/.hidl_for_test
diff --git a/tests/memory/1.0/Android.bp b/tests/memory/1.0/Android.bp
index 5a62896..d39ba28 100644
--- a/tests/memory/1.0/Android.bp
+++ b/tests/memory/1.0/Android.bp
@@ -35,13 +35,16 @@
     ],
 }
 
-cc_library_shared {
+cc_test_library {
     name: "android.hardware.tests.memory@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.tests.memory@1.0_genc++"],
     generated_headers: ["android.hardware.tests.memory@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.tests.memory@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/tests/msgq/1.0/.hidl_for_test b/tests/msgq/1.0/.hidl_for_test
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/msgq/1.0/.hidl_for_test
diff --git a/tests/msgq/1.0/Android.bp b/tests/msgq/1.0/Android.bp
index 19ff89c..7758ee8 100644
--- a/tests/msgq/1.0/Android.bp
+++ b/tests/msgq/1.0/Android.bp
@@ -42,13 +42,16 @@
     ],
 }
 
-cc_library_shared {
+cc_test_library {
     name: "android.hardware.tests.msgq@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.tests.msgq@1.0_genc++"],
     generated_headers: ["android.hardware.tests.msgq@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.tests.msgq@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/tests/multithread/1.0/.hidl_for_test b/tests/multithread/1.0/.hidl_for_test
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/multithread/1.0/.hidl_for_test
diff --git a/tests/multithread/1.0/Android.bp b/tests/multithread/1.0/Android.bp
new file mode 100644
index 0000000..76ad2c1
--- /dev/null
+++ b/tests/multithread/1.0/Android.bp
@@ -0,0 +1,62 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+filegroup {
+    name: "android.hardware.tests.multithread@1.0_hal",
+    srcs: [
+        "IMultithread.hal",
+    ],
+}
+
+genrule {
+    name: "android.hardware.tests.multithread@1.0_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++-sources -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.tests.multithread@1.0",
+    srcs: [
+        ":android.hardware.tests.multithread@1.0_hal",
+    ],
+    out: [
+        "android/hardware/tests/multithread/1.0/MultithreadAll.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.tests.multithread@1.0_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++-headers -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.tests.multithread@1.0",
+    srcs: [
+        ":android.hardware.tests.multithread@1.0_hal",
+    ],
+    out: [
+        "android/hardware/tests/multithread/1.0/IMultithread.h",
+        "android/hardware/tests/multithread/1.0/IHwMultithread.h",
+        "android/hardware/tests/multithread/1.0/BnHwMultithread.h",
+        "android/hardware/tests/multithread/1.0/BpHwMultithread.h",
+        "android/hardware/tests/multithread/1.0/BsMultithread.h",
+    ],
+}
+
+cc_test_library {
+    name: "android.hardware.tests.multithread@1.0",
+    defaults: ["hidl-module-defaults"],
+    generated_sources: ["android.hardware.tests.multithread@1.0_genc++"],
+    generated_headers: ["android.hardware.tests.multithread@1.0_genc++_headers"],
+    export_generated_headers: ["android.hardware.tests.multithread@1.0_genc++_headers"],
+    vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+    ],
+}
diff --git a/tests/multithread/1.0/Android.mk b/tests/multithread/1.0/Android.mk
new file mode 100644
index 0000000..f63381d
--- /dev/null
+++ b/tests/multithread/1.0/Android.mk
@@ -0,0 +1,76 @@
+# This file is autogenerated by hidl-gen. Do not edit manually.
+
+LOCAL_PATH := $(call my-dir)
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.tests.multithread-V1.0-java
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(call local-generated-sources-dir, COMMON)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+
+LOCAL_JAVA_LIBRARIES := \
+    android.hidl.base-V1.0-java \
+
+
+#
+# Build IMultithread.hal
+#
+GEN := $(intermediates)/android/hardware/tests/multithread/V1_0/IMultithread.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IMultithread.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.tests.multithread@1.0::IMultithread
+
+$(GEN): $(LOCAL_PATH)/IMultithread.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+include $(BUILD_JAVA_LIBRARY)
+
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.tests.multithread-V1.0-java-static
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(call local-generated-sources-dir, COMMON)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    android.hidl.base-V1.0-java-static \
+
+
+#
+# Build IMultithread.hal
+#
+GEN := $(intermediates)/android/hardware/tests/multithread/V1_0/IMultithread.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IMultithread.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.tests.multithread@1.0::IMultithread
+
+$(GEN): $(LOCAL_PATH)/IMultithread.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/tests/multithread/1.0/IMultithread.hal b/tests/multithread/1.0/IMultithread.hal
new file mode 100644
index 0000000..19dc4f6
--- /dev/null
+++ b/tests/multithread/1.0/IMultithread.hal
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+package android.hardware.tests.multithread@1.0;
+
+/**
+ * IMultithread tests configureRpcThreadpool
+ *
+ * Makes calls finish only when specific number of them are running in parallel
+ */
+interface IMultithread {
+    /**
+     * Sets up controller
+     * Must be called for each test
+     * @param maxThreads arg passed to configureRpcThreadpool
+     * Could not be decremented by future calls
+     * @param numThreads number of calls in parallel to finish
+     */
+    setNumThreads(int32_t maxThreads, int32_t numThreads);
+
+    /**
+     * Makes a new call
+     * @return noTimeout numThreads appeared in parallel before timeout
+     * Shall return the same value for one setNumThreads call
+     */
+    runNewThread() generates (bool noTimeout);
+};
diff --git a/tests/multithread/1.0/default/Android.bp b/tests/multithread/1.0/default/Android.bp
new file mode 100644
index 0000000..a7a750a
--- /dev/null
+++ b/tests/multithread/1.0/default/Android.bp
@@ -0,0 +1,16 @@
+cc_library_shared {
+    name: "android.hardware.tests.multithread@1.0-impl",
+    defaults: ["hidl_defaults"],
+    relative_install_path: "hw",
+    srcs: [
+        "Multithread.cpp",
+    ],
+    shared_libs: [
+        "libbase",
+        "libhidlbase",
+        "libhidltransport",
+        "liblog",
+        "libutils",
+        "android.hardware.tests.multithread@1.0",
+    ],
+}
diff --git a/tests/multithread/1.0/default/Multithread.cpp b/tests/multithread/1.0/default/Multithread.cpp
new file mode 100644
index 0000000..1fb267c
--- /dev/null
+++ b/tests/multithread/1.0/default/Multithread.cpp
@@ -0,0 +1,63 @@
+#define LOG_TAG "hidl_test"
+
+#include <android-base/logging.h>
+#include "Multithread.h"
+#include <inttypes.h>
+#include <thread>
+
+#include <hidl/HidlTransportSupport.h>
+
+namespace android {
+namespace hardware {
+namespace tests {
+namespace multithread {
+namespace V1_0 {
+namespace implementation {
+
+// Methods from ::android::hardware::tests::multithread::V1_0::IMultithread follow.
+Return<void> Multithread::setNumThreads(int32_t maxThreads, int32_t numThreads) {
+    LOG(INFO) << "SERVER(Multithread) setNumThreads("
+              << maxThreads << ", " << numThreads << ")";
+
+    LOG(INFO) << "SERVER(Multithread) call configureRpcThreadpool("
+              << maxThreads << ")";
+    ::android::hardware::configureRpcThreadpool(maxThreads, /*willjoin*/ false);
+
+    mNumThreads = numThreads;
+    mNoTimeout = true;
+
+    return Void();
+}
+
+Return<bool> Multithread::runNewThread() {
+    LOG(INFO) << "SERVER(Multithread) runNewThread()";
+
+    std::unique_lock<std::mutex> lk(mCvMutex);
+    --mNumThreads;
+
+    LOG(INFO) << "SERVER(Multithread) runNewThread()";
+    LOG(INFO) << mNumThreads << "threads left";
+
+    mCv.notify_all();
+    bool noTimeout = mCv.wait_for(lk, kTimeoutDuration,
+        [&] { return mNumThreads <= 0 || !mNoTimeout; });
+
+    if (!noTimeout) {
+        mNoTimeout = false;
+        mCv.notify_all();
+    }
+    return mNoTimeout;
+}
+
+IMultithread* HIDL_FETCH_IMultithread(const char* /* name */) {
+    return new Multithread();
+}
+
+decltype(Multithread::kTimeoutDuration) Multithread::kTimeoutDuration;
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace multithread
+}  // namespace tests
+}  // namespace hardware
+}  // namespace android
diff --git a/tests/multithread/1.0/default/Multithread.h b/tests/multithread/1.0/default/Multithread.h
new file mode 100644
index 0000000..0d4a007
--- /dev/null
+++ b/tests/multithread/1.0/default/Multithread.h
@@ -0,0 +1,48 @@
+#ifndef ANDROID_HARDWARE_TESTS_MULTITHREAD_V1_0_MULTITHREAD_H
+#define ANDROID_HARDWARE_TESTS_MULTITHREAD_V1_0_MULTITHREAD_H
+
+#include <android/hardware/tests/multithread/1.0/IMultithread.h>
+#include <hidl/Status.h>
+
+#include <chrono>
+#include <condition_variable>
+#include <mutex>
+
+namespace android {
+namespace hardware {
+namespace tests {
+namespace multithread {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::tests::multithread::V1_0::IMultithread;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+
+using namespace std::chrono_literals;
+
+struct Multithread : public IMultithread {
+    // Methods from ::android::hardware::tests::multithread::V1_0::IMultithread follow.
+    virtual Return<void> setNumThreads(int32_t maxThreads, int32_t numThreads) override;
+    virtual Return<bool> runNewThread() override;
+
+   private:
+    int32_t mNumThreads;
+    bool mNoTimeout;
+
+    std::condition_variable mCv;
+    std::mutex mCvMutex;
+
+    static constexpr auto kTimeoutDuration = 100ms;
+};
+
+extern "C" IMultithread* HIDL_FETCH_IMultithread(const char* name);
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace multithread
+}  // namespace tests
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_TESTS_MULTITHREAD_V1_0_MULTITHREAD_H
diff --git a/tests/pointer/1.0/.hidl_for_test b/tests/pointer/1.0/.hidl_for_test
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/pointer/1.0/.hidl_for_test
diff --git a/tests/pointer/1.0/Android.bp b/tests/pointer/1.0/Android.bp
index 37fea94..178f165 100644
--- a/tests/pointer/1.0/Android.bp
+++ b/tests/pointer/1.0/Android.bp
@@ -42,13 +42,16 @@
     ],
 }
 
-cc_library_shared {
+cc_test_library {
     name: "android.hardware.tests.pointer@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.tests.pointer@1.0_genc++"],
     generated_headers: ["android.hardware.tests.pointer@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.tests.pointer@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/tetheroffload/config/1.0/Android.bp b/tetheroffload/config/1.0/Android.bp
index 7beefbf..2d62f16 100644
--- a/tetheroffload/config/1.0/Android.bp
+++ b/tetheroffload/config/1.0/Android.bp
@@ -35,13 +35,16 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.tetheroffload.config@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.tetheroffload.config@1.0_genc++"],
     generated_headers: ["android.hardware.tetheroffload.config@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.tetheroffload.config@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/tetheroffload/config/1.0/vts/functional/Android.bp b/tetheroffload/config/1.0/vts/functional/Android.bp
index 2e720c6..dc95eaa 100644
--- a/tetheroffload/config/1.0/vts/functional/Android.bp
+++ b/tetheroffload/config/1.0/vts/functional/Android.bp
@@ -14,20 +14,7 @@
 
 cc_test {
     name: "VtsHalTetheroffloadConfigV1_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalTetheroffloadConfigV1_0TargetTest.cpp"],
-    shared_libs: [
-        "android.hardware.tetheroffload.config@1.0",
-        "libbase",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "liblog",
-        "libutils",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ],
+    static_libs: ["android.hardware.tetheroffload.config@1.0"],
 }
diff --git a/tetheroffload/control/1.0/Android.bp b/tetheroffload/control/1.0/Android.bp
index d351edb..72f410e 100644
--- a/tetheroffload/control/1.0/Android.bp
+++ b/tetheroffload/control/1.0/Android.bp
@@ -46,13 +46,16 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.tetheroffload.control@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.tetheroffload.control@1.0_genc++"],
     generated_headers: ["android.hardware.tetheroffload.control@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.tetheroffload.control@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/tetheroffload/control/1.0/vts/functional/Android.bp b/tetheroffload/control/1.0/vts/functional/Android.bp
index 69fac6e..c6216a2 100644
--- a/tetheroffload/control/1.0/vts/functional/Android.bp
+++ b/tetheroffload/control/1.0/vts/functional/Android.bp
@@ -14,21 +14,10 @@
 
 cc_test {
     name: "VtsHalTetheroffloadControlV1_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalTetheroffloadControlV1_0TargetTest.cpp"],
-    shared_libs: [
+    static_libs: [
         "android.hardware.tetheroffload.config@1.0",
         "android.hardware.tetheroffload.control@1.0",
-        "libbase",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "liblog",
-        "libutils",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
     ],
 }
diff --git a/thermal/1.0/Android.bp b/thermal/1.0/Android.bp
index 6a9f9c7..aa97175 100644
--- a/thermal/1.0/Android.bp
+++ b/thermal/1.0/Android.bp
@@ -39,13 +39,16 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.thermal@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.thermal@1.0_genc++"],
     generated_headers: ["android.hardware.thermal@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.thermal@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/thermal/1.0/vts/functional/Android.bp b/thermal/1.0/vts/functional/Android.bp
index 9046882..f661f1e 100644
--- a/thermal/1.0/vts/functional/Android.bp
+++ b/thermal/1.0/vts/functional/Android.bp
@@ -16,22 +16,8 @@
 
 cc_test {
     name: "VtsHalThermalV1_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalThermalV1_0TargetTest.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libnativehelper",
-        "libutils",
-        "android.hardware.thermal@1.0",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ],
+    static_libs: ["android.hardware.thermal@1.0"],
 }
 
diff --git a/thermal/1.1/Android.bp b/thermal/1.1/Android.bp
new file mode 100644
index 0000000..0985d94
--- /dev/null
+++ b/thermal/1.1/Android.bp
@@ -0,0 +1,71 @@
+// This file is autogenerated by hidl-gen. Do not edit manually.
+
+filegroup {
+    name: "android.hardware.thermal@1.1_hal",
+    srcs: [
+        "IThermal.hal",
+        "IThermalCallback.hal",
+    ],
+}
+
+genrule {
+    name: "android.hardware.thermal@1.1_genc++",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++-sources -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.thermal@1.1",
+    srcs: [
+        ":android.hardware.thermal@1.1_hal",
+    ],
+    out: [
+        "android/hardware/thermal/1.1/ThermalAll.cpp",
+        "android/hardware/thermal/1.1/ThermalCallbackAll.cpp",
+    ],
+}
+
+genrule {
+    name: "android.hardware.thermal@1.1_genc++_headers",
+    tools: ["hidl-gen"],
+    cmd: "$(location hidl-gen) -o $(genDir) -Lc++-headers -randroid.hardware:hardware/interfaces -randroid.hidl:system/libhidl/transport android.hardware.thermal@1.1",
+    srcs: [
+        ":android.hardware.thermal@1.1_hal",
+    ],
+    out: [
+        "android/hardware/thermal/1.1/IThermal.h",
+        "android/hardware/thermal/1.1/IHwThermal.h",
+        "android/hardware/thermal/1.1/BnHwThermal.h",
+        "android/hardware/thermal/1.1/BpHwThermal.h",
+        "android/hardware/thermal/1.1/BsThermal.h",
+        "android/hardware/thermal/1.1/IThermalCallback.h",
+        "android/hardware/thermal/1.1/IHwThermalCallback.h",
+        "android/hardware/thermal/1.1/BnHwThermalCallback.h",
+        "android/hardware/thermal/1.1/BpHwThermalCallback.h",
+        "android/hardware/thermal/1.1/BsThermalCallback.h",
+    ],
+}
+
+cc_library {
+    name: "android.hardware.thermal@1.1",
+    defaults: ["hidl-module-defaults"],
+    generated_sources: ["android.hardware.thermal@1.1_genc++"],
+    generated_headers: ["android.hardware.thermal@1.1_genc++_headers"],
+    export_generated_headers: ["android.hardware.thermal@1.1_genc++_headers"],
+    vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "android.hardware.thermal@1.0",
+    ],
+    export_shared_lib_headers: [
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libutils",
+        "android.hardware.thermal@1.0",
+    ],
+}
diff --git a/thermal/1.1/Android.mk b/thermal/1.1/Android.mk
new file mode 100644
index 0000000..082d65b
--- /dev/null
+++ b/thermal/1.1/Android.mk
@@ -0,0 +1,120 @@
+# This file is autogenerated by hidl-gen. Do not edit manually.
+
+LOCAL_PATH := $(call my-dir)
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.thermal-V1.1-java
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(call local-generated-sources-dir, COMMON)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+
+LOCAL_JAVA_LIBRARIES := \
+    android.hardware.thermal-V1.0-java \
+    android.hidl.base-V1.0-java \
+
+
+#
+# Build IThermal.hal
+#
+GEN := $(intermediates)/android/hardware/thermal/V1_1/IThermal.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IThermal.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IThermalCallback.hal
+$(GEN): $(LOCAL_PATH)/IThermalCallback.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.thermal@1.1::IThermal
+
+$(GEN): $(LOCAL_PATH)/IThermal.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IThermalCallback.hal
+#
+GEN := $(intermediates)/android/hardware/thermal/V1_1/IThermalCallback.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IThermalCallback.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.thermal@1.1::IThermalCallback
+
+$(GEN): $(LOCAL_PATH)/IThermalCallback.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+include $(BUILD_JAVA_LIBRARY)
+
+
+################################################################################
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.thermal-V1.1-java-static
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+intermediates := $(call local-generated-sources-dir, COMMON)
+
+HIDL := $(HOST_OUT_EXECUTABLES)/hidl-gen$(HOST_EXECUTABLE_SUFFIX)
+
+LOCAL_STATIC_JAVA_LIBRARIES := \
+    android.hardware.thermal-V1.0-java-static \
+    android.hidl.base-V1.0-java-static \
+
+
+#
+# Build IThermal.hal
+#
+GEN := $(intermediates)/android/hardware/thermal/V1_1/IThermal.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IThermal.hal
+$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IThermalCallback.hal
+$(GEN): $(LOCAL_PATH)/IThermalCallback.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.thermal@1.1::IThermal
+
+$(GEN): $(LOCAL_PATH)/IThermal.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+
+#
+# Build IThermalCallback.hal
+#
+GEN := $(intermediates)/android/hardware/thermal/V1_1/IThermalCallback.java
+$(GEN): $(HIDL)
+$(GEN): PRIVATE_HIDL := $(HIDL)
+$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IThermalCallback.hal
+$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
+$(GEN): PRIVATE_CUSTOM_TOOL = \
+        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
+        -Ljava \
+        -randroid.hardware:hardware/interfaces \
+        -randroid.hidl:system/libhidl/transport \
+        android.hardware.thermal@1.1::IThermalCallback
+
+$(GEN): $(LOCAL_PATH)/IThermalCallback.hal
+	$(transform-generated-source)
+LOCAL_GENERATED_SOURCES += $(GEN)
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+
+
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/thermal/1.1/IThermal.hal b/thermal/1.1/IThermal.hal
new file mode 100644
index 0000000..14f35ba
--- /dev/null
+++ b/thermal/1.1/IThermal.hal
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+package android.hardware.thermal@1.1;
+
+import android.hardware.thermal@1.0::IThermal;
+import IThermalCallback;
+
+interface IThermal extends @1.0::IThermal {
+   /**
+    * Register an IThermalCallback, used by the Thermal HAL
+    * to send thermal events to the framework thermal service.
+    *
+    * @param callback the IThermalCallback to use for sending
+    *        thermal events, or nullptr to set no callback
+    */
+    registerThermalCallback(IThermalCallback callback);
+};
diff --git a/thermal/1.1/IThermalCallback.hal b/thermal/1.1/IThermalCallback.hal
new file mode 100644
index 0000000..f418ec3
--- /dev/null
+++ b/thermal/1.1/IThermalCallback.hal
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+package android.hardware.thermal@1.1;
+
+import android.hardware.thermal@1.0::Temperature;
+
+/**
+ * IThermalCallback connects vendor code to the framework binder ThermalService.
+ */
+interface IThermalCallback {
+    /**
+     * Send a thermal throttling start/stop event to all ThermalService
+     * thermal event listeners.
+     * @param isThrottling true if device is currently throttling
+     * @param temperature The temperature associated with the throttling
+     *        start/stop event
+     */
+    oneway notifyThrottling(bool isThrottling, Temperature temperature);
+};
diff --git a/thermal/1.1/vts/functional/Android.bp b/thermal/1.1/vts/functional/Android.bp
new file mode 100644
index 0000000..f5f01fa
--- /dev/null
+++ b/thermal/1.1/vts/functional/Android.bp
@@ -0,0 +1,26 @@
+//
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_test {
+    name: "VtsHalThermalV1_1TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: ["VtsHalThermalV1_1TargetTest.cpp"],
+    static_libs: [
+        "android.hardware.thermal@1.0",
+        "android.hardware.thermal@1.1",
+    ],
+}
+
diff --git a/thermal/1.1/vts/functional/VtsHalThermalV1_1TargetTest.cpp b/thermal/1.1/vts/functional/VtsHalThermalV1_1TargetTest.cpp
new file mode 100644
index 0000000..6c1599b
--- /dev/null
+++ b/thermal/1.1/vts/functional/VtsHalThermalV1_1TargetTest.cpp
@@ -0,0 +1,106 @@
+/*
+ * 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.
+ */
+
+#include <android/hardware/thermal/1.1/IThermal.h>
+#include <android/hardware/thermal/1.1/IThermalCallback.h>
+#include <android/hardware/thermal/1.0/types.h>
+
+#include <VtsHalHidlTargetCallbackBase.h>
+#include <VtsHalHidlTargetTestBase.h>
+
+using ::android::hardware::thermal::V1_0::Temperature;
+using ::android::hardware::thermal::V1_0::TemperatureType;
+using ::android::hardware::thermal::V1_1::IThermal;
+using ::android::hardware::thermal::V1_1::IThermalCallback;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::sp;
+
+constexpr char kCallbackNameNotifyThrottling[] = "notifyThrottling";
+static const Temperature kThrottleTemp = {
+    .type = TemperatureType::CPU,
+    .name = "test temperature sensor",
+    .currentValue = 98.6,
+    .throttlingThreshold = 58,
+    .shutdownThreshold = 60,
+    .vrThrottlingThreshold = 59,
+};
+
+class ThermalCallbackArgs {
+   public:
+     bool isThrottling;
+     Temperature temperature;
+};
+
+// Callback class for receiving thermal event notifications from main class
+class ThermalCallback
+    : public ::testing::VtsHalHidlTargetCallbackBase<ThermalCallbackArgs>,
+      public IThermalCallback {
+   public:
+    virtual ~ThermalCallback() = default;
+
+    Return<void> notifyThrottling(bool isThrottling,
+                                  const Temperature& temperature) override {
+        ThermalCallbackArgs args;
+        args.isThrottling = isThrottling;
+        args.temperature = temperature;
+        NotifyFromCallback(kCallbackNameNotifyThrottling, args);
+        return Void();
+    }
+};
+
+// The main test class for THERMAL HIDL HAL 1.1.
+class ThermalHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+   public:
+    virtual void SetUp() override {
+        mThermal = ::testing::VtsHalHidlTargetTestBase::getService<IThermal>();
+        ASSERT_NE(mThermal, nullptr);
+        mThermalCallback = new(std::nothrow) ThermalCallback();
+        ASSERT_NE(mThermalCallback, nullptr);
+        auto ret = mThermal->registerThermalCallback(mThermalCallback);
+        ASSERT_TRUE(ret.isOk());
+    }
+
+    virtual void TearDown() override {
+        auto ret = mThermal->registerThermalCallback(nullptr);
+        ASSERT_TRUE(ret.isOk());
+    }
+
+   protected:
+    sp<IThermal> mThermal;
+    sp<ThermalCallback> mThermalCallback;
+}; // class ThermalHidlTest
+
+// Test ThermalCallback::notifyThrottling().
+// This just calls into and back from our local ThermalCallback impl.
+// Note: a real thermal throttling event from the Thermal HAL could be
+// inadvertently received here.
+TEST_F(ThermalHidlTest, NotifyThrottlingTest) {
+    auto ret = mThermalCallback->notifyThrottling(true, kThrottleTemp);
+    ASSERT_TRUE(ret.isOk());
+    auto res = mThermalCallback->WaitForCallback(kCallbackNameNotifyThrottling);
+    EXPECT_TRUE(res.no_timeout);
+    ASSERT_TRUE(res.args);
+    EXPECT_EQ(true, res.args->isThrottling);
+    EXPECT_EQ(kThrottleTemp, res.args->temperature);
+}
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    int status = RUN_ALL_TESTS();
+    cout << "Test result = " << status << std::endl;
+    return status;
+}
diff --git a/thermal/Android.bp b/thermal/Android.bp
index ed19a37..a5415df 100644
--- a/thermal/Android.bp
+++ b/thermal/Android.bp
@@ -3,4 +3,6 @@
     "1.0",
     "1.0/default",
     "1.0/vts/functional",
+    "1.1",
+    "1.1/vts/functional",
 ]
diff --git a/tv/cec/1.0/Android.bp b/tv/cec/1.0/Android.bp
index bf3ffe2..c9da737 100644
--- a/tv/cec/1.0/Android.bp
+++ b/tv/cec/1.0/Android.bp
@@ -46,13 +46,16 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.tv.cec@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.tv.cec@1.0_genc++"],
     generated_headers: ["android.hardware.tv.cec@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.tv.cec@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/tv/input/1.0/Android.bp b/tv/input/1.0/Android.bp
index a3f8c94..22ea1d8 100644
--- a/tv/input/1.0/Android.bp
+++ b/tv/input/1.0/Android.bp
@@ -46,13 +46,16 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.tv.input@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.tv.input@1.0_genc++"],
     generated_headers: ["android.hardware.tv.input@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.tv.input@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/tv/input/1.0/vts/functional/Android.bp b/tv/input/1.0/vts/functional/Android.bp
index c862429..978830c 100644
--- a/tv/input/1.0/vts/functional/Android.bp
+++ b/tv/input/1.0/vts/functional/Android.bp
@@ -16,22 +16,8 @@
 
 cc_test {
     name: "VtsHalTvInputV1_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalTvInputV1_0TargetTest.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libnativehelper",
-        "libutils",
-        "android.hardware.tv.input@1.0",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ]
+    static_libs: ["android.hardware.tv.input@1.0"],
 }
 
diff --git a/usb/1.0/Android.bp b/usb/1.0/Android.bp
index b03f75b..afe1931 100644
--- a/usb/1.0/Android.bp
+++ b/usb/1.0/Android.bp
@@ -46,13 +46,16 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.usb@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.usb@1.0_genc++"],
     generated_headers: ["android.hardware.usb@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.usb@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/usb/1.0/vts/functional/Android.bp b/usb/1.0/vts/functional/Android.bp
index 7438bc7..96d3c0e 100644
--- a/usb/1.0/vts/functional/Android.bp
+++ b/usb/1.0/vts/functional/Android.bp
@@ -16,21 +16,7 @@
 
 cc_test {
     name: "VtsHalUsbV1_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalUsbV1_0TargetTest.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libnativehelper",
-        "libutils",
-        "android.hardware.usb@1.0",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ],
+    static_libs: ["android.hardware.usb@1.0"],
 }
diff --git a/usb/1.1/Android.bp b/usb/1.1/Android.bp
index f067606..5466001 100644
--- a/usb/1.1/Android.bp
+++ b/usb/1.1/Android.bp
@@ -46,13 +46,16 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.usb@1.1",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.usb@1.1_genc++"],
     generated_headers: ["android.hardware.usb@1.1_genc++_headers"],
     export_generated_headers: ["android.hardware.usb@1.1_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/usb/1.1/vts/functional/Android.bp b/usb/1.1/vts/functional/Android.bp
index 820f794..4bb3203 100644
--- a/usb/1.1/vts/functional/Android.bp
+++ b/usb/1.1/vts/functional/Android.bp
@@ -16,23 +16,11 @@
 
 cc_test {
     name: "VtsHalUsbV1_1TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalUsbV1_1TargetTest.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libnativehelper",
-        "libutils",
+    static_libs: [
         "android.hardware.usb@1.0",
         "android.hardware.usb@1.1",
     ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ],
 }
 
diff --git a/vibrator/1.0/Android.bp b/vibrator/1.0/Android.bp
index 0beff68..354b83f 100644
--- a/vibrator/1.0/Android.bp
+++ b/vibrator/1.0/Android.bp
@@ -39,13 +39,16 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.vibrator@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.vibrator@1.0_genc++"],
     generated_headers: ["android.hardware.vibrator@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.vibrator@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/vibrator/1.0/vts/functional/Android.bp b/vibrator/1.0/vts/functional/Android.bp
index 9e25def..016d627 100644
--- a/vibrator/1.0/vts/functional/Android.bp
+++ b/vibrator/1.0/vts/functional/Android.bp
@@ -16,19 +16,8 @@
 
 cc_test {
     name: "VtsHalVibratorV1_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalVibratorV1_0TargetTest.cpp"],
-    shared_libs: [
-        "libbase",
-        "libhidlbase",
-        "liblog",
-        "libutils",
-        "android.hardware.vibrator@1.0",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ],
+    static_libs: ["android.hardware.vibrator@1.0"],
 }
 
diff --git a/vibrator/1.1/Android.bp b/vibrator/1.1/Android.bp
index ee81d83..a47f37c 100644
--- a/vibrator/1.1/Android.bp
+++ b/vibrator/1.1/Android.bp
@@ -39,13 +39,16 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.vibrator@1.1",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.vibrator@1.1_genc++"],
     generated_headers: ["android.hardware.vibrator@1.1_genc++_headers"],
     export_generated_headers: ["android.hardware.vibrator@1.1_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/vibrator/1.1/vts/functional/Android.bp b/vibrator/1.1/vts/functional/Android.bp
index 5baa8ed..4f6454b 100644
--- a/vibrator/1.1/vts/functional/Android.bp
+++ b/vibrator/1.1/vts/functional/Android.bp
@@ -16,19 +16,11 @@
 
 cc_test {
     name: "VtsHalVibratorV1_1TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalVibratorV1_1TargetTest.cpp"],
-    shared_libs: [
-        "libbase",
-        "libhidlbase",
-        "liblog",
-        "libutils",
+    static_libs: [
+        "android.hardware.vibrator@1.0",
         "android.hardware.vibrator@1.1",
     ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ],
 }
 
diff --git a/vr/1.0/Android.bp b/vr/1.0/Android.bp
index d6949c5..cb9e2af 100644
--- a/vr/1.0/Android.bp
+++ b/vr/1.0/Android.bp
@@ -35,13 +35,16 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.vr@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.vr@1.0_genc++"],
     generated_headers: ["android.hardware.vr@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.vr@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/vr/1.0/vts/functional/Android.bp b/vr/1.0/vts/functional/Android.bp
index 5d5a99a..4029137 100644
--- a/vr/1.0/vts/functional/Android.bp
+++ b/vr/1.0/vts/functional/Android.bp
@@ -16,17 +16,7 @@
 
 cc_test {
     name: "VtsHalVrV1_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalVrV1_0TargetTest.cpp"],
-    shared_libs: [
-        "liblog",
-        "libhidlbase",
-        "libutils",
-        "android.hardware.vr@1.0",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-       "-O0",
-        "-g",
-    ]
+    static_libs: ["android.hardware.vr@1.0"],
 }
diff --git a/weaver/1.0/Android.bp b/weaver/1.0/Android.bp
index b64391c..cdc59c9 100644
--- a/weaver/1.0/Android.bp
+++ b/weaver/1.0/Android.bp
@@ -39,13 +39,16 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.weaver@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.weaver@1.0_genc++"],
     generated_headers: ["android.hardware.weaver@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.weaver@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/weaver/1.0/vts/functional/Android.bp b/weaver/1.0/vts/functional/Android.bp
index 9b0ff6d..0089d89 100644
--- a/weaver/1.0/vts/functional/Android.bp
+++ b/weaver/1.0/vts/functional/Android.bp
@@ -16,21 +16,7 @@
 
 cc_test {
     name: "VtsHalWeaverV1_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalWeaverV1_0TargetTest.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libnativehelper",
-        "libutils",
-        "android.hardware.weaver@1.0",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ],
+    static_libs: ["android.hardware.weaver@1.0"],
 }
diff --git a/wifi/1.0/Android.bp b/wifi/1.0/Android.bp
index c8b694c..d7db770 100644
--- a/wifi/1.0/Android.bp
+++ b/wifi/1.0/Android.bp
@@ -123,13 +123,16 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.wifi@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.wifi@1.0_genc++"],
     generated_headers: ["android.hardware.wifi@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.wifi@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/wifi/1.0/types.hal b/wifi/1.0/types.hal
index 1b5f8f7..b9fb0bd 100644
--- a/wifi/1.0/types.hal
+++ b/wifi/1.0/types.hal
@@ -1355,8 +1355,8 @@
    */
   uint32_t maxNdiInterfaces;
   /**
-   * Maximum number of data paths (NDP) which can be created concurrently on each individual
-   * data interface (NDI).
+   * Maximum number of data paths (NDP) which can be created concurrently on the device, across all
+   * data interfaces (NDI).
    */
   uint32_t maxNdpSessions;
   /**
diff --git a/wifi/1.0/vts/functional/Android.bp b/wifi/1.0/vts/functional/Android.bp
index 2d6679f..0cebbfc 100644
--- a/wifi/1.0/vts/functional/Android.bp
+++ b/wifi/1.0/vts/functional/Android.bp
@@ -38,50 +38,30 @@
 
 cc_test {
     name: "VtsHalWifiV1_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: [
         "VtsHalWifiV1_0TargetTest.cpp",
         "wifi_ap_iface_hidl_test.cpp",
         "wifi_chip_hidl_test.cpp",
         "wifi_p2p_iface_hidl_test.cpp",
         "wifi_rtt_controller_hidl_test.cpp",
-        "wifi_sta_iface_hidl_test.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libnativehelper",
-        "libutils",
-        "android.hardware.wifi@1.0",
+        "wifi_sta_iface_hidl_test.cpp",
     ],
-    static_libs: ["VtsHalWifiV1_0TargetTestUtil", "VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
+    static_libs: [
+        "VtsHalWifiV1_0TargetTestUtil",
+        "android.hardware.wifi@1.0",
     ],
 }
 
 cc_test {
     name: "VtsHalWifiNanV1_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: [
         "VtsHalWifiV1_0TargetTest.cpp",
-        "wifi_nan_iface_hidl_test.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libnativehelper",
-        "libutils",
-        "android.hardware.wifi@1.0",
+        "wifi_nan_iface_hidl_test.cpp",
     ],
-    static_libs: ["VtsHalWifiV1_0TargetTestUtil", "VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
+    static_libs: [
+        "VtsHalWifiV1_0TargetTestUtil",
+        "android.hardware.wifi@1.0",
     ],
 }
diff --git a/wifi/1.1/Android.bp b/wifi/1.1/Android.bp
index f991fa5..aa6e937 100644
--- a/wifi/1.1/Android.bp
+++ b/wifi/1.1/Android.bp
@@ -42,13 +42,16 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.wifi@1.1",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.wifi@1.1_genc++"],
     generated_headers: ["android.hardware.wifi@1.1_genc++_headers"],
     export_generated_headers: ["android.hardware.wifi@1.1_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/wifi/1.1/default/OWNERS b/wifi/1.1/default/OWNERS
new file mode 100644
index 0000000..2878acc
--- /dev/null
+++ b/wifi/1.1/default/OWNERS
@@ -0,0 +1,2 @@
+rpius@google.com
+quiche@google.com
diff --git a/wifi/1.1/default/hidl_return_util.h b/wifi/1.1/default/hidl_return_util.h
index 2f95c23..f36c8bd 100644
--- a/wifi/1.1/default/hidl_return_util.h
+++ b/wifi/1.1/default/hidl_return_util.h
@@ -55,6 +55,25 @@
   return Void();
 }
 
+// Use for HIDL methods which return only an instance of WifiStatus.
+// This version passes the global lock acquired to the body of the method.
+// Note: Only used by IWifi::stop() currently.
+template <typename ObjT, typename WorkFuncT, typename... Args>
+Return<void> validateAndCallWithLock(
+    ObjT* obj,
+    WifiStatusCode status_code_if_invalid,
+    WorkFuncT&& work,
+    const std::function<void(const WifiStatus&)>& hidl_cb,
+    Args&&... args) {
+  auto lock = hidl_sync_util::acquireGlobalLock();
+  if (obj->isValid()) {
+    hidl_cb((obj->*work)(&lock, std::forward<Args>(args)...));
+  } else {
+    hidl_cb(createWifiStatus(status_code_if_invalid));
+  }
+  return Void();
+}
+
 // Use for HIDL methods which return instance of WifiStatus and a single return
 // value.
 template <typename ObjT, typename WorkFuncT, typename ReturnT, typename... Args>
diff --git a/wifi/1.1/default/wifi.cpp b/wifi/1.1/default/wifi.cpp
index 8456b90..c46ef95 100644
--- a/wifi/1.1/default/wifi.cpp
+++ b/wifi/1.1/default/wifi.cpp
@@ -31,6 +31,7 @@
 namespace V1_1 {
 namespace implementation {
 using hidl_return_util::validateAndCall;
+using hidl_return_util::validateAndCallWithLock;
 
 Wifi::Wifi()
     : legacy_hal_(new legacy_hal::WifiLegacyHal()),
@@ -64,8 +65,8 @@
 }
 
 Return<void> Wifi::stop(stop_cb hidl_status_cb) {
-  return validateAndCall(
-      this, WifiStatusCode::ERROR_UNKNOWN, &Wifi::stopInternal, hidl_status_cb);
+  return validateAndCallWithLock(this, WifiStatusCode::ERROR_UNKNOWN,
+                                 &Wifi::stopInternal, hidl_status_cb);
 }
 
 Return<void> Wifi::getChipIds(getChipIds_cb hidl_status_cb) {
@@ -120,7 +121,8 @@
   return wifi_status;
 }
 
-WifiStatus Wifi::stopInternal() {
+WifiStatus Wifi::stopInternal(
+    /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock) {
   if (run_state_ == RunState::STOPPED) {
     return createWifiStatus(WifiStatusCode::SUCCESS);
   } else if (run_state_ == RunState::STOPPING) {
@@ -133,7 +135,7 @@
     chip_->invalidate();
     chip_.clear();
   }
-  WifiStatus wifi_status = stopLegacyHalAndDeinitializeModeController();
+  WifiStatus wifi_status = stopLegacyHalAndDeinitializeModeController(lock);
   if (wifi_status.code == WifiStatusCode::SUCCESS) {
     for (const auto& callback : event_cb_handler_.getCallbacks()) {
       if (!callback->onStop().isOk()) {
@@ -180,11 +182,11 @@
   return createWifiStatus(WifiStatusCode::SUCCESS);
 }
 
-WifiStatus Wifi::stopLegacyHalAndDeinitializeModeController() {
+WifiStatus Wifi::stopLegacyHalAndDeinitializeModeController(
+    /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock) {
   run_state_ = RunState::STOPPING;
-  const auto on_complete_callback_ = [&]() { run_state_ = RunState::STOPPED; };
   legacy_hal::wifi_error legacy_status =
-      legacy_hal_->stop(on_complete_callback_);
+      legacy_hal_->stop(lock, [&]() { run_state_ = RunState::STOPPED; });
   if (legacy_status != legacy_hal::WIFI_SUCCESS) {
     LOG(ERROR) << "Failed to stop legacy HAL: "
                << legacyErrorToString(legacy_status);
diff --git a/wifi/1.1/default/wifi.h b/wifi/1.1/default/wifi.h
index 1ade2d8..3a64cbd 100644
--- a/wifi/1.1/default/wifi.h
+++ b/wifi/1.1/default/wifi.h
@@ -61,12 +61,13 @@
   WifiStatus registerEventCallbackInternal(
       const sp<IWifiEventCallback>& event_callback);
   WifiStatus startInternal();
-  WifiStatus stopInternal();
+  WifiStatus stopInternal(std::unique_lock<std::recursive_mutex>* lock);
   std::pair<WifiStatus, std::vector<ChipId>> getChipIdsInternal();
   std::pair<WifiStatus, sp<IWifiChip>> getChipInternal(ChipId chip_id);
 
   WifiStatus initializeLegacyHal();
-  WifiStatus stopLegacyHalAndDeinitializeModeController();
+  WifiStatus stopLegacyHalAndDeinitializeModeController(
+      std::unique_lock<std::recursive_mutex>* lock);
 
   // Instance is created in this root level |IWifi| HIDL interface object
   // and shared with all the child HIDL interface objects.
diff --git a/wifi/1.1/default/wifi_legacy_hal.cpp b/wifi/1.1/default/wifi_legacy_hal.cpp
index 7d683d3..a6f6971 100644
--- a/wifi/1.1/default/wifi_legacy_hal.cpp
+++ b/wifi/1.1/default/wifi_legacy_hal.cpp
@@ -15,6 +15,7 @@
  */
 
 #include <array>
+#include <chrono>
 
 #include <android-base/logging.h>
 #include <cutils/properties.h>
@@ -34,6 +35,7 @@
 static constexpr uint32_t kLinkLayerStatsDataMpduSizeThreshold = 128;
 static constexpr uint32_t kMaxWakeReasonStatsArraySize = 32;
 static constexpr uint32_t kMaxRingBuffers = 10;
+static constexpr uint32_t kMaxStopCompleteWaitMs = 50;
 
 // Helper function to create a non-const char* for legacy Hal API's.
 std::vector<char> makeCharVec(const std::string& str) {
@@ -53,7 +55,8 @@
 // Legacy HAL functions accept "C" style function pointers, so use global
 // functions to pass to the legacy HAL function and store the corresponding
 // std::function methods to be invoked.
-// Callback to be invoked once |stop| is complete.
+//
+// Callback to be invoked once |stop| is complete
 std::function<void(wifi_handle handle)> on_stop_complete_internal_callback;
 void onAsyncStopComplete(wifi_handle handle) {
   const auto lock = hidl_sync_util::acquireGlobalLock();
@@ -369,6 +372,7 @@
 }
 
 wifi_error WifiLegacyHal::stop(
+    /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock,
     const std::function<void()>& on_stop_complete_user_callback) {
   if (!is_started_) {
     LOG(DEBUG) << "Legacy HAL already stopped";
@@ -376,19 +380,27 @@
     return WIFI_SUCCESS;
   }
   LOG(DEBUG) << "Stopping legacy HAL";
-  on_stop_complete_internal_callback = [on_stop_complete_user_callback,
-                                        this](wifi_handle handle) {
+  on_stop_complete_internal_callback =
+      [on_stop_complete_user_callback, this](wifi_handle handle) {
     CHECK_EQ(global_handle_, handle) << "Handle mismatch";
+    LOG(INFO) << "Legacy HAL stop complete callback received";
     // Invalidate all the internal pointers now that the HAL is
     // stopped.
     invalidate();
     iface_tool_.SetWifiUpState(false);
     on_stop_complete_user_callback();
+    is_started_ = false;
   };
   awaiting_event_loop_termination_ = true;
   global_func_table_.wifi_cleanup(global_handle_, onAsyncStopComplete);
+  const auto status = stop_wait_cv_.wait_for(
+      *lock, std::chrono::milliseconds(kMaxStopCompleteWaitMs),
+      [this] { return !awaiting_event_loop_termination_; });
+  if (!status) {
+    LOG(ERROR) << "Legacy HAL stop failed or timed out";
+    return WIFI_ERROR_UNKNOWN;
+  }
   LOG(DEBUG) << "Legacy HAL stop complete";
-  is_started_ = false;
   return WIFI_SUCCESS;
 }
 
@@ -1257,11 +1269,13 @@
 void WifiLegacyHal::runEventLoop() {
   LOG(DEBUG) << "Starting legacy HAL event loop";
   global_func_table_.wifi_event_loop(global_handle_);
+  const auto lock = hidl_sync_util::acquireGlobalLock();
   if (!awaiting_event_loop_termination_) {
     LOG(FATAL) << "Legacy HAL event loop terminated, but HAL was not stopping";
   }
   LOG(DEBUG) << "Legacy HAL event loop terminated";
   awaiting_event_loop_termination_ = false;
+  stop_wait_cv_.notify_one();
 }
 
 std::pair<wifi_error, std::vector<wifi_cached_scan_results>>
@@ -1284,7 +1298,7 @@
     for (int i = 0; i < num_scan_results; i++) {
       auto& scan_result = cached_scan_result.results[i];
       if (scan_result.ie_length > 0) {
-        LOG(ERROR) << "Cached scan result has non-zero IE length "
+        LOG(DEBUG) << "Cached scan result has non-zero IE length "
                    << scan_result.ie_length;
         scan_result.ie_length = 0;
       }
diff --git a/wifi/1.1/default/wifi_legacy_hal.h b/wifi/1.1/default/wifi_legacy_hal.h
index caa1bd5..5498803 100644
--- a/wifi/1.1/default/wifi_legacy_hal.h
+++ b/wifi/1.1/default/wifi_legacy_hal.h
@@ -20,6 +20,7 @@
 #include <functional>
 #include <thread>
 #include <vector>
+#include <condition_variable>
 
 #include <wifi_system/interface_tool.h>
 
@@ -149,8 +150,10 @@
   wifi_error initialize();
   // Start the legacy HAL and the event looper thread.
   wifi_error start();
-  // Deinitialize the legacy HAL and stop the event looper thread.
-  wifi_error stop(const std::function<void()>& on_complete_callback);
+  // Deinitialize the legacy HAL and wait for the event loop thread to exit
+  // using a predefined timeout.
+  wifi_error stop(std::unique_lock<std::recursive_mutex>* lock,
+                  const std::function<void()>& on_complete_callback);
   // Wrappers for all the functions in the legacy HAL function table.
   std::pair<wifi_error, std::string> getDriverVersion();
   std::pair<wifi_error, std::string> getFirmwareVersion();
@@ -293,6 +296,7 @@
   wifi_interface_handle wlan_interface_handle_;
   // Flag to indicate if we have initiated the cleanup of legacy HAL.
   std::atomic<bool> awaiting_event_loop_termination_;
+  std::condition_variable_any stop_wait_cv_;
   // Flag to indicate if the legacy HAL has been started.
   bool is_started_;
   wifi_system::InterfaceTool iface_tool_;
diff --git a/wifi/1.1/vts/functional/Android.bp b/wifi/1.1/vts/functional/Android.bp
index 6b0baf7..1b0c12d 100644
--- a/wifi/1.1/vts/functional/Android.bp
+++ b/wifi/1.1/vts/functional/Android.bp
@@ -16,24 +16,13 @@
 
 cc_test {
     name: "VtsHalWifiV1_1TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: [
         "VtsHalWifiV1_1TargetTest.cpp",
         "wifi_chip_hidl_test.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libnativehelper",
-        "libutils",
+    static_libs: [
+        "VtsHalWifiV1_0TargetTestUtil",
         "android.hardware.wifi@1.0",
         "android.hardware.wifi@1.1",
     ],
-    static_libs: ["VtsHalWifiV1_0TargetTestUtil", "VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ],
 }
diff --git a/wifi/1.1/vts/functional/OWNERS b/wifi/1.1/vts/functional/OWNERS
new file mode 100644
index 0000000..2878acc
--- /dev/null
+++ b/wifi/1.1/vts/functional/OWNERS
@@ -0,0 +1,2 @@
+rpius@google.com
+quiche@google.com
diff --git a/wifi/Android.bp b/wifi/Android.bp
index b4ab98f..1153b0c 100644
--- a/wifi/Android.bp
+++ b/wifi/Android.bp
@@ -7,4 +7,5 @@
     "offload/1.0",
     "offload/1.0/vts/functional",
     "supplicant/1.0",
+    "supplicant/1.0/vts/functional",
 ]
diff --git a/wifi/offload/1.0/Android.bp b/wifi/offload/1.0/Android.bp
index 28e8e6a..5b7fcad 100644
--- a/wifi/offload/1.0/Android.bp
+++ b/wifi/offload/1.0/Android.bp
@@ -46,13 +46,16 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.wifi.offload@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.wifi.offload@1.0_genc++"],
     generated_headers: ["android.hardware.wifi.offload@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.wifi.offload@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/wifi/offload/1.0/vts/functional/Android.bp b/wifi/offload/1.0/vts/functional/Android.bp
index f907a89..140e45e 100644
--- a/wifi/offload/1.0/vts/functional/Android.bp
+++ b/wifi/offload/1.0/vts/functional/Android.bp
@@ -16,21 +16,7 @@
 
 cc_test {
     name: "VtsHalWifiOffloadV1_0TargetTest",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalWifiOffloadV1_0TargetTest.cpp"],
-    shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libnativehelper",
-        "libutils",
-        "android.hardware.wifi.offload@1.0",
-    ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
-    cflags: [
-        "-O0",
-        "-g",
-    ],
+    static_libs: ["android.hardware.wifi.offload@1.0"],
 }
diff --git a/wifi/supplicant/1.0/Android.bp b/wifi/supplicant/1.0/Android.bp
index 9242fb6..978192d 100644
--- a/wifi/supplicant/1.0/Android.bp
+++ b/wifi/supplicant/1.0/Android.bp
@@ -116,13 +116,16 @@
     ],
 }
 
-cc_library_shared {
+cc_library {
     name: "android.hardware.wifi.supplicant@1.0",
     defaults: ["hidl-module-defaults"],
     generated_sources: ["android.hardware.wifi.supplicant@1.0_genc++"],
     generated_headers: ["android.hardware.wifi.supplicant@1.0_genc++_headers"],
     export_generated_headers: ["android.hardware.wifi.supplicant@1.0_genc++_headers"],
     vendor_available: true,
+    vndk: {
+        enabled: true,
+    },
     shared_libs: [
         "libhidlbase",
         "libhidltransport",
diff --git a/wifi/supplicant/1.0/vts/functional/Android.bp b/wifi/supplicant/1.0/vts/functional/Android.bp
new file mode 100644
index 0000000..24b9f6f
--- /dev/null
+++ b/wifi/supplicant/1.0/vts/functional/Android.bp
@@ -0,0 +1,37 @@
+//
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_test {
+    name: "VtsHalWifiSupplicantV1_0TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: [
+        "VtsHalWifiSupplicantV1_0TargetTest.cpp",
+        "supplicant_hidl_test.cpp",
+        "supplicant_hidl_test_utils.cpp",
+        "supplicant_p2p_iface_hidl_test.cpp",
+        "supplicant_sta_iface_hidl_test.cpp",
+        "supplicant_sta_network_hidl_test.cpp",
+    ],
+    static_libs: [
+        "VtsHalWifiV1_0TargetTestUtil",
+        "android.hardware.wifi.supplicant@1.0",
+        "android.hardware.wifi@1.0",
+        "libcrypto",
+        "libgmock",
+        "libwifi-system",
+        "libwifi-system-iface",
+    ],
+}
diff --git a/wifi/supplicant/1.0/vts/functional/Android.mk b/wifi/supplicant/1.0/vts/functional/Android.mk
deleted file mode 100644
index c6e3950..0000000
--- a/wifi/supplicant/1.0/vts/functional/Android.mk
+++ /dev/null
@@ -1,44 +0,0 @@
-#
-# Copyright (C) 2016 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := VtsHalWifiSupplicantV1_0TargetTest
-LOCAL_CPPFLAGS := -Wall -Werror -Wextra
-LOCAL_SRC_FILES := \
-    VtsHalWifiSupplicantV1_0TargetTest.cpp \
-    supplicant_hidl_test.cpp \
-    supplicant_hidl_test_utils.cpp \
-    supplicant_p2p_iface_hidl_test.cpp \
-    supplicant_sta_iface_hidl_test.cpp \
-    supplicant_sta_network_hidl_test.cpp
-LOCAL_SHARED_LIBRARIES := \
-    android.hardware.wifi.supplicant@1.0 \
-    android.hardware.wifi@1.0 \
-    libbase \
-    libcutils \
-    libhidlbase \
-    libhidltransport \
-    liblog \
-    libutils \
-    libwifi-system \
-    libwifi-system-iface
-LOCAL_STATIC_LIBRARIES := \
-    libgmock \
-    VtsHalHidlTargetTestBase \
-    VtsHalWifiV1_0TargetTestUtil
-include $(BUILD_NATIVE_TEST)
-