Merge "Remove conditional vndbinder usage in CAS." am: 231626d43d am: 897864234e
am: 905ca6a633  -s ours

Change-Id: I9470d42992400699d9f6eb2f6cb06064fe5c73b1
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 3788bc6..f04a390 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -60,6 +60,6 @@
 $(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*)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/lib/vndk-sp/android.hardware.graphics.allocator*)
diff --git a/audio/2.0/default/ParametersUtil.cpp b/audio/2.0/default/ParametersUtil.cpp
index 2140885..c113ac7 100644
--- a/audio/2.0/default/ParametersUtil.cpp
+++ b/audio/2.0/default/ParametersUtil.cpp
@@ -22,7 +22,9 @@
 namespace V2_0 {
 namespace implementation {
 
-// Static method and not private method to avoid leaking status_t dependency
+/** Converts a status_t in Result according to the rules of AudioParameter::get*
+ * Note: Static method and not private method to avoid leaking status_t dependency
+ */
 static Result getHalStatusToResult(status_t status) {
     switch (status) {
         case OK:
@@ -141,12 +143,20 @@
 
 Result ParametersUtil::setParams(const AudioParameter& param) {
     int halStatus = halSetParameters(param.toString().string());
-    if (halStatus == OK)
-        return Result::OK;
-    else if (halStatus == -ENOSYS)
-        return Result::INVALID_STATE;
-    else
-        return Result::INVALID_ARGUMENTS;
+    switch (halStatus) {
+        case OK: return Result::OK;
+        case -EINVAL: return Result::INVALID_ARGUMENTS;
+        case -ENODATA: return Result::INVALID_STATE;
+        case -ENODEV: return Result::NOT_INITIALIZED;
+        // The rest of the API (*::analyseStatus) returns NOT_SUPPORTED
+        // when the legacy API returns -ENOSYS
+        // However the legacy API explicitly state that for get_paramers,
+        // -ENOSYS should be returned if
+        // "the implementation does not accept a parameter change while the
+        //  output is active but the parameter is acceptable otherwise"
+        case -ENOSYS: return Result::INVALID_STATE;
+        default: return Result::INVALID_ARGUMENTS;
+    }
 }
 
 }  // namespace implementation
diff --git a/audio/2.0/default/android.hardware.audio@2.0-service.rc b/audio/2.0/default/android.hardware.audio@2.0-service.rc
index eeaf71b..a76770d 100644
--- a/audio/2.0/default/android.hardware.audio@2.0-service.rc
+++ b/audio/2.0/default/android.hardware.audio@2.0-service.rc
@@ -1,4 +1,4 @@
-service audio-hal-2-0 /vendor/bin/hw/android.hardware.audio@2.0-service
+service vendor.audio-hal-2-0 /vendor/bin/hw/android.hardware.audio@2.0-service
     class hal
     user audioserver
     # media gid needed for /dev/fm (radio) and for /data/misc/media (tee)
diff --git a/audio/2.0/vts/functional/ValidateAudioConfiguration.cpp b/audio/2.0/vts/functional/ValidateAudioConfiguration.cpp
index ec3259a..4e280f5 100644
--- a/audio/2.0/vts/functional/ValidateAudioConfiguration.cpp
+++ b/audio/2.0/vts/functional/ValidateAudioConfiguration.cpp
@@ -20,15 +20,11 @@
 #include "utility/ValidateXml.h"
 
 TEST(CheckConfig, audioPolicyConfigurationValidation) {
-    const char* configName = "audio_policy_configuration.xml";
-    const char* possibleConfigLocations[] = {"/odm/etc", "/vendor/etc", "/system/etc"};
-    const char* configSchemaPath = "/data/local/tmp/audio_policy_configuration.xsd";
+    RecordProperty("description",
+                   "Verify that the audio policy configuration file "
+                   "is valid according to the schema");
 
-    for (std::string folder : possibleConfigLocations) {
-        const auto configPath = folder + '/' + configName;
-        if (access(configPath.c_str(), R_OK) == 0) {
-            ASSERT_VALID_XML(configPath.c_str(), configSchemaPath);
-            return; // The framework does not read past the first config file found
-        }
-    }
+    std::vector<const char*> locations = {"/odm/etc", "/vendor/etc", "/system/etc"};
+    EXPECT_ONE_VALID_XML_MULTIPLE_LOCATIONS("audio_policy_configuration.xml", locations,
+                                            "/data/local/tmp/audio_policy_configuration.xsd");
 }
diff --git a/audio/common/test/utility/include/utility/ValidateXml.h b/audio/common/test/utility/include/utility/ValidateXml.h
index fdfa506..d718839 100644
--- a/audio/common/test/utility/include/utility/ValidateXml.h
+++ b/audio/common/test/utility/include/utility/ValidateXml.h
@@ -32,13 +32,44 @@
  * See ASSERT_VALID_XML for a helper macro.
  */
 ::testing::AssertionResult validateXml(const char* xmlFilePathExpr, const char* xsdFilePathExpr,
-                                       const char* xmlFilePath, const char* xsdPathName);
+                                       const char* xmlFilePath, const char* xsdFilePath);
 
-/** Helper gtest ASSERT to test xml validity against an xsd. */
+/** Helper gtest ASSERT to test XML validity against an XSD. */
 #define ASSERT_VALID_XML(xmlFilePath, xsdFilePath)                                      \
     ASSERT_PRED_FORMAT2(::android::hardware::audio::common::test::utility::validateXml, \
                         xmlFilePath, xsdFilePath)
 
+/** Helper gtest EXPECT to test XML validity against an XSD. */
+#define EXPECT_VALID_XML(xmlFilePath, xsdFilePath)                                      \
+    EXPECT_PRED_FORMAT2(::android::hardware::audio::common::test::utility::validateXml, \
+                        xmlFilePath, xsdFilePath)
+
+/** Validate an XML according to an xsd.
+ * The XML file must be in at least one of the provided locations.
+ * If multiple are found, all are validated.
+ */
+::testing::AssertionResult validateXmlMultipleLocations(
+    const char* xmlFileNameExpr, const char* xmlFileLocationsExpr, const char* xsdFilePathExpr,
+    const char* xmlFileName, std::vector<const char*> xmlFileLocations, const char* xsdFilePath);
+
+/** ASSERT that an XML is valid according to an xsd.
+ * The XML file must be in at least one of the provided locations.
+ * If multiple are found, all are validated.
+ */
+#define ASSERT_ONE_VALID_XML_MULTIPLE_LOCATIONS(xmlFileName, xmlFileLocations, xsdFilePath) \
+    ASSERT_PRED_FORMAT3(                                                                    \
+        ::android::hardware::audio::common::test::utility::validateXmlMultipleLocations,    \
+        xmlFileName, xmlFileLocations, xsdFilePath)
+
+/** EXPECT an XML to be valid according to an xsd.
+ * The XML file must be in at least one of the provided locations.
+ * If multiple are found, all are validated.
+ */
+#define EXPECT_ONE_VALID_XML_MULTIPLE_LOCATIONS(xmlFileName, xmlFileLocations, xsdFilePath) \
+    EXPECT_PRED_FORMAT3(                                                                    \
+        ::android::hardware::audio::common::test::utility::validateXmlMultipleLocations,    \
+        xmlFileName, xmlFileLocations, xsdFilePath)
+
 }  // utility
 }  // test
 }  // common
diff --git a/audio/common/test/utility/src/ValidateXml.cpp b/audio/common/test/utility/src/ValidateXml.cpp
index 784f940..30dec30 100644
--- a/audio/common/test/utility/src/ValidateXml.cpp
+++ b/audio/common/test/utility/src/ValidateXml.cpp
@@ -17,6 +17,8 @@
 #define LOG_TAG "ValidateAudioConfig"
 #include <utils/Log.h>
 
+#include <numeric>
+
 #define LIBXML_SCHEMAS_ENABLED
 #include <libxml/xmlschemastypes.h>
 #define LIBXML_XINCLUDE_ENABLED
@@ -94,9 +96,9 @@
     Libxml2Global libxml2;
 
     auto context = [&]() {
-        return std::string() + "    While validating: " + xmlFilePathExpr +
+        return std::string() + "  While validating: " + xmlFilePathExpr +
                "\n          Which is: " + xmlFilePath + "\nAgainst the schema: " + xsdFilePathExpr +
-               "\n          Which is: " + xsdFilePath + "Libxml2 errors\n" + libxml2.getErrors();
+               "\n          Which is: " + xsdFilePath + "\nLibxml2 errors:\n" + libxml2.getErrors();
     };
 
     auto schemaParserCtxt = make_xmlUnique(xmlSchemaNewParserCtxt(xsdFilePath));
@@ -117,7 +119,7 @@
     auto schemaCtxt = make_xmlUnique(xmlSchemaNewValidCtxt(schema.get()));
     int ret = xmlSchemaValidateDoc(schemaCtxt.get(), doc.get());
     if (ret > 0) {
-        return ::testing::AssertionFailure() << "xml is not valid according to the xsd.\n"
+        return ::testing::AssertionFailure() << "XML is not valid according to the xsd\n"
                                              << context();
     }
     if (ret < 0) {
@@ -127,6 +129,40 @@
     return ::testing::AssertionSuccess();
 }
 
+::testing::AssertionResult validateXmlMultipleLocations(
+    const char* xmlFileNameExpr, const char* xmlFileLocationsExpr, const char* xsdFilePathExpr,
+    const char* xmlFileName, std::vector<const char*> xmlFileLocations, const char* xsdFilePath) {
+    using namespace std::string_literals;
+
+    std::vector<std::string> errors;
+    std::vector<std::string> foundFiles;
+
+    for (const char* location : xmlFileLocations) {
+        std::string xmlFilePath = location + "/"s + xmlFileName;
+        if (access(xmlFilePath.c_str(), F_OK) != 0) {
+            // If the file does not exist ignore this location and fallback on the next one
+            continue;
+        }
+        foundFiles.push_back("    " + xmlFilePath + '\n');
+        auto result = validateXml("xmlFilePath", xsdFilePathExpr, xmlFilePath.c_str(), xsdFilePath);
+        if (!result) {
+            errors.push_back(result.message());
+        }
+    }
+
+    if (foundFiles.empty()) {
+        errors.push_back("No xml file found in provided locations.\n");
+    }
+
+    return ::testing::AssertionResult(errors.empty())
+           << errors.size() << " error" << (errors.size() == 1 ? " " : "s ")
+           << std::accumulate(begin(errors), end(errors), "occurred during xml validation:\n"s)
+           << "     While validating all: " << xmlFileNameExpr
+           << "\n                 Which is: " << xmlFileName
+           << "\n In the following folders: " << xmlFileLocationsExpr
+           << "\n                 Which is: " << ::testing::PrintToString(xmlFileLocations);
+}
+
 }  // utility
 }  // test
 }  // common
diff --git a/audio/effect/2.0/vts/functional/Android.bp b/audio/effect/2.0/vts/functional/Android.bp
index 7b421cb..f5a49b3 100644
--- a/audio/effect/2.0/vts/functional/Android.bp
+++ b/audio/effect/2.0/vts/functional/Android.bp
@@ -30,6 +30,7 @@
         "libxml2",
     ],
     shared_libs: [
+        "libeffectsconfig",
         "libicuuc",
     ],
 }
diff --git a/audio/effect/2.0/vts/functional/ValidateAudioEffectsConfiguration.cpp b/audio/effect/2.0/vts/functional/ValidateAudioEffectsConfiguration.cpp
index fdc1347..d0bc690 100644
--- a/audio/effect/2.0/vts/functional/ValidateAudioEffectsConfiguration.cpp
+++ b/audio/effect/2.0/vts/functional/ValidateAudioEffectsConfiguration.cpp
@@ -15,16 +15,18 @@
  */
 
 #include <unistd.h>
+#include <iterator>
+
+#include <media/EffectsConfig.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");
-    }
+    using namespace android::effectsConfig;
+
+    std::vector<const char*> locations(std::begin(DEFAULT_LOCATIONS), std::end(DEFAULT_LOCATIONS));
+    EXPECT_ONE_VALID_XML_MULTIPLE_LOCATIONS(DEFAULT_NAME, locations,
+                                            "/data/local/tmp/audio_effects_conf_V2_0.xsd");
 }
diff --git a/automotive/evs/1.0/default/ServiceNames.h b/automotive/evs/1.0/default/ServiceNames.h
index d20a37f..1178da5 100644
--- a/automotive/evs/1.0/default/ServiceNames.h
+++ b/automotive/evs/1.0/default/ServiceNames.h
@@ -14,4 +14,4 @@
  * limitations under the License.
  */
 
-const static char kEnumeratorServiceName[] = "EvsEnumeratorHw-Mock";
+const static char kEnumeratorServiceName[] = "EvsEnumeratorHw";
diff --git a/automotive/evs/1.0/default/android.hardware.automotive.evs@1.0-service.rc b/automotive/evs/1.0/default/android.hardware.automotive.evs@1.0-service.rc
index 16d521d..117c249 100644
--- a/automotive/evs/1.0/default/android.hardware.automotive.evs@1.0-service.rc
+++ b/automotive/evs/1.0/default/android.hardware.automotive.evs@1.0-service.rc
@@ -1,4 +1,4 @@
-service evs-hal-mock /vendor/bin/hw/android.hardware.automotive.evs@1.0-service
+service vendor.evs-hal-mock /vendor/bin/hw/android.hardware.automotive.evs@1.0-service
     class hal
     user automotive_evs
     group automotive_evs
diff --git a/automotive/evs/1.0/vts/functional/Android.bp b/automotive/evs/1.0/vts/functional/Android.bp
index 555ff5b..6ac2458 100644
--- a/automotive/evs/1.0/vts/functional/Android.bp
+++ b/automotive/evs/1.0/vts/functional/Android.bp
@@ -15,7 +15,7 @@
 //
 
 cc_test {
-    name: "VtsHalEvsV1_0Target",
+    name: "VtsHalEvsV1_0TargetTest",
 
     srcs: [
         "VtsHalEvsV1_0TargetTest.cpp",
diff --git a/automotive/vehicle/2.0/Android.bp b/automotive/vehicle/2.0/Android.bp
index 3441a25..7ab2387 100644
--- a/automotive/vehicle/2.0/Android.bp
+++ b/automotive/vehicle/2.0/Android.bp
@@ -17,6 +17,8 @@
     types: [
         "DiagnosticFloatSensorIndex",
         "DiagnosticIntegerSensorIndex",
+        "EvConnectorType",
+        "FuelType",
         "Obd2CommonIgnitionMonitors",
         "Obd2CompressionIgnitionMonitors",
         "Obd2FuelSystemStatus",
diff --git a/automotive/vehicle/2.0/Android.mk b/automotive/vehicle/2.0/Android.mk
deleted file mode 100644
index a731d6d..0000000
--- a/automotive/vehicle/2.0/Android.mk
+++ /dev/null
@@ -1,1282 +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.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 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
-$(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.StatusCode
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (SubscribeFlags)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/SubscribeFlags.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.SubscribeFlags
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (SubscribeOptions)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/SubscribeOptions.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.SubscribeOptions
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VehicleApPowerBootupReason)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VehicleApPowerBootupReason.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.VehicleApPowerBootupReason
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VehicleApPowerSetState)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VehicleApPowerSetState.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.VehicleApPowerSetState
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VehicleApPowerState)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VehicleApPowerState.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.VehicleApPowerState
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VehicleApPowerStateConfigFlag)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VehicleApPowerStateConfigFlag.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.VehicleApPowerStateConfigFlag
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VehicleApPowerStateIndex)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VehicleApPowerStateIndex.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.VehicleApPowerStateIndex
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VehicleApPowerStateShutdownParam)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VehicleApPowerStateShutdownParam.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.VehicleApPowerStateShutdownParam
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VehicleArea)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VehicleArea.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.VehicleArea
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VehicleAreaConfig)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VehicleAreaConfig.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.VehicleAreaConfig
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VehicleAreaDoor)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VehicleAreaDoor.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.VehicleAreaDoor
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VehicleAreaMirror)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VehicleAreaMirror.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.VehicleAreaMirror
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VehicleAreaSeat)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VehicleAreaSeat.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.VehicleAreaSeat
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VehicleAreaWindow)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VehicleAreaWindow.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.VehicleAreaWindow
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VehicleAreaZone)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VehicleAreaZone.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.VehicleAreaZone
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VehicleAudioContextFlag)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VehicleAudioContextFlag.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.VehicleAudioContextFlag
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VehicleAudioExtFocusFlag)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VehicleAudioExtFocusFlag.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.VehicleAudioExtFocusFlag
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VehicleAudioFocusIndex)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VehicleAudioFocusIndex.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.VehicleAudioFocusIndex
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VehicleAudioFocusRequest)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VehicleAudioFocusRequest.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.VehicleAudioFocusRequest
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VehicleAudioFocusState)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VehicleAudioFocusState.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.VehicleAudioFocusState
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VehicleAudioHwVariantConfigFlag)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VehicleAudioHwVariantConfigFlag.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.VehicleAudioHwVariantConfigFlag
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VehicleAudioRoutingPolicyIndex)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VehicleAudioRoutingPolicyIndex.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.VehicleAudioRoutingPolicyIndex
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VehicleAudioStream)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VehicleAudioStream.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.VehicleAudioStream
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VehicleAudioStreamFlag)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VehicleAudioStreamFlag.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.VehicleAudioStreamFlag
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VehicleAudioVolumeCapabilityFlag)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VehicleAudioVolumeCapabilityFlag.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.VehicleAudioVolumeCapabilityFlag
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VehicleAudioVolumeIndex)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VehicleAudioVolumeIndex.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.VehicleAudioVolumeIndex
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VehicleAudioVolumeLimitIndex)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VehicleAudioVolumeLimitIndex.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.VehicleAudioVolumeLimitIndex
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VehicleAudioVolumeState)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VehicleAudioVolumeState.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.VehicleAudioVolumeState
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VehicleDisplay)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VehicleDisplay.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.VehicleDisplay
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VehicleDrivingStatus)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VehicleDrivingStatus.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.VehicleDrivingStatus
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VehicleGear)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VehicleGear.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.VehicleGear
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VehicleHvacFanDirection)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VehicleHvacFanDirection.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.VehicleHvacFanDirection
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VehicleHwKeyInputAction)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VehicleHwKeyInputAction.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.VehicleHwKeyInputAction
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VehicleIgnitionState)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VehicleIgnitionState.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/types.hal
-$(GEN): PRIVATE_OUTPUT_DIR := $(intermediates)
-$(GEN): PRIVATE_CUSTOM_TOOL = \
-        $(PRIVATE_HIDL) -o $(PRIVATE_OUTPUT_DIR) \
-        -Ljava \
-        -randroid.hardware:hardware/interfaces \
-        -randroid.hidl:system/libhidl/transport \
-        android.hardware.automotive.vehicle@2.0::types.VehicleIgnitionState
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VehicleInstrumentClusterType)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VehicleInstrumentClusterType.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.VehicleInstrumentClusterType
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VehiclePropConfig)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VehiclePropConfig.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.VehiclePropConfig
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VehiclePropValue)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VehiclePropValue.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.VehiclePropValue
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VehicleProperty)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/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.0::types.VehicleProperty
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VehiclePropertyAccess)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VehiclePropertyAccess.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.VehiclePropertyAccess
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VehiclePropertyChangeMode)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VehiclePropertyChangeMode.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.VehiclePropertyChangeMode
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VehiclePropertyGroup)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VehiclePropertyGroup.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.VehiclePropertyGroup
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VehiclePropertyOperation)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VehiclePropertyOperation.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.VehiclePropertyOperation
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VehiclePropertyType)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VehiclePropertyType.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.VehiclePropertyType
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VehicleRadioConstants)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VehicleRadioConstants.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.VehicleRadioConstants
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VehicleTurnSignal)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VehicleTurnSignal.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.VehicleTurnSignal
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build types.hal (VehicleUnit)
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/VehicleUnit.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.VehicleUnit
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-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
-$(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.Wheel
-
-$(GEN): $(LOCAL_PATH)/types.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build IVehicle.hal
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/IVehicle.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IVehicle.hal
-$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/IVehicleCallback.hal
-$(GEN): $(LOCAL_PATH)/IVehicleCallback.hal
-$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
-$(GEN): $(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::IVehicle
-
-$(GEN): $(LOCAL_PATH)/IVehicle.hal
-	$(transform-generated-source)
-LOCAL_GENERATED_SOURCES += $(GEN)
-
-#
-# Build IVehicleCallback.hal
-#
-GEN := $(intermediates)/android/hardware/automotive/vehicle/V2_0/IVehicleCallback.java
-$(GEN): $(HIDL)
-$(GEN): PRIVATE_HIDL := $(HIDL)
-$(GEN): PRIVATE_DEPS := $(LOCAL_PATH)/IVehicleCallback.hal
-$(GEN): PRIVATE_DEPS += $(LOCAL_PATH)/types.hal
-$(GEN): $(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::IVehicleCallback
-
-$(GEN): $(LOCAL_PATH)/IVehicleCallback.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.0/default/OWNERS b/automotive/vehicle/2.0/default/OWNERS
new file mode 100644
index 0000000..d5d9d4c
--- /dev/null
+++ b/automotive/vehicle/2.0/default/OWNERS
@@ -0,0 +1,3 @@
+egranata@google.com
+pavelm@google.com
+spaik@google.com
diff --git a/automotive/vehicle/2.0/default/android.hardware.automotive.vehicle@2.0-service.rc b/automotive/vehicle/2.0/default/android.hardware.automotive.vehicle@2.0-service.rc
index 30e249e..c8c89dc 100644
--- a/automotive/vehicle/2.0/default/android.hardware.automotive.vehicle@2.0-service.rc
+++ b/automotive/vehicle/2.0/default/android.hardware.automotive.vehicle@2.0-service.rc
@@ -1,4 +1,4 @@
-service vehicle-hal-2.0 /vendor/bin/hw/android.hardware.automotive.vehicle@2.0-service
+service vendor.vehicle-hal-2.0 /vendor/bin/hw/android.hardware.automotive.vehicle@2.0-service
     class hal
     user vehicle_network
     group system inet
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 08d3d79..71601a0 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
@@ -78,6 +78,38 @@
 const ConfigDeclaration kVehicleProperties[]{
     {.config =
          {
+             .prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY),
+             .access = VehiclePropertyAccess::READ,
+             .changeMode = VehiclePropertyChangeMode::STATIC,
+         },
+     .initialValue = {.floatValues = {15000}}},
+
+    {.config =
+         {
+             .prop = toInt(VehicleProperty::INFO_FUEL_TYPE),
+             .access = VehiclePropertyAccess::READ,
+             .changeMode = VehiclePropertyChangeMode::STATIC,
+         },
+     .initialValue = {.int32Values = {1}}},
+
+    {.config =
+         {
+             .prop = toInt(VehicleProperty::INFO_EV_BATTERY_CAPACITY),
+             .access = VehiclePropertyAccess::READ,
+             .changeMode = VehiclePropertyChangeMode::STATIC,
+         },
+     .initialValue = {.floatValues = {150000}}},
+
+    {.config =
+         {
+             .prop = toInt(VehicleProperty::INFO_EV_CONNECTOR_TYPE),
+             .access = VehiclePropertyAccess::READ,
+             .changeMode = VehiclePropertyChangeMode::STATIC,
+         },
+     .initialValue = {.int32Values = {1}}},
+
+    {.config =
+         {
              .prop = toInt(VehicleProperty::INFO_MAKE),
              .access = VehiclePropertyAccess::READ,
              .changeMode = VehiclePropertyChangeMode::STATIC,
@@ -89,7 +121,7 @@
              .access = VehiclePropertyAccess::READ,
              .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
              .minSampleRate = 1.0f,
-             .maxSampleRate = 1000.0f,
+             .maxSampleRate = 10.0f,
          },
      .initialValue = {.floatValues = {0.0f}}},
 
@@ -101,6 +133,14 @@
          },
      .initialValue = {.floatValues = {0.0f}}},
 
+    {.config =
+         {
+             .prop = toInt(VehicleProperty::ENGINE_ON),
+             .access = VehiclePropertyAccess::READ,
+             .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+         },
+     .initialValue = {.int32Values = {0}}},
+
     {
         .config =
             {
@@ -108,13 +148,61 @@
                 .access = VehiclePropertyAccess::READ,
                 .changeMode = VehiclePropertyChangeMode::CONTINUOUS,
                 .minSampleRate = 1.0f,
-                .maxSampleRate = 1000.0f,
+                .maxSampleRate = 10.0f,
             },
         .initialValue = {.floatValues = {0.0f}},
     },
 
     {.config =
          {
+             .prop = toInt(VehicleProperty::FUEL_LEVEL),
+             .access = VehiclePropertyAccess::READ,
+             .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+         },
+     .initialValue = {.floatValues = {15000}}},
+
+    {.config =
+         {
+             .prop = toInt(VehicleProperty::FUEL_DOOR_OPEN),
+             .access = VehiclePropertyAccess::READ,
+             .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+         },
+     .initialValue = {.int32Values = {0}}},
+
+    {.config =
+         {
+             .prop = toInt(VehicleProperty::EV_BATTERY_LEVEL),
+             .access = VehiclePropertyAccess::READ,
+             .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+         },
+     .initialValue = {.floatValues = {150000}}},
+
+    {.config =
+         {
+             .prop = toInt(VehicleProperty::EV_CHARGE_PORT_OPEN),
+             .access = VehiclePropertyAccess::READ,
+             .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+         },
+     .initialValue = {.int32Values = {0}}},
+
+    {.config =
+         {
+             .prop = toInt(VehicleProperty::EV_CHARGE_PORT_CONNECTED),
+             .access = VehiclePropertyAccess::READ,
+             .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+         },
+     .initialValue = {.int32Values = {0}}},
+
+    {.config =
+         {
+             .prop = toInt(VehicleProperty::EV_BATTERY_INSTANTANEOUS_CHARGE_RATE),
+             .access = VehiclePropertyAccess::READ,
+             .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+         },
+     .initialValue = {.floatValues = {0}}},
+
+    {.config =
+         {
              .prop = toInt(VehicleProperty::CURRENT_GEAR),
              .access = VehiclePropertyAccess::READ,
              .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
@@ -139,6 +227,14 @@
 
     {.config =
          {
+             .prop = toInt(VehicleProperty::HW_KEY_INPUT),
+             .access = VehiclePropertyAccess::READ,
+             .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+         },
+     .initialValue = {.int32Values = {0, 0, 0}}},
+
+    {.config =
+         {
              .prop = toInt(VehicleProperty::HVAC_POWER_ON),
              .access = VehiclePropertyAccess::READ_WRITE,
              .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
@@ -246,16 +342,6 @@
          },
      .initialValue = {.int32Values = {toInt(VehicleGear::GEAR_PARK)}}},
 
-    {
-        .config =
-            {
-                .prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY),
-                .access = VehiclePropertyAccess::READ,
-                .changeMode = VehiclePropertyChangeMode::STATIC,
-            },
-        .initialValue = {.floatValues = {123000.0f}}  // In Milliliters
-    },
-
     {.config = {.prop = toInt(VehicleProperty::DISPLAY_BRIGHTNESS),
                 .access = VehiclePropertyAccess::READ_WRITE,
                 .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
@@ -297,17 +383,16 @@
          },
      .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 = WHEEL_TICK,
+             .access = VehiclePropertyAccess::READ,
+             .changeMode = VehiclePropertyChangeMode::CONTINUOUS,
+             .configArray = {ALL_WHEELS, 50000, 50000, 50000, 50000},
+             .minSampleRate = 1.0f,
+             .maxSampleRate = 10.0f,
+         },
+     .initialValue = {.int64Values = {0, 100000, 200000, 300000, 400000}}},
 
     {
         .config =
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
index ec35200..6754843 100644
--- 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
@@ -23,5 +23,9 @@
     strip: {
         keep_symbols: true,
     },
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
     srcs: ["VehicleHalProto.proto"]
 }
diff --git a/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal
index 7c08b4a..e07917e 100644
--- a/automotive/vehicle/2.0/types.hal
+++ b/automotive/vehicle/2.0/types.hal
@@ -148,7 +148,7 @@
         | VehicleArea:GLOBAL),
 
     /**
-     * Fuel capacity of the vehicle
+     * Fuel capacity of the vehicle in milliliters
      *
      * @change_mode VehiclePropertyChangeMode:STATIC
      * @access VehiclePropertyAccess:READ
@@ -161,6 +161,45 @@
         | VehicleArea:GLOBAL),
 
     /**
+     * List of fuels the vehicle may use.  Uses enum FuelType
+     *
+     * @change_mode VehiclePropertyChangeMode:STATIC
+     * @access VehiclePropertyAccess:READ
+     * @unit VehicleUnit:MILLILITERS
+     */
+    INFO_FUEL_TYPE = (
+        0x0105
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32_VEC
+        | VehicleArea:GLOBAL),
+
+    /**
+     * Battery capacity of the vehicle, if EV or hybrid.  This is the nominal
+     * battery capacity when the vehicle is new.
+     *
+     * @change_mode VehiclePropertyChangeMode:STATIC
+     * @access VehiclePropertyAccess:READ
+     * @unit VehicleUnit:WH
+     */
+    INFO_EV_BATTERY_CAPACITY = (
+        0x0106
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:FLOAT
+        | VehicleArea:GLOBAL),
+
+    /**
+     * List of connectors this EV may use.  Uses enum EvConnectorType
+     *
+     * @change_mode VehiclePropertyChangeMode:STATIC
+     * @access VehiclePropertyAccess:READ
+     */
+    INFO_EV_CONNECTOR_TYPE = (
+        0x0107
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:INT32_VEC
+        | VehicleArea:GLOBAL),
+
+    /**
      * Current odometer value of the vehicle
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE | VehiclePropertyChangeMode:CONTINUOUS
@@ -187,6 +226,19 @@
         | VehicleArea:GLOBAL),
 
     /**
+     * Engine on
+     *
+     * @change_mode VehiclePropertyChangeMode:STATIC
+     * @access VehiclePropertyAccess:READ
+     */
+    ENGINE_ON = (
+        0x0300
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:BOOLEAN
+        | VehicleArea:GLOBAL),
+
+
+    /**
      * Temperature of engine coolant
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE|VehiclePropertyChangeMode:CONTINUOUS
@@ -259,8 +311,6 @@
      *
      * @change_mode VehiclePropertyChangeMode:CONTINUOUS
      * @access VehiclePropertyAccess:READ
-     *
-     * @since o.mr1
      */
     WHEEL_TICK = (
       0x0306
@@ -270,6 +320,88 @@
 
 
     /**
+     * Fuel remaining in the the vehicle, in milliliters
+     *
+     * Value may not exceed INFO_FUEL_CAPACITY
+     *
+     * @change_mode VehiclePropertyChangeMode:STATIC
+     * @access VehiclePropertyAccess:READ
+     * @unit VehicleUnit:MILLILITER
+     */
+    FUEL_LEVEL = (
+        0x0307
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:FLOAT
+        | VehicleArea:GLOBAL),
+
+    /**
+     * Fuel door open
+     *
+     * @change_mode VehiclePropertyChangeMode:STATIC
+     * @access VehiclePropertyAccess:READ
+     */
+    FUEL_DOOR_OPEN = (
+        0x0308
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:BOOLEAN
+        | VehicleArea:GLOBAL),
+
+    /**
+     * EV battery level in WH, if EV or hybrid
+     *
+     * Value may not exceed INFO_EV_BATTERY_CAPACITY
+     *
+     * @change_mode VehiclePropertyChangeMode:STATIC
+     * @access VehiclePropertyAccess:READ
+     * @unit VehicleUnit:WH
+     */
+    EV_BATTERY_LEVEL = (
+        0x0309
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:FLOAT
+        | VehicleArea:GLOBAL),
+
+    /**
+     * EV charge port open
+     *
+     * @change_mode VehiclePropertyChangeMode:STATIC
+     * @access VehiclePropertyAccess:READ
+     */
+    EV_CHARGE_PORT_OPEN = (
+        0x030A
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:BOOLEAN
+        | VehicleArea:GLOBAL),
+
+    /**
+     * EV charge port connected
+     *
+     * @change_mode VehiclePropertyChangeMode:STATIC
+     * @access VehiclePropertyAccess:READ
+     */
+    EV_CHARGE_PORT_CONNECTED = (
+        0x030B
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:BOOLEAN
+        | VehicleArea:GLOBAL),
+
+    /**
+     * EV instantaneous charge rate in milliwatts
+     *
+     * Positive value indicates battery is being charged.
+     * Negative value indicates battery being discharged.
+     *
+     * @change_mode VehiclePropertyChangeMode:STATIC
+     * @access VehiclePropertyAccess:READ
+     * @unit VehicleUnit:MW
+     */
+    EV_BATTERY_INSTANTANEOUS_CHARGE_RATE = (
+        0x030C
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:FLOAT
+        | VehicleArea:GLOBAL),
+
+    /**
      * Currently selected gear
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
@@ -376,8 +508,6 @@
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ
-     *
-     * @since o.mr1
      */
     ABS_ACTIVE = (
         0x040A
@@ -390,8 +520,6 @@
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ
-     *
-     * @since o.mr1
      */
     TRACTION_CONTROL_ACTIVE = (
         0x040B
@@ -720,8 +848,6 @@
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ_WRITE
-     *
-     * @since o.mr1
      */
     HVAC_AUTO_RECIRC_ON = (
         0x0512
@@ -1899,8 +2025,6 @@
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ_WRITE
-     *
-     * @since o.mr1
      */
     VEHICLE_MAP_SERVICE = (
         0x0C00
@@ -1948,8 +2072,6 @@
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ
-     *
-     * @since o.mr1
      */
     OBD2_LIVE_FRAME = (
       0x0D00
@@ -1980,8 +2102,6 @@
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ
-     *
-     * @since o.mr1
      */
     OBD2_FREEZE_FRAME = (
       0x0D01
@@ -2003,8 +2123,6 @@
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:READ
-     *
-     * @since o.mr1
      */
     OBD2_FREEZE_FRAME_INFO = (
       0x0D02
@@ -2031,8 +2149,6 @@
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
      * @access VehiclePropertyAccess:WRITE
-     *
-     * @since o.mr1
      */
     OBD2_FREEZE_FRAME_CLEAR = (
       0x0D03
@@ -2042,6 +2158,73 @@
 };
 
 /**
+ * Used by INFO_EV_CONNECTOR_TYPE to enumerate the type of connectors
+ * available to charge the vehicle.  Consistent with projection protocol.
+ */
+enum EvConnectorType : int32_t {
+    /**
+     * Default type if the vehicle does not know or report the EV connector
+     * type.
+     */
+    EV_CONNECTOR_TYPE_UNKNOWN = 0,
+    EV_CONNECTOR_TYPE_J1772 = 1,
+    EV_CONNECTOR_TYPE_MENNEKES = 2,
+    EV_CONNECTOR_TYPE_CHADEMO = 3,
+    EV_CONNECTOR_TYPE_COMBO_1 = 4,
+    EV_CONNECTOR_TYPE_COMBO_2 = 5,
+    EV_CONNECTOR_TYPE_TESLA_ROADSTER = 6,
+    EV_CONNECTOR_TYPE_TESLA_HPWC = 7,
+    EV_CONNECTOR_TYPE_TESLA_SUPERCHARGER = 8,
+    EV_CONNECTOR_TYPE_GBT = 9,
+
+    /**
+     * Connector type to use when no other types apply. Before using this
+     * value, work with Google to see if the EvConnectorType enum can be
+     * extended with an appropriate value.
+     */
+    EV_CONNECTOR_TYPE_OTHER = 101,
+};
+
+/**
+ * Used by INFO_FUEL_TYPE to enumerate the type of fuels this vehicle uses.
+ * Consistent with projection protocol.
+ */
+enum FuelType : int32_t {
+    /**
+     * Fuel type to use if the HU does not know on which types of fuel the vehicle
+     * runs. The use of this value is generally discouraged outside of aftermarket units.
+     */
+    FUEL_TYPE_UNKNOWN = 0,
+    /** Unleaded gasoline */
+    FUEL_TYPE_UNLEADED = 1,
+    /** Leaded gasoline */
+    FUEL_TYPE_LEADED = 2,
+    /** Diesel #1 */
+    FUEL_TYPE_DIESEL_1 = 3,
+    /** Diesel #2 */
+    FUEL_TYPE_DIESEL_2 = 4,
+    /** Biodiesel */
+    FUEL_TYPE_BIODIESEL = 5,
+    /** 85% ethanol/gasoline blend */
+    FUEL_TYPE_E85 = 6,
+    /** Liquified petroleum gas */
+    FUEL_TYPE_LPG = 7,
+    /** Compressed natural gas */
+    FUEL_TYPE_CNG = 8,
+    /** Liquified natural gas */
+    FUEL_TYPE_LNG = 9,
+    /** Electric */
+    FUEL_TYPE_ELECTRIC = 10,
+    /** Hydrogen fuel cell */
+    FUEL_TYPE_HYDROGEN = 11,
+    /**
+     * Fuel type to use when no other types apply. Before using this value, work with
+     * Google to see if the FuelType enum can be extended with an appropriate value.
+     */
+    FUEL_TYPE_OTHER = 12,
+};
+
+/**
  * Bit flags for fan direction
  */
 enum VehicleHvacFanDirection : int32_t {
@@ -2511,6 +2694,12 @@
     NANO_SECS      = 0x50,
     SECS           = 0x53,
     YEAR           = 0x59,
+
+    // Electrical Units
+    WATT_HOUR      = 0x60,
+    MILLIAMPERE    = 0x61,
+    MILLIVOLT      = 0x62,
+    MILLIWATTS     = 0x63,
 };
 
   /**
diff --git a/biometrics/fingerprint/2.1/default/android.hardware.biometrics.fingerprint@2.1-service.rc b/biometrics/fingerprint/2.1/default/android.hardware.biometrics.fingerprint@2.1-service.rc
index aa767a6..123d339 100644
--- a/biometrics/fingerprint/2.1/default/android.hardware.biometrics.fingerprint@2.1-service.rc
+++ b/biometrics/fingerprint/2.1/default/android.hardware.biometrics.fingerprint@2.1-service.rc
@@ -1,4 +1,4 @@
-service fps_hal /vendor/bin/hw/android.hardware.biometrics.fingerprint@2.1-service
+service vendor.fps_hal /vendor/bin/hw/android.hardware.biometrics.fingerprint@2.1-service
     # "class hal" causes a race condition on some devices due to files created
     # in /data. As a workaround, postpone startup until later in boot once
     # /data is mounted.
diff --git a/bluetooth/1.0/default/android.hardware.bluetooth@1.0-service.rc b/bluetooth/1.0/default/android.hardware.bluetooth@1.0-service.rc
index 47cc13e..e1f5faa 100644
--- a/bluetooth/1.0/default/android.hardware.bluetooth@1.0-service.rc
+++ b/bluetooth/1.0/default/android.hardware.bluetooth@1.0-service.rc
@@ -1,14 +1,14 @@
-service bluetooth-1-0 /vendor/bin/hw/android.hardware.bluetooth@1.0-service
+service vendor.bluetooth-1-0 /vendor/bin/hw/android.hardware.bluetooth@1.0-service
     class hal
     user bluetooth
     group bluetooth
     writepid /dev/stune/foreground/tasks
 
 on property:vts.native_server.on=1 && property:ro.build.type=userdebug
-    stop bluetooth-1-0
+    stop vendor.bluetooth-1-0
 on property:vts.native_server.on=1 && property:ro.build.type=eng
-    stop bluetooth-1-0
+    stop vendor.bluetooth-1-0
 on property:vts.native_server.on=0 && property:ro.build.type=userdebug
-    start bluetooth-1-0
+    start vendor.bluetooth-1-0
 on property:vts.native_server.on=0 && property:ro.build.type=eng
-    start bluetooth-1-0
+    start vendor.bluetooth-1-0
diff --git a/boot/1.0/default/android.hardware.boot@1.0-service.rc b/boot/1.0/default/android.hardware.boot@1.0-service.rc
index 68e7c22..32f3a45 100644
--- a/boot/1.0/default/android.hardware.boot@1.0-service.rc
+++ b/boot/1.0/default/android.hardware.boot@1.0-service.rc
@@ -1,4 +1,4 @@
-service boot-hal-1-0 /vendor/bin/hw/android.hardware.boot@1.0-service
+service vendor.boot-hal-1-0 /vendor/bin/hw/android.hardware.boot@1.0-service
     class early_hal
     user root
     group root
diff --git a/broadcastradio/1.1/utils/OWNERS b/broadcastradio/1.1/utils/OWNERS
deleted file mode 100644
index 0c27b71..0000000
--- a/broadcastradio/1.1/utils/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# Automotive team
-egranata@google.com
-keunyoung@google.com
-twasilczyk@google.com
diff --git a/broadcastradio/1.1/vts/OWNERS b/broadcastradio/1.1/vts/OWNERS
index aa5ce82..7736681 100644
--- a/broadcastradio/1.1/vts/OWNERS
+++ b/broadcastradio/1.1/vts/OWNERS
@@ -4,5 +4,5 @@
 twasilczyk@google.com
 
 # VTS team
-ryanjcampbell@google.com
+yuexima@google.com
 yim@google.com
diff --git a/broadcastradio/1.1/vts/functional/Android.bp b/broadcastradio/1.1/vts/functional/Android.bp
index 4b93cbc..27ae4e9 100644
--- a/broadcastradio/1.1/vts/functional/Android.bp
+++ b/broadcastradio/1.1/vts/functional/Android.bp
@@ -21,8 +21,9 @@
     static_libs: [
         "android.hardware.broadcastradio@1.0",
         "android.hardware.broadcastradio@1.1",
-        "android.hardware.broadcastradio@1.1-utils-lib",
-        "android.hardware.broadcastradio@1.1-vts-utils-lib",
+        "android.hardware.broadcastradio@1.2",  // common-utils-lib dependency
+        "android.hardware.broadcastradio@common-utils-1x-lib",
+        "android.hardware.broadcastradio@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 a46378e..823d14c 100644
--- a/broadcastradio/1.1/vts/functional/VtsHalBroadcastradioV1_1TargetTest.cpp
+++ b/broadcastradio/1.1/vts/functional/VtsHalBroadcastradioV1_1TargetTest.cpp
@@ -17,15 +17,16 @@
 #define LOG_TAG "broadcastradio.vts"
 
 #include <VtsHalHidlTargetTestBase.h>
+#include <android-base/logging.h>
 #include <android/hardware/broadcastradio/1.1/IBroadcastRadio.h>
 #include <android/hardware/broadcastradio/1.1/IBroadcastRadioFactory.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-utils-1x/Utils.h>
 #include <broadcastradio-vts-utils/call-barrier.h>
 #include <broadcastradio-vts-utils/mock-timeout.h>
+#include <broadcastradio-vts-utils/pointer-utils.h>
 #include <cutils/native_handle.h>
 #include <cutils/properties.h>
 #include <gmock/gmock.h>
@@ -56,8 +57,7 @@
 using V1_0::MetadataKey;
 using V1_0::MetadataType;
 
-using std::chrono::steady_clock;
-using std::this_thread::sleep_for;
+using broadcastradio::vts::clearAndWait;
 
 static constexpr auto kConfigTimeout = 10s;
 static constexpr auto kConnectModuleTimeout = 1s;
@@ -115,27 +115,6 @@
     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);
-    }
-}
-
 void BroadcastRadioHalTest::SetUp() {
     radioClass = GetParam();
 
@@ -525,6 +504,98 @@
     ASSERT_FALSE(forced);
 }
 
+static void verifyIdentifier(const ProgramIdentifier& id) {
+    EXPECT_NE(id.type, 0u);
+    auto val = id.value;
+
+    switch (static_cast<IdentifierType>(id.type)) {
+        case IdentifierType::AMFM_FREQUENCY:
+        case IdentifierType::DAB_FREQUENCY:
+        case IdentifierType::DRMO_FREQUENCY:
+            EXPECT_GT(val, 100u) << "Expected f > 100kHz";
+            EXPECT_LT(val, 10000000u) << "Expected f < 10GHz";
+            break;
+        case IdentifierType::RDS_PI:
+            EXPECT_GT(val, 0u);
+            EXPECT_LE(val, 0xFFFFu) << "Expected 16bit id";
+            break;
+        case IdentifierType::HD_STATION_ID_EXT: {
+            auto stationId = val & 0xFFFFFFFF;  // 32bit
+            val >>= 32;
+            auto subchannel = val & 0xF;  // 4bit
+            val >>= 4;
+            auto freq = val & 0x3FFFF;  // 18bit
+            EXPECT_GT(stationId, 0u);
+            EXPECT_LT(subchannel, 8u) << "Expected ch < 8";
+            EXPECT_GT(freq, 100u) << "Expected f > 100kHz";
+            EXPECT_LT(freq, 10000000u) << "Expected f < 10GHz";
+            break;
+        }
+        case IdentifierType::HD_SUBCHANNEL:
+            EXPECT_LT(val, 8u) << "Expected ch < 8";
+            break;
+        case IdentifierType::DAB_SIDECC: {
+            auto sid = val & 0xFFFF;  // 16bit
+            val >>= 16;
+            auto ecc = val & 0xFF;  // 8bit
+            EXPECT_NE(sid, 0u);
+            EXPECT_GE(ecc, 0xA0u) << "Invalid ECC, see ETSI TS 101 756 V2.1.1";
+            EXPECT_LE(ecc, 0xF6u) << "Invalid ECC, see ETSI TS 101 756 V2.1.1";
+            break;
+        }
+        case IdentifierType::DAB_ENSEMBLE:
+            EXPECT_GT(val, 0u);
+            EXPECT_LE(val, 0xFFFFu) << "Expected 16bit id";
+            break;
+        case IdentifierType::DAB_SCID:
+            EXPECT_GT(val, 0xFu) << "Expected 12bit SCId (not 4bit SCIdS)";
+            EXPECT_LE(val, 0xFFFu) << "Expected 12bit id";
+            break;
+        case IdentifierType::DRMO_SERVICE_ID:
+            EXPECT_GT(val, 0u);
+            EXPECT_LE(val, 0xFFFFFFu) << "Expected 24bit id";
+            break;
+        case IdentifierType::DRMO_MODULATION:
+            EXPECT_GE(val, static_cast<uint32_t>(Modulation::AM));
+            EXPECT_LE(val, static_cast<uint32_t>(Modulation::FM));
+            break;
+        case IdentifierType::SXM_SERVICE_ID:
+            EXPECT_GT(val, 0u);
+            EXPECT_LE(val, 0xFFFFFFFFu) << "Expected 32bit id";
+            break;
+        case IdentifierType::SXM_CHANNEL:
+            EXPECT_LT(val, 1000u);
+            break;
+        case IdentifierType::VENDOR_PRIMARY_START:
+        case IdentifierType::VENDOR_PRIMARY_END:
+            // skip
+            break;
+    }
+}
+
+/**
+ * Test ProgramIdentifier format.
+ *
+ * Verifies that:
+ * - values of ProgramIdentifier match their definitions at IdentifierType.
+ */
+TEST_P(BroadcastRadioHalTest, VerifyIdentifiersFormat) {
+    if (skipped) return;
+    ASSERT_TRUE(openTuner());
+
+    do {
+        auto getCb = [&](const hidl_vec<ProgramInfo>& list) {
+            for (auto&& program : list) {
+                verifyIdentifier(program.selector.primaryId);
+                for (auto&& id : program.selector.secondaryIds) {
+                    verifyIdentifier(id);
+                }
+            }
+        };
+        getProgramList(getCb);
+    } while (nextBand());
+}
+
 INSTANTIATE_TEST_CASE_P(BroadcastRadioHalTestCases, BroadcastRadioHalTest,
                         ::testing::Values(Class::AM_FM, Class::SAT, Class::DT));
 
diff --git a/broadcastradio/1.2/Android.bp b/broadcastradio/1.2/Android.bp
new file mode 100644
index 0000000..40eb4e0
--- /dev/null
+++ b/broadcastradio/1.2/Android.bp
@@ -0,0 +1,25 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.broadcastradio@1.2",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "types.hal",
+        "IBroadcastRadioFactory.hal",
+        "ITuner.hal",
+        "ITunerCallback.hal",
+    ],
+    interfaces: [
+        "android.hardware.broadcastradio@1.0",
+        "android.hardware.broadcastradio@1.1",
+        "android.hidl.base@1.0",
+    ],
+    types: [
+        "IdentifierType",
+    ],
+    gen_java: false,
+}
+
diff --git a/broadcastradio/1.2/IBroadcastRadioFactory.hal b/broadcastradio/1.2/IBroadcastRadioFactory.hal
new file mode 100644
index 0000000..29f6ab3
--- /dev/null
+++ b/broadcastradio/1.2/IBroadcastRadioFactory.hal
@@ -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.
+ */
+
+package android.hardware.broadcastradio@1.2;
+
+import @1.1::IBroadcastRadioFactory;
+
+/**
+ * To use 1.2 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_2::ITuner::castFrom() call.
+ *
+ * The 1.2 server must always return the 1.2 version of specific interface.
+ */
+interface IBroadcastRadioFactory extends @1.1::IBroadcastRadioFactory {
+};
diff --git a/broadcastradio/1.2/ITuner.hal b/broadcastradio/1.2/ITuner.hal
new file mode 100644
index 0000000..ba97ea0
--- /dev/null
+++ b/broadcastradio/1.2/ITuner.hal
@@ -0,0 +1,70 @@
+/*
+ * 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.broadcastradio@1.2;
+
+import @1.1::ITuner;
+
+interface ITuner extends @1.1::ITuner {
+    /**
+     * Generic method for setting vendor-specific parameter values.
+     * The framework does not interpret the parameters, they are passed
+     * in an opaque manner between a vendor application and HAL.
+     *
+     * Framework does not make any assumptions on the keys or values, other than
+     * ones stated in VendorKeyValue documentation (a requirement of key
+     * prefixes).
+     *
+     * For each pair in the result vector, the key must be one of the keys
+     * contained in the input (possibly with wildcards expanded), and the value
+     * must be a vendor-specific result status (i.e. the string "OK" or an error
+     * code). The implementation may choose to return an empty vector, or only
+     * return a status for a subset of the provided inputs, at its discretion.
+     *
+     * Application and HAL must not use keys with unknown prefix. In particular,
+     * it must not place a key-value pair in results vector for unknown key from
+     * parameters vector - instead, an unknown key should simply be ignored.
+     * In other words, results vector may contain a subset of parameter keys
+     * (however, the framework doesn't enforce a strict subset - the only
+     * formal requirement is vendor domain prefix for keys).
+     *
+     * @param parameters Vendor-specific key-value pairs.
+     * @return results Operation completion status for parameters being set.
+     */
+    setParameters(vec<VendorKeyValue> parameters)
+            generates (vec<VendorKeyValue> results);
+
+    /**
+     * Generic method for retrieving vendor-specific parameter values.
+     * The framework does not interpret the parameters, they are passed
+     * in an opaque manner between a vendor application and HAL.
+     *
+     * Framework does not cache set/get requests, so it's allowed for
+     * getParameter to return a different value than previous setParameter call.
+     *
+     * The syntax and semantics of keys are up to the vendor (as long as prefix
+     * rules are obeyed). For instance, vendors may include some form of
+     * wildcard support. In such case, result vector may be of different size
+     * than requested keys vector. However, wildcards are not recognized by
+     * framework and they are passed as-is to the HAL implementation.
+     *
+     * Unknown keys must be ignored and not placed into results vector.
+     *
+     * @param keys Parameter keys to fetch.
+     * @return parameters Vendor-specific key-value pairs.
+     */
+    getParameters(vec<string> keys) generates (vec<VendorKeyValue> parameters);
+};
diff --git a/broadcastradio/1.2/ITunerCallback.hal b/broadcastradio/1.2/ITunerCallback.hal
new file mode 100644
index 0000000..4e3d0a5
--- /dev/null
+++ b/broadcastradio/1.2/ITunerCallback.hal
@@ -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.
+ */
+
+package android.hardware.broadcastradio@1.2;
+
+import @1.1::ITunerCallback;
+
+interface ITunerCallback extends @1.1::ITunerCallback {
+    /**
+     * Generic callback for passing updates to vendor-specific parameter values.
+     * The framework does not interpret the parameters, they are passed
+     * in an opaque manner between a vendor application and HAL.
+     *
+     * It's up to the HAL implementation if and how to implement this callback,
+     * as long as it obeys the prefix rule. In particular, only selected keys
+     * may be notified this way. However, setParameters must not trigger
+     * this callback, while an internal event can change parameters
+     * asynchronously.
+     *
+     * @param parameters Vendor-specific key-value pairs.
+     */
+    oneway parametersUpdated(vec<VendorKeyValue> parameters);
+};
diff --git a/broadcastradio/1.1/default/Android.bp b/broadcastradio/1.2/default/Android.bp
similarity index 80%
rename from broadcastradio/1.1/default/Android.bp
rename to broadcastradio/1.2/default/Android.bp
index 6d26b11..bd4be77 100644
--- a/broadcastradio/1.1/default/Android.bp
+++ b/broadcastradio/1.2/default/Android.bp
@@ -15,8 +15,8 @@
 //
 
 cc_binary {
-    name: "android.hardware.broadcastradio@1.1-service",
-    init_rc: ["android.hardware.broadcastradio@1.1-service.rc"],
+    name: "android.hardware.broadcastradio@1.2-service",
+    init_rc: ["android.hardware.broadcastradio@1.2-service.rc"],
     vendor: true,
     relative_install_path: "hw",
     cflags: [
@@ -33,11 +33,13 @@
         "service.cpp"
     ],
     static_libs: [
-        "android.hardware.broadcastradio@1.1-utils-lib",
+        "android.hardware.broadcastradio@common-utils-1x-lib",
+        "android.hardware.broadcastradio@common-utils-lib",
     ],
     shared_libs: [
         "android.hardware.broadcastradio@1.0",
         "android.hardware.broadcastradio@1.1",
+        "android.hardware.broadcastradio@1.2",
         "libbase",
         "libhidlbase",
         "libhidltransport",
diff --git a/broadcastradio/1.1/default/BroadcastRadio.cpp b/broadcastradio/1.2/default/BroadcastRadio.cpp
similarity index 96%
rename from broadcastradio/1.1/default/BroadcastRadio.cpp
rename to broadcastradio/1.2/default/BroadcastRadio.cpp
index 1bcfd82..5164e47 100644
--- a/broadcastradio/1.1/default/BroadcastRadio.cpp
+++ b/broadcastradio/1.2/default/BroadcastRadio.cpp
@@ -25,7 +25,7 @@
 namespace android {
 namespace hardware {
 namespace broadcastradio {
-namespace V1_1 {
+namespace V1_2 {
 namespace implementation {
 
 using V1_0::Band;
@@ -33,6 +33,11 @@
 using V1_0::Class;
 using V1_0::Deemphasis;
 using V1_0::Rds;
+using V1_1::IdentifierType;
+using V1_1::ProgramSelector;
+using V1_1::ProgramType;
+using V1_1::Properties;
+using V1_1::VendorKeyValue;
 
 using std::lock_guard;
 using std::map;
@@ -185,7 +190,7 @@
 }
 
 }  // namespace implementation
-}  // namespace V1_1
+}  // namespace V1_2
 }  // namespace broadcastradio
 }  // namespace hardware
 }  // namespace android
diff --git a/broadcastradio/1.1/default/BroadcastRadio.h b/broadcastradio/1.2/default/BroadcastRadio.h
similarity index 88%
rename from broadcastradio/1.1/default/BroadcastRadio.h
rename to broadcastradio/1.2/default/BroadcastRadio.h
index a96a2ab..94d62b9 100644
--- a/broadcastradio/1.1/default/BroadcastRadio.h
+++ b/broadcastradio/1.2/default/BroadcastRadio.h
@@ -13,18 +13,18 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#ifndef ANDROID_HARDWARE_BROADCASTRADIO_V1_1_BROADCASTRADIO_H
-#define ANDROID_HARDWARE_BROADCASTRADIO_V1_1_BROADCASTRADIO_H
+#ifndef ANDROID_HARDWARE_BROADCASTRADIO_V1_2_BROADCASTRADIO_H
+#define ANDROID_HARDWARE_BROADCASTRADIO_V1_2_BROADCASTRADIO_H
 
 #include "Tuner.h"
 
 #include <android/hardware/broadcastradio/1.1/IBroadcastRadio.h>
-#include <android/hardware/broadcastradio/1.1/types.h>
+#include <android/hardware/broadcastradio/1.2/types.h>
 
 namespace android {
 namespace hardware {
 namespace broadcastradio {
-namespace V1_1 {
+namespace V1_2 {
 namespace implementation {
 
 struct AmFmBandConfig {
@@ -73,9 +73,9 @@
 };
 
 }  // namespace implementation
-}  // namespace V1_1
+}  // namespace V1_2
 }  // namespace broadcastradio
 }  // namespace hardware
 }  // namespace android
 
-#endif  // ANDROID_HARDWARE_BROADCASTRADIO_V1_1_BROADCASTRADIO_H
+#endif  // ANDROID_HARDWARE_BROADCASTRADIO_V1_2_BROADCASTRADIO_H
diff --git a/broadcastradio/1.1/default/BroadcastRadioFactory.cpp b/broadcastradio/1.2/default/BroadcastRadioFactory.cpp
similarity index 90%
rename from broadcastradio/1.1/default/BroadcastRadioFactory.cpp
rename to broadcastradio/1.2/default/BroadcastRadioFactory.cpp
index f57bc79..8f17aff 100644
--- a/broadcastradio/1.1/default/BroadcastRadioFactory.cpp
+++ b/broadcastradio/1.2/default/BroadcastRadioFactory.cpp
@@ -25,7 +25,7 @@
 namespace android {
 namespace hardware {
 namespace broadcastradio {
-namespace V1_1 {
+namespace V1_2 {
 namespace implementation {
 
 using V1_0::Class;
@@ -36,10 +36,6 @@
     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;
@@ -61,7 +57,7 @@
 }
 
 }  // namespace implementation
-}  // namespace V1_1
+}  // namespace V1_2
 }  // namespace broadcastradio
 }  // namespace hardware
 }  // namespace android
diff --git a/broadcastradio/1.1/default/BroadcastRadioFactory.h b/broadcastradio/1.2/default/BroadcastRadioFactory.h
similarity index 69%
rename from broadcastradio/1.1/default/BroadcastRadioFactory.h
rename to broadcastradio/1.2/default/BroadcastRadioFactory.h
index 8b67ac3..c365ae0 100644
--- a/broadcastradio/1.1/default/BroadcastRadioFactory.h
+++ b/broadcastradio/1.2/default/BroadcastRadioFactory.h
@@ -13,21 +13,19 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#ifndef ANDROID_HARDWARE_BROADCASTRADIO_V1_1_BROADCASTRADIOFACTORY_H
-#define ANDROID_HARDWARE_BROADCASTRADIO_V1_1_BROADCASTRADIOFACTORY_H
+#ifndef ANDROID_HARDWARE_BROADCASTRADIO_V1_2_BROADCASTRADIOFACTORY_H
+#define ANDROID_HARDWARE_BROADCASTRADIO_V1_2_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>
+#include <android/hardware/broadcastradio/1.2/IBroadcastRadioFactory.h>
+#include <android/hardware/broadcastradio/1.2/types.h>
 
 namespace android {
 namespace hardware {
 namespace broadcastradio {
-namespace V1_1 {
+namespace V1_2 {
 namespace implementation {
 
-extern "C" IBroadcastRadioFactory* HIDL_FETCH_IBroadcastRadioFactory(const char* name);
-
 struct BroadcastRadioFactory : public IBroadcastRadioFactory {
     BroadcastRadioFactory();
 
@@ -35,13 +33,13 @@
     Return<void> connectModule(V1_0::Class classId, connectModule_cb _hidl_cb) override;
 
    private:
-    std::map<V1_0::Class, sp<IBroadcastRadio>> mRadioModules;
+    std::map<V1_0::Class, sp<V1_1::IBroadcastRadio>> mRadioModules;
 };
 
 }  // namespace implementation
-}  // namespace V1_1
+}  // namespace V1_2
 }  // namespace broadcastradio
 }  // namespace hardware
 }  // namespace android
 
-#endif  // ANDROID_HARDWARE_BROADCASTRADIO_V1_1_BROADCASTRADIOFACTORY_H
+#endif  // ANDROID_HARDWARE_BROADCASTRADIO_V1_2_BROADCASTRADIOFACTORY_H
diff --git a/broadcastradio/1.1/default/OWNERS b/broadcastradio/1.2/default/OWNERS
similarity index 74%
rename from broadcastradio/1.1/default/OWNERS
rename to broadcastradio/1.2/default/OWNERS
index 0c27b71..136b607 100644
--- a/broadcastradio/1.1/default/OWNERS
+++ b/broadcastradio/1.2/default/OWNERS
@@ -1,4 +1,3 @@
 # Automotive team
 egranata@google.com
-keunyoung@google.com
 twasilczyk@google.com
diff --git a/broadcastradio/1.1/default/Tuner.cpp b/broadcastradio/1.2/default/Tuner.cpp
similarity index 90%
rename from broadcastradio/1.1/default/Tuner.cpp
rename to broadcastradio/1.2/default/Tuner.cpp
index 9a34cb1..f589332 100644
--- a/broadcastradio/1.1/default/Tuner.cpp
+++ b/broadcastradio/1.2/default/Tuner.cpp
@@ -20,13 +20,13 @@
 #include "BroadcastRadio.h"
 #include "Tuner.h"
 
-#include <broadcastradio-utils/Utils.h>
+#include <broadcastradio-utils-1x/Utils.h>
 #include <log/log.h>
 
 namespace android {
 namespace hardware {
 namespace broadcastradio {
-namespace V1_1 {
+namespace V1_2 {
 namespace implementation {
 
 using namespace std::chrono_literals;
@@ -35,6 +35,13 @@
 using V1_0::BandConfig;
 using V1_0::Class;
 using V1_0::Direction;
+using V1_1::ProgramInfo;
+using V1_1::ProgramInfoFlags;
+using V1_1::ProgramListResult;
+using V1_1::ProgramSelector;
+using V1_1::ProgramType;
+using V1_1::VendorKeyValue;
+using V1_2::IdentifierType;
 using utils::HalRevision;
 
 using std::chrono::milliseconds;
@@ -54,7 +61,8 @@
 Tuner::Tuner(V1_0::Class classId, const sp<V1_0::ITunerCallback>& callback)
     : mClassId(classId),
       mCallback(callback),
-      mCallback1_1(ITunerCallback::castFrom(callback).withDefault(nullptr)),
+      mCallback1_1(V1_1::ITunerCallback::castFrom(callback).withDefault(nullptr)),
+      mCallback1_2(V1_2::ITunerCallback::castFrom(callback).withDefault(nullptr)),
       mVirtualRadio(getRadio(classId)),
       mIsAnalogForced(false) {}
 
@@ -122,7 +130,9 @@
 }
 
 HalRevision Tuner::getHalRev() const {
-    if (mCallback1_1 != nullptr) {
+    if (mCallback1_2 != nullptr) {
+        return HalRevision::V1_2;
+    } else if (mCallback1_1 != nullptr) {
         return HalRevision::V1_1;
     } else {
         return HalRevision::V1_0;
@@ -272,7 +282,7 @@
             return Result::INVALID_ARGUMENTS;
         }
     } else if (programType == ProgramType::DAB) {
-        if (!utils::hasId(sel, IdentifierType::DAB_SIDECC)) return Result::INVALID_ARGUMENTS;
+        if (!utils::hasId(sel, IdentifierType::DAB_SID_EXT)) 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) {
@@ -310,9 +320,8 @@
 
 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 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) {
@@ -373,8 +382,24 @@
     return {};
 }
 
+Return<void> Tuner::setParameters(const hidl_vec<VendorKeyValue>& /* parameters */,
+        setParameters_cb _hidl_cb) {
+    ALOGV("%s", __func__);
+
+    _hidl_cb({});
+    return {};
+}
+
+Return<void> Tuner::getParameters(const hidl_vec<hidl_string>& /* keys */,
+        getParameters_cb _hidl_cb) {
+    ALOGV("%s", __func__);
+
+    _hidl_cb({});
+    return {};
+}
+
 }  // namespace implementation
-}  // namespace V1_1
+}  // namespace V1_2
 }  // namespace broadcastradio
 }  // namespace hardware
 }  // namespace android
diff --git a/broadcastradio/1.1/default/Tuner.h b/broadcastradio/1.2/default/Tuner.h
similarity index 68%
rename from broadcastradio/1.1/default/Tuner.h
rename to broadcastradio/1.2/default/Tuner.h
index 07d3189..7e68354 100644
--- a/broadcastradio/1.1/default/Tuner.h
+++ b/broadcastradio/1.2/default/Tuner.h
@@ -13,19 +13,19 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#ifndef ANDROID_HARDWARE_BROADCASTRADIO_V1_1_TUNER_H
-#define ANDROID_HARDWARE_BROADCASTRADIO_V1_1_TUNER_H
+#ifndef ANDROID_HARDWARE_BROADCASTRADIO_V1_2_TUNER_H
+#define ANDROID_HARDWARE_BROADCASTRADIO_V1_2_TUNER_H
 
 #include "VirtualRadio.h"
 
-#include <android/hardware/broadcastradio/1.1/ITuner.h>
-#include <android/hardware/broadcastradio/1.1/ITunerCallback.h>
+#include <android/hardware/broadcastradio/1.2/ITuner.h>
+#include <android/hardware/broadcastradio/1.2/ITunerCallback.h>
 #include <broadcastradio-utils/WorkerThread.h>
 
 namespace android {
 namespace hardware {
 namespace broadcastradio {
-namespace V1_1 {
+namespace V1_2 {
 namespace implementation {
 
 struct Tuner : public ITuner {
@@ -33,22 +33,26 @@
 
     void forceClose();
 
-    // V1_1::ITuner methods
+    // V1_2::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> tuneByProgramSelector(const V1_1::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,
+    virtual Return<V1_1::ProgramListResult> startBackgroundScan() override;
+    virtual Return<void> getProgramList(const hidl_vec<V1_1::VendorKeyValue>& filter,
                                         getProgramList_cb _hidl_cb) override;
     virtual Return<Result> setAnalogForced(bool isForced) override;
     virtual Return<void> isAnalogForced(isAnalogForced_cb _hidl_cb) override;
+    virtual Return<void> setParameters(const hidl_vec<V1_1::VendorKeyValue>& parameters,
+                                       setParameters_cb _hidl_cb) override;
+    virtual Return<void> getParameters(const hidl_vec<hidl_string>& keys,
+                                       getParameters_cb _hidl_cb) override;
 
    private:
     std::mutex mMut;
@@ -58,23 +62,24 @@
     V1_0::Class mClassId;
     const sp<V1_0::ITunerCallback> mCallback;
     const sp<V1_1::ITunerCallback> mCallback1_1;
+    const sp<V1_2::ITunerCallback> mCallback1_2;
 
     std::reference_wrapper<VirtualRadio> mVirtualRadio;
     bool mIsAmfmConfigSet = false;
     V1_0::BandConfig mAmfmConfig;
     bool mIsTuneCompleted = false;
-    ProgramSelector mCurrentProgram = {};
-    ProgramInfo mCurrentProgramInfo = {};
+    V1_1::ProgramSelector mCurrentProgram = {};
+    V1_1::ProgramInfo mCurrentProgramInfo = {};
     std::atomic<bool> mIsAnalogForced;
 
     utils::HalRevision getHalRev() const;
-    void tuneInternalLocked(const ProgramSelector& sel);
+    void tuneInternalLocked(const V1_1::ProgramSelector& sel);
 };
 
 }  // namespace implementation
-}  // namespace V1_1
+}  // namespace V1_2
 }  // namespace broadcastradio
 }  // namespace hardware
 }  // namespace android
 
-#endif  // ANDROID_HARDWARE_BROADCASTRADIO_V1_1_TUNER_H
+#endif  // ANDROID_HARDWARE_BROADCASTRADIO_V1_2_TUNER_H
diff --git a/broadcastradio/1.1/default/VirtualProgram.cpp b/broadcastradio/1.2/default/VirtualProgram.cpp
similarity index 88%
rename from broadcastradio/1.1/default/VirtualProgram.cpp
rename to broadcastradio/1.2/default/VirtualProgram.cpp
index 7977391..3594f64 100644
--- a/broadcastradio/1.1/default/VirtualProgram.cpp
+++ b/broadcastradio/1.2/default/VirtualProgram.cpp
@@ -15,14 +15,14 @@
  */
 #include "VirtualProgram.h"
 
-#include <broadcastradio-utils/Utils.h>
+#include <broadcastradio-utils-1x/Utils.h>
 
 #include "resources.h"
 
 namespace android {
 namespace hardware {
 namespace broadcastradio {
-namespace V1_1 {
+namespace V1_2 {
 namespace implementation {
 
 using std::vector;
@@ -30,6 +30,9 @@
 using V1_0::MetaData;
 using V1_0::MetadataKey;
 using V1_0::MetadataType;
+using V1_1::ProgramInfo;
+using V1_1::VendorKeyValue;
+using V1_2::IdentifierType;
 using utils::HalRevision;
 
 static MetaData createDemoBitmap(MetadataKey key, HalRevision halRev) {
@@ -80,13 +83,6 @@
     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;
 }
 
@@ -100,7 +96,7 @@
 }
 
 }  // namespace implementation
-}  // namespace V1_1
+}  // namespace V1_2
 }  // namespace broadcastradio
 }  // namespace hardware
 }  // namespace android
diff --git a/broadcastradio/1.1/default/VirtualProgram.h b/broadcastradio/1.2/default/VirtualProgram.h
similarity index 66%
copy from broadcastradio/1.1/default/VirtualProgram.h
copy to broadcastradio/1.2/default/VirtualProgram.h
index a14830d..c0b20f0 100644
--- a/broadcastradio/1.1/default/VirtualProgram.h
+++ b/broadcastradio/1.2/default/VirtualProgram.h
@@ -13,16 +13,16 @@
  * 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
+#ifndef ANDROID_HARDWARE_BROADCASTRADIO_V1_2_VIRTUALPROGRAM_H
+#define ANDROID_HARDWARE_BROADCASTRADIO_V1_2_VIRTUALPROGRAM_H
 
-#include <android/hardware/broadcastradio/1.1/types.h>
-#include <broadcastradio-utils/Utils.h>
+#include <android/hardware/broadcastradio/1.2/types.h>
+#include <broadcastradio-utils-1x/Utils.h>
 
 namespace android {
 namespace hardware {
 namespace broadcastradio {
-namespace V1_1 {
+namespace V1_2 {
 namespace implementation {
 
 /**
@@ -32,24 +32,24 @@
  * not an entry for a captured station in the radio tuner memory.
  */
 struct VirtualProgram {
-    ProgramSelector selector;
+    V1_1::ProgramSelector selector;
 
     std::string programName = "";
     std::string songArtist = "";
     std::string songTitle = "";
 
-    ProgramInfo getProgramInfo(utils::HalRevision halRev) const;
+    V1_1::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);
+std::vector<V1_1::ProgramInfo> getProgramInfoVector(const std::vector<VirtualProgram>& vec,
+                                                    utils::HalRevision halRev);
 
 }  // namespace implementation
-}  // namespace V1_1
+}  // namespace V1_2
 }  // namespace broadcastradio
 }  // namespace hardware
 }  // namespace android
 
-#endif  // ANDROID_HARDWARE_BROADCASTRADIO_V1_1_VIRTUALPROGRAM_H
+#endif  // ANDROID_HARDWARE_BROADCASTRADIO_V1_2_VIRTUALPROGRAM_H
diff --git a/broadcastradio/1.1/default/VirtualRadio.cpp b/broadcastradio/1.2/default/VirtualRadio.cpp
similarity index 96%
rename from broadcastradio/1.1/default/VirtualRadio.cpp
rename to broadcastradio/1.2/default/VirtualRadio.cpp
index 36d47a9..8988080 100644
--- a/broadcastradio/1.1/default/VirtualRadio.cpp
+++ b/broadcastradio/1.2/default/VirtualRadio.cpp
@@ -18,17 +18,18 @@
 
 #include "VirtualRadio.h"
 
-#include <broadcastradio-utils/Utils.h>
+#include <broadcastradio-utils-1x/Utils.h>
 #include <log/log.h>
 
 namespace android {
 namespace hardware {
 namespace broadcastradio {
-namespace V1_1 {
+namespace V1_2 {
 namespace implementation {
 
 using V1_0::Band;
 using V1_0::Class;
+using V1_1::ProgramSelector;
 
 using std::lock_guard;
 using std::move;
@@ -99,7 +100,7 @@
 }
 
 }  // namespace implementation
-}  // namespace V1_1
+}  // namespace V1_2
 }  // namespace broadcastradio
 }  // namespace hardware
 }  // namespace android
diff --git a/broadcastradio/1.1/default/VirtualRadio.h b/broadcastradio/1.2/default/VirtualRadio.h
similarity index 87%
rename from broadcastradio/1.1/default/VirtualRadio.h
rename to broadcastradio/1.2/default/VirtualRadio.h
index 3c7ae5c..8cfaefe 100644
--- a/broadcastradio/1.1/default/VirtualRadio.h
+++ b/broadcastradio/1.2/default/VirtualRadio.h
@@ -13,8 +13,8 @@
  * 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
+#ifndef ANDROID_HARDWARE_BROADCASTRADIO_V1_2_VIRTUALRADIO_H
+#define ANDROID_HARDWARE_BROADCASTRADIO_V1_2_VIRTUALRADIO_H
 
 #include "VirtualProgram.h"
 
@@ -24,7 +24,7 @@
 namespace android {
 namespace hardware {
 namespace broadcastradio {
-namespace V1_1 {
+namespace V1_2 {
 namespace implementation {
 
 /**
@@ -40,7 +40,7 @@
     VirtualRadio(const std::vector<VirtualProgram> initialList);
 
     std::vector<VirtualProgram> getProgramList();
-    bool getProgram(const ProgramSelector& selector, VirtualProgram& program);
+    bool getProgram(const V1_1::ProgramSelector& selector, VirtualProgram& program);
 
    private:
     std::mutex mMut;
@@ -72,9 +72,9 @@
 VirtualRadio& getDigitalRadio();
 
 }  // namespace implementation
-}  // namespace V1_1
+}  // namespace V1_2
 }  // namespace broadcastradio
 }  // namespace hardware
 }  // namespace android
 
-#endif  // ANDROID_HARDWARE_BROADCASTRADIO_V1_1_VIRTUALRADIO_H
+#endif  // ANDROID_HARDWARE_BROADCASTRADIO_V1_2_VIRTUALRADIO_H
diff --git a/broadcastradio/1.1/default/android.hardware.broadcastradio@1.1-service.rc b/broadcastradio/1.2/default/android.hardware.broadcastradio@1.2-service.rc
similarity index 83%
rename from broadcastradio/1.1/default/android.hardware.broadcastradio@1.1-service.rc
rename to broadcastradio/1.2/default/android.hardware.broadcastradio@1.2-service.rc
index 7c57135..3741f21 100644
--- a/broadcastradio/1.1/default/android.hardware.broadcastradio@1.1-service.rc
+++ b/broadcastradio/1.2/default/android.hardware.broadcastradio@1.2-service.rc
@@ -1,4 +1,4 @@
-service broadcastradio-hal /vendor/bin/hw/android.hardware.broadcastradio@1.1-service
+service broadcastradio-hal /vendor/bin/hw/android.hardware.broadcastradio@1.2-service
     class hal
     user audioserver
     group audio
diff --git a/broadcastradio/1.1/default/resources.h b/broadcastradio/1.2/default/resources.h
similarity index 89%
copy from broadcastradio/1.1/default/resources.h
copy to broadcastradio/1.2/default/resources.h
index b7e709f..b383c27 100644
--- a/broadcastradio/1.1/default/resources.h
+++ b/broadcastradio/1.2/default/resources.h
@@ -13,13 +13,13 @@
  * 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
+#ifndef ANDROID_HARDWARE_BROADCASTRADIO_V1_2_RESOURCES_H
+#define ANDROID_HARDWARE_BROADCASTRADIO_V1_2_RESOURCES_H
 
 namespace android {
 namespace hardware {
 namespace broadcastradio {
-namespace V1_1 {
+namespace V1_2 {
 namespace implementation {
 namespace resources {
 
@@ -38,9 +38,9 @@
 
 }  // namespace resources
 }  // namespace implementation
-}  // namespace V1_1
+}  // namespace V1_2
 }  // namespace broadcastradio
 }  // namespace hardware
 }  // namespace android
 
-#endif  // ANDROID_HARDWARE_BROADCASTRADIO_V1_1_RESOURCES_H
+#endif  // ANDROID_HARDWARE_BROADCASTRADIO_V1_2_RESOURCES_H
diff --git a/broadcastradio/1.1/default/service.cpp b/broadcastradio/1.2/default/service.cpp
similarity index 94%
rename from broadcastradio/1.1/default/service.cpp
rename to broadcastradio/1.2/default/service.cpp
index f8af0b7..ea86fba 100644
--- a/broadcastradio/1.1/default/service.cpp
+++ b/broadcastradio/1.2/default/service.cpp
@@ -22,7 +22,7 @@
 
 using android::hardware::configureRpcThreadpool;
 using android::hardware::joinRpcThreadpool;
-using android::hardware::broadcastradio::V1_1::implementation::BroadcastRadioFactory;
+using android::hardware::broadcastradio::V1_2::implementation::BroadcastRadioFactory;
 
 int main(int /* argc */, char** /* argv */) {
     configureRpcThreadpool(4, true);
diff --git a/broadcastradio/1.2/types.hal b/broadcastradio/1.2/types.hal
new file mode 100644
index 0000000..7301e13
--- /dev/null
+++ b/broadcastradio/1.2/types.hal
@@ -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.
+ */
+
+package android.hardware.broadcastradio@1.2;
+
+import @1.1::IdentifierType;
+import @1.1::Result;
+import @1.1::VendorKeyValue;
+
+typedef @1.1::Result Result;
+typedef @1.1::VendorKeyValue VendorKeyValue;
+
+enum IdentifierType : @1.1::IdentifierType {
+    /**
+     * 28bit compound primary identifier for DAB.
+     *
+     * Consists of (from the LSB):
+     * - 16bit: SId;
+     * - 8bit: ECC code;
+     * - 4bit: SCIdS (optional).
+     *
+     * SCIdS (Service Component Identifier within the Service) value
+     * of 0 represents the main service, while 1 and above represents
+     * secondary services.
+     *
+     * The remaining bits should be set to zeros when writing on the chip side
+     * and ignored when read.
+     *
+     * This identifier deprecates DAB_SIDECC and makes new primary identifier
+     * for DAB. If the hal implementation detects 1.2 client (by casting
+     * V1_0::ITunerCallback to V1_2::ITunerCallback), it must use DAB_SID_EXT
+     * as a primary identifier for DAB program type. If the hal client detects
+     * either 1.1 or 1.2 HAL, it must convert those identifiers to the
+     * correct version.
+     */
+    DAB_SID_EXT = SXM_CHANNEL + 1,
+};
diff --git a/broadcastradio/1.1/tests/OWNERS b/broadcastradio/1.2/vts/OWNERS
similarity index 65%
rename from broadcastradio/1.1/tests/OWNERS
rename to broadcastradio/1.2/vts/OWNERS
index aa5ce82..12adf57 100644
--- a/broadcastradio/1.1/tests/OWNERS
+++ b/broadcastradio/1.2/vts/OWNERS
@@ -1,8 +1,7 @@
 # Automotive team
 egranata@google.com
-keunyoung@google.com
 twasilczyk@google.com
 
 # VTS team
-ryanjcampbell@google.com
+yuexima@google.com
 yim@google.com
diff --git a/broadcastradio/1.1/utils/Android.bp b/broadcastradio/1.2/vts/functional/Android.bp
similarity index 66%
copy from broadcastradio/1.1/utils/Android.bp
copy to broadcastradio/1.2/vts/functional/Android.bp
index e80d133..fd1c254 100644
--- a/broadcastradio/1.1/utils/Android.bp
+++ b/broadcastradio/1.2/vts/functional/Android.bp
@@ -14,21 +14,15 @@
 // 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: [
+cc_test {
+    name: "VtsHalBroadcastradioV1_2TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: ["VtsHalBroadcastradioV1_2TargetTest.cpp"],
+    static_libs: [
+        "android.hardware.broadcastradio@1.0",
         "android.hardware.broadcastradio@1.1",
+        "android.hardware.broadcastradio@1.2",
+        "android.hardware.broadcastradio@vts-utils-lib",
+        "libgmock",
     ],
 }
diff --git a/broadcastradio/1.2/vts/functional/VtsHalBroadcastradioV1_2TargetTest.cpp b/broadcastradio/1.2/vts/functional/VtsHalBroadcastradioV1_2TargetTest.cpp
new file mode 100644
index 0000000..085206b
--- /dev/null
+++ b/broadcastradio/1.2/vts/functional/VtsHalBroadcastradioV1_2TargetTest.cpp
@@ -0,0 +1,293 @@
+/*
+ * 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 "broadcastradio.vts"
+
+#include <VtsHalHidlTargetTestBase.h>
+#include <android-base/logging.h>
+#include <android/hardware/broadcastradio/1.1/IBroadcastRadio.h>
+#include <android/hardware/broadcastradio/1.2/IBroadcastRadioFactory.h>
+#include <android/hardware/broadcastradio/1.2/ITuner.h>
+#include <android/hardware/broadcastradio/1.2/ITunerCallback.h>
+#include <android/hardware/broadcastradio/1.2/types.h>
+#include <broadcastradio-vts-utils/call-barrier.h>
+#include <broadcastradio-vts-utils/mock-timeout.h>
+#include <broadcastradio-vts-utils/pointer-utils.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 android {
+namespace hardware {
+namespace broadcastradio {
+namespace V1_2 {
+namespace vts {
+
+using namespace std::chrono_literals;
+
+using testing::_;
+using testing::AnyNumber;
+using testing::ByMove;
+using testing::DoAll;
+using testing::Invoke;
+using testing::SaveArg;
+
+using broadcastradio::vts::CallBarrier;
+using V1_0::BandConfig;
+using V1_0::Class;
+using V1_0::MetaData;
+using V1_0::MetadataKey;
+using V1_0::MetadataType;
+using V1_1::IBroadcastRadio;
+using V1_1::ProgramInfo;
+using V1_1::ProgramListResult;
+using V1_1::ProgramSelector;
+using V1_1::Properties;
+
+using broadcastradio::vts::clearAndWait;
+
+static constexpr auto kConfigTimeout = 10s;
+static constexpr auto kConnectModuleTimeout = 1s;
+
+static void printSkipped(std::string msg) {
+    std::cout << "[  SKIPPED ] " << msg << std::endl;
+}
+
+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&));
+    MOCK_METHOD1(parametersUpdated, Return<void>(const hidl_vec<VendorKeyValue>& parameters));
+};
+
+class BroadcastRadioHalTest : public ::testing::VtsHalHidlTargetTestBase,
+                              public ::testing::WithParamInterface<Class> {
+   protected:
+    virtual void SetUp() override;
+    virtual void TearDown() override;
+
+    bool openTuner();
+
+    Class radioClass;
+    bool skipped = false;
+
+    sp<IBroadcastRadio> mRadioModule;
+    sp<ITuner> mTuner;
+    sp<TunerCallbackMock> mCallback = new TunerCallbackMock();
+
+   private:
+    const BandConfig& getBand(unsigned idx);
+
+    hidl_vec<BandConfig> mBands;
+};
+
+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);
+    };
+    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;
+        mTuner->getConfiguration([&](Result result, const BandConfig& config) {
+            halResult = result;
+            halConfig = config;
+        });
+        EXPECT_EQ(Result::OK, halResult);
+        EXPECT_TRUE(halConfig.antennaConnected);
+    }
+
+    EXPECT_NE(nullptr, mTuner.get());
+    return nullptr != mTuner.get();
+}
+
+const BandConfig& BroadcastRadioHalTest::getBand(unsigned idx) {
+    static const BandConfig dummyBandConfig = {};
+
+    if (radioClass != Class::AM_FM) {
+        ALOGD("Not AM/FM radio, returning dummy band config");
+        return dummyBandConfig;
+    }
+
+    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;
+}
+
+/**
+ * Test IBroadcastRadio::get|setParameters() methods called with no parameters.
+ *
+ * Verifies that:
+ *  - callback is called for empty parameters set.
+ */
+TEST_P(BroadcastRadioHalTest, NoParameters) {
+    if (skipped) return;
+
+    ASSERT_TRUE(openTuner());
+
+    hidl_vec<VendorKeyValue> halResults = {};
+    bool wasCalled = false;
+    auto cb = [&](hidl_vec<VendorKeyValue> results) {
+        wasCalled = true;
+        halResults = results;
+    };
+
+    auto hidlResult = mTuner->setParameters({}, cb);
+    ASSERT_TRUE(hidlResult.isOk());
+    ASSERT_TRUE(wasCalled);
+    ASSERT_EQ(0u, halResults.size());
+
+    wasCalled = false;
+    hidlResult = mTuner->getParameters({}, cb);
+    ASSERT_TRUE(hidlResult.isOk());
+    ASSERT_TRUE(wasCalled);
+    ASSERT_EQ(0u, halResults.size());
+}
+
+/**
+ * Test IBroadcastRadio::get|setParameters() methods called with unknown parameters.
+ *
+ * Verifies that:
+ *  - unknown parameters are ignored;
+ *  - callback is called also for empty results set.
+ */
+TEST_P(BroadcastRadioHalTest, UnknownParameters) {
+    if (skipped) return;
+
+    ASSERT_TRUE(openTuner());
+
+    hidl_vec<VendorKeyValue> halResults = {};
+    bool wasCalled = false;
+    auto cb = [&](hidl_vec<VendorKeyValue> results) {
+        wasCalled = true;
+        halResults = results;
+    };
+
+    auto hidlResult = mTuner->setParameters({{"com.google.unknown", "dummy"}}, cb);
+    ASSERT_TRUE(hidlResult.isOk());
+    ASSERT_TRUE(wasCalled);
+    ASSERT_EQ(0u, halResults.size());
+
+    wasCalled = false;
+    hidlResult = mTuner->getParameters({{"com.google.unknown*", "dummy"}}, cb);
+    ASSERT_TRUE(hidlResult.isOk());
+    ASSERT_TRUE(wasCalled);
+    ASSERT_EQ(0u, halResults.size());
+}
+
+// TODO(b/69860743): implement VerifyIdentifiersFormat test when
+// the new program list fetching mechanism is implemented
+
+INSTANTIATE_TEST_CASE_P(BroadcastRadioHalTestCases, BroadcastRadioHalTest,
+                        ::testing::Values(Class::AM_FM, Class::SAT, Class::DT));
+
+}  // namespace vts
+}  // namespace V1_2
+}  // namespace broadcastradio
+}  // namespace hardware
+}  // namespace android
+
+int main(int argc, char** argv) {
+  ::testing::InitGoogleTest(&argc, argv);
+  int status = RUN_ALL_TESTS();
+  ALOGI("Test result = %d", status);
+  return status;
+}
diff --git a/broadcastradio/2.0/Android.bp b/broadcastradio/2.0/Android.bp
new file mode 100644
index 0000000..afbd6d4
--- /dev/null
+++ b/broadcastradio/2.0/Android.bp
@@ -0,0 +1,34 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.broadcastradio@2.0",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "types.hal",
+        "IBroadcastRadio.hal",
+        "ITunerCallback.hal",
+        "ITunerSession.hal",
+    ],
+    interfaces: [
+        "android.hidl.base@1.0",
+    ],
+    types: [
+        "ConfigFlag",
+        "Constants",
+        "IdentifierType",
+        "Metadata",
+        "MetadataKey",
+        "ProgramIdentifier",
+        "ProgramInfo",
+        "ProgramInfoFlags",
+        "ProgramSelector",
+        "Properties",
+        "Result",
+        "VendorKeyValue",
+    ],
+    gen_java: true,
+}
+
diff --git a/broadcastradio/2.0/IBroadcastRadio.hal b/broadcastradio/2.0/IBroadcastRadio.hal
new file mode 100644
index 0000000..3ab1cc2
--- /dev/null
+++ b/broadcastradio/2.0/IBroadcastRadio.hal
@@ -0,0 +1,81 @@
+/* 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.broadcastradio@2.0;
+
+import ITunerCallback;
+import ITunerSession;
+
+/**
+ * Represents a hardware broadcast radio module. A single module may contain
+ * multiple hardware tuners (i.e. with an additional background tuner), but the
+ * layers above the HAL see them as a single logical unit.
+ */
+interface IBroadcastRadio {
+    /**
+     * Returns module properties: a description of a module and its
+     * capabilities. This method must not fail.
+     *
+     * @return properties Module description.
+     */
+    getProperties() generates (Properties properties);
+
+    /**
+     * Opens a new tuner session.
+     *
+     * There may be only one session active at a time. If the new session was
+     * requested when the old one was active, the old must be terminated
+     * (aggressive open).
+     *
+     * @param callback The callback interface.
+     * @return result OK in case of success.
+     * @return session The session interface.
+     */
+    openSession(ITunerCallback callback)
+            generates (Result result, ITunerSession session);
+
+    /**
+     * Fetch image from radio module cache.
+     *
+     * This is out-of-band transport mechanism for images carried with metadata.
+     * The metadata vector only passes the identifier, so the client may cache
+     * images or even not fetch them.
+     *
+     * The identifier may be any arbitrary number (i.e. sha256 prefix) selected
+     * by the vendor. It must be stable across sessions so the application may
+     * cache it.
+     *
+     * The data must 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 onCurrentProgramInfoChanged is called.
+     *
+     * There is still a race condition possible between
+     * onCurrentProgramInfoChanged callback and the HAL implementation eagerly
+     * clearing the cache (because the next onCurrentProgramInfoChanged came).
+     * In such case, client application may expect the new
+     * onCurrentProgramInfoChanged callback with updated image identifier.
+     *
+     * @param id Identifier of an image (value of Constants::INVALID_IMAGE is
+     *           reserved and must be treated as invalid image).
+     * @return image A binary blob with image data
+     *               or a zero-length vector if identifier doesn't exist.
+     */
+    getImage(uint32_t id) generates (vec<uint8_t> image);
+};
diff --git a/broadcastradio/2.0/ITunerCallback.hal b/broadcastradio/2.0/ITunerCallback.hal
new file mode 100644
index 0000000..1aefc4e
--- /dev/null
+++ b/broadcastradio/2.0/ITunerCallback.hal
@@ -0,0 +1,67 @@
+/* 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.broadcastradio@2.0;
+
+interface ITunerCallback {
+    /**
+     * Method called by the HAL when a tuning operation fails
+     * following a step(), scan() or tune() command.
+     *
+     * @param result OK if tune succeeded;
+     *               TIMEOUT in case of time out.
+     * @param selector A ProgramSelector structure passed from tune(),
+     *                 empty for step() and scan().
+     */
+    oneway onTuneFailed(Result result, ProgramSelector selector);
+
+    /**
+     * Method called by the HAL when current program information (including
+     * metadata) is updated.
+     *
+     * This is also called when the radio tuned to the static (not a valid
+     * station), see the TUNED flag of ProgramInfoFlags.
+     *
+     * @param info Current program information.
+     */
+    oneway onCurrentProgramInfoChanged(ProgramInfo info);
+
+    /**
+     * Method called by the HAL when the antenna gets connected or disconnected.
+     *
+     * For a new tuner session, client must assume the antenna is connected.
+     * If it's not, then antennaStateChange must be called within
+     * Constants::ANTENNA_DISCONNECTED_TIMEOUT_MS to indicate that.
+     *
+     * @param connected True if the antenna is now connected, false otherwise.
+     */
+    oneway onAntennaStateChange(bool connected);
+
+    /**
+     * Generic callback for passing updates to vendor-specific parameter values.
+     * The framework does not interpret the parameters, they are passed
+     * in an opaque manner between a vendor application and HAL.
+     *
+     * It's up to the HAL implementation if and how to implement this callback,
+     * as long as it obeys the prefix rule. In particular, only selected keys
+     * may be notified this way. However, setParameters must not trigger
+     * this callback, while an internal event can change parameters
+     * asynchronously.
+     *
+     * @param parameters Vendor-specific key-value pairs,
+     *                   opaque to Android framework.
+     */
+    oneway onParametersUpdated(vec<VendorKeyValue> parameters);
+};
diff --git a/broadcastradio/2.0/ITunerSession.hal b/broadcastradio/2.0/ITunerSession.hal
new file mode 100644
index 0000000..8a21768
--- /dev/null
+++ b/broadcastradio/2.0/ITunerSession.hal
@@ -0,0 +1,163 @@
+/* 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.broadcastradio@2.0;
+
+interface ITunerSession {
+    /**
+     * Tune to a specified program.
+     *
+     * Automatically cancels pending scan, step or tune.
+     * If the method returns OK, tuneFailed or currentProgramInfoChanged
+     * callback must be called.
+     *
+     * @param program Program to tune to.
+     * @return result OK if successfully started tuning.
+     *                NOT_SUPPORTED if the program selector doesn't contain any
+     *                supported identifier.
+     *                INVALID_ARGUMENTS if the program selector contains
+     *                identifiers in invalid format (i.e. out of range).
+     */
+    tune(ProgramSelector program) generates (Result result);
+
+    /**
+     * Tune to the next valid program.
+     *
+     * Automatically cancels pending scan, step or tune.
+     * If the method returns OK, tuneFailed or currentProgramInfoChanged
+     * callback must be called.
+     *
+     * The skipSubChannel parameter is used to skip digital radio subchannels:
+     *  - HD Radio SPS;
+     *  - DAB secondary service.
+     *
+     * As an implementation detail, the HAL has the option to perform an actual
+     * scan or select the next program from the list retrieved in the
+     * background, if one is not stale.
+     *
+     * @param directionUp True to change towards higher numeric values
+     *                    (frequency, channel number), false towards lower.
+     * @param skipSubChannel Don't tune to subchannels.
+     * @return result OK if the scan has successfully started.
+     */
+    scan(bool directionUp, bool skipSubChannel) generates (Result result);
+
+    /**
+     * Tune to the adjacent channel, which may not be occupied by any program.
+     *
+     * Automatically cancels pending scan, step or tune.
+     * If the method returns OK, tuneFailed or currentProgramInfoChanged
+     * callback must be called.
+     *
+     * @param directionUp True to change towards higher numeric values
+     *                    (frequency, channel number), false towards lower.
+     * @return result OK successfully started tuning.
+     *                NOT_SUPPORTED if tuning to an unoccupied channel is not
+     *                supported (i.e. for satellite radio).
+     */
+    step(bool directionUp) generates (Result result);
+
+    /**
+     * Cancel a scan, step or tune operation.
+     *
+     * If there is no such operation running, the call must be ignored.
+     */
+    cancel();
+
+    /**
+     * Fetches the current setting of a given config flag.
+     *
+     * The success/failure result must be consistent with setConfigFlag.
+     *
+     * @param flag Flag to fetch.
+     * @return result OK successfully fetched the flag.
+     *                INVALID_STATE if the flag is not applicable right now.
+     *                NOT_SUPPORTED if the flag is not supported at all.
+     * @return value The current value of the flag, if result is OK.
+     */
+    getConfigFlag(ConfigFlag flag) generates (Result result, bool value);
+
+    /**
+     * Sets the config flag.
+     *
+     * The success/failure result must be consistent with getConfigFlag.
+     *
+     * @param flag Flag to set.
+     * @param value The new value of a given flag.
+     * @return result OK successfully set the flag.
+     *                INVALID_STATE if the flag is not applicable right now.
+     *                NOT_SUPPORTED if the flag is not supported at all.
+     */
+    setConfigFlag(ConfigFlag flag, bool value) generates (Result result);
+
+    /**
+     * Generic method for setting vendor-specific parameter values.
+     * The framework does not interpret the parameters, they are passed
+     * in an opaque manner between a vendor application and HAL.
+     *
+     * Framework does not make any assumptions on the keys or values, other than
+     * ones stated in VendorKeyValue documentation (a requirement of key
+     * prefixes).
+     *
+     * For each pair in the result vector, the key must be one of the keys
+     * contained in the input (possibly with wildcards expanded), and the value
+     * must be a vendor-specific result status (i.e. the string "OK" or an error
+     * code). The implementation may choose to return an empty vector, or only
+     * return a status for a subset of the provided inputs, at its discretion.
+     *
+     * Application and HAL must not use keys with unknown prefix. In particular,
+     * it must not place a key-value pair in results vector for unknown key from
+     * parameters vector - instead, an unknown key should simply be ignored.
+     * In other words, results vector may contain a subset of parameter keys
+     * (however, the framework doesn't enforce a strict subset - the only
+     * formal requirement is vendor domain prefix for keys).
+     *
+     * @param parameters Vendor-specific key-value pairs.
+     * @return results Operation completion status for parameters being set.
+     */
+    setParameters(vec<VendorKeyValue> parameters)
+            generates (vec<VendorKeyValue> results);
+
+    /**
+     * Generic method for retrieving vendor-specific parameter values.
+     * The framework does not interpret the parameters, they are passed
+     * in an opaque manner between a vendor application and HAL.
+     *
+     * Framework does not cache set/get requests, so it's allowed for
+     * getParameter to return a different value than previous setParameter call.
+     *
+     * The syntax and semantics of keys are up to the vendor (as long as prefix
+     * rules are obeyed). For instance, vendors may include some form of
+     * wildcard support. In such case, result vector may be of different size
+     * than requested keys vector. However, wildcards are not recognized by
+     * framework and they are passed as-is to the HAL implementation.
+     *
+     * Unknown keys must be ignored and not placed into results vector.
+     *
+     * @param keys Parameter keys to fetch.
+     * @return parameters Vendor-specific key-value pairs.
+     */
+    getParameters(vec<string> keys) generates (vec<VendorKeyValue> parameters);
+
+    /**
+     * Closes the session.
+     *
+     * The call must not fail and must only be issued once.
+     *
+     * After the close call is executed, no other calls to this interface
+     * are allowed.
+     */
+    close();
+};
diff --git a/broadcastradio/1.1/default/Android.bp b/broadcastradio/2.0/default/Android.bp
similarity index 76%
copy from broadcastradio/1.1/default/Android.bp
copy to broadcastradio/2.0/default/Android.bp
index 6d26b11..6d4effb 100644
--- a/broadcastradio/1.1/default/Android.bp
+++ b/broadcastradio/2.0/default/Android.bp
@@ -15,8 +15,8 @@
 //
 
 cc_binary {
-    name: "android.hardware.broadcastradio@1.1-service",
-    init_rc: ["android.hardware.broadcastradio@1.1-service.rc"],
+    name: "android.hardware.broadcastradio@2.0-service",
+    init_rc: ["android.hardware.broadcastradio@2.0-service.rc"],
     vendor: true,
     relative_install_path: "hw",
     cflags: [
@@ -26,18 +26,17 @@
     ],
     srcs: [
         "BroadcastRadio.cpp",
-        "BroadcastRadioFactory.cpp",
-        "Tuner.cpp",
+        "TunerSession.cpp",
         "VirtualProgram.cpp",
         "VirtualRadio.cpp",
         "service.cpp"
     ],
     static_libs: [
-        "android.hardware.broadcastradio@1.1-utils-lib",
+        "android.hardware.broadcastradio@common-utils-2x-lib",
+        "android.hardware.broadcastradio@common-utils-lib",
     ],
     shared_libs: [
-        "android.hardware.broadcastradio@1.0",
-        "android.hardware.broadcastradio@1.1",
+        "android.hardware.broadcastradio@2.0",
         "libbase",
         "libhidlbase",
         "libhidltransport",
diff --git a/broadcastradio/2.0/default/BroadcastRadio.cpp b/broadcastradio/2.0/default/BroadcastRadio.cpp
new file mode 100644
index 0000000..5ab517d
--- /dev/null
+++ b/broadcastradio/2.0/default/BroadcastRadio.cpp
@@ -0,0 +1,98 @@
+/*
+ * 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 "BcRadioDef.module"
+#define LOG_NDEBUG 0
+
+#include "BroadcastRadio.h"
+
+#include <log/log.h>
+
+#include "resources.h"
+
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace V2_0 {
+namespace implementation {
+
+using std::lock_guard;
+using std::map;
+using std::mutex;
+using std::vector;
+
+static Properties initProperties(const VirtualRadio& virtualRadio) {
+    Properties prop = {};
+
+    prop.maker = "Google";
+    prop.product = virtualRadio.getName();
+    prop.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),
+    });
+    prop.vendorInfo = hidl_vec<VendorKeyValue>({
+        {"com.google.dummy", "dummy"},
+    });
+
+    return prop;
+}
+
+BroadcastRadio::BroadcastRadio(const VirtualRadio& virtualRadio)
+    : mVirtualRadio(virtualRadio), mProperties(initProperties(virtualRadio)) {}
+
+Return<void> BroadcastRadio::getProperties(getProperties_cb _hidl_cb) {
+    ALOGV("%s", __func__);
+    _hidl_cb(mProperties);
+    return {};
+}
+
+Return<void> BroadcastRadio::openSession(const sp<ITunerCallback>& callback,
+                                         openSession_cb _hidl_cb) {
+    ALOGV("%s", __func__);
+    lock_guard<mutex> lk(mMut);
+
+    auto oldSession = mSession.promote();
+    if (oldSession != nullptr) {
+        ALOGI("Closing previously opened tuner");
+        oldSession->close();
+        mSession = nullptr;
+    }
+
+    sp<TunerSession> newSession = new TunerSession(*this, callback);
+    mSession = newSession;
+
+    _hidl_cb(Result::OK, newSession);
+    return {};
+}
+
+Return<void> BroadcastRadio::getImage(uint32_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 {};
+}
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace broadcastradio
+}  // namespace hardware
+}  // namespace android
diff --git a/broadcastradio/2.0/default/BroadcastRadio.h b/broadcastradio/2.0/default/BroadcastRadio.h
new file mode 100644
index 0000000..fcf0615
--- /dev/null
+++ b/broadcastradio/2.0/default/BroadcastRadio.h
@@ -0,0 +1,52 @@
+/*
+ * 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_V2_0_BROADCASTRADIO_H
+#define ANDROID_HARDWARE_BROADCASTRADIO_V2_0_BROADCASTRADIO_H
+
+#include "TunerSession.h"
+
+#include <android/hardware/broadcastradio/2.0/IBroadcastRadio.h>
+#include <android/hardware/broadcastradio/2.0/types.h>
+
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace V2_0 {
+namespace implementation {
+
+struct BroadcastRadio : public IBroadcastRadio {
+    BroadcastRadio(const VirtualRadio& virtualRadio);
+
+    // V2_0::IBroadcastRadio methods
+    Return<void> getProperties(getProperties_cb _hidl_cb) override;
+    Return<void> openSession(const sp<ITunerCallback>& callback, openSession_cb _hidl_cb) override;
+    Return<void> getImage(uint32_t id, getImage_cb _hidl_cb);
+
+    std::reference_wrapper<const VirtualRadio> mVirtualRadio;
+    Properties mProperties;
+
+   private:
+    std::mutex mMut;
+    wp<TunerSession> mSession;
+};
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace broadcastradio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_BROADCASTRADIO_V2_0_BROADCASTRADIO_H
diff --git a/broadcastradio/1.1/default/OWNERS b/broadcastradio/2.0/default/OWNERS
similarity index 74%
copy from broadcastradio/1.1/default/OWNERS
copy to broadcastradio/2.0/default/OWNERS
index 0c27b71..136b607 100644
--- a/broadcastradio/1.1/default/OWNERS
+++ b/broadcastradio/2.0/default/OWNERS
@@ -1,4 +1,3 @@
 # Automotive team
 egranata@google.com
-keunyoung@google.com
 twasilczyk@google.com
diff --git a/broadcastradio/2.0/default/TunerSession.cpp b/broadcastradio/2.0/default/TunerSession.cpp
new file mode 100644
index 0000000..54af3389
--- /dev/null
+++ b/broadcastradio/2.0/default/TunerSession.cpp
@@ -0,0 +1,251 @@
+/*
+ * 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 "BcRadioDef.tuner"
+#define LOG_NDEBUG 0
+
+#include "TunerSession.h"
+
+#include "BroadcastRadio.h"
+
+#include <broadcastradio-utils-2x/Utils.h>
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace V2_0 {
+namespace implementation {
+
+using namespace std::chrono_literals;
+
+using utils::tunesTo;
+
+using std::lock_guard;
+using std::move;
+using std::mutex;
+using std::sort;
+using std::vector;
+
+namespace delay {
+
+static constexpr auto scan = 200ms;
+static constexpr auto step = 100ms;
+static constexpr auto tune = 150ms;
+
+}  // namespace delay
+
+TunerSession::TunerSession(BroadcastRadio& module, const sp<ITunerCallback>& callback)
+    : mCallback(callback), mModule(module) {}
+
+// makes ProgramInfo that points to no program
+static ProgramInfo makeDummyProgramInfo(const ProgramSelector& selector) {
+    ProgramInfo info = {};
+    info.selector = selector;
+    return info;
+}
+
+void TunerSession::tuneInternalLocked(const ProgramSelector& sel) {
+    VirtualProgram virtualProgram;
+    ProgramInfo programInfo;
+    if (virtualRadio().getProgram(sel, virtualProgram)) {
+        mCurrentProgram = virtualProgram.selector;
+        programInfo = virtualProgram;
+    } else {
+        mCurrentProgram = sel;
+        programInfo = makeDummyProgramInfo(sel);
+    }
+    mIsTuneCompleted = true;
+
+    mCallback->onCurrentProgramInfoChanged(programInfo);
+}
+
+const VirtualRadio& TunerSession::virtualRadio() const {
+    return mModule.get().mVirtualRadio;
+}
+
+Return<Result> TunerSession::tune(const ProgramSelector& sel) {
+    ALOGV("%s(%s)", __func__, toString(sel).c_str());
+    lock_guard<mutex> lk(mMut);
+    if (mIsClosed) return Result::INVALID_STATE;
+
+    if (!utils::isSupported(mModule.get().mProperties, sel)) {
+        ALOGW("Selector not supported");
+        return Result::NOT_SUPPORTED;
+    }
+
+    if (!utils::isValid(sel)) {
+        ALOGE("ProgramSelector is not valid");
+        return Result::INVALID_ARGUMENTS;
+    }
+
+    mIsTuneCompleted = false;
+    auto task = [this, sel]() {
+        lock_guard<mutex> lk(mMut);
+        tuneInternalLocked(sel);
+    };
+    mThread.schedule(task, delay::tune);
+
+    return Result::OK;
+}
+
+Return<Result> TunerSession::scan(bool directionUp, bool /* skipSubChannel */) {
+    ALOGV("%s", __func__);
+    lock_guard<mutex> lk(mMut);
+    if (mIsClosed) return Result::INVALID_STATE;
+
+    auto list = virtualRadio().getProgramList();
+
+    if (list.empty()) {
+        mIsTuneCompleted = false;
+        auto task = [this, directionUp]() {
+            ALOGI("Performing failed scan up=%d", directionUp);
+
+            mCallback->onTuneFailed(Result::TIMEOUT, {});
+        };
+        mThread.schedule(task, delay::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 (directionUp) {
+        if (found < list.end() - 1) {
+            if (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, directionUp]() {
+        ALOGI("Performing scan up=%d", directionUp);
+
+        lock_guard<mutex> lk(mMut);
+        tuneInternalLocked(tuneTo);
+    };
+    mThread.schedule(task, delay::scan);
+
+    return Result::OK;
+}
+
+Return<Result> TunerSession::step(bool directionUp) {
+    ALOGV("%s", __func__);
+    lock_guard<mutex> lk(mMut);
+    if (mIsClosed) return Result::INVALID_STATE;
+
+    if (!utils::hasId(mCurrentProgram, IdentifierType::AMFM_FREQUENCY)) {
+        ALOGE("Can't step in anything else than AM/FM");
+        return Result::NOT_SUPPORTED;
+    }
+
+    mIsTuneCompleted = false;
+
+    auto stepTo = utils::getId(mCurrentProgram, IdentifierType::AMFM_FREQUENCY);
+#if 0
+    // TODO(b/69958423): handle regions
+    if (directionUp) {
+        stepTo += mAmfmConfig.spacings[0];
+    } else {
+        stepTo -= mAmfmConfig.spacings[0];
+    }
+
+    if (stepTo > mAmfmConfig.upperLimit) stepTo = mAmfmConfig.lowerLimit;
+    if (stepTo < mAmfmConfig.lowerLimit) stepTo = mAmfmConfig.upperLimit;
+#else
+    if (directionUp) {
+        stepTo += 100;
+    } else {
+        stepTo -= 100;
+    }
+#endif
+
+    auto task = [this, stepTo]() {
+        ALOGI("Performing step to %s", std::to_string(stepTo).c_str());
+
+        lock_guard<mutex> lk(mMut);
+
+        tuneInternalLocked(utils::make_selector_amfm(stepTo));
+    };
+    mThread.schedule(task, delay::step);
+
+    return Result::OK;
+}
+
+Return<void> TunerSession::cancel() {
+    ALOGV("%s", __func__);
+    lock_guard<mutex> lk(mMut);
+    if (mIsClosed) return {};
+
+    mThread.cancelAll();
+    return {};
+}
+
+Return<void> TunerSession::getConfigFlag(ConfigFlag flag, getConfigFlag_cb _hidl_cb) {
+    ALOGV("%s(%s)", __func__, toString(flag).c_str());
+
+    _hidl_cb(Result::NOT_SUPPORTED, false);
+    return {};
+}
+
+Return<Result> TunerSession::setConfigFlag(ConfigFlag flag, bool value) {
+    ALOGV("%s(%s, %d)", __func__, toString(flag).c_str(), value);
+
+    return Result::NOT_SUPPORTED;
+}
+
+Return<void> TunerSession::setParameters(const hidl_vec<VendorKeyValue>& /* parameters */,
+                                         setParameters_cb _hidl_cb) {
+    ALOGV("%s", __func__);
+
+    _hidl_cb({});
+    return {};
+}
+
+Return<void> TunerSession::getParameters(const hidl_vec<hidl_string>& /* keys */,
+                                         getParameters_cb _hidl_cb) {
+    ALOGV("%s", __func__);
+
+    _hidl_cb({});
+    return {};
+}
+
+Return<void> TunerSession::close() {
+    ALOGV("%s", __func__);
+    lock_guard<mutex> lk(mMut);
+    if (mIsClosed) return {};
+
+    mIsClosed = true;
+    mThread.cancelAll();
+    return {};
+}
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace broadcastradio
+}  // namespace hardware
+}  // namespace android
diff --git a/broadcastradio/2.0/default/TunerSession.h b/broadcastradio/2.0/default/TunerSession.h
new file mode 100644
index 0000000..9a72182
--- /dev/null
+++ b/broadcastradio/2.0/default/TunerSession.h
@@ -0,0 +1,70 @@
+/*
+ * 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_V2_0_TUNER_H
+#define ANDROID_HARDWARE_BROADCASTRADIO_V2_0_TUNER_H
+
+#include "VirtualRadio.h"
+
+#include <android/hardware/broadcastradio/2.0/ITunerCallback.h>
+#include <android/hardware/broadcastradio/2.0/ITunerSession.h>
+#include <broadcastradio-utils/WorkerThread.h>
+
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace V2_0 {
+namespace implementation {
+
+struct BroadcastRadio;
+
+struct TunerSession : public ITunerSession {
+    TunerSession(BroadcastRadio& module, const sp<ITunerCallback>& callback);
+
+    // V2_0::ITunerSession methods
+    virtual Return<Result> tune(const ProgramSelector& program) override;
+    virtual Return<Result> scan(bool directionUp, bool skipSubChannel) override;
+    virtual Return<Result> step(bool directionUp) override;
+    virtual Return<void> cancel() override;
+    virtual Return<void> getConfigFlag(ConfigFlag flag, getConfigFlag_cb _hidl_cb);
+    virtual Return<Result> setConfigFlag(ConfigFlag flag, bool value);
+    virtual Return<void> setParameters(const hidl_vec<VendorKeyValue>& parameters,
+                                       setParameters_cb _hidl_cb) override;
+    virtual Return<void> getParameters(const hidl_vec<hidl_string>& keys,
+                                       getParameters_cb _hidl_cb) override;
+    virtual Return<void> close() override;
+
+   private:
+    std::mutex mMut;
+    WorkerThread mThread;
+    bool mIsClosed = false;
+
+    const sp<ITunerCallback> mCallback;
+
+    std::reference_wrapper<BroadcastRadio> mModule;
+    bool mIsTuneCompleted = false;
+    ProgramSelector mCurrentProgram = {};
+
+    void tuneInternalLocked(const ProgramSelector& sel);
+    const VirtualRadio& virtualRadio() const;
+};
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace broadcastradio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_BROADCASTRADIO_V2_0_TUNER_H
diff --git a/broadcastradio/2.0/default/VirtualProgram.cpp b/broadcastradio/2.0/default/VirtualProgram.cpp
new file mode 100644
index 0000000..1acd4d3
--- /dev/null
+++ b/broadcastradio/2.0/default/VirtualProgram.cpp
@@ -0,0 +1,76 @@
+/*
+ * 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 "resources.h"
+
+#include <broadcastradio-utils-2x/Utils.h>
+
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace V2_0 {
+namespace implementation {
+
+using utils::getType;
+using utils::make_metadata;
+
+using std::vector;
+
+VirtualProgram::operator ProgramInfo() const {
+    ProgramInfo info = {};
+
+    info.selector = selector;
+
+    auto pType = getType(selector.primaryId);
+    auto isDigital = (pType != IdentifierType::AMFM_FREQUENCY && pType != IdentifierType::RDS_PI);
+
+    info.infoFlags |= ProgramInfoFlags::TUNED;
+    info.infoFlags |= ProgramInfoFlags::STEREO;
+    info.signalQuality = isDigital ? 100 : 80;
+
+    info.metadata = hidl_vec<Metadata>({
+        make_metadata(MetadataKey::RDS_PS, programName),
+        make_metadata(MetadataKey::SONG_TITLE, songTitle),
+        make_metadata(MetadataKey::SONG_ARTIST, songArtist),
+        make_metadata(MetadataKey::STATION_ICON, resources::demoPngId),
+        make_metadata(MetadataKey::ALBUM_ART, resources::demoPngId),
+    });
+
+    info.vendorInfo = hidl_vec<VendorKeyValue>({
+        {"com.google.dummy", "dummy"},
+        {"com.google.dummy.VirtualProgram", std::to_string(reinterpret_cast<uintptr_t>(this))},
+    });
+
+    return info;
+}
+
+bool operator<(const VirtualProgram& lhs, const VirtualProgram& rhs) {
+    auto& l = lhs.selector;
+    auto& r = rhs.selector;
+
+    // Two programs with the same primaryId are considered the same.
+    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;
+
+    return false;
+}
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace broadcastradio
+}  // namespace hardware
+}  // namespace android
diff --git a/broadcastradio/1.1/default/VirtualProgram.h b/broadcastradio/2.0/default/VirtualProgram.h
similarity index 69%
rename from broadcastradio/1.1/default/VirtualProgram.h
rename to broadcastradio/2.0/default/VirtualProgram.h
index a14830d..e1c4f75 100644
--- a/broadcastradio/1.1/default/VirtualProgram.h
+++ b/broadcastradio/2.0/default/VirtualProgram.h
@@ -13,16 +13,15 @@
  * 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
+#ifndef ANDROID_HARDWARE_BROADCASTRADIO_V2_0_VIRTUALPROGRAM_H
+#define ANDROID_HARDWARE_BROADCASTRADIO_V2_0_VIRTUALPROGRAM_H
 
-#include <android/hardware/broadcastradio/1.1/types.h>
-#include <broadcastradio-utils/Utils.h>
+#include <android/hardware/broadcastradio/2.0/types.h>
 
 namespace android {
 namespace hardware {
 namespace broadcastradio {
-namespace V1_1 {
+namespace V2_0 {
 namespace implementation {
 
 /**
@@ -38,18 +37,21 @@
     std::string songArtist = "";
     std::string songTitle = "";
 
-    ProgramInfo getProgramInfo(utils::HalRevision halRev) const;
+    operator ProgramInfo() const;
 
+    /**
+     * Defines order on how virtual programs appear on the "air" with
+     * ITunerSession::scan operation.
+     *
+     * It's for default implementation purposes, may not be complete or correct.
+     */
     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 V2_0
 }  // namespace broadcastradio
 }  // namespace hardware
 }  // namespace android
 
-#endif  // ANDROID_HARDWARE_BROADCASTRADIO_V1_1_VIRTUALPROGRAM_H
+#endif  // ANDROID_HARDWARE_BROADCASTRADIO_V2_0_VIRTUALPROGRAM_H
diff --git a/broadcastradio/2.0/default/VirtualRadio.cpp b/broadcastradio/2.0/default/VirtualRadio.cpp
new file mode 100644
index 0000000..f601d41
--- /dev/null
+++ b/broadcastradio/2.0/default/VirtualRadio.cpp
@@ -0,0 +1,75 @@
+/*
+ * 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 "BcRadioDef.VirtualRadio"
+//#define LOG_NDEBUG 0
+
+#include "VirtualRadio.h"
+
+#include <broadcastradio-utils-2x/Utils.h>
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace V2_0 {
+namespace implementation {
+
+using std::lock_guard;
+using std::move;
+using std::mutex;
+using std::vector;
+using utils::make_selector_amfm;
+
+VirtualRadio gAmFmRadio(
+    "AM/FM radio mock",
+    {
+        {make_selector_amfm(94900), "Wild 94.9", "Drake ft. Rihanna", "Too Good"},
+        {make_selector_amfm(96500), "KOIT", "Celine Dion", "All By Myself"},
+        {make_selector_amfm(97300), "Alice@97.3", "Drops of Jupiter", "Train"},
+        {make_selector_amfm(99700), "99.7 Now!", "The Chainsmokers", "Closer"},
+        {make_selector_amfm(101300), "101-3 KISS-FM", "Justin Timberlake", "Rock Your Body"},
+        {make_selector_amfm(103700), "iHeart80s @ 103.7", "Michael Jackson", "Billie Jean"},
+        {make_selector_amfm(106100), "106 KMEL", "Drake", "Marvins Room"},
+    });
+
+VirtualRadio::VirtualRadio(const std::string& name, const vector<VirtualProgram>& initialList)
+    : mName(name), mPrograms(initialList) {}
+
+std::string VirtualRadio::getName() const {
+    return mName;
+}
+
+vector<VirtualProgram> VirtualRadio::getProgramList() const {
+    lock_guard<mutex> lk(mMut);
+    return mPrograms;
+}
+
+bool VirtualRadio::getProgram(const ProgramSelector& selector, VirtualProgram& programOut) const {
+    lock_guard<mutex> lk(mMut);
+    for (auto&& program : mPrograms) {
+        if (utils::tunesTo(selector, program.selector)) {
+            programOut = program;
+            return true;
+        }
+    }
+    return false;
+}
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace broadcastradio
+}  // namespace hardware
+}  // namespace android
diff --git a/broadcastradio/2.0/default/VirtualRadio.h b/broadcastradio/2.0/default/VirtualRadio.h
new file mode 100644
index 0000000..9c07816
--- /dev/null
+++ b/broadcastradio/2.0/default/VirtualRadio.h
@@ -0,0 +1,61 @@
+/*
+ * 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_V2_0_VIRTUALRADIO_H
+#define ANDROID_HARDWARE_BROADCASTRADIO_V2_0_VIRTUALRADIO_H
+
+#include "VirtualProgram.h"
+
+#include <mutex>
+#include <vector>
+
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace V2_0 {
+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::string& name, const std::vector<VirtualProgram>& initialList);
+
+    std::string getName() const;
+    std::vector<VirtualProgram> getProgramList() const;
+    bool getProgram(const ProgramSelector& selector, VirtualProgram& program) const;
+
+   private:
+    mutable std::mutex mMut;
+    std::string mName;
+    std::vector<VirtualProgram> mPrograms;
+};
+
+/** AM/FM virtual radio space. */
+extern VirtualRadio gAmFmRadio;
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace broadcastradio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_BROADCASTRADIO_V2_0_VIRTUALRADIO_H
diff --git a/broadcastradio/2.0/default/android.hardware.broadcastradio@2.0-service.rc b/broadcastradio/2.0/default/android.hardware.broadcastradio@2.0-service.rc
new file mode 100644
index 0000000..7d68b6c
--- /dev/null
+++ b/broadcastradio/2.0/default/android.hardware.broadcastradio@2.0-service.rc
@@ -0,0 +1,4 @@
+service broadcastradio-hal2 /vendor/bin/hw/android.hardware.broadcastradio@2.0-service
+    class hal
+    user audioserver
+    group audio
diff --git a/broadcastradio/1.1/default/resources.h b/broadcastradio/2.0/default/resources.h
similarity index 89%
rename from broadcastradio/1.1/default/resources.h
rename to broadcastradio/2.0/default/resources.h
index b7e709f..97360dd 100644
--- a/broadcastradio/1.1/default/resources.h
+++ b/broadcastradio/2.0/default/resources.h
@@ -13,13 +13,13 @@
  * 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
+#ifndef ANDROID_HARDWARE_BROADCASTRADIO_V2_0_RESOURCES_H
+#define ANDROID_HARDWARE_BROADCASTRADIO_V2_0_RESOURCES_H
 
 namespace android {
 namespace hardware {
 namespace broadcastradio {
-namespace V1_1 {
+namespace V2_0 {
 namespace implementation {
 namespace resources {
 
@@ -38,9 +38,9 @@
 
 }  // namespace resources
 }  // namespace implementation
-}  // namespace V1_1
+}  // namespace V2_0
 }  // namespace broadcastradio
 }  // namespace hardware
 }  // namespace android
 
-#endif  // ANDROID_HARDWARE_BROADCASTRADIO_V1_1_RESOURCES_H
+#endif  // ANDROID_HARDWARE_BROADCASTRADIO_V2_0_RESOURCES_H
diff --git a/broadcastradio/1.1/default/service.cpp b/broadcastradio/2.0/default/service.cpp
similarity index 75%
copy from broadcastradio/1.1/default/service.cpp
copy to broadcastradio/2.0/default/service.cpp
index f8af0b7..7e677a1 100644
--- a/broadcastradio/1.1/default/service.cpp
+++ b/broadcastradio/2.0/default/service.cpp
@@ -13,22 +13,24 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#define LOG_TAG "BroadcastRadioDefault.service"
+#define LOG_TAG "BcRadioDef.service"
 
 #include <android-base/logging.h>
 #include <hidl/HidlTransportSupport.h>
 
-#include "BroadcastRadioFactory.h"
+#include "BroadcastRadio.h"
+#include "VirtualRadio.h"
 
 using android::hardware::configureRpcThreadpool;
 using android::hardware::joinRpcThreadpool;
-using android::hardware::broadcastradio::V1_1::implementation::BroadcastRadioFactory;
+using android::hardware::broadcastradio::V2_0::implementation::BroadcastRadio;
+using android::hardware::broadcastradio::V2_0::implementation::gAmFmRadio;
 
 int main(int /* argc */, char** /* argv */) {
     configureRpcThreadpool(4, true);
 
-    BroadcastRadioFactory broadcastRadioFactory;
-    auto status = broadcastRadioFactory.registerAsService();
+    BroadcastRadio broadcastRadio(gAmFmRadio);
+    auto status = broadcastRadio.registerAsService();
     CHECK_EQ(status, android::OK) << "Failed to register Broadcast Radio HAL implementation";
 
     joinRpcThreadpool();
diff --git a/broadcastradio/2.0/types.hal b/broadcastradio/2.0/types.hal
new file mode 100644
index 0000000..fc5809f
--- /dev/null
+++ b/broadcastradio/2.0/types.hal
@@ -0,0 +1,478 @@
+/* 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.broadcastradio@2.0;
+
+/** Constants used by broadcast radio HAL. */
+enum Constants : int32_t {
+    /** Invalid identifier for IBroadcastRadio::getImage. */
+    INVALID_IMAGE = 0,
+
+    /**
+     * If the antenna is disconnected from the beginning, the
+     * onAntennaStateChange callback must be called within this time.
+     */
+    ANTENNA_DISCONNECTED_TIMEOUT_MS = 100,
+};
+
+enum Result : int32_t {
+    OK,
+    UNKNOWN_ERROR,
+    INVALID_ARGUMENTS,
+    INVALID_STATE,
+    NOT_SUPPORTED,
+    TIMEOUT,
+};
+
+/**
+ * Configuration flags to be used with getConfigFlag and setConfigFlag methods
+ * of ITunerSession.
+ */
+enum ConfigFlag : uint32_t {
+    /**
+     * Forces mono audio stream reception.
+     *
+     * Analog broadcasts can recover poor reception conditions by jointing
+     * stereo channels into one. Mainly for, but not limited to AM/FM.
+     */
+    FORCE_MONO = 1,
+
+    /**
+     * Forces the analog playback for the supporting radio technology.
+     *
+     * User may disable digital playback for FM HD Radio or hybrid FM/DAB with
+     * this option. This is purely user choice, ie. does not reflect digital-
+     * analog handover state managed from the HAL implementation side.
+     *
+     * Some radio technologies may not support this, ie. DAB.
+     */
+    FORCE_ANALOG,
+
+    /**
+     * Forces the digital playback for the supporting radio technology.
+     *
+     * User may disable digital-analog handover that happens with poor
+     * receiption conditions. With digital forced, the radio will remain silent
+     * instead of switching to analog channel if it's available. This is purely
+     * user choice, it does not reflect the actual state of handover.
+     */
+    FORCE_DIGITAL,
+
+    /**
+     * RDS Alternative Frequencies.
+     *
+     * If set, radio tuner automatically switches to the best available
+     * frequency that currently listened RDS station broadcasts.
+     */
+    RDS_AF,
+
+    /**
+     * RDS region-specific program lock-down.
+     *
+     * Allows user to lock to the current region as they move into the
+     * other region.
+     */
+    RDS_REG,
+
+    /**
+     * Enables DAB implicit linking, based on program identifiers
+     * (DAB SId, RDS PI).
+     */
+    DAB_IMPLICIT_LINKING,
+
+    /**
+     * Enables DAB hard linking (the same content).
+     */
+    DAB_HARD_LINKING,
+
+    /**
+     * Enables DAB hard linking (related content).
+     */
+    DAB_SOFT_LINKING,
+};
+
+/**
+ * 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 start 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;
+};
+
+/**
+ * Properties of a given broadcast radio module.
+ */
+struct Properties {
+    /**
+     * A company name who made the radio module. Must be a valid, registered
+     * name of the company itself.
+     *
+     * It must be opaque to the Android framework.
+     */
+    string maker;
+
+    /**
+     * A product name. Must be unique within the company.
+     *
+     * It must be opaque to the Android framework.
+     */
+    string product;
+
+    /**
+     * Version of the hardware module.
+     *
+     * It must be opaque to the Android framework.
+     */
+    string version;
+
+    /**
+     * Hardware serial number (for subscription services).
+     *
+     * It must be opaque to the Android framework.
+     */
+    string serial;
+
+    /**
+     * 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;
+};
+
+/**
+ * Program (channel, station) information.
+ *
+ * Carries both user-visible information (like station name) and technical
+ * details (tuning selector).
+ */
+struct ProgramInfo {
+    /**
+     * An identifier used to point at the program (primarily to tune to it).
+     */
+    ProgramSelector selector;
+
+    bitfield<ProgramInfoFlags> infoFlags;
+
+    /**
+     * Signal quality measured in 0% to 100% range to be shown in the UI.
+     *
+     * The purpose of this field is primarily informative, must not be used to
+     * determine to which frequency should it tune to.
+     */
+    uint32_t signalQuality;
+
+    /**
+     * Program metadata (station name, PTY, song title).
+     */
+    vec<Metadata> metadata;
+
+    /**
+     * Vendor-specific information.
+     *
+     * It may be used for extra features, not supported by the platform,
+     * for example: paid-service=true; bitrate=320kbps.
+     */
+    vec<VendorKeyValue> vendorInfo;
+};
+
+enum ProgramInfoFlags : uint32_t {
+    /**
+     * Set when the program is currently playing live stream.
+     * This may result in a slightly altered reception parameters,
+     * usually targetted at reduced latency.
+     */
+    LIVE = 1 << 0,
+
+    /**
+     * Radio stream is not playing, ie. due to bad reception conditions or
+     * buffering. In this state volume knob MAY be disabled to prevent user
+     * 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,
+
+    /**
+     * Tuned to a program (not playing a static).
+     *
+     * It's the same condition that would stop scan() operation.
+     */
+    TUNED = 1 << 4,
+
+    /**
+     * Audio stream is MONO if this bit is not set.
+     */
+    STEREO = 1 << 5,
+};
+
+/**
+ * Type of program identifier component.
+ *
+ * Each identifier type corresponds to exactly one radio technology,
+ * i.e. DAB_ENSEMBLE is specifically for DAB.
+ *
+ * VENDOR identifier types must be opaque to the framework.
+ *
+ * The value format for each (but VENDOR_*) 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 {
+    /**
+     * Primary/secondary identifier for vendor-specific radio technology.
+     * The value format is determined by a vendor.
+     *
+     * The vendor identifiers have limited serialization capabilities - see
+     * ProgramSelector description.
+     */
+    VENDOR_START = 1000,
+
+    /** See VENDOR_START */
+    VENDOR_END = 1999,
+
+    /**
+     * Primary identifier for analogue (without RDS) AM/FM stations:
+     * frequency in kHz.
+     *
+     * This identifier also contains band information:
+     *  - <500kHz: AM LW;
+     *  - 500kHz - 1705kHz: AM MW;
+     *  - 1.71MHz - 30MHz: AM SW;
+     *  - >60MHz: FM.
+     */
+    AMFM_FREQUENCY = 1,
+
+    /**
+     * 16bit primary identifier for FM RDS station.
+     */
+    RDS_PI,
+
+    /**
+     * 64bit compound primary identifier for HD Radio.
+     *
+     * Consists of (from the LSB):
+     * - 32bit: Station ID number;
+     * - 4bit: HD Radio subchannel;
+     * - 18bit: AMFM_FREQUENCY. // TODO(b/69958777): is it necessary?
+     *
+     * HD Radio subchannel is a value in range 0-7.
+     * This index is 0-based (where 0 is MPS and 1..7 are SPS),
+     * as opposed to HD Radio standard (where it's 1-based).
+     *
+     * The remaining bits should be set to zeros when writing on the chip side
+     * and ignored when read.
+     */
+    HD_STATION_ID_EXT,
+
+    /**
+     * 28bit compound primary identifier for Digital Audio Broadcasting.
+     *
+     * Consists of (from the LSB):
+     * - 16bit: SId;
+     * - 8bit: ECC code;
+     * - 4bit: SCIdS.
+     *
+     * SCIdS (Service Component Identifier within the Service) value
+     * of 0 represents the main service, while 1 and above represents
+     * secondary services.
+     *
+     * The remaining bits should be set to zeros when writing on the chip side
+     * and ignored when read.
+     */
+    DAB_SID_EXT = HD_STATION_ID_EXT + 2,
+
+    /** 16bit */
+    DAB_ENSEMBLE,
+
+    /** 12bit */
+    DAB_SCID,
+
+    /** kHz (see AMFM_FREQUENCY) */
+    DAB_FREQUENCY,
+
+    /**
+     * 24bit primary identifier for Digital Radio Mondiale.
+     */
+    DRMO_SERVICE_ID,
+
+    /** kHz (see AMFM_FREQUENCY) */
+    DRMO_FREQUENCY,
+
+    /**
+     * 32bit primary identifier for SiriusXM Satellite Radio.
+     */
+    SXM_SERVICE_ID = DRMO_FREQUENCY + 2,
+
+    /** 0-999 range */
+    SXM_CHANNEL,
+};
+
+/**
+ * A single program identifier component, i.e. frequency or channel ID.
+ */
+struct ProgramIdentifier {
+    /**
+     * Maps to IdentifierType enum. 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.
+     */
+    uint32_t type;
+
+    /**
+     * The uint64_t value field holds the value in format described in comments
+     * for IdentifierType enum.
+     */
+    uint64_t value;
+};
+
+/**
+ * A set of identifiers necessary to tune to a given station.
+ *
+ * This can hold a combination of various identifiers, like:
+ * - AM/FM frequency,
+ * - HD Radio subchannel,
+ * - DAB service ID.
+ *
+ * The type of radio technology is determined by the primary identifier - if the
+ * primary identifier is for DAB, the program is DAB. However, a program of a
+ * specific radio technology may have additional secondary identifiers for other
+ * technologies, i.e. a satellite program may have FM fallback frequency,
+ * if a station broadcasts both via satellite and FM.
+ *
+ * The identifiers from VENDOR_START..VENDOR_END range have limited
+ * serialization capabilities: they are serialized locally, but ignored by the
+ * cloud services. If a program has primary id from vendor range, it's not
+ * synchronized with other devices at all.
+ */
+struct ProgramSelector {
+    /**
+     * Primary program identifier.
+     *
+     * This identifier uniquely identifies a station and can be used for
+     * equality check.
+     *
+     * It can hold only a subset of identifier types, one per each
+     * radio technology:
+     *  - analogue AM/FM: AMFM_FREQUENCY;
+     *  - FM RDS: RDS_PI;
+     *  - HD Radio: HD_STATION_ID_EXT;
+     *  - DAB: DAB_SID_EXT;
+     *  - Digital Radio Mondiale: DRMO_SERVICE_ID;
+     *  - SiriusXM: SXM_SERVICE_ID;
+     *  - vendor-specific: VENDOR_START..VENDOR_END.
+     *
+     * The list may change in future versions, so the implementation must obey,
+     * but not rely on it.
+     */
+    ProgramIdentifier primaryId;
+
+    /**
+     * Secondary program identifiers.
+     *
+     * These identifiers are supplementary and can speed up tuning process,
+     * but the primary ID must be sufficient (i.e. RDS PI is enough to select
+     * a station from the list 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).
+     */
+    vec<ProgramIdentifier> secondaryIds;
+};
+
+enum MetadataKey : int32_t {
+    /** RDS PS (string) */
+    RDS_PS = 1,
+
+    /** RDS PTY (uint8_t) */
+    RDS_PTY,
+
+    /** RBDS PTY (uint8_t) */
+    RBDS_PTY,
+
+    /** RDS RT (string) */
+    RDS_RT,
+
+    /** Song title (string) */
+    SONG_TITLE,
+
+    /** Artist name (string) */
+    SONG_ARTIST,
+
+    /** Album name (string) */
+    SONG_ALBUM,
+
+    /** Station icon (uint32_t, see IBroadcastRadio::getImage) */
+    STATION_ICON,
+
+    /** Album art (uint32_t, see IBroadcastRadio::getImage) */
+    ALBUM_ART,
+};
+
+/**
+ * An element of metadata vector.
+ *
+ * Contains one of the entries explained in MetadataKey.
+ *
+ * Depending on a type described in the comment for a specific key, either the
+ * intValue or stringValue field must be populated.
+ */
+struct Metadata {
+    /**
+     * Maps to MetadataKey enum. 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.
+     */
+    uint32_t key;
+
+    int64_t intValue;
+    string stringValue;
+};
diff --git a/broadcastradio/1.1/tests/OWNERS b/broadcastradio/2.0/vts/OWNERS
similarity index 65%
copy from broadcastradio/1.1/tests/OWNERS
copy to broadcastradio/2.0/vts/OWNERS
index aa5ce82..12adf57 100644
--- a/broadcastradio/1.1/tests/OWNERS
+++ b/broadcastradio/2.0/vts/OWNERS
@@ -1,8 +1,7 @@
 # Automotive team
 egranata@google.com
-keunyoung@google.com
 twasilczyk@google.com
 
 # VTS team
-ryanjcampbell@google.com
+yuexima@google.com
 yim@google.com
diff --git a/broadcastradio/1.1/utils/Android.bp b/broadcastradio/2.0/vts/functional/Android.bp
similarity index 60%
copy from broadcastradio/1.1/utils/Android.bp
copy to broadcastradio/2.0/vts/functional/Android.bp
index e80d133..6017b15 100644
--- a/broadcastradio/1.1/utils/Android.bp
+++ b/broadcastradio/2.0/vts/functional/Android.bp
@@ -14,21 +14,15 @@
 // 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",
+cc_test {
+    name: "VtsHalBroadcastradioV2_0TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: ["VtsHalBroadcastradioV2_0TargetTest.cpp"],
+    static_libs: [
+        "android.hardware.broadcastradio@2.0",
+        "android.hardware.broadcastradio@common-utils-2x-lib",
+        "android.hardware.broadcastradio@vts-utils-lib",
+        "android.hardware.broadcastradio@vts-utils-lib",
+        "libgmock",
     ],
 }
diff --git a/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp b/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp
new file mode 100644
index 0000000..d0e4144
--- /dev/null
+++ b/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp
@@ -0,0 +1,477 @@
+/*
+ * 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 "BcRadio.vts"
+
+#include <VtsHalHidlTargetTestBase.h>
+#include <android-base/logging.h>
+#include <android/hardware/broadcastradio/2.0/IBroadcastRadio.h>
+#include <android/hardware/broadcastradio/2.0/ITunerCallback.h>
+#include <android/hardware/broadcastradio/2.0/ITunerSession.h>
+#include <android/hardware/broadcastradio/2.0/types.h>
+#include <broadcastradio-utils-2x/Utils.h>
+#include <broadcastradio-vts-utils/call-barrier.h>
+#include <broadcastradio-vts-utils/mock-timeout.h>
+#include <broadcastradio-vts-utils/pointer-utils.h>
+#include <gmock/gmock.h>
+
+#include <chrono>
+
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace V2_0 {
+namespace vts {
+
+using namespace std::chrono_literals;
+
+using std::vector;
+using testing::_;
+using testing::AnyNumber;
+using testing::ByMove;
+using testing::DoAll;
+using testing::Invoke;
+using testing::SaveArg;
+
+using broadcastradio::vts::CallBarrier;
+using broadcastradio::vts::clearAndWait;
+using utils::make_identifier;
+using utils::make_selector_amfm;
+
+namespace timeout {
+
+static constexpr auto tune = 30s;
+
+}  // namespace timeout
+
+static const ConfigFlag gConfigFlagValues[] = {
+    ConfigFlag::FORCE_MONO,       ConfigFlag::FORCE_ANALOG,     ConfigFlag::FORCE_DIGITAL,
+    ConfigFlag::RDS_AF,           ConfigFlag::RDS_REG,          ConfigFlag::DAB_IMPLICIT_LINKING,
+    ConfigFlag::DAB_HARD_LINKING, ConfigFlag::DAB_SOFT_LINKING,
+};
+
+struct TunerCallbackMock : public ITunerCallback {
+    TunerCallbackMock() {
+        // we expect the antenna is connected through the whole test
+        EXPECT_CALL(*this, onAntennaStateChange(false)).Times(0);
+    }
+
+    MOCK_METHOD2(onTuneFailed, Return<void>(Result, const ProgramSelector&));
+    MOCK_TIMEOUT_METHOD1(onCurrentProgramInfoChanged, Return<void>(const ProgramInfo&));
+    MOCK_METHOD1(onAntennaStateChange, Return<void>(bool connected));
+    MOCK_METHOD1(onParametersUpdated, Return<void>(const hidl_vec<VendorKeyValue>& parameters));
+};
+
+class BroadcastRadioHalTest : public ::testing::VtsHalHidlTargetTestBase {
+   protected:
+    virtual void SetUp() override;
+    virtual void TearDown() override;
+
+    bool openSession();
+
+    sp<IBroadcastRadio> mModule;
+    Properties mProperties;
+    sp<ITunerSession> mSession;
+    sp<TunerCallbackMock> mCallback = new TunerCallbackMock();
+};
+
+void BroadcastRadioHalTest::SetUp() {
+    EXPECT_EQ(nullptr, mModule.get()) << "Module is already open";
+
+    // lookup HIDL service (radio module)
+    mModule = getService<IBroadcastRadio>();
+    ASSERT_NE(nullptr, mModule.get()) << "Couldn't find broadcast radio HAL implementation";
+
+    // get module properties
+    auto propResult = mModule->getProperties([&](const Properties& p) { mProperties = p; });
+    ASSERT_TRUE(propResult.isOk());
+
+    EXPECT_FALSE(mProperties.maker.empty());
+    EXPECT_FALSE(mProperties.product.empty());
+    EXPECT_GT(mProperties.supportedIdentifierTypes.size(), 0u);
+}
+
+void BroadcastRadioHalTest::TearDown() {
+    mSession.clear();
+    mModule.clear();
+    clearAndWait(mCallback, 1s);
+}
+
+bool BroadcastRadioHalTest::openSession() {
+    EXPECT_EQ(nullptr, mSession.get()) << "Session is already open";
+
+    Result halResult = Result::UNKNOWN_ERROR;
+    auto openCb = [&](Result result, const sp<ITunerSession>& session) {
+        halResult = result;
+        if (result != Result::OK) return;
+        mSession = session;
+    };
+    auto hidlResult = mModule->openSession(mCallback, openCb);
+
+    EXPECT_TRUE(hidlResult.isOk());
+    EXPECT_EQ(Result::OK, halResult);
+    EXPECT_NE(nullptr, mSession.get());
+
+    return nullptr != mSession.get();
+}
+
+/**
+ * Test session opening.
+ *
+ * Verifies that:
+ *  - the method succeeds on a first and subsequent calls;
+ *  - the method succeeds when called for the second time without
+ *    closing previous session.
+ */
+TEST_F(BroadcastRadioHalTest, OpenSession) {
+    // simply open session for the first time
+    ASSERT_TRUE(openSession());
+
+    // drop (without explicit close) and re-open the session
+    mSession.clear();
+    ASSERT_TRUE(openSession());
+
+    // open the second session (the first one should be forcibly closed)
+    auto secondSession = mSession;
+    mSession.clear();
+    ASSERT_TRUE(openSession());
+}
+
+/**
+ * Test tuning with FM selector.
+ *
+ * Verifies that:
+ *  - if AM/FM selector is not supported, the method returns NOT_SUPPORTED;
+ *  - if it is supported, the method succeeds;
+ *  - after a successful tune call, onCurrentProgramInfoChanged callback is
+ *    invoked carrying a proper selector;
+ *  - program changes exactly to what was requested.
+ */
+TEST_F(BroadcastRadioHalTest, FmTune) {
+    ASSERT_TRUE(openSession());
+
+    uint64_t freq = 100100;  // 100.1 FM
+    auto sel = make_selector_amfm(freq);
+
+    // try tuning
+    ProgramInfo infoCb = {};
+    EXPECT_TIMEOUT_CALL(*mCallback, onCurrentProgramInfoChanged, _)
+        .Times(AnyNumber())
+        .WillOnce(DoAll(SaveArg<0>(&infoCb), testing::Return(ByMove(Void()))));
+    auto result = mSession->tune(sel);
+
+    // expect a failure if it's not supported
+    if (!utils::isSupported(mProperties, sel)) {
+        EXPECT_EQ(Result::NOT_SUPPORTED, result);
+        return;
+    }
+
+    // expect a callback if it succeeds
+    EXPECT_EQ(Result::OK, result);
+    EXPECT_TIMEOUT_CALL_WAIT(*mCallback, onCurrentProgramInfoChanged, timeout::tune);
+
+    // it should tune exactly to what was requested
+    auto freqs = utils::getAllIds(infoCb.selector, IdentifierType::AMFM_FREQUENCY);
+    EXPECT_NE(freqs.end(), find(freqs.begin(), freqs.end(), freq));
+}
+
+/**
+ * Test tuning with invalid selectors.
+ *
+ * Verifies that:
+ *  - if the selector is not supported, it's ignored;
+ *  - if it is supported, an invalid value results with INVALID_ARGUMENTS;
+ */
+TEST_F(BroadcastRadioHalTest, TuneFailsWithInvalid) {
+    ASSERT_TRUE(openSession());
+
+    vector<ProgramIdentifier> invalid = {
+        make_identifier(IdentifierType::AMFM_FREQUENCY, 0),
+        make_identifier(IdentifierType::RDS_PI, 0x10000),
+        make_identifier(IdentifierType::HD_STATION_ID_EXT, 0x100000000),
+        make_identifier(IdentifierType::DAB_SID_EXT, 0),
+        make_identifier(IdentifierType::DRMO_SERVICE_ID, 0x100000000),
+        make_identifier(IdentifierType::SXM_SERVICE_ID, 0x100000000),
+    };
+
+    for (auto&& id : invalid) {
+        ProgramSelector sel{id, {}};
+
+        auto result = mSession->tune(sel);
+
+        if (utils::isSupported(mProperties, sel)) {
+            EXPECT_EQ(Result::INVALID_ARGUMENTS, result);
+        } else {
+            EXPECT_EQ(Result::NOT_SUPPORTED, result);
+        }
+    }
+}
+
+/**
+ * Test tuning with empty program selector.
+ *
+ * Verifies that:
+ *  - tune fails with NOT_SUPPORTED when program selector is not initialized.
+ */
+TEST_F(BroadcastRadioHalTest, TuneFailsWithEmpty) {
+    ASSERT_TRUE(openSession());
+
+    // Program type is 1-based, so 0 will always be invalid.
+    ProgramSelector sel = {};
+    auto result = mSession->tune(sel);
+    ASSERT_EQ(Result::NOT_SUPPORTED, result);
+}
+
+/**
+ * Test scanning to next/prev station.
+ *
+ * Verifies that:
+ *  - the method succeeds;
+ *  - the program info is changed within timeout::tune;
+ *  - works both directions and with or without skipping sub-channel.
+ */
+TEST_F(BroadcastRadioHalTest, Scan) {
+    ASSERT_TRUE(openSession());
+
+    EXPECT_TIMEOUT_CALL(*mCallback, onCurrentProgramInfoChanged, _);
+    auto result = mSession->scan(true /* up */, true /* skip subchannel */);
+    EXPECT_EQ(Result::OK, result);
+    EXPECT_TIMEOUT_CALL_WAIT(*mCallback, onCurrentProgramInfoChanged, timeout::tune);
+
+    EXPECT_TIMEOUT_CALL(*mCallback, onCurrentProgramInfoChanged, _);
+    result = mSession->scan(false /* down */, false /* don't skip subchannel */);
+    EXPECT_EQ(Result::OK, result);
+    EXPECT_TIMEOUT_CALL_WAIT(*mCallback, onCurrentProgramInfoChanged, timeout::tune);
+}
+
+/**
+ * Test step operation.
+ *
+ * Verifies that:
+ *  - the method succeeds or returns NOT_SUPPORTED;
+ *  - the program info is changed within timeout::tune if the method succeeded;
+ *  - works both directions.
+ */
+TEST_F(BroadcastRadioHalTest, Step) {
+    ASSERT_TRUE(openSession());
+
+    EXPECT_TIMEOUT_CALL(*mCallback, onCurrentProgramInfoChanged, _).Times(AnyNumber());
+    auto result = mSession->step(true /* up */);
+    if (result == Result::NOT_SUPPORTED) return;
+    EXPECT_EQ(Result::OK, result);
+    EXPECT_TIMEOUT_CALL_WAIT(*mCallback, onCurrentProgramInfoChanged, timeout::tune);
+
+    EXPECT_TIMEOUT_CALL(*mCallback, onCurrentProgramInfoChanged, _);
+    result = mSession->step(false /* down */);
+    EXPECT_EQ(Result::OK, result);
+    EXPECT_TIMEOUT_CALL_WAIT(*mCallback, onCurrentProgramInfoChanged, timeout::tune);
+}
+
+/**
+ * Test tune cancellation.
+ *
+ * Verifies that:
+ *  - the method does not crash after being invoked multiple times.
+ */
+TEST_F(BroadcastRadioHalTest, Cancel) {
+    ASSERT_TRUE(openSession());
+
+    for (int i = 0; i < 10; i++) {
+        auto scanResult = mSession->scan(true /* up */, true /* skip subchannel */);
+        ASSERT_EQ(Result::OK, scanResult);
+
+        auto cancelResult = mSession->cancel();
+        ASSERT_TRUE(cancelResult.isOk());
+    }
+}
+
+/**
+ * Test IBroadcastRadio::get|setParameters() methods called with no parameters.
+ *
+ * Verifies that:
+ *  - callback is called for empty parameters set.
+ */
+TEST_F(BroadcastRadioHalTest, NoParameters) {
+    ASSERT_TRUE(openSession());
+
+    hidl_vec<VendorKeyValue> halResults = {};
+    bool wasCalled = false;
+    auto cb = [&](hidl_vec<VendorKeyValue> results) {
+        wasCalled = true;
+        halResults = results;
+    };
+
+    auto hidlResult = mSession->setParameters({}, cb);
+    ASSERT_TRUE(hidlResult.isOk());
+    ASSERT_TRUE(wasCalled);
+    ASSERT_EQ(0u, halResults.size());
+
+    wasCalled = false;
+    hidlResult = mSession->getParameters({}, cb);
+    ASSERT_TRUE(hidlResult.isOk());
+    ASSERT_TRUE(wasCalled);
+    ASSERT_EQ(0u, halResults.size());
+}
+
+/**
+ * Test IBroadcastRadio::get|setParameters() methods called with unknown parameters.
+ *
+ * Verifies that:
+ *  - unknown parameters are ignored;
+ *  - callback is called also for empty results set.
+ */
+TEST_F(BroadcastRadioHalTest, UnknownParameters) {
+    ASSERT_TRUE(openSession());
+
+    hidl_vec<VendorKeyValue> halResults = {};
+    bool wasCalled = false;
+    auto cb = [&](hidl_vec<VendorKeyValue> results) {
+        wasCalled = true;
+        halResults = results;
+    };
+
+    auto hidlResult = mSession->setParameters({{"com.google.unknown", "dummy"}}, cb);
+    ASSERT_TRUE(hidlResult.isOk());
+    ASSERT_TRUE(wasCalled);
+    ASSERT_EQ(0u, halResults.size());
+
+    wasCalled = false;
+    hidlResult = mSession->getParameters({{"com.google.unknown*", "dummy"}}, cb);
+    ASSERT_TRUE(hidlResult.isOk());
+    ASSERT_TRUE(wasCalled);
+    ASSERT_EQ(0u, halResults.size());
+}
+
+/**
+ * Test session closing.
+ *
+ * Verifies that:
+ *  - the method does not crash after being invoked multiple times.
+ */
+TEST_F(BroadcastRadioHalTest, Close) {
+    ASSERT_TRUE(openSession());
+
+    for (int i = 0; i < 10; i++) {
+        auto cancelResult = mSession->close();
+        ASSERT_TRUE(cancelResult.isOk());
+    }
+}
+
+/**
+ * Test geting image of invalid ID.
+ *
+ * Verifies that:
+ * - getImage call handles argument 0 gracefully.
+ */
+TEST_F(BroadcastRadioHalTest, GetNoImage) {
+    size_t len = 0;
+    auto result = mModule->getImage(0, [&](hidl_vec<uint8_t> rawImage) { len = rawImage.size(); });
+
+    ASSERT_TRUE(result.isOk());
+    ASSERT_EQ(0u, len);
+}
+
+/**
+ * Test getting config flags.
+ *
+ * Verifies that:
+ * - getConfigFlag either succeeds or ends with NOT_SUPPORTED or INVALID_STATE;
+ * - call success or failure is consistent with setConfigFlag.
+ */
+TEST_F(BroadcastRadioHalTest, GetConfigFlags) {
+    ASSERT_TRUE(openSession());
+
+    for (auto flag : gConfigFlagValues) {
+        auto halResult = Result::UNKNOWN_ERROR;
+        auto cb = [&](Result result, bool) { halResult = result; };
+        auto hidlResult = mSession->getConfigFlag(flag, cb);
+        EXPECT_TRUE(hidlResult.isOk());
+
+        if (halResult != Result::NOT_SUPPORTED && halResult != Result::INVALID_STATE) {
+            ASSERT_EQ(Result::OK, halResult);
+        }
+
+        // set must fail or succeed the same way as get
+        auto setResult = mSession->setConfigFlag(flag, false);
+        EXPECT_EQ(halResult, setResult);
+        setResult = mSession->setConfigFlag(flag, true);
+        EXPECT_EQ(halResult, setResult);
+    }
+}
+
+/**
+ * Test setting config flags.
+ *
+ * Verifies that:
+ * - setConfigFlag either succeeds or ends with NOT_SUPPORTED or INVALID_STATE;
+ * - getConfigFlag reflects the state requested immediately after the set call.
+ */
+TEST_F(BroadcastRadioHalTest, SetConfigFlags) {
+    ASSERT_TRUE(openSession());
+
+    auto get = [&](ConfigFlag flag) {
+        auto halResult = Result::UNKNOWN_ERROR;
+        bool gotValue = false;
+        auto cb = [&](Result result, bool value) {
+            halResult = result;
+            gotValue = value;
+        };
+        auto hidlResult = mSession->getConfigFlag(flag, cb);
+        EXPECT_TRUE(hidlResult.isOk());
+        EXPECT_EQ(Result::OK, halResult);
+        return gotValue;
+    };
+
+    for (auto flag : gConfigFlagValues) {
+        auto result = mSession->setConfigFlag(flag, false);
+        if (result == Result::NOT_SUPPORTED || result == Result::INVALID_STATE) {
+            // setting to true must result in the same error as false
+            auto secondResult = mSession->setConfigFlag(flag, true);
+            EXPECT_EQ(result, secondResult);
+            continue;
+        }
+        ASSERT_EQ(Result::OK, result);
+
+        // verify false is set
+        auto value = get(flag);
+        EXPECT_FALSE(value);
+
+        // try setting true this time
+        result = mSession->setConfigFlag(flag, true);
+        ASSERT_EQ(Result::OK, result);
+        value = get(flag);
+        EXPECT_TRUE(value);
+
+        // false again
+        result = mSession->setConfigFlag(flag, false);
+        ASSERT_EQ(Result::OK, result);
+        value = get(flag);
+        EXPECT_FALSE(value);
+    }
+}
+
+}  // namespace vts
+}  // namespace V2_0
+}  // namespace broadcastradio
+}  // namespace hardware
+}  // namespace android
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    int status = RUN_ALL_TESTS();
+    ALOGI("Test result = %d", status);
+    return status;
+}
diff --git a/broadcastradio/1.1/default/OWNERS b/broadcastradio/common/OWNERS
similarity index 73%
copy from broadcastradio/1.1/default/OWNERS
copy to broadcastradio/common/OWNERS
index 0c27b71..136b607 100644
--- a/broadcastradio/1.1/default/OWNERS
+++ b/broadcastradio/common/OWNERS
@@ -1,4 +1,3 @@
 # Automotive team
 egranata@google.com
-keunyoung@google.com
 twasilczyk@google.com
diff --git a/broadcastradio/common/tests/Android.bp b/broadcastradio/common/tests/Android.bp
new file mode 100644
index 0000000..bbad527
--- /dev/null
+++ b/broadcastradio/common/tests/Android.bp
@@ -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.
+//
+
+cc_test {
+    name: "android.hardware.broadcastradio@common-utils-tests",
+    vendor: true,
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+    ],
+    srcs: [
+        "WorkerThread_test.cpp",
+    ],
+    static_libs: ["android.hardware.broadcastradio@common-utils-lib"],
+}
+
+cc_test {
+    name: "android.hardware.broadcastradio@common-utils-xx-tests",
+    vendor: true,
+    cflags: [
+        "-Wall",
+        "-Wextra",
+        "-Werror",
+    ],
+    srcs: [
+        "CommonXX_test.cpp",
+    ],
+    static_libs: [
+        "android.hardware.broadcastradio@common-utils-1x-lib",
+        "android.hardware.broadcastradio@common-utils-2x-lib",
+    ],
+    shared_libs: [
+        "android.hardware.broadcastradio@1.2",
+        "android.hardware.broadcastradio@2.0",
+    ],
+}
diff --git a/broadcastradio/common/tests/CommonXX_test.cpp b/broadcastradio/common/tests/CommonXX_test.cpp
new file mode 100644
index 0000000..d19204e
--- /dev/null
+++ b/broadcastradio/common/tests/CommonXX_test.cpp
@@ -0,0 +1,18 @@
+/*
+ * 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-1x/Utils.h>
+#include <broadcastradio-utils-2x/Utils.h>
diff --git a/broadcastradio/1.1/tests/WorkerThread_test.cpp b/broadcastradio/common/tests/WorkerThread_test.cpp
similarity index 100%
rename from broadcastradio/1.1/tests/WorkerThread_test.cpp
rename to broadcastradio/common/tests/WorkerThread_test.cpp
diff --git a/broadcastradio/1.1/utils/Android.bp b/broadcastradio/common/utils/Android.bp
similarity index 87%
rename from broadcastradio/1.1/utils/Android.bp
rename to broadcastradio/common/utils/Android.bp
index e80d133..33ba7da 100644
--- a/broadcastradio/1.1/utils/Android.bp
+++ b/broadcastradio/common/utils/Android.bp
@@ -15,7 +15,7 @@
 //
 
 cc_library_static {
-    name: "android.hardware.broadcastradio@1.1-utils-lib",
+    name: "android.hardware.broadcastradio@common-utils-lib",
     vendor_available: true,
     relative_install_path: "hw",
     cflags: [
@@ -24,11 +24,12 @@
         "-Werror",
     ],
     srcs: [
-        "Utils.cpp",
         "WorkerThread.cpp",
     ],
     export_include_dirs: ["include"],
     shared_libs: [
-        "android.hardware.broadcastradio@1.1",
+        "libbase",
+        "liblog",
+        "libutils",
     ],
 }
diff --git a/broadcastradio/1.1/utils/WorkerThread.cpp b/broadcastradio/common/utils/WorkerThread.cpp
similarity index 100%
rename from broadcastradio/1.1/utils/WorkerThread.cpp
rename to broadcastradio/common/utils/WorkerThread.cpp
diff --git a/broadcastradio/1.1/utils/include/broadcastradio-utils/WorkerThread.h b/broadcastradio/common/utils/include/broadcastradio-utils/WorkerThread.h
similarity index 87%
rename from broadcastradio/1.1/utils/include/broadcastradio-utils/WorkerThread.h
rename to broadcastradio/common/utils/include/broadcastradio-utils/WorkerThread.h
index 635876f..62bede6 100644
--- a/broadcastradio/1.1/utils/include/broadcastradio-utils/WorkerThread.h
+++ b/broadcastradio/common/utils/include/broadcastradio-utils/WorkerThread.h
@@ -13,8 +13,8 @@
  * 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
+#ifndef ANDROID_HARDWARE_BROADCASTRADIO_COMMON_WORKERTHREAD_H
+#define ANDROID_HARDWARE_BROADCASTRADIO_COMMON_WORKERTHREAD_H
 
 #include <chrono>
 #include <queue>
@@ -48,4 +48,4 @@
 
 }  // namespace android
 
-#endif  // ANDROID_HARDWARE_BROADCASTRADIO_V1_1_WORKERTHREAD_H
+#endif  // ANDROID_HARDWARE_BROADCASTRADIO_COMMON_WORKERTHREAD_H
diff --git a/broadcastradio/1.1/utils/Android.bp b/broadcastradio/common/utils1x/Android.bp
similarity index 86%
copy from broadcastradio/1.1/utils/Android.bp
copy to broadcastradio/common/utils1x/Android.bp
index e80d133..127c15a 100644
--- a/broadcastradio/1.1/utils/Android.bp
+++ b/broadcastradio/common/utils1x/Android.bp
@@ -15,7 +15,7 @@
 //
 
 cc_library_static {
-    name: "android.hardware.broadcastradio@1.1-utils-lib",
+    name: "android.hardware.broadcastradio@common-utils-1x-lib",
     vendor_available: true,
     relative_install_path: "hw",
     cflags: [
@@ -25,10 +25,9 @@
     ],
     srcs: [
         "Utils.cpp",
-        "WorkerThread.cpp",
     ],
     export_include_dirs: ["include"],
     shared_libs: [
-        "android.hardware.broadcastradio@1.1",
+        "android.hardware.broadcastradio@1.2",
     ],
 }
diff --git a/broadcastradio/1.1/utils/Utils.cpp b/broadcastradio/common/utils1x/Utils.cpp
similarity index 84%
rename from broadcastradio/1.1/utils/Utils.cpp
rename to broadcastradio/common/utils1x/Utils.cpp
index 4dd6b13..7a59d6a 100644
--- a/broadcastradio/1.1/utils/Utils.cpp
+++ b/broadcastradio/common/utils1x/Utils.cpp
@@ -16,17 +16,20 @@
 #define LOG_TAG "BroadcastRadioDefault.utils"
 //#define LOG_NDEBUG 0
 
-#include <broadcastradio-utils/Utils.h>
+#include <broadcastradio-utils-1x/Utils.h>
 
 #include <log/log.h>
 
 namespace android {
 namespace hardware {
 namespace broadcastradio {
-namespace V1_1 {
 namespace utils {
 
 using V1_0::Band;
+using V1_1::ProgramIdentifier;
+using V1_1::ProgramSelector;
+using V1_1::ProgramType;
+using V1_2::IdentifierType;
 
 static bool isCompatibleProgramType(const uint32_t ia, const uint32_t ib) {
     auto a = static_cast<ProgramType>(ia);
@@ -56,9 +59,7 @@
     /* 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;
+    return getId(a, type) == getId(b, type);
 }
 
 bool tunesTo(const ProgramSelector& a, const ProgramSelector& b) {
@@ -85,7 +86,7 @@
 
             return haveEqualIds(a, b, IdentifierType::AMFM_FREQUENCY);
         case ProgramType::DAB:
-            return haveEqualIds(a, b, IdentifierType::DAB_SIDECC);
+            return haveEqualIds(a, b, IdentifierType::DAB_SID_EXT);
         case ProgramType::DRMO:
             return haveEqualIds(a, b, IdentifierType::DRMO_SERVICE_ID);
         case ProgramType::SXM:
@@ -123,23 +124,50 @@
     return band == Band::FM || band == Band::FM_HD;
 }
 
-bool hasId(const ProgramSelector& sel, const IdentifierType type) {
+static bool maybeGetId(const ProgramSelector& sel, const IdentifierType type, uint64_t* val) {
     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;
+    auto itypeAlt = itype;
+    if (type == IdentifierType::DAB_SIDECC) {
+        itypeAlt = static_cast<uint32_t>(IdentifierType::DAB_SID_EXT);
     }
-    return false;
+    if (type == IdentifierType::DAB_SID_EXT) {
+        itypeAlt = static_cast<uint32_t>(IdentifierType::DAB_SIDECC);
+    }
+
+    if (sel.primaryId.type == itype || sel.primaryId.type == itypeAlt) {
+        if (val) *val = sel.primaryId.value;
+        return true;
+    }
+
+    // not optimal, but we don't care in default impl
+    bool gotAlt = false;
+    for (auto&& id : sel.secondaryIds) {
+        if (id.type == itype) {
+            if (val) *val = id.value;
+            return true;
+        }
+        // alternative identifier is a backup, we prefer original value
+        if (id.type == itypeAlt) {
+            if (val) *val = id.value;
+            gotAlt = true;
+            continue;
+        }
+    }
+
+    return gotAlt;
+}
+
+bool hasId(const ProgramSelector& sel, const IdentifierType type) {
+    return maybeGetId(sel, type, nullptr);
 }
 
 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;
+    uint64_t val;
+
+    if (maybeGetId(sel, type, &val)) {
+        return val;
     }
+
     ALOGW("Identifier %s not found", toString(type).c_str());
     return 0;
 }
@@ -208,19 +236,20 @@
 }
 
 }  // namespace utils
-}  // namespace V1_1
 
 namespace V1_0 {
 
 bool operator==(const BandConfig& l, const BandConfig& r) {
+    using namespace utils;
+
     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)) {
+    if (isAm(l.type)) {
         return l.ext.am == r.ext.am;
-    } else if (V1_1::utils::isFm(l.type)) {
+    } else if (isFm(l.type)) {
         return l.ext.fm == r.ext.fm;
     } else {
         ALOGW("Unsupported band config type: %s", toString(l.type).c_str());
diff --git a/broadcastradio/1.1/utils/include/broadcastradio-utils/Utils.h b/broadcastradio/common/utils1x/include/broadcastradio-utils-1x/Utils.h
similarity index 64%
rename from broadcastradio/1.1/utils/include/broadcastradio-utils/Utils.h
rename to broadcastradio/common/utils1x/include/broadcastradio-utils-1x/Utils.h
index 24c60ee..5884b5a 100644
--- a/broadcastradio/1.1/utils/include/broadcastradio-utils/Utils.h
+++ b/broadcastradio/common/utils1x/include/broadcastradio-utils-1x/Utils.h
@@ -13,10 +13,10 @@
  * 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
+#ifndef ANDROID_HARDWARE_BROADCASTRADIO_COMMON_UTILS_1X_H
+#define ANDROID_HARDWARE_BROADCASTRADIO_COMMON_UTILS_1X_H
 
-#include <android/hardware/broadcastradio/1.1/types.h>
+#include <android/hardware/broadcastradio/1.2/types.h>
 #include <chrono>
 #include <queue>
 #include <thread>
@@ -24,13 +24,12 @@
 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,
+    V1_2,
 };
 
 /**
@@ -43,38 +42,38 @@
  * @param pointer selector we're trying to match against channel.
  * @param channel existing channel.
  */
-bool tunesTo(const ProgramSelector& pointer, const ProgramSelector& channel);
+bool tunesTo(const V1_1::ProgramSelector& pointer, const V1_1::ProgramSelector& channel);
 
-ProgramType getType(const ProgramSelector& sel);
-bool isAmFm(const ProgramType type);
+V1_1::ProgramType getType(const V1_1::ProgramSelector& sel);
+bool isAmFm(const V1_1::ProgramType type);
 
 bool isAm(const V1_0::Band band);
 bool isFm(const V1_0::Band band);
 
-bool hasId(const ProgramSelector& sel, const IdentifierType type);
+bool hasId(const V1_1::ProgramSelector& sel, const V1_2::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);
+uint64_t getId(const V1_1::ProgramSelector& sel, const V1_2::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);
+uint64_t getId(const V1_1::ProgramSelector& sel, const V1_2::IdentifierType type, uint64_t defval);
 
-ProgramSelector make_selector(V1_0::Band band, uint32_t channel, uint32_t subChannel = 0);
+V1_1::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 getLegacyChannel(const V1_1::ProgramSelector& sel, uint32_t* channelOut,
+                      uint32_t* subChannelOut);
 
-bool isDigital(const ProgramSelector& sel);
+bool isDigital(const V1_1::ProgramSelector& sel);
 
 }  // namespace utils
-}  // namespace V1_1
 
 namespace V1_0 {
 
@@ -86,4 +85,4 @@
 }  // namespace hardware
 }  // namespace android
 
-#endif  // ANDROID_HARDWARE_BROADCASTRADIO_V1_1_UTILS_H
+#endif  // ANDROID_HARDWARE_BROADCASTRADIO_COMMON_UTILS_1X_H
diff --git a/broadcastradio/1.1/utils/Android.bp b/broadcastradio/common/utils2x/Android.bp
similarity index 86%
copy from broadcastradio/1.1/utils/Android.bp
copy to broadcastradio/common/utils2x/Android.bp
index e80d133..c6b94af 100644
--- a/broadcastradio/1.1/utils/Android.bp
+++ b/broadcastradio/common/utils2x/Android.bp
@@ -15,7 +15,7 @@
 //
 
 cc_library_static {
-    name: "android.hardware.broadcastradio@1.1-utils-lib",
+    name: "android.hardware.broadcastradio@common-utils-2x-lib",
     vendor_available: true,
     relative_install_path: "hw",
     cflags: [
@@ -25,10 +25,9 @@
     ],
     srcs: [
         "Utils.cpp",
-        "WorkerThread.cpp",
     ],
     export_include_dirs: ["include"],
     shared_libs: [
-        "android.hardware.broadcastradio@1.1",
+        "android.hardware.broadcastradio@2.0",
     ],
 }
diff --git a/broadcastradio/common/utils2x/Utils.cpp b/broadcastradio/common/utils2x/Utils.cpp
new file mode 100644
index 0000000..d157108
--- /dev/null
+++ b/broadcastradio/common/utils2x/Utils.cpp
@@ -0,0 +1,249 @@
+/*
+ * 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 "BcRadioDef.utils"
+//#define LOG_NDEBUG 0
+
+#include <broadcastradio-utils-2x/Utils.h>
+
+#include <log/log.h>
+
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace utils {
+
+using V2_0::IdentifierType;
+using V2_0::Metadata;
+using V2_0::MetadataKey;
+using V2_0::ProgramIdentifier;
+using V2_0::ProgramSelector;
+
+using std::string;
+using std::vector;
+
+IdentifierType getType(const ProgramIdentifier& id) {
+    return static_cast<IdentifierType>(id.type);
+}
+
+static bool bothHaveId(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.
+     */
+    return getId(a, type) == getId(b, type);
+}
+
+static int getHdSubchannel(const ProgramSelector& sel) {
+    auto hdsidext = getId(sel, IdentifierType::HD_STATION_ID_EXT, 0);
+    hdsidext >>= 32;        // Station ID number
+    return hdsidext & 0xF;  // HD Radio subchannel
+}
+
+bool tunesTo(const ProgramSelector& a, const ProgramSelector& b) {
+    auto type = getType(b.primaryId);
+
+    switch (type) {
+        case IdentifierType::HD_STATION_ID_EXT:
+        case IdentifierType::RDS_PI:
+        case IdentifierType::AMFM_FREQUENCY:
+            if (haveEqualIds(a, b, IdentifierType::HD_STATION_ID_EXT)) return true;
+            if (haveEqualIds(a, b, IdentifierType::RDS_PI)) return true;
+            return getHdSubchannel(b) == 0 && haveEqualIds(a, b, IdentifierType::AMFM_FREQUENCY);
+        case IdentifierType::DAB_SID_EXT:
+            return haveEqualIds(a, b, IdentifierType::DAB_SID_EXT);
+        case IdentifierType::DRMO_SERVICE_ID:
+            return haveEqualIds(a, b, IdentifierType::DRMO_SERVICE_ID);
+        case IdentifierType::SXM_SERVICE_ID:
+            return haveEqualIds(a, b, IdentifierType::SXM_SERVICE_ID);
+        default:  // includes all vendor types
+            ALOGW("Unsupported program type: %s", toString(type).c_str());
+            return false;
+    }
+}
+
+static bool maybeGetId(const ProgramSelector& sel, const IdentifierType type, uint64_t* val) {
+    auto itype = static_cast<uint32_t>(type);
+
+    if (sel.primaryId.type == itype) {
+        if (val) *val = sel.primaryId.value;
+        return true;
+    }
+
+    // not optimal, but we don't care in default impl
+    for (auto&& id : sel.secondaryIds) {
+        if (id.type == itype) {
+            if (val) *val = id.value;
+            return true;
+        }
+    }
+
+    return false;
+}
+
+bool hasId(const ProgramSelector& sel, const IdentifierType type) {
+    return maybeGetId(sel, type, nullptr);
+}
+
+uint64_t getId(const ProgramSelector& sel, const IdentifierType type) {
+    uint64_t val;
+
+    if (maybeGetId(sel, type, &val)) {
+        return val;
+    }
+
+    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);
+}
+
+vector<uint64_t> getAllIds(const ProgramSelector& sel, const IdentifierType type) {
+    vector<uint64_t> ret;
+    auto itype = static_cast<uint32_t>(type);
+
+    if (sel.primaryId.type == itype) ret.push_back(sel.primaryId.value);
+
+    for (auto&& id : sel.secondaryIds) {
+        if (id.type == itype) ret.push_back(id.value);
+    }
+
+    return ret;
+}
+
+bool isSupported(const V2_0::Properties& prop, const V2_0::ProgramSelector& sel) {
+    // Not optimal, but it doesn't matter for default impl nor VTS tests.
+    for (auto&& idTypeI : prop.supportedIdentifierTypes) {
+        auto idType = static_cast<IdentifierType>(idTypeI);
+        if (hasId(sel, idType)) return true;
+    }
+    return false;
+}
+
+static bool isValid(const ProgramIdentifier& id) {
+    auto val = id.value;
+    bool valid = true;
+
+    auto expect = [&valid](bool condition, std::string message) {
+        if (!condition) {
+            valid = false;
+            ALOGE("Identifier not valid, expected %s", message.c_str());
+        }
+    };
+
+    switch (static_cast<IdentifierType>(id.type)) {
+        case IdentifierType::AMFM_FREQUENCY:
+        case IdentifierType::DAB_FREQUENCY:
+        case IdentifierType::DRMO_FREQUENCY:
+            expect(val > 100u, "f > 100kHz");
+            expect(val < 10000000u, "f < 10GHz");
+            break;
+        case IdentifierType::RDS_PI:
+            expect(val != 0u, "RDS PI != 0");
+            expect(val <= 0xFFFFu, "16bit id");
+            break;
+        case IdentifierType::HD_STATION_ID_EXT: {
+            auto stationId = val & 0xFFFFFFFF;  // 32bit
+            val >>= 32;
+            auto subchannel = val & 0xF;  // 4bit
+            val >>= 4;
+            auto freq = val & 0x3FFFF;  // 18bit
+            expect(stationId != 0u, "HD station id != 0");
+            expect(subchannel < 8u, "HD subch < 8");
+            expect(freq > 100u, "f > 100kHz");
+            expect(freq < 10000000u, "f < 10GHz");
+            break;
+        }
+        case IdentifierType::DAB_SID_EXT: {
+            auto sid = val & 0xFFFF;  // 16bit
+            val >>= 16;
+            auto ecc = val & 0xFF;  // 8bit
+            expect(sid != 0u, "DAB SId != 0");
+            expect(ecc >= 0xA0u && ecc <= 0xF6u, "Invalid ECC, see ETSI TS 101 756 V2.1.1");
+            break;
+        }
+        case IdentifierType::DAB_ENSEMBLE:
+            expect(val != 0u, "DAB ensemble != 0");
+            expect(val <= 0xFFFFu, "16bit id");
+            break;
+        case IdentifierType::DAB_SCID:
+            expect(val > 0xFu, "12bit SCId (not 4bit SCIdS)");
+            expect(val <= 0xFFFu, "12bit id");
+            break;
+        case IdentifierType::DRMO_SERVICE_ID:
+            expect(val != 0u, "DRM SId != 0");
+            expect(val <= 0xFFFFFFu, "24bit id");
+            break;
+        case IdentifierType::SXM_SERVICE_ID:
+            expect(val != 0u, "SXM SId != 0");
+            expect(val <= 0xFFFFFFFFu, "32bit id");
+            break;
+        case IdentifierType::SXM_CHANNEL:
+            expect(val < 1000u, "SXM channel < 1000");
+            break;
+        case IdentifierType::VENDOR_START:
+        case IdentifierType::VENDOR_END:
+            // skip
+            break;
+    }
+
+    return valid;
+}
+
+bool isValid(const V2_0::ProgramSelector& sel) {
+    if (!isValid(sel.primaryId)) return false;
+    for (auto&& id : sel.secondaryIds) {
+        if (!isValid(id)) return false;
+    }
+    return true;
+}
+
+ProgramIdentifier make_identifier(IdentifierType type, uint64_t value) {
+    return {static_cast<uint32_t>(type), value};
+}
+
+ProgramSelector make_selector_amfm(uint32_t frequency) {
+    ProgramSelector sel = {};
+    sel.primaryId = make_identifier(IdentifierType::AMFM_FREQUENCY, frequency);
+    return sel;
+}
+
+Metadata make_metadata(MetadataKey key, int64_t value) {
+    Metadata meta = {};
+    meta.key = static_cast<uint32_t>(key);
+    meta.intValue = value;
+    return meta;
+}
+
+Metadata make_metadata(MetadataKey key, string value) {
+    Metadata meta = {};
+    meta.key = static_cast<uint32_t>(key);
+    meta.stringValue = value;
+    return meta;
+}
+
+}  // namespace utils
+}  // namespace broadcastradio
+}  // namespace hardware
+}  // namespace android
diff --git a/broadcastradio/common/utils2x/include/broadcastradio-utils-2x/Utils.h b/broadcastradio/common/utils2x/include/broadcastradio-utils-2x/Utils.h
new file mode 100644
index 0000000..dd01852
--- /dev/null
+++ b/broadcastradio/common/utils2x/include/broadcastradio-utils-2x/Utils.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 ANDROID_HARDWARE_BROADCASTRADIO_COMMON_UTILS_2X_H
+#define ANDROID_HARDWARE_BROADCASTRADIO_COMMON_UTILS_2X_H
+
+#include <android/hardware/broadcastradio/2.0/types.h>
+#include <chrono>
+#include <queue>
+#include <thread>
+
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace utils {
+
+V2_0::IdentifierType getType(const V2_0::ProgramIdentifier& id);
+
+/**
+ * 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 V2_0::ProgramSelector& pointer, const V2_0::ProgramSelector& channel);
+
+bool hasId(const V2_0::ProgramSelector& sel, const V2_0::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 V2_0::ProgramSelector& sel, const V2_0::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 V2_0::ProgramSelector& sel, const V2_0::IdentifierType type, uint64_t defval);
+
+/**
+ * Returns all IDs of a given type.
+ */
+std::vector<uint64_t> getAllIds(const V2_0::ProgramSelector& sel, const V2_0::IdentifierType type);
+
+/**
+ * Checks, if a given selector is supported by the radio module.
+ *
+ * @param prop Module description.
+ * @param sel The selector to check.
+ * @return True, if the selector is supported, false otherwise.
+ */
+bool isSupported(const V2_0::Properties& prop, const V2_0::ProgramSelector& sel);
+
+bool isValid(const V2_0::ProgramSelector& sel);
+
+V2_0::ProgramIdentifier make_identifier(V2_0::IdentifierType type, uint64_t value);
+V2_0::ProgramSelector make_selector_amfm(uint32_t frequency);
+V2_0::Metadata make_metadata(V2_0::MetadataKey key, int64_t value);
+V2_0::Metadata make_metadata(V2_0::MetadataKey key, std::string value);
+
+}  // namespace utils
+}  // namespace broadcastradio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_BROADCASTRADIO_COMMON_UTILS_2X_H
diff --git a/broadcastradio/1.1/vts/utils/Android.bp b/broadcastradio/common/vts/utils/Android.bp
similarity index 92%
rename from broadcastradio/1.1/vts/utils/Android.bp
rename to broadcastradio/common/vts/utils/Android.bp
index 0c7e2a4..4ba8a17 100644
--- a/broadcastradio/1.1/vts/utils/Android.bp
+++ b/broadcastradio/common/vts/utils/Android.bp
@@ -15,7 +15,7 @@
 //
 
 cc_library_static {
-    name: "android.hardware.broadcastradio@1.1-vts-utils-lib",
+    name: "android.hardware.broadcastradio@vts-utils-lib",
     srcs: [
         "call-barrier.cpp",
     ],
diff --git a/broadcastradio/1.1/vts/utils/call-barrier.cpp b/broadcastradio/common/vts/utils/call-barrier.cpp
similarity index 100%
rename from broadcastradio/1.1/vts/utils/call-barrier.cpp
rename to broadcastradio/common/vts/utils/call-barrier.cpp
diff --git a/broadcastradio/1.1/vts/utils/include/broadcastradio-vts-utils/call-barrier.h b/broadcastradio/common/vts/utils/include/broadcastradio-vts-utils/call-barrier.h
similarity index 100%
rename from broadcastradio/1.1/vts/utils/include/broadcastradio-vts-utils/call-barrier.h
rename to broadcastradio/common/vts/utils/include/broadcastradio-vts-utils/call-barrier.h
diff --git a/broadcastradio/1.1/vts/utils/include/broadcastradio-vts-utils/mock-timeout.h b/broadcastradio/common/vts/utils/include/broadcastradio-vts-utils/mock-timeout.h
similarity index 100%
rename from broadcastradio/1.1/vts/utils/include/broadcastradio-vts-utils/mock-timeout.h
rename to broadcastradio/common/vts/utils/include/broadcastradio-vts-utils/mock-timeout.h
diff --git a/broadcastradio/common/vts/utils/include/broadcastradio-vts-utils/pointer-utils.h b/broadcastradio/common/vts/utils/include/broadcastradio-vts-utils/pointer-utils.h
new file mode 100644
index 0000000..0b6f5eb
--- /dev/null
+++ b/broadcastradio/common/vts/utils/include/broadcastradio-vts-utils/pointer-utils.h
@@ -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.
+ */
+#ifndef ANDROID_HARDWARE_BROADCASTRADIO_VTS_POINTER_UTILS
+#define ANDROID_HARDWARE_BROADCASTRADIO_VTS_POINTER_UTILS
+
+#include <chrono>
+#include <thread>
+
+namespace android {
+namespace hardware {
+namespace broadcastradio {
+namespace vts {
+
+/**
+ * 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) {
+    using std::chrono::steady_clock;
+
+    constexpr auto step = 10ms;
+
+    wp<T> wptr = ptr;
+    ptr.clear();
+
+    auto limit = steady_clock::now() + timeout;
+    while (wptr.promote() != nullptr) {
+        if (steady_clock::now() + step > limit) {
+            FAIL() << "Pointer was not released within timeout";
+            break;
+        }
+        std::this_thread::sleep_for(step);
+    }
+}
+
+}  // namespace vts
+}  // namespace broadcastradio
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_BROADCASTRADIO_VTS_POINTER_UTILS
diff --git a/camera/metadata/3.2/types.hal b/camera/metadata/3.2/types.hal
index 17d1d5e..67b4e44 100644
--- a/camera/metadata/3.2/types.hal
+++ b/camera/metadata/3.2/types.hal
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * 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.
@@ -14,13 +14,17 @@
  * limitations under the License.
  */
 
+/*
+ * Autogenerated from camera metadata definitions in
+ * /system/media/camera/docs/metadata_definitions.xml
+ * *** DO NOT EDIT BY HAND ***
+ */
+
 package android.hardware.camera.metadata@3.2;
 
 /**
  * Top level hierarchy definitions for camera metadata. *_INFO sections are for
  * the static metadata that can be retrived without opening the camera device.
- * New sections must be added right before ANDROID_SECTION_COUNT to maintain
- * existing enumerations.
  */
 enum CameraMetadataSection : uint32_t {
     ANDROID_COLOR_CORRECTION,
@@ -82,7 +86,7 @@
 };
 
 /**
- * Hierarchy positions in enum space. All vendor extension tags must be
+ * Hierarchy positions in enum space. All vendor extension sections must be
  * defined with tag >= VENDOR_SECTION_START
  */
 enum CameraMetadataSectionStart : uint32_t {
@@ -143,1175 +147,2325 @@
 };
 
 /**
- * Main enum for defining camera metadata tags. New entries must always go
- * before the section _END tag to preserve existing enumeration values. In
- * addition, the name and type of the tag needs to be added to
- * system/media/camera/src/camera_metadata_tag_info.c
+ * Main enumeration for defining camera metadata tags added in this revision
+ *
+ * <p>Partial documentation is included for each tag; for complete documentation, reference
+ * '/system/media/camera/docs/docs.html' in the corresponding Android source tree.</p>
  */
 enum CameraMetadataTag : uint32_t {
+    /** android.colorCorrection.mode [dynamic, enum, public]
+     *
+     * <p>The mode control selects how the image data is converted from the
+     * sensor's native color into linear sRGB color.</p>
+     */
     ANDROID_COLOR_CORRECTION_MODE = CameraMetadataSectionStart:ANDROID_COLOR_CORRECTION_START,
 
+    /** android.colorCorrection.transform [dynamic, rational[], public]
+     *
+     * <p>A color transform matrix to use to transform
+     * from sensor RGB color space to output linear sRGB color space.</p>
+     */
     ANDROID_COLOR_CORRECTION_TRANSFORM,
 
+    /** android.colorCorrection.gains [dynamic, float[], public]
+     *
+     * <p>Gains applying to Bayer raw color channels for
+     * white-balance.</p>
+     */
     ANDROID_COLOR_CORRECTION_GAINS,
 
+    /** android.colorCorrection.aberrationMode [dynamic, enum, public]
+     *
+     * <p>Mode of operation for the chromatic aberration correction algorithm.</p>
+     */
     ANDROID_COLOR_CORRECTION_ABERRATION_MODE,
 
+    /** android.colorCorrection.availableAberrationModes [static, byte[], public]
+     *
+     * <p>List of aberration correction modes for ANDROID_COLOR_CORRECTION_ABERRATION_MODE that are
+     * supported by this camera device.</p>
+     *
+     * @see ANDROID_COLOR_CORRECTION_ABERRATION_MODE
+     */
     ANDROID_COLOR_CORRECTION_AVAILABLE_ABERRATION_MODES,
 
     ANDROID_COLOR_CORRECTION_END,
 
+    /** android.control.aeAntibandingMode [dynamic, enum, public]
+     *
+     * <p>The desired setting for the camera device's auto-exposure
+     * algorithm's antibanding compensation.</p>
+     */
     ANDROID_CONTROL_AE_ANTIBANDING_MODE = CameraMetadataSectionStart:ANDROID_CONTROL_START,
 
+    /** android.control.aeExposureCompensation [dynamic, int32, public]
+     *
+     * <p>Adjustment to auto-exposure (AE) target image
+     * brightness.</p>
+     */
     ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION,
 
+    /** android.control.aeLock [dynamic, enum, public]
+     *
+     * <p>Whether auto-exposure (AE) is currently locked to its latest
+     * calculated values.</p>
+     */
     ANDROID_CONTROL_AE_LOCK,
 
+    /** android.control.aeMode [dynamic, enum, public]
+     *
+     * <p>The desired mode for the camera device's
+     * auto-exposure routine.</p>
+     */
     ANDROID_CONTROL_AE_MODE,
 
+    /** android.control.aeRegions [dynamic, int32[], public]
+     *
+     * <p>List of metering areas to use for auto-exposure adjustment.</p>
+     */
     ANDROID_CONTROL_AE_REGIONS,
 
+    /** android.control.aeTargetFpsRange [dynamic, int32[], public]
+     *
+     * <p>Range over which the auto-exposure routine can
+     * adjust the capture frame rate to maintain good
+     * exposure.</p>
+     */
     ANDROID_CONTROL_AE_TARGET_FPS_RANGE,
 
+    /** android.control.aePrecaptureTrigger [dynamic, enum, public]
+     *
+     * <p>Whether the camera device will trigger a precapture
+     * metering sequence when it processes this request.</p>
+     */
     ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER,
 
+    /** android.control.afMode [dynamic, enum, public]
+     *
+     * <p>Whether auto-focus (AF) is currently enabled, and what
+     * mode it is set to.</p>
+     */
     ANDROID_CONTROL_AF_MODE,
 
+    /** android.control.afRegions [dynamic, int32[], public]
+     *
+     * <p>List of metering areas to use for auto-focus.</p>
+     */
     ANDROID_CONTROL_AF_REGIONS,
 
+    /** android.control.afTrigger [dynamic, enum, public]
+     *
+     * <p>Whether the camera device will trigger autofocus for this request.</p>
+     */
     ANDROID_CONTROL_AF_TRIGGER,
 
+    /** android.control.awbLock [dynamic, enum, public]
+     *
+     * <p>Whether auto-white balance (AWB) is currently locked to its
+     * latest calculated values.</p>
+     */
     ANDROID_CONTROL_AWB_LOCK,
 
+    /** android.control.awbMode [dynamic, enum, public]
+     *
+     * <p>Whether auto-white balance (AWB) is currently setting the color
+     * transform fields, and what its illumination target
+     * is.</p>
+     */
     ANDROID_CONTROL_AWB_MODE,
 
+    /** android.control.awbRegions [dynamic, int32[], public]
+     *
+     * <p>List of metering areas to use for auto-white-balance illuminant
+     * estimation.</p>
+     */
     ANDROID_CONTROL_AWB_REGIONS,
 
+    /** android.control.captureIntent [dynamic, enum, public]
+     *
+     * <p>Information to the camera device 3A (auto-exposure,
+     * auto-focus, auto-white balance) routines about the purpose
+     * of this capture, to help the camera device to decide optimal 3A
+     * strategy.</p>
+     */
     ANDROID_CONTROL_CAPTURE_INTENT,
 
+    /** android.control.effectMode [dynamic, enum, public]
+     *
+     * <p>A special color effect to apply.</p>
+     */
     ANDROID_CONTROL_EFFECT_MODE,
 
+    /** android.control.mode [dynamic, enum, public]
+     *
+     * <p>Overall mode of 3A (auto-exposure, auto-white-balance, auto-focus) control
+     * routines.</p>
+     */
     ANDROID_CONTROL_MODE,
 
+    /** android.control.sceneMode [dynamic, enum, public]
+     *
+     * <p>Control for which scene mode is currently active.</p>
+     */
     ANDROID_CONTROL_SCENE_MODE,
 
+    /** android.control.videoStabilizationMode [dynamic, enum, public]
+     *
+     * <p>Whether video stabilization is
+     * active.</p>
+     */
     ANDROID_CONTROL_VIDEO_STABILIZATION_MODE,
 
+    /** android.control.aeAvailableAntibandingModes [static, byte[], public]
+     *
+     * <p>List of auto-exposure antibanding modes for ANDROID_CONTROL_AE_ANTIBANDING_MODE that are
+     * supported by this camera device.</p>
+     *
+     * @see ANDROID_CONTROL_AE_ANTIBANDING_MODE
+     */
     ANDROID_CONTROL_AE_AVAILABLE_ANTIBANDING_MODES,
 
+    /** android.control.aeAvailableModes [static, byte[], public]
+     *
+     * <p>List of auto-exposure modes for ANDROID_CONTROL_AE_MODE that are supported by this camera
+     * device.</p>
+     *
+     * @see ANDROID_CONTROL_AE_MODE
+     */
     ANDROID_CONTROL_AE_AVAILABLE_MODES,
 
+    /** android.control.aeAvailableTargetFpsRanges [static, int32[], public]
+     *
+     * <p>List of frame rate ranges for ANDROID_CONTROL_AE_TARGET_FPS_RANGE supported by
+     * this camera device.</p>
+     *
+     * @see ANDROID_CONTROL_AE_TARGET_FPS_RANGE
+     */
     ANDROID_CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES,
 
+    /** android.control.aeCompensationRange [static, int32[], public]
+     *
+     * <p>Maximum and minimum exposure compensation values for
+     * ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION, in counts of ANDROID_CONTROL_AE_COMPENSATION_STEP,
+     * that are supported by this camera device.</p>
+     *
+     * @see ANDROID_CONTROL_AE_COMPENSATION_STEP
+     * @see ANDROID_CONTROL_AE_EXPOSURE_COMPENSATION
+     */
     ANDROID_CONTROL_AE_COMPENSATION_RANGE,
 
+    /** android.control.aeCompensationStep [static, rational, public]
+     *
+     * <p>Smallest step by which the exposure compensation
+     * can be changed.</p>
+     */
     ANDROID_CONTROL_AE_COMPENSATION_STEP,
 
+    /** android.control.afAvailableModes [static, byte[], public]
+     *
+     * <p>List of auto-focus (AF) modes for ANDROID_CONTROL_AF_MODE that are
+     * supported by this camera device.</p>
+     *
+     * @see ANDROID_CONTROL_AF_MODE
+     */
     ANDROID_CONTROL_AF_AVAILABLE_MODES,
 
+    /** android.control.availableEffects [static, byte[], public]
+     *
+     * <p>List of color effects for ANDROID_CONTROL_EFFECT_MODE that are supported by this camera
+     * device.</p>
+     *
+     * @see ANDROID_CONTROL_EFFECT_MODE
+     */
     ANDROID_CONTROL_AVAILABLE_EFFECTS,
 
+    /** android.control.availableSceneModes [static, byte[], public]
+     *
+     * <p>List of scene modes for ANDROID_CONTROL_SCENE_MODE that are supported by this camera
+     * device.</p>
+     *
+     * @see ANDROID_CONTROL_SCENE_MODE
+     */
     ANDROID_CONTROL_AVAILABLE_SCENE_MODES,
 
+    /** android.control.availableVideoStabilizationModes [static, byte[], public]
+     *
+     * <p>List of video stabilization modes for ANDROID_CONTROL_VIDEO_STABILIZATION_MODE
+     * that are supported by this camera device.</p>
+     *
+     * @see ANDROID_CONTROL_VIDEO_STABILIZATION_MODE
+     */
     ANDROID_CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES,
 
+    /** android.control.awbAvailableModes [static, byte[], public]
+     *
+     * <p>List of auto-white-balance modes for ANDROID_CONTROL_AWB_MODE that are supported by this
+     * camera device.</p>
+     *
+     * @see ANDROID_CONTROL_AWB_MODE
+     */
     ANDROID_CONTROL_AWB_AVAILABLE_MODES,
 
+    /** android.control.maxRegions [static, int32[], ndk_public]
+     *
+     * <p>List of the maximum number of regions that can be used for metering in
+     * auto-exposure (AE), auto-white balance (AWB), and auto-focus (AF);
+     * this corresponds to the the maximum number of elements in
+     * ANDROID_CONTROL_AE_REGIONS, ANDROID_CONTROL_AWB_REGIONS,
+     * and ANDROID_CONTROL_AF_REGIONS.</p>
+     *
+     * @see ANDROID_CONTROL_AE_REGIONS
+     * @see ANDROID_CONTROL_AF_REGIONS
+     * @see ANDROID_CONTROL_AWB_REGIONS
+     */
     ANDROID_CONTROL_MAX_REGIONS,
 
+    /** android.control.sceneModeOverrides [static, byte[], system]
+     *
+     * <p>Ordered list of auto-exposure, auto-white balance, and auto-focus
+     * settings to use with each available scene mode.</p>
+     */
     ANDROID_CONTROL_SCENE_MODE_OVERRIDES,
 
+    /** android.control.aePrecaptureId [dynamic, int32, system]
+     *
+     * <p>The ID sent with the latest
+     * CAMERA2_TRIGGER_PRECAPTURE_METERING call</p>
+     */
     ANDROID_CONTROL_AE_PRECAPTURE_ID,
 
+    /** android.control.aeState [dynamic, enum, public]
+     *
+     * <p>Current state of the auto-exposure (AE) algorithm.</p>
+     */
     ANDROID_CONTROL_AE_STATE,
 
+    /** android.control.afState [dynamic, enum, public]
+     *
+     * <p>Current state of auto-focus (AF) algorithm.</p>
+     */
     ANDROID_CONTROL_AF_STATE,
 
+    /** android.control.afTriggerId [dynamic, int32, system]
+     *
+     * <p>The ID sent with the latest
+     * CAMERA2_TRIGGER_AUTOFOCUS call</p>
+     */
     ANDROID_CONTROL_AF_TRIGGER_ID,
 
+    /** android.control.awbState [dynamic, enum, public]
+     *
+     * <p>Current state of auto-white balance (AWB) algorithm.</p>
+     */
     ANDROID_CONTROL_AWB_STATE,
 
+    /** android.control.availableHighSpeedVideoConfigurations [static, int32[], hidden]
+     *
+     * <p>List of available high speed video size, fps range and max batch size configurations
+     * supported by the camera device, in the format of (width, height, fps_min, fps_max, batch_size_max).</p>
+     */
     ANDROID_CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS,
 
+    /** android.control.aeLockAvailable [static, enum, public]
+     *
+     * <p>Whether the camera device supports ANDROID_CONTROL_AE_LOCK</p>
+     *
+     * @see ANDROID_CONTROL_AE_LOCK
+     */
     ANDROID_CONTROL_AE_LOCK_AVAILABLE,
 
+    /** android.control.awbLockAvailable [static, enum, public]
+     *
+     * <p>Whether the camera device supports ANDROID_CONTROL_AWB_LOCK</p>
+     *
+     * @see ANDROID_CONTROL_AWB_LOCK
+     */
     ANDROID_CONTROL_AWB_LOCK_AVAILABLE,
 
+    /** android.control.availableModes [static, byte[], public]
+     *
+     * <p>List of control modes for ANDROID_CONTROL_MODE that are supported by this camera
+     * device.</p>
+     *
+     * @see ANDROID_CONTROL_MODE
+     */
     ANDROID_CONTROL_AVAILABLE_MODES,
 
+    /** android.control.postRawSensitivityBoostRange [static, int32[], public]
+     *
+     * <p>Range of boosts for ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST supported
+     * by this camera device.</p>
+     *
+     * @see ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST
+     */
     ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST_RANGE,
 
+    /** android.control.postRawSensitivityBoost [dynamic, int32, public]
+     *
+     * <p>The amount of additional sensitivity boost applied to output images
+     * after RAW sensor data is captured.</p>
+     */
     ANDROID_CONTROL_POST_RAW_SENSITIVITY_BOOST,
 
+    /** android.control.enableZsl [dynamic, enum, public]
+     *
+     * <p>Allow camera device to enable zero-shutter-lag mode for requests with
+     * ANDROID_CONTROL_CAPTURE_INTENT == STILL_CAPTURE.</p>
+     *
+     * @see ANDROID_CONTROL_CAPTURE_INTENT
+     */
     ANDROID_CONTROL_ENABLE_ZSL,
 
     ANDROID_CONTROL_END,
 
+    /** android.demosaic.mode [controls, enum, system]
+     *
+     * <p>Controls the quality of the demosaicing
+     * processing.</p>
+     */
     ANDROID_DEMOSAIC_MODE = CameraMetadataSectionStart:ANDROID_DEMOSAIC_START,
 
     ANDROID_DEMOSAIC_END,
 
+    /** android.edge.mode [dynamic, enum, public]
+     *
+     * <p>Operation mode for edge
+     * enhancement.</p>
+     */
     ANDROID_EDGE_MODE = CameraMetadataSectionStart:ANDROID_EDGE_START,
 
+    /** android.edge.strength [controls, byte, system]
+     *
+     * <p>Control the amount of edge enhancement
+     * applied to the images</p>
+     */
     ANDROID_EDGE_STRENGTH,
 
+    /** android.edge.availableEdgeModes [static, byte[], public]
+     *
+     * <p>List of edge enhancement modes for ANDROID_EDGE_MODE that are supported by this camera
+     * device.</p>
+     *
+     * @see ANDROID_EDGE_MODE
+     */
     ANDROID_EDGE_AVAILABLE_EDGE_MODES,
 
     ANDROID_EDGE_END,
 
+    /** android.flash.firingPower [dynamic, byte, system]
+     *
+     * <p>Power for flash firing/torch</p>
+     */
     ANDROID_FLASH_FIRING_POWER = CameraMetadataSectionStart:ANDROID_FLASH_START,
 
+    /** android.flash.firingTime [dynamic, int64, system]
+     *
+     * <p>Firing time of flash relative to start of
+     * exposure</p>
+     */
     ANDROID_FLASH_FIRING_TIME,
 
+    /** android.flash.mode [dynamic, enum, public]
+     *
+     * <p>The desired mode for for the camera device's flash control.</p>
+     */
     ANDROID_FLASH_MODE,
 
+    /** android.flash.colorTemperature [static, byte, system]
+     *
+     * <p>The x,y whitepoint of the
+     * flash</p>
+     */
     ANDROID_FLASH_COLOR_TEMPERATURE,
 
+    /** android.flash.maxEnergy [static, byte, system]
+     *
+     * <p>Max energy output of the flash for a full
+     * power single flash</p>
+     */
     ANDROID_FLASH_MAX_ENERGY,
 
+    /** android.flash.state [dynamic, enum, public]
+     *
+     * <p>Current state of the flash
+     * unit.</p>
+     */
     ANDROID_FLASH_STATE,
 
     ANDROID_FLASH_END,
 
+    /** android.flash.info.available [static, enum, public]
+     *
+     * <p>Whether this camera device has a
+     * flash unit.</p>
+     */
     ANDROID_FLASH_INFO_AVAILABLE = CameraMetadataSectionStart:ANDROID_FLASH_INFO_START,
 
+    /** android.flash.info.chargeDuration [static, int64, system]
+     *
+     * <p>Time taken before flash can fire
+     * again</p>
+     */
     ANDROID_FLASH_INFO_CHARGE_DURATION,
 
     ANDROID_FLASH_INFO_END,
 
+    /** android.hotPixel.mode [dynamic, enum, public]
+     *
+     * <p>Operational mode for hot pixel correction.</p>
+     */
     ANDROID_HOT_PIXEL_MODE = CameraMetadataSectionStart:ANDROID_HOT_PIXEL_START,
 
+    /** android.hotPixel.availableHotPixelModes [static, byte[], public]
+     *
+     * <p>List of hot pixel correction modes for ANDROID_HOT_PIXEL_MODE that are supported by this
+     * camera device.</p>
+     *
+     * @see ANDROID_HOT_PIXEL_MODE
+     */
     ANDROID_HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES,
 
     ANDROID_HOT_PIXEL_END,
 
+    /** android.jpeg.gpsCoordinates [dynamic, double[], ndk_public]
+     *
+     * <p>GPS coordinates to include in output JPEG
+     * EXIF.</p>
+     */
     ANDROID_JPEG_GPS_COORDINATES = CameraMetadataSectionStart:ANDROID_JPEG_START,
 
+    /** android.jpeg.gpsProcessingMethod [dynamic, byte, ndk_public]
+     *
+     * <p>32 characters describing GPS algorithm to
+     * include in EXIF.</p>
+     */
     ANDROID_JPEG_GPS_PROCESSING_METHOD,
 
+    /** android.jpeg.gpsTimestamp [dynamic, int64, ndk_public]
+     *
+     * <p>Time GPS fix was made to include in
+     * EXIF.</p>
+     */
     ANDROID_JPEG_GPS_TIMESTAMP,
 
+    /** android.jpeg.orientation [dynamic, int32, public]
+     *
+     * <p>The orientation for a JPEG image.</p>
+     */
     ANDROID_JPEG_ORIENTATION,
 
+    /** android.jpeg.quality [dynamic, byte, public]
+     *
+     * <p>Compression quality of the final JPEG
+     * image.</p>
+     */
     ANDROID_JPEG_QUALITY,
 
+    /** android.jpeg.thumbnailQuality [dynamic, byte, public]
+     *
+     * <p>Compression quality of JPEG
+     * thumbnail.</p>
+     */
     ANDROID_JPEG_THUMBNAIL_QUALITY,
 
+    /** android.jpeg.thumbnailSize [dynamic, int32[], public]
+     *
+     * <p>Resolution of embedded JPEG thumbnail.</p>
+     */
     ANDROID_JPEG_THUMBNAIL_SIZE,
 
+    /** android.jpeg.availableThumbnailSizes [static, int32[], public]
+     *
+     * <p>List of JPEG thumbnail sizes for ANDROID_JPEG_THUMBNAIL_SIZE supported by this
+     * camera device.</p>
+     *
+     * @see ANDROID_JPEG_THUMBNAIL_SIZE
+     */
     ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES,
 
+    /** android.jpeg.maxSize [static, int32, system]
+     *
+     * <p>Maximum size in bytes for the compressed
+     * JPEG buffer</p>
+     */
     ANDROID_JPEG_MAX_SIZE,
 
+    /** android.jpeg.size [dynamic, int32, system]
+     *
+     * <p>The size of the compressed JPEG image, in
+     * bytes</p>
+     */
     ANDROID_JPEG_SIZE,
 
     ANDROID_JPEG_END,
 
+    /** android.lens.aperture [dynamic, float, public]
+     *
+     * <p>The desired lens aperture size, as a ratio of lens focal length to the
+     * effective aperture diameter.</p>
+     */
     ANDROID_LENS_APERTURE = CameraMetadataSectionStart:ANDROID_LENS_START,
 
+    /** android.lens.filterDensity [dynamic, float, public]
+     *
+     * <p>The desired setting for the lens neutral density filter(s).</p>
+     */
     ANDROID_LENS_FILTER_DENSITY,
 
+    /** android.lens.focalLength [dynamic, float, public]
+     *
+     * <p>The desired lens focal length; used for optical zoom.</p>
+     */
     ANDROID_LENS_FOCAL_LENGTH,
 
+    /** android.lens.focusDistance [dynamic, float, public]
+     *
+     * <p>Desired distance to plane of sharpest focus,
+     * measured from frontmost surface of the lens.</p>
+     */
     ANDROID_LENS_FOCUS_DISTANCE,
 
+    /** android.lens.opticalStabilizationMode [dynamic, enum, public]
+     *
+     * <p>Sets whether the camera device uses optical image stabilization (OIS)
+     * when capturing images.</p>
+     */
     ANDROID_LENS_OPTICAL_STABILIZATION_MODE,
 
+    /** android.lens.facing [static, enum, public]
+     *
+     * <p>Direction the camera faces relative to
+     * device screen.</p>
+     */
     ANDROID_LENS_FACING,
 
+    /** android.lens.poseRotation [dynamic, float[], public]
+     *
+     * <p>The orientation of the camera relative to the sensor
+     * coordinate system.</p>
+     */
     ANDROID_LENS_POSE_ROTATION,
 
+    /** android.lens.poseTranslation [dynamic, float[], public]
+     *
+     * <p>Position of the camera optical center.</p>
+     */
     ANDROID_LENS_POSE_TRANSLATION,
 
+    /** android.lens.focusRange [dynamic, float[], public]
+     *
+     * <p>The range of scene distances that are in
+     * sharp focus (depth of field).</p>
+     */
     ANDROID_LENS_FOCUS_RANGE,
 
+    /** android.lens.state [dynamic, enum, public]
+     *
+     * <p>Current lens status.</p>
+     */
     ANDROID_LENS_STATE,
 
+    /** android.lens.intrinsicCalibration [dynamic, float[], public]
+     *
+     * <p>The parameters for this camera device's intrinsic
+     * calibration.</p>
+     */
     ANDROID_LENS_INTRINSIC_CALIBRATION,
 
+    /** android.lens.radialDistortion [dynamic, float[], public]
+     *
+     * <p>The correction coefficients to correct for this camera device's
+     * radial and tangential lens distortion.</p>
+     */
     ANDROID_LENS_RADIAL_DISTORTION,
 
     ANDROID_LENS_END,
 
+    /** android.lens.info.availableApertures [static, float[], public]
+     *
+     * <p>List of aperture size values for ANDROID_LENS_APERTURE that are
+     * supported by this camera device.</p>
+     *
+     * @see ANDROID_LENS_APERTURE
+     */
     ANDROID_LENS_INFO_AVAILABLE_APERTURES = CameraMetadataSectionStart:ANDROID_LENS_INFO_START,
 
+    /** android.lens.info.availableFilterDensities [static, float[], public]
+     *
+     * <p>List of neutral density filter values for
+     * ANDROID_LENS_FILTER_DENSITY that are supported by this camera device.</p>
+     *
+     * @see ANDROID_LENS_FILTER_DENSITY
+     */
     ANDROID_LENS_INFO_AVAILABLE_FILTER_DENSITIES,
 
+    /** android.lens.info.availableFocalLengths [static, float[], public]
+     *
+     * <p>List of focal lengths for ANDROID_LENS_FOCAL_LENGTH that are supported by this camera
+     * device.</p>
+     *
+     * @see ANDROID_LENS_FOCAL_LENGTH
+     */
     ANDROID_LENS_INFO_AVAILABLE_FOCAL_LENGTHS,
 
+    /** android.lens.info.availableOpticalStabilization [static, byte[], public]
+     *
+     * <p>List of optical image stabilization (OIS) modes for
+     * ANDROID_LENS_OPTICAL_STABILIZATION_MODE that are supported by this camera device.</p>
+     *
+     * @see ANDROID_LENS_OPTICAL_STABILIZATION_MODE
+     */
     ANDROID_LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION,
 
+    /** android.lens.info.hyperfocalDistance [static, float, public]
+     *
+     * <p>Hyperfocal distance for this lens.</p>
+     */
     ANDROID_LENS_INFO_HYPERFOCAL_DISTANCE,
 
+    /** android.lens.info.minimumFocusDistance [static, float, public]
+     *
+     * <p>Shortest distance from frontmost surface
+     * of the lens that can be brought into sharp focus.</p>
+     */
     ANDROID_LENS_INFO_MINIMUM_FOCUS_DISTANCE,
 
+    /** android.lens.info.shadingMapSize [static, int32[], ndk_public]
+     *
+     * <p>Dimensions of lens shading map.</p>
+     */
     ANDROID_LENS_INFO_SHADING_MAP_SIZE,
 
+    /** android.lens.info.focusDistanceCalibration [static, enum, public]
+     *
+     * <p>The lens focus distance calibration quality.</p>
+     */
     ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION,
 
     ANDROID_LENS_INFO_END,
 
+    /** android.noiseReduction.mode [dynamic, enum, public]
+     *
+     * <p>Mode of operation for the noise reduction algorithm.</p>
+     */
     ANDROID_NOISE_REDUCTION_MODE = CameraMetadataSectionStart:ANDROID_NOISE_REDUCTION_START,
 
+    /** android.noiseReduction.strength [controls, byte, system]
+     *
+     * <p>Control the amount of noise reduction
+     * applied to the images</p>
+     */
     ANDROID_NOISE_REDUCTION_STRENGTH,
 
+    /** android.noiseReduction.availableNoiseReductionModes [static, byte[], public]
+     *
+     * <p>List of noise reduction modes for ANDROID_NOISE_REDUCTION_MODE that are supported
+     * by this camera device.</p>
+     *
+     * @see ANDROID_NOISE_REDUCTION_MODE
+     */
     ANDROID_NOISE_REDUCTION_AVAILABLE_NOISE_REDUCTION_MODES,
 
     ANDROID_NOISE_REDUCTION_END,
 
+    /** android.quirks.meteringCropRegion [static, byte, system]
+     *
+     * <p>If set to 1, the camera service does not
+     * scale 'normalized' coordinates with respect to the crop
+     * region. This applies to metering input (a{e,f,wb}Region
+     * and output (face rectangles).</p>
+     */
     ANDROID_QUIRKS_METERING_CROP_REGION = CameraMetadataSectionStart:ANDROID_QUIRKS_START,
 
+    /** android.quirks.triggerAfWithAuto [static, byte, system]
+     *
+     * <p>If set to 1, then the camera service always
+     * switches to FOCUS_MODE_AUTO before issuing a AF
+     * trigger.</p>
+     */
     ANDROID_QUIRKS_TRIGGER_AF_WITH_AUTO,
 
+    /** android.quirks.useZslFormat [static, byte, system]
+     *
+     * <p>If set to 1, the camera service uses
+     * CAMERA2_PIXEL_FORMAT_ZSL instead of
+     * HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED for the zero
+     * shutter lag stream</p>
+     */
     ANDROID_QUIRKS_USE_ZSL_FORMAT,
 
+    /** android.quirks.usePartialResult [static, byte, hidden]
+     *
+     * <p>If set to 1, the HAL will always split result
+     * metadata for a single capture into multiple buffers,
+     * returned using multiple process_capture_result calls.</p>
+     */
     ANDROID_QUIRKS_USE_PARTIAL_RESULT,
 
+    /** android.quirks.partialResult [dynamic, enum, hidden]
+     *
+     * <p>Whether a result given to the framework is the
+     * final one for the capture, or only a partial that contains a
+     * subset of the full set of dynamic metadata
+     * values.</p>
+     */
     ANDROID_QUIRKS_PARTIAL_RESULT,
 
     ANDROID_QUIRKS_END,
 
+    /** android.request.frameCount [dynamic, int32, hidden]
+     *
+     * <p>A frame counter set by the framework. This value monotonically
+     * increases with every new result (that is, each new result has a unique
+     * frameCount value).</p>
+     */
     ANDROID_REQUEST_FRAME_COUNT = CameraMetadataSectionStart:ANDROID_REQUEST_START,
 
+    /** android.request.id [dynamic, int32, hidden]
+     *
+     * <p>An application-specified ID for the current
+     * request. Must be maintained unchanged in output
+     * frame</p>
+     */
     ANDROID_REQUEST_ID,
 
+    /** android.request.inputStreams [controls, int32[], system]
+     *
+     * <p>List which camera reprocess stream is used
+     * for the source of reprocessing data.</p>
+     */
     ANDROID_REQUEST_INPUT_STREAMS,
 
+    /** android.request.metadataMode [dynamic, enum, system]
+     *
+     * <p>How much metadata to produce on
+     * output</p>
+     */
     ANDROID_REQUEST_METADATA_MODE,
 
+    /** android.request.outputStreams [dynamic, int32[], system]
+     *
+     * <p>Lists which camera output streams image data
+     * from this capture must be sent to</p>
+     */
     ANDROID_REQUEST_OUTPUT_STREAMS,
 
+    /** android.request.type [controls, enum, system]
+     *
+     * <p>The type of the request; either CAPTURE or
+     * REPROCESS. For legacy HAL3, this tag is redundant.</p>
+     */
     ANDROID_REQUEST_TYPE,
 
+    /** android.request.maxNumOutputStreams [static, int32[], ndk_public]
+     *
+     * <p>The maximum numbers of different types of output streams
+     * that can be configured and used simultaneously by a camera device.</p>
+     */
     ANDROID_REQUEST_MAX_NUM_OUTPUT_STREAMS,
 
+    /** android.request.maxNumReprocessStreams [static, int32[], system]
+     *
+     * <p>How many reprocessing streams of any type
+     * can be allocated at the same time.</p>
+     */
     ANDROID_REQUEST_MAX_NUM_REPROCESS_STREAMS,
 
+    /** android.request.maxNumInputStreams [static, int32, java_public]
+     *
+     * <p>The maximum numbers of any type of input streams
+     * that can be configured and used simultaneously by a camera device.</p>
+     */
     ANDROID_REQUEST_MAX_NUM_INPUT_STREAMS,
 
+    /** android.request.pipelineDepth [dynamic, byte, public]
+     *
+     * <p>Specifies the number of pipeline stages the frame went
+     * through from when it was exposed to when the final completed result
+     * was available to the framework.</p>
+     */
     ANDROID_REQUEST_PIPELINE_DEPTH,
 
+    /** android.request.pipelineMaxDepth [static, byte, public]
+     *
+     * <p>Specifies the number of maximum pipeline stages a frame
+     * has to go through from when it's exposed to when it's available
+     * to the framework.</p>
+     */
     ANDROID_REQUEST_PIPELINE_MAX_DEPTH,
 
+    /** android.request.partialResultCount [static, int32, public]
+     *
+     * <p>Defines how many sub-components
+     * a result will be composed of.</p>
+     */
     ANDROID_REQUEST_PARTIAL_RESULT_COUNT,
 
+    /** android.request.availableCapabilities [static, enum[], public]
+     *
+     * <p>List of capabilities that this camera device
+     * advertises as fully supporting.</p>
+     */
     ANDROID_REQUEST_AVAILABLE_CAPABILITIES,
 
+    /** android.request.availableRequestKeys [static, int32[], ndk_public]
+     *
+     * <p>A list of all keys that the camera device has available
+     * to use with {@link ACaptureRequest }.</p>
+     */
     ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS,
 
+    /** android.request.availableResultKeys [static, int32[], ndk_public]
+     *
+     * <p>A list of all keys that the camera device has available to use with {@link ACameraCaptureSession_captureCallback_result }.</p>
+     */
     ANDROID_REQUEST_AVAILABLE_RESULT_KEYS,
 
+    /** android.request.availableCharacteristicsKeys [static, int32[], ndk_public]
+     *
+     * <p>A list of all keys that the camera device has available to use with {@link ACameraManager_getCameraCharacteristics }.</p>
+     */
     ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS,
 
     ANDROID_REQUEST_END,
 
+    /** android.scaler.cropRegion [dynamic, int32[], public]
+     *
+     * <p>The desired region of the sensor to read out for this capture.</p>
+     */
     ANDROID_SCALER_CROP_REGION = CameraMetadataSectionStart:ANDROID_SCALER_START,
 
+    /** android.scaler.availableFormats [static, enum[], hidden]
+     *
+     * <p>The list of image formats that are supported by this
+     * camera device for output streams.</p>
+     */
     ANDROID_SCALER_AVAILABLE_FORMATS,
 
+    /** android.scaler.availableJpegMinDurations [static, int64[], hidden]
+     *
+     * <p>The minimum frame duration that is supported
+     * for each resolution in ANDROID_SCALER_AVAILABLE_JPEG_SIZES.</p>
+     *
+     * @see ANDROID_SCALER_AVAILABLE_JPEG_SIZES
+     */
     ANDROID_SCALER_AVAILABLE_JPEG_MIN_DURATIONS,
 
+    /** android.scaler.availableJpegSizes [static, int32[], hidden]
+     *
+     * <p>The JPEG resolutions that are supported by this camera device.</p>
+     */
     ANDROID_SCALER_AVAILABLE_JPEG_SIZES,
 
+    /** android.scaler.availableMaxDigitalZoom [static, float, public]
+     *
+     * <p>The maximum ratio between both active area width
+     * and crop region width, and active area height and
+     * crop region height, for ANDROID_SCALER_CROP_REGION.</p>
+     *
+     * @see ANDROID_SCALER_CROP_REGION
+     */
     ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM,
 
+    /** android.scaler.availableProcessedMinDurations [static, int64[], hidden]
+     *
+     * <p>For each available processed output size (defined in
+     * ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES), this property lists the
+     * minimum supportable frame duration for that size.</p>
+     *
+     * @see ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES
+     */
     ANDROID_SCALER_AVAILABLE_PROCESSED_MIN_DURATIONS,
 
+    /** android.scaler.availableProcessedSizes [static, int32[], hidden]
+     *
+     * <p>The resolutions available for use with
+     * processed output streams, such as YV12, NV12, and
+     * platform opaque YUV/RGB streams to the GPU or video
+     * encoders.</p>
+     */
     ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES,
 
+    /** android.scaler.availableRawMinDurations [static, int64[], system]
+     *
+     * <p>For each available raw output size (defined in
+     * ANDROID_SCALER_AVAILABLE_RAW_SIZES), this property lists the minimum
+     * supportable frame duration for that size.</p>
+     *
+     * @see ANDROID_SCALER_AVAILABLE_RAW_SIZES
+     */
     ANDROID_SCALER_AVAILABLE_RAW_MIN_DURATIONS,
 
+    /** android.scaler.availableRawSizes [static, int32[], system]
+     *
+     * <p>The resolutions available for use with raw
+     * sensor output streams, listed as width,
+     * height</p>
+     */
     ANDROID_SCALER_AVAILABLE_RAW_SIZES,
 
+    /** android.scaler.availableInputOutputFormatsMap [static, int32, hidden]
+     *
+     * <p>The mapping of image formats that are supported by this
+     * camera device for input streams, to their corresponding output formats.</p>
+     */
     ANDROID_SCALER_AVAILABLE_INPUT_OUTPUT_FORMATS_MAP,
 
+    /** android.scaler.availableStreamConfigurations [static, enum[], ndk_public]
+     *
+     * <p>The available stream configurations that this
+     * camera device supports
+     * (i.e. format, width, height, output/input stream).</p>
+     */
     ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS,
 
+    /** android.scaler.availableMinFrameDurations [static, int64[], ndk_public]
+     *
+     * <p>This lists the minimum frame duration for each
+     * format/size combination.</p>
+     */
     ANDROID_SCALER_AVAILABLE_MIN_FRAME_DURATIONS,
 
+    /** android.scaler.availableStallDurations [static, int64[], ndk_public]
+     *
+     * <p>This lists the maximum stall duration for each
+     * output format/size combination.</p>
+     */
     ANDROID_SCALER_AVAILABLE_STALL_DURATIONS,
 
+    /** android.scaler.croppingType [static, enum, public]
+     *
+     * <p>The crop type that this camera device supports.</p>
+     */
     ANDROID_SCALER_CROPPING_TYPE,
 
     ANDROID_SCALER_END,
 
+    /** android.sensor.exposureTime [dynamic, int64, public]
+     *
+     * <p>Duration each pixel is exposed to
+     * light.</p>
+     */
     ANDROID_SENSOR_EXPOSURE_TIME = CameraMetadataSectionStart:ANDROID_SENSOR_START,
 
+    /** android.sensor.frameDuration [dynamic, int64, public]
+     *
+     * <p>Duration from start of frame exposure to
+     * start of next frame exposure.</p>
+     */
     ANDROID_SENSOR_FRAME_DURATION,
 
+    /** android.sensor.sensitivity [dynamic, int32, public]
+     *
+     * <p>The amount of gain applied to sensor data
+     * before processing.</p>
+     */
     ANDROID_SENSOR_SENSITIVITY,
 
+    /** android.sensor.referenceIlluminant1 [static, enum, public]
+     *
+     * <p>The standard reference illuminant used as the scene light source when
+     * calculating the ANDROID_SENSOR_COLOR_TRANSFORM1,
+     * ANDROID_SENSOR_CALIBRATION_TRANSFORM1, and
+     * ANDROID_SENSOR_FORWARD_MATRIX1 matrices.</p>
+     *
+     * @see ANDROID_SENSOR_CALIBRATION_TRANSFORM1
+     * @see ANDROID_SENSOR_COLOR_TRANSFORM1
+     * @see ANDROID_SENSOR_FORWARD_MATRIX1
+     */
     ANDROID_SENSOR_REFERENCE_ILLUMINANT1,
 
+    /** android.sensor.referenceIlluminant2 [static, byte, public]
+     *
+     * <p>The standard reference illuminant used as the scene light source when
+     * calculating the ANDROID_SENSOR_COLOR_TRANSFORM2,
+     * ANDROID_SENSOR_CALIBRATION_TRANSFORM2, and
+     * ANDROID_SENSOR_FORWARD_MATRIX2 matrices.</p>
+     *
+     * @see ANDROID_SENSOR_CALIBRATION_TRANSFORM2
+     * @see ANDROID_SENSOR_COLOR_TRANSFORM2
+     * @see ANDROID_SENSOR_FORWARD_MATRIX2
+     */
     ANDROID_SENSOR_REFERENCE_ILLUMINANT2,
 
+    /** android.sensor.calibrationTransform1 [static, rational[], public]
+     *
+     * <p>A per-device calibration transform matrix that maps from the
+     * reference sensor colorspace to the actual device sensor colorspace.</p>
+     */
     ANDROID_SENSOR_CALIBRATION_TRANSFORM1,
 
+    /** android.sensor.calibrationTransform2 [static, rational[], public]
+     *
+     * <p>A per-device calibration transform matrix that maps from the
+     * reference sensor colorspace to the actual device sensor colorspace
+     * (this is the colorspace of the raw buffer data).</p>
+     */
     ANDROID_SENSOR_CALIBRATION_TRANSFORM2,
 
+    /** android.sensor.colorTransform1 [static, rational[], public]
+     *
+     * <p>A matrix that transforms color values from CIE XYZ color space to
+     * reference sensor color space.</p>
+     */
     ANDROID_SENSOR_COLOR_TRANSFORM1,
 
+    /** android.sensor.colorTransform2 [static, rational[], public]
+     *
+     * <p>A matrix that transforms color values from CIE XYZ color space to
+     * reference sensor color space.</p>
+     */
     ANDROID_SENSOR_COLOR_TRANSFORM2,
 
+    /** android.sensor.forwardMatrix1 [static, rational[], public]
+     *
+     * <p>A matrix that transforms white balanced camera colors from the reference
+     * sensor colorspace to the CIE XYZ colorspace with a D50 whitepoint.</p>
+     */
     ANDROID_SENSOR_FORWARD_MATRIX1,
 
+    /** android.sensor.forwardMatrix2 [static, rational[], public]
+     *
+     * <p>A matrix that transforms white balanced camera colors from the reference
+     * sensor colorspace to the CIE XYZ colorspace with a D50 whitepoint.</p>
+     */
     ANDROID_SENSOR_FORWARD_MATRIX2,
 
+    /** android.sensor.baseGainFactor [static, rational, system]
+     *
+     * <p>Gain factor from electrons to raw units when
+     * ISO=100</p>
+     */
     ANDROID_SENSOR_BASE_GAIN_FACTOR,
 
+    /** android.sensor.blackLevelPattern [static, int32[], public]
+     *
+     * <p>A fixed black level offset for each of the color filter arrangement
+     * (CFA) mosaic channels.</p>
+     */
     ANDROID_SENSOR_BLACK_LEVEL_PATTERN,
 
+    /** android.sensor.maxAnalogSensitivity [static, int32, public]
+     *
+     * <p>Maximum sensitivity that is implemented
+     * purely through analog gain.</p>
+     */
     ANDROID_SENSOR_MAX_ANALOG_SENSITIVITY,
 
+    /** android.sensor.orientation [static, int32, public]
+     *
+     * <p>Clockwise angle through which the output image needs to be rotated to be
+     * upright on the device screen in its native orientation.</p>
+     */
     ANDROID_SENSOR_ORIENTATION,
 
+    /** android.sensor.profileHueSatMapDimensions [static, int32[], system]
+     *
+     * <p>The number of input samples for each dimension of
+     * ANDROID_SENSOR_PROFILE_HUE_SAT_MAP.</p>
+     *
+     * @see ANDROID_SENSOR_PROFILE_HUE_SAT_MAP
+     */
     ANDROID_SENSOR_PROFILE_HUE_SAT_MAP_DIMENSIONS,
 
+    /** android.sensor.timestamp [dynamic, int64, public]
+     *
+     * <p>Time at start of exposure of first
+     * row of the image sensor active array, in nanoseconds.</p>
+     */
     ANDROID_SENSOR_TIMESTAMP,
 
+    /** android.sensor.temperature [dynamic, float, system]
+     *
+     * <p>The temperature of the sensor, sampled at the time
+     * exposure began for this frame.</p>
+     * <p>The thermal diode being queried should be inside the sensor PCB, or
+     * somewhere close to it.</p>
+     */
     ANDROID_SENSOR_TEMPERATURE,
 
+    /** android.sensor.neutralColorPoint [dynamic, rational[], public]
+     *
+     * <p>The estimated camera neutral color in the native sensor colorspace at
+     * the time of capture.</p>
+     */
     ANDROID_SENSOR_NEUTRAL_COLOR_POINT,
 
+    /** android.sensor.noiseProfile [dynamic, double[], public]
+     *
+     * <p>Noise model coefficients for each CFA mosaic channel.</p>
+     */
     ANDROID_SENSOR_NOISE_PROFILE,
 
+    /** android.sensor.profileHueSatMap [dynamic, float[], system]
+     *
+     * <p>A mapping containing a hue shift, saturation scale, and value scale
+     * for each pixel.</p>
+     */
     ANDROID_SENSOR_PROFILE_HUE_SAT_MAP,
 
+    /** android.sensor.profileToneCurve [dynamic, float[], system]
+     *
+     * <p>A list of x,y samples defining a tone-mapping curve for gamma adjustment.</p>
+     */
     ANDROID_SENSOR_PROFILE_TONE_CURVE,
 
+    /** android.sensor.greenSplit [dynamic, float, public]
+     *
+     * <p>The worst-case divergence between Bayer green channels.</p>
+     */
     ANDROID_SENSOR_GREEN_SPLIT,
 
+    /** android.sensor.testPatternData [dynamic, int32[], public]
+     *
+     * <p>A pixel <code>[R, G_even, G_odd, B]</code> that supplies the test pattern
+     * when ANDROID_SENSOR_TEST_PATTERN_MODE is SOLID_COLOR.</p>
+     *
+     * @see ANDROID_SENSOR_TEST_PATTERN_MODE
+     */
     ANDROID_SENSOR_TEST_PATTERN_DATA,
 
+    /** android.sensor.testPatternMode [dynamic, enum, public]
+     *
+     * <p>When enabled, the sensor sends a test pattern instead of
+     * doing a real exposure from the camera.</p>
+     */
     ANDROID_SENSOR_TEST_PATTERN_MODE,
 
+    /** android.sensor.availableTestPatternModes [static, int32[], public]
+     *
+     * <p>List of sensor test pattern modes for ANDROID_SENSOR_TEST_PATTERN_MODE
+     * supported by this camera device.</p>
+     *
+     * @see ANDROID_SENSOR_TEST_PATTERN_MODE
+     */
     ANDROID_SENSOR_AVAILABLE_TEST_PATTERN_MODES,
 
+    /** android.sensor.rollingShutterSkew [dynamic, int64, public]
+     *
+     * <p>Duration between the start of first row exposure
+     * and the start of last row exposure.</p>
+     */
     ANDROID_SENSOR_ROLLING_SHUTTER_SKEW,
 
+    /** android.sensor.opticalBlackRegions [static, int32[], public]
+     *
+     * <p>List of disjoint rectangles indicating the sensor
+     * optically shielded black pixel regions.</p>
+     */
     ANDROID_SENSOR_OPTICAL_BLACK_REGIONS,
 
+    /** android.sensor.dynamicBlackLevel [dynamic, float[], public]
+     *
+     * <p>A per-frame dynamic black level offset for each of the color filter
+     * arrangement (CFA) mosaic channels.</p>
+     */
     ANDROID_SENSOR_DYNAMIC_BLACK_LEVEL,
 
+    /** android.sensor.dynamicWhiteLevel [dynamic, int32, public]
+     *
+     * <p>Maximum raw value output by sensor for this frame.</p>
+     */
     ANDROID_SENSOR_DYNAMIC_WHITE_LEVEL,
 
+    /** android.sensor.opaqueRawSize [static, int32[], system]
+     *
+     * <p>Size in bytes for all the listed opaque RAW buffer sizes</p>
+     */
     ANDROID_SENSOR_OPAQUE_RAW_SIZE,
 
     ANDROID_SENSOR_END,
 
+    /** android.sensor.info.activeArraySize [static, int32[], public]
+     *
+     * <p>The area of the image sensor which corresponds to active pixels after any geometric
+     * distortion correction has been applied.</p>
+     */
     ANDROID_SENSOR_INFO_ACTIVE_ARRAY_SIZE = CameraMetadataSectionStart:ANDROID_SENSOR_INFO_START,
 
+    /** android.sensor.info.sensitivityRange [static, int32[], public]
+     *
+     * <p>Range of sensitivities for ANDROID_SENSOR_SENSITIVITY supported by this
+     * camera device.</p>
+     *
+     * @see ANDROID_SENSOR_SENSITIVITY
+     */
     ANDROID_SENSOR_INFO_SENSITIVITY_RANGE,
 
+    /** android.sensor.info.colorFilterArrangement [static, enum, public]
+     *
+     * <p>The arrangement of color filters on sensor;
+     * represents the colors in the top-left 2x2 section of
+     * the sensor, in reading order.</p>
+     */
     ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT,
 
+    /** android.sensor.info.exposureTimeRange [static, int64[], public]
+     *
+     * <p>The range of image exposure times for ANDROID_SENSOR_EXPOSURE_TIME supported
+     * by this camera device.</p>
+     *
+     * @see ANDROID_SENSOR_EXPOSURE_TIME
+     */
     ANDROID_SENSOR_INFO_EXPOSURE_TIME_RANGE,
 
+    /** android.sensor.info.maxFrameDuration [static, int64, public]
+     *
+     * <p>The maximum possible frame duration (minimum frame rate) for
+     * ANDROID_SENSOR_FRAME_DURATION that is supported this camera device.</p>
+     *
+     * @see ANDROID_SENSOR_FRAME_DURATION
+     */
     ANDROID_SENSOR_INFO_MAX_FRAME_DURATION,
 
+    /** android.sensor.info.physicalSize [static, float[], public]
+     *
+     * <p>The physical dimensions of the full pixel
+     * array.</p>
+     */
     ANDROID_SENSOR_INFO_PHYSICAL_SIZE,
 
+    /** android.sensor.info.pixelArraySize [static, int32[], public]
+     *
+     * <p>Dimensions of the full pixel array, possibly
+     * including black calibration pixels.</p>
+     */
     ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE,
 
+    /** android.sensor.info.whiteLevel [static, int32, public]
+     *
+     * <p>Maximum raw value output by sensor.</p>
+     */
     ANDROID_SENSOR_INFO_WHITE_LEVEL,
 
+    /** android.sensor.info.timestampSource [static, enum, public]
+     *
+     * <p>The time base source for sensor capture start timestamps.</p>
+     */
     ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE,
 
+    /** android.sensor.info.lensShadingApplied [static, enum, public]
+     *
+     * <p>Whether the RAW images output from this camera device are subject to
+     * lens shading correction.</p>
+     */
     ANDROID_SENSOR_INFO_LENS_SHADING_APPLIED,
 
+    /** android.sensor.info.preCorrectionActiveArraySize [static, int32[], public]
+     *
+     * <p>The area of the image sensor which corresponds to active pixels prior to the
+     * application of any geometric distortion correction.</p>
+     */
     ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE,
 
     ANDROID_SENSOR_INFO_END,
 
+    /** android.shading.mode [dynamic, enum, public]
+     *
+     * <p>Quality of lens shading correction applied
+     * to the image data.</p>
+     */
     ANDROID_SHADING_MODE = CameraMetadataSectionStart:ANDROID_SHADING_START,
 
+    /** android.shading.strength [controls, byte, system]
+     *
+     * <p>Control the amount of shading correction
+     * applied to the images</p>
+     */
     ANDROID_SHADING_STRENGTH,
 
+    /** android.shading.availableModes [static, byte[], public]
+     *
+     * <p>List of lens shading modes for ANDROID_SHADING_MODE that are supported by this camera device.</p>
+     *
+     * @see ANDROID_SHADING_MODE
+     */
     ANDROID_SHADING_AVAILABLE_MODES,
 
     ANDROID_SHADING_END,
 
+    /** android.statistics.faceDetectMode [dynamic, enum, public]
+     *
+     * <p>Operating mode for the face detector
+     * unit.</p>
+     */
     ANDROID_STATISTICS_FACE_DETECT_MODE = CameraMetadataSectionStart:ANDROID_STATISTICS_START,
 
+    /** android.statistics.histogramMode [dynamic, enum, system]
+     *
+     * <p>Operating mode for histogram
+     * generation</p>
+     */
     ANDROID_STATISTICS_HISTOGRAM_MODE,
 
+    /** android.statistics.sharpnessMapMode [dynamic, enum, system]
+     *
+     * <p>Operating mode for sharpness map
+     * generation</p>
+     */
     ANDROID_STATISTICS_SHARPNESS_MAP_MODE,
 
+    /** android.statistics.hotPixelMapMode [dynamic, enum, public]
+     *
+     * <p>Operating mode for hot pixel map generation.</p>
+     */
     ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE,
 
+    /** android.statistics.faceIds [dynamic, int32[], ndk_public]
+     *
+     * <p>List of unique IDs for detected faces.</p>
+     */
     ANDROID_STATISTICS_FACE_IDS,
 
+    /** android.statistics.faceLandmarks [dynamic, int32[], ndk_public]
+     *
+     * <p>List of landmarks for detected
+     * faces.</p>
+     */
     ANDROID_STATISTICS_FACE_LANDMARKS,
 
+    /** android.statistics.faceRectangles [dynamic, int32[], ndk_public]
+     *
+     * <p>List of the bounding rectangles for detected
+     * faces.</p>
+     */
     ANDROID_STATISTICS_FACE_RECTANGLES,
 
+    /** android.statistics.faceScores [dynamic, byte[], ndk_public]
+     *
+     * <p>List of the face confidence scores for
+     * detected faces</p>
+     */
     ANDROID_STATISTICS_FACE_SCORES,
 
+    /** android.statistics.histogram [dynamic, int32[], system]
+     *
+     * <p>A 3-channel histogram based on the raw
+     * sensor data</p>
+     */
     ANDROID_STATISTICS_HISTOGRAM,
 
+    /** android.statistics.sharpnessMap [dynamic, int32[], system]
+     *
+     * <p>A 3-channel sharpness map, based on the raw
+     * sensor data</p>
+     */
     ANDROID_STATISTICS_SHARPNESS_MAP,
 
+    /** android.statistics.lensShadingCorrectionMap [dynamic, byte, java_public]
+     *
+     * <p>The shading map is a low-resolution floating-point map
+     * that lists the coefficients used to correct for vignetting, for each
+     * Bayer color channel.</p>
+     */
     ANDROID_STATISTICS_LENS_SHADING_CORRECTION_MAP,
 
+    /** android.statistics.lensShadingMap [dynamic, float[], ndk_public]
+     *
+     * <p>The shading map is a low-resolution floating-point map
+     * that lists the coefficients used to correct for vignetting and color shading,
+     * for each Bayer color channel of RAW image data.</p>
+     */
     ANDROID_STATISTICS_LENS_SHADING_MAP,
 
+    /** android.statistics.predictedColorGains [dynamic, float[], hidden]
+     *
+     * <p>The best-fit color channel gains calculated
+     * by the camera device's statistics units for the current output frame.</p>
+     */
     ANDROID_STATISTICS_PREDICTED_COLOR_GAINS,
 
+    /** android.statistics.predictedColorTransform [dynamic, rational[], hidden]
+     *
+     * <p>The best-fit color transform matrix estimate
+     * calculated by the camera device's statistics units for the current
+     * output frame.</p>
+     */
     ANDROID_STATISTICS_PREDICTED_COLOR_TRANSFORM,
 
+    /** android.statistics.sceneFlicker [dynamic, enum, public]
+     *
+     * <p>The camera device estimated scene illumination lighting
+     * frequency.</p>
+     */
     ANDROID_STATISTICS_SCENE_FLICKER,
 
+    /** android.statistics.hotPixelMap [dynamic, int32[], public]
+     *
+     * <p>List of <code>(x, y)</code> coordinates of hot/defective pixels on the sensor.</p>
+     */
     ANDROID_STATISTICS_HOT_PIXEL_MAP,
 
+    /** android.statistics.lensShadingMapMode [dynamic, enum, public]
+     *
+     * <p>Whether the camera device will output the lens
+     * shading map in output result metadata.</p>
+     */
     ANDROID_STATISTICS_LENS_SHADING_MAP_MODE,
 
     ANDROID_STATISTICS_END,
 
-    ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES =
-            CameraMetadataSectionStart:ANDROID_STATISTICS_INFO_START,
+    /** android.statistics.info.availableFaceDetectModes [static, byte[], public]
+     *
+     * <p>List of face detection modes for ANDROID_STATISTICS_FACE_DETECT_MODE that are
+     * supported by this camera device.</p>
+     *
+     * @see ANDROID_STATISTICS_FACE_DETECT_MODE
+     */
+    ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES = CameraMetadataSectionStart:ANDROID_STATISTICS_INFO_START,
 
+    /** android.statistics.info.histogramBucketCount [static, int32, system]
+     *
+     * <p>Number of histogram buckets
+     * supported</p>
+     */
     ANDROID_STATISTICS_INFO_HISTOGRAM_BUCKET_COUNT,
 
+    /** android.statistics.info.maxFaceCount [static, int32, public]
+     *
+     * <p>The maximum number of simultaneously detectable
+     * faces.</p>
+     */
     ANDROID_STATISTICS_INFO_MAX_FACE_COUNT,
 
+    /** android.statistics.info.maxHistogramCount [static, int32, system]
+     *
+     * <p>Maximum value possible for a histogram
+     * bucket</p>
+     */
     ANDROID_STATISTICS_INFO_MAX_HISTOGRAM_COUNT,
 
+    /** android.statistics.info.maxSharpnessMapValue [static, int32, system]
+     *
+     * <p>Maximum value possible for a sharpness map
+     * region.</p>
+     */
     ANDROID_STATISTICS_INFO_MAX_SHARPNESS_MAP_VALUE,
 
+    /** android.statistics.info.sharpnessMapSize [static, int32[], system]
+     *
+     * <p>Dimensions of the sharpness
+     * map</p>
+     */
     ANDROID_STATISTICS_INFO_SHARPNESS_MAP_SIZE,
 
+    /** android.statistics.info.availableHotPixelMapModes [static, byte[], public]
+     *
+     * <p>List of hot pixel map output modes for ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE that are
+     * supported by this camera device.</p>
+     *
+     * @see ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE
+     */
     ANDROID_STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES,
 
+    /** android.statistics.info.availableLensShadingMapModes [static, byte[], public]
+     *
+     * <p>List of lens shading map output modes for ANDROID_STATISTICS_LENS_SHADING_MAP_MODE that
+     * are supported by this camera device.</p>
+     *
+     * @see ANDROID_STATISTICS_LENS_SHADING_MAP_MODE
+     */
     ANDROID_STATISTICS_INFO_AVAILABLE_LENS_SHADING_MAP_MODES,
 
     ANDROID_STATISTICS_INFO_END,
 
+    /** android.tonemap.curveBlue [dynamic, float[], ndk_public]
+     *
+     * <p>Tonemapping / contrast / gamma curve for the blue
+     * channel, to use when ANDROID_TONEMAP_MODE is
+     * CONTRAST_CURVE.</p>
+     *
+     * @see ANDROID_TONEMAP_MODE
+     */
     ANDROID_TONEMAP_CURVE_BLUE = CameraMetadataSectionStart:ANDROID_TONEMAP_START,
 
+    /** android.tonemap.curveGreen [dynamic, float[], ndk_public]
+     *
+     * <p>Tonemapping / contrast / gamma curve for the green
+     * channel, to use when ANDROID_TONEMAP_MODE is
+     * CONTRAST_CURVE.</p>
+     *
+     * @see ANDROID_TONEMAP_MODE
+     */
     ANDROID_TONEMAP_CURVE_GREEN,
 
+    /** android.tonemap.curveRed [dynamic, float[], ndk_public]
+     *
+     * <p>Tonemapping / contrast / gamma curve for the red
+     * channel, to use when ANDROID_TONEMAP_MODE is
+     * CONTRAST_CURVE.</p>
+     *
+     * @see ANDROID_TONEMAP_MODE
+     */
     ANDROID_TONEMAP_CURVE_RED,
 
+    /** android.tonemap.mode [dynamic, enum, public]
+     *
+     * <p>High-level global contrast/gamma/tonemapping control.</p>
+     */
     ANDROID_TONEMAP_MODE,
 
+    /** android.tonemap.maxCurvePoints [static, int32, public]
+     *
+     * <p>Maximum number of supported points in the
+     * tonemap curve that can be used for ANDROID_TONEMAP_CURVE.</p>
+     *
+     * @see ANDROID_TONEMAP_CURVE
+     */
     ANDROID_TONEMAP_MAX_CURVE_POINTS,
 
+    /** android.tonemap.availableToneMapModes [static, byte[], public]
+     *
+     * <p>List of tonemapping modes for ANDROID_TONEMAP_MODE that are supported by this camera
+     * device.</p>
+     *
+     * @see ANDROID_TONEMAP_MODE
+     */
     ANDROID_TONEMAP_AVAILABLE_TONE_MAP_MODES,
 
+    /** android.tonemap.gamma [dynamic, float, public]
+     *
+     * <p>Tonemapping curve to use when ANDROID_TONEMAP_MODE is
+     * GAMMA_VALUE</p>
+     *
+     * @see ANDROID_TONEMAP_MODE
+     */
     ANDROID_TONEMAP_GAMMA,
 
+    /** android.tonemap.presetCurve [dynamic, enum, public]
+     *
+     * <p>Tonemapping curve to use when ANDROID_TONEMAP_MODE is
+     * PRESET_CURVE</p>
+     *
+     * @see ANDROID_TONEMAP_MODE
+     */
     ANDROID_TONEMAP_PRESET_CURVE,
 
     ANDROID_TONEMAP_END,
 
+    /** android.led.transmit [dynamic, enum, hidden]
+     *
+     * <p>This LED is nominally used to indicate to the user
+     * that the camera is powered on and may be streaming images back to the
+     * Application Processor. In certain rare circumstances, the OS may
+     * disable this when video is processed locally and not transmitted to
+     * any untrusted applications.</p>
+     * <p>In particular, the LED <em>must</em> always be on when the data could be
+     * transmitted off the device. The LED <em>should</em> always be on whenever
+     * data is stored locally on the device.</p>
+     * <p>The LED <em>may</em> be off if a trusted application is using the data that
+     * doesn't violate the above rules.</p>
+     */
     ANDROID_LED_TRANSMIT = CameraMetadataSectionStart:ANDROID_LED_START,
 
+    /** android.led.availableLeds [static, enum[], hidden]
+     *
+     * <p>A list of camera LEDs that are available on this system.</p>
+     */
     ANDROID_LED_AVAILABLE_LEDS,
 
     ANDROID_LED_END,
 
+    /** android.info.supportedHardwareLevel [static, enum, public]
+     *
+     * <p>Generally classifies the overall set of the camera device functionality.</p>
+     */
     ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL = CameraMetadataSectionStart:ANDROID_INFO_START,
 
     ANDROID_INFO_END,
 
+    /** android.blackLevel.lock [dynamic, enum, public]
+     *
+     * <p>Whether black-level compensation is locked
+     * to its current values, or is free to vary.</p>
+     */
     ANDROID_BLACK_LEVEL_LOCK = CameraMetadataSectionStart:ANDROID_BLACK_LEVEL_START,
 
     ANDROID_BLACK_LEVEL_END,
 
+    /** android.sync.frameNumber [dynamic, enum, ndk_public]
+     *
+     * <p>The frame number corresponding to the last request
+     * with which the output result (metadata + buffers) has been fully
+     * synchronized.</p>
+     */
     ANDROID_SYNC_FRAME_NUMBER = CameraMetadataSectionStart:ANDROID_SYNC_START,
 
+    /** android.sync.maxLatency [static, enum, public]
+     *
+     * <p>The maximum number of frames that can occur after a request
+     * (different than the previous) has been submitted, and before the
+     * result's state becomes synchronized.</p>
+     */
     ANDROID_SYNC_MAX_LATENCY,
 
     ANDROID_SYNC_END,
 
+    /** android.reprocess.effectiveExposureFactor [dynamic, float, java_public]
+     *
+     * <p>The amount of exposure time increase factor applied to the original output
+     * frame by the application processing before sending for reprocessing.</p>
+     */
     ANDROID_REPROCESS_EFFECTIVE_EXPOSURE_FACTOR = CameraMetadataSectionStart:ANDROID_REPROCESS_START,
 
+    /** android.reprocess.maxCaptureStall [static, int32, java_public]
+     *
+     * <p>The maximal camera capture pipeline stall (in unit of frame count) introduced by a
+     * reprocess capture request.</p>
+     */
     ANDROID_REPROCESS_MAX_CAPTURE_STALL,
 
     ANDROID_REPROCESS_END,
 
+    /** android.depth.maxDepthSamples [static, int32, system]
+     *
+     * <p>Maximum number of points that a depth point cloud may contain.</p>
+     */
     ANDROID_DEPTH_MAX_DEPTH_SAMPLES = CameraMetadataSectionStart:ANDROID_DEPTH_START,
 
+    /** android.depth.availableDepthStreamConfigurations [static, enum[], ndk_public]
+     *
+     * <p>The available depth dataspace stream
+     * configurations that this camera device supports
+     * (i.e. format, width, height, output/input stream).</p>
+     */
     ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS,
 
+    /** android.depth.availableDepthMinFrameDurations [static, int64[], ndk_public]
+     *
+     * <p>This lists the minimum frame duration for each
+     * format/size combination for depth output formats.</p>
+     */
     ANDROID_DEPTH_AVAILABLE_DEPTH_MIN_FRAME_DURATIONS,
 
+    /** android.depth.availableDepthStallDurations [static, int64[], ndk_public]
+     *
+     * <p>This lists the maximum stall duration for each
+     * output format/size combination for depth streams.</p>
+     */
     ANDROID_DEPTH_AVAILABLE_DEPTH_STALL_DURATIONS,
 
+    /** android.depth.depthIsExclusive [static, enum, public]
+     *
+     * <p>Indicates whether a capture request may target both a
+     * DEPTH16 / DEPTH_POINT_CLOUD output, and normal color outputs (such as
+     * YUV_420_888, JPEG, or RAW) simultaneously.</p>
+     */
     ANDROID_DEPTH_DEPTH_IS_EXCLUSIVE,
 
     ANDROID_DEPTH_END,
 
 };
 
-/**
+/*
  * Enumeration definitions for the various entries that need them
  */
+
+/** android.colorCorrection.mode enumeration values
+ * @see ANDROID_COLOR_CORRECTION_MODE
+ */
 enum CameraMetadataEnumAndroidColorCorrectionMode : uint32_t {
     ANDROID_COLOR_CORRECTION_MODE_TRANSFORM_MATRIX,
-
     ANDROID_COLOR_CORRECTION_MODE_FAST,
-
     ANDROID_COLOR_CORRECTION_MODE_HIGH_QUALITY,
-
 };
 
+/** android.colorCorrection.aberrationMode enumeration values
+ * @see ANDROID_COLOR_CORRECTION_ABERRATION_MODE
+ */
 enum CameraMetadataEnumAndroidColorCorrectionAberrationMode : uint32_t {
     ANDROID_COLOR_CORRECTION_ABERRATION_MODE_OFF,
-
     ANDROID_COLOR_CORRECTION_ABERRATION_MODE_FAST,
-
     ANDROID_COLOR_CORRECTION_ABERRATION_MODE_HIGH_QUALITY,
-
 };
 
+/** android.control.aeAntibandingMode enumeration values
+ * @see ANDROID_CONTROL_AE_ANTIBANDING_MODE
+ */
 enum CameraMetadataEnumAndroidControlAeAntibandingMode : uint32_t {
     ANDROID_CONTROL_AE_ANTIBANDING_MODE_OFF,
-
     ANDROID_CONTROL_AE_ANTIBANDING_MODE_50HZ,
-
     ANDROID_CONTROL_AE_ANTIBANDING_MODE_60HZ,
-
     ANDROID_CONTROL_AE_ANTIBANDING_MODE_AUTO,
-
 };
 
+/** android.control.aeLock enumeration values
+ * @see ANDROID_CONTROL_AE_LOCK
+ */
 enum CameraMetadataEnumAndroidControlAeLock : uint32_t {
     ANDROID_CONTROL_AE_LOCK_OFF,
-
     ANDROID_CONTROL_AE_LOCK_ON,
-
 };
 
+/** android.control.aeMode enumeration values
+ * @see ANDROID_CONTROL_AE_MODE
+ */
 enum CameraMetadataEnumAndroidControlAeMode : uint32_t {
     ANDROID_CONTROL_AE_MODE_OFF,
-
     ANDROID_CONTROL_AE_MODE_ON,
-
     ANDROID_CONTROL_AE_MODE_ON_AUTO_FLASH,
-
     ANDROID_CONTROL_AE_MODE_ON_ALWAYS_FLASH,
-
     ANDROID_CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE,
-
 };
 
+/** android.control.aePrecaptureTrigger enumeration values
+ * @see ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER
+ */
 enum CameraMetadataEnumAndroidControlAePrecaptureTrigger : uint32_t {
     ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_IDLE,
-
     ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_START,
-
     ANDROID_CONTROL_AE_PRECAPTURE_TRIGGER_CANCEL,
-
 };
 
+/** android.control.afMode enumeration values
+ * @see ANDROID_CONTROL_AF_MODE
+ */
 enum CameraMetadataEnumAndroidControlAfMode : uint32_t {
     ANDROID_CONTROL_AF_MODE_OFF,
-
     ANDROID_CONTROL_AF_MODE_AUTO,
-
     ANDROID_CONTROL_AF_MODE_MACRO,
-
     ANDROID_CONTROL_AF_MODE_CONTINUOUS_VIDEO,
-
     ANDROID_CONTROL_AF_MODE_CONTINUOUS_PICTURE,
-
     ANDROID_CONTROL_AF_MODE_EDOF,
-
 };
 
+/** android.control.afTrigger enumeration values
+ * @see ANDROID_CONTROL_AF_TRIGGER
+ */
 enum CameraMetadataEnumAndroidControlAfTrigger : uint32_t {
     ANDROID_CONTROL_AF_TRIGGER_IDLE,
-
     ANDROID_CONTROL_AF_TRIGGER_START,
-
     ANDROID_CONTROL_AF_TRIGGER_CANCEL,
-
 };
 
+/** android.control.awbLock enumeration values
+ * @see ANDROID_CONTROL_AWB_LOCK
+ */
 enum CameraMetadataEnumAndroidControlAwbLock : uint32_t {
     ANDROID_CONTROL_AWB_LOCK_OFF,
-
     ANDROID_CONTROL_AWB_LOCK_ON,
-
 };
 
+/** android.control.awbMode enumeration values
+ * @see ANDROID_CONTROL_AWB_MODE
+ */
 enum CameraMetadataEnumAndroidControlAwbMode : uint32_t {
     ANDROID_CONTROL_AWB_MODE_OFF,
-
     ANDROID_CONTROL_AWB_MODE_AUTO,
-
     ANDROID_CONTROL_AWB_MODE_INCANDESCENT,
-
     ANDROID_CONTROL_AWB_MODE_FLUORESCENT,
-
     ANDROID_CONTROL_AWB_MODE_WARM_FLUORESCENT,
-
     ANDROID_CONTROL_AWB_MODE_DAYLIGHT,
-
     ANDROID_CONTROL_AWB_MODE_CLOUDY_DAYLIGHT,
-
     ANDROID_CONTROL_AWB_MODE_TWILIGHT,
-
     ANDROID_CONTROL_AWB_MODE_SHADE,
-
 };
 
+/** android.control.captureIntent enumeration values
+ * @see ANDROID_CONTROL_CAPTURE_INTENT
+ */
 enum CameraMetadataEnumAndroidControlCaptureIntent : uint32_t {
     ANDROID_CONTROL_CAPTURE_INTENT_CUSTOM,
-
     ANDROID_CONTROL_CAPTURE_INTENT_PREVIEW,
-
     ANDROID_CONTROL_CAPTURE_INTENT_STILL_CAPTURE,
-
     ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_RECORD,
-
     ANDROID_CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT,
-
     ANDROID_CONTROL_CAPTURE_INTENT_ZERO_SHUTTER_LAG,
-
     ANDROID_CONTROL_CAPTURE_INTENT_MANUAL,
-
 };
 
+/** android.control.effectMode enumeration values
+ * @see ANDROID_CONTROL_EFFECT_MODE
+ */
 enum CameraMetadataEnumAndroidControlEffectMode : uint32_t {
     ANDROID_CONTROL_EFFECT_MODE_OFF,
-
     ANDROID_CONTROL_EFFECT_MODE_MONO,
-
     ANDROID_CONTROL_EFFECT_MODE_NEGATIVE,
-
     ANDROID_CONTROL_EFFECT_MODE_SOLARIZE,
-
     ANDROID_CONTROL_EFFECT_MODE_SEPIA,
-
     ANDROID_CONTROL_EFFECT_MODE_POSTERIZE,
-
     ANDROID_CONTROL_EFFECT_MODE_WHITEBOARD,
-
     ANDROID_CONTROL_EFFECT_MODE_BLACKBOARD,
-
     ANDROID_CONTROL_EFFECT_MODE_AQUA,
-
 };
 
+/** android.control.mode enumeration values
+ * @see ANDROID_CONTROL_MODE
+ */
 enum CameraMetadataEnumAndroidControlMode : uint32_t {
     ANDROID_CONTROL_MODE_OFF,
-
     ANDROID_CONTROL_MODE_AUTO,
-
     ANDROID_CONTROL_MODE_USE_SCENE_MODE,
-
     ANDROID_CONTROL_MODE_OFF_KEEP_STATE,
-
 };
 
+/** android.control.sceneMode enumeration values
+ * @see ANDROID_CONTROL_SCENE_MODE
+ */
 enum CameraMetadataEnumAndroidControlSceneMode : uint32_t {
-    ANDROID_CONTROL_SCENE_MODE_DISABLED = 0,
-
+    ANDROID_CONTROL_SCENE_MODE_DISABLED                         = 0,
     ANDROID_CONTROL_SCENE_MODE_FACE_PRIORITY,
-
     ANDROID_CONTROL_SCENE_MODE_ACTION,
-
     ANDROID_CONTROL_SCENE_MODE_PORTRAIT,
-
     ANDROID_CONTROL_SCENE_MODE_LANDSCAPE,
-
     ANDROID_CONTROL_SCENE_MODE_NIGHT,
-
     ANDROID_CONTROL_SCENE_MODE_NIGHT_PORTRAIT,
-
     ANDROID_CONTROL_SCENE_MODE_THEATRE,
-
     ANDROID_CONTROL_SCENE_MODE_BEACH,
-
     ANDROID_CONTROL_SCENE_MODE_SNOW,
-
     ANDROID_CONTROL_SCENE_MODE_SUNSET,
-
     ANDROID_CONTROL_SCENE_MODE_STEADYPHOTO,
-
     ANDROID_CONTROL_SCENE_MODE_FIREWORKS,
-
     ANDROID_CONTROL_SCENE_MODE_SPORTS,
-
     ANDROID_CONTROL_SCENE_MODE_PARTY,
-
     ANDROID_CONTROL_SCENE_MODE_CANDLELIGHT,
-
     ANDROID_CONTROL_SCENE_MODE_BARCODE,
-
     ANDROID_CONTROL_SCENE_MODE_HIGH_SPEED_VIDEO,
-
     ANDROID_CONTROL_SCENE_MODE_HDR,
-
     ANDROID_CONTROL_SCENE_MODE_FACE_PRIORITY_LOW_LIGHT,
-
-    ANDROID_CONTROL_SCENE_MODE_DEVICE_CUSTOM_START = 100,
-
-    ANDROID_CONTROL_SCENE_MODE_DEVICE_CUSTOM_END = 127,
-
+    ANDROID_CONTROL_SCENE_MODE_DEVICE_CUSTOM_START              = 100,
+    ANDROID_CONTROL_SCENE_MODE_DEVICE_CUSTOM_END                = 127,
 };
 
+/** android.control.videoStabilizationMode enumeration values
+ * @see ANDROID_CONTROL_VIDEO_STABILIZATION_MODE
+ */
 enum CameraMetadataEnumAndroidControlVideoStabilizationMode : uint32_t {
     ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_OFF,
-
     ANDROID_CONTROL_VIDEO_STABILIZATION_MODE_ON,
-
 };
 
+/** android.control.aeState enumeration values
+ * @see ANDROID_CONTROL_AE_STATE
+ */
 enum CameraMetadataEnumAndroidControlAeState : uint32_t {
     ANDROID_CONTROL_AE_STATE_INACTIVE,
-
     ANDROID_CONTROL_AE_STATE_SEARCHING,
-
     ANDROID_CONTROL_AE_STATE_CONVERGED,
-
     ANDROID_CONTROL_AE_STATE_LOCKED,
-
     ANDROID_CONTROL_AE_STATE_FLASH_REQUIRED,
-
     ANDROID_CONTROL_AE_STATE_PRECAPTURE,
-
 };
 
+/** android.control.afState enumeration values
+ * @see ANDROID_CONTROL_AF_STATE
+ */
 enum CameraMetadataEnumAndroidControlAfState : uint32_t {
     ANDROID_CONTROL_AF_STATE_INACTIVE,
-
     ANDROID_CONTROL_AF_STATE_PASSIVE_SCAN,
-
     ANDROID_CONTROL_AF_STATE_PASSIVE_FOCUSED,
-
     ANDROID_CONTROL_AF_STATE_ACTIVE_SCAN,
-
     ANDROID_CONTROL_AF_STATE_FOCUSED_LOCKED,
-
     ANDROID_CONTROL_AF_STATE_NOT_FOCUSED_LOCKED,
-
     ANDROID_CONTROL_AF_STATE_PASSIVE_UNFOCUSED,
-
 };
 
+/** android.control.awbState enumeration values
+ * @see ANDROID_CONTROL_AWB_STATE
+ */
 enum CameraMetadataEnumAndroidControlAwbState : uint32_t {
     ANDROID_CONTROL_AWB_STATE_INACTIVE,
-
     ANDROID_CONTROL_AWB_STATE_SEARCHING,
-
     ANDROID_CONTROL_AWB_STATE_CONVERGED,
-
     ANDROID_CONTROL_AWB_STATE_LOCKED,
-
 };
 
+/** android.control.aeLockAvailable enumeration values
+ * @see ANDROID_CONTROL_AE_LOCK_AVAILABLE
+ */
 enum CameraMetadataEnumAndroidControlAeLockAvailable : uint32_t {
     ANDROID_CONTROL_AE_LOCK_AVAILABLE_FALSE,
-
     ANDROID_CONTROL_AE_LOCK_AVAILABLE_TRUE,
-
 };
 
+/** android.control.awbLockAvailable enumeration values
+ * @see ANDROID_CONTROL_AWB_LOCK_AVAILABLE
+ */
 enum CameraMetadataEnumAndroidControlAwbLockAvailable : uint32_t {
     ANDROID_CONTROL_AWB_LOCK_AVAILABLE_FALSE,
-
     ANDROID_CONTROL_AWB_LOCK_AVAILABLE_TRUE,
-
 };
 
+/** android.control.enableZsl enumeration values
+ * @see ANDROID_CONTROL_ENABLE_ZSL
+ */
 enum CameraMetadataEnumAndroidControlEnableZsl : uint32_t {
     ANDROID_CONTROL_ENABLE_ZSL_FALSE,
-
     ANDROID_CONTROL_ENABLE_ZSL_TRUE,
-
 };
 
+/** android.demosaic.mode enumeration values
+ * @see ANDROID_DEMOSAIC_MODE
+ */
 enum CameraMetadataEnumAndroidDemosaicMode : uint32_t {
     ANDROID_DEMOSAIC_MODE_FAST,
-
     ANDROID_DEMOSAIC_MODE_HIGH_QUALITY,
-
 };
 
+/** android.edge.mode enumeration values
+ * @see ANDROID_EDGE_MODE
+ */
 enum CameraMetadataEnumAndroidEdgeMode : uint32_t {
     ANDROID_EDGE_MODE_OFF,
-
     ANDROID_EDGE_MODE_FAST,
-
     ANDROID_EDGE_MODE_HIGH_QUALITY,
-
     ANDROID_EDGE_MODE_ZERO_SHUTTER_LAG,
-
 };
 
+/** android.flash.mode enumeration values
+ * @see ANDROID_FLASH_MODE
+ */
 enum CameraMetadataEnumAndroidFlashMode : uint32_t {
     ANDROID_FLASH_MODE_OFF,
-
     ANDROID_FLASH_MODE_SINGLE,
-
     ANDROID_FLASH_MODE_TORCH,
-
 };
 
+/** android.flash.state enumeration values
+ * @see ANDROID_FLASH_STATE
+ */
 enum CameraMetadataEnumAndroidFlashState : uint32_t {
     ANDROID_FLASH_STATE_UNAVAILABLE,
-
     ANDROID_FLASH_STATE_CHARGING,
-
     ANDROID_FLASH_STATE_READY,
-
     ANDROID_FLASH_STATE_FIRED,
-
     ANDROID_FLASH_STATE_PARTIAL,
-
 };
 
+/** android.flash.info.available enumeration values
+ * @see ANDROID_FLASH_INFO_AVAILABLE
+ */
 enum CameraMetadataEnumAndroidFlashInfoAvailable : uint32_t {
     ANDROID_FLASH_INFO_AVAILABLE_FALSE,
-
     ANDROID_FLASH_INFO_AVAILABLE_TRUE,
-
 };
 
+/** android.hotPixel.mode enumeration values
+ * @see ANDROID_HOT_PIXEL_MODE
+ */
 enum CameraMetadataEnumAndroidHotPixelMode : uint32_t {
     ANDROID_HOT_PIXEL_MODE_OFF,
-
     ANDROID_HOT_PIXEL_MODE_FAST,
-
     ANDROID_HOT_PIXEL_MODE_HIGH_QUALITY,
-
 };
 
+/** android.lens.opticalStabilizationMode enumeration values
+ * @see ANDROID_LENS_OPTICAL_STABILIZATION_MODE
+ */
 enum CameraMetadataEnumAndroidLensOpticalStabilizationMode : uint32_t {
     ANDROID_LENS_OPTICAL_STABILIZATION_MODE_OFF,
-
     ANDROID_LENS_OPTICAL_STABILIZATION_MODE_ON,
-
 };
 
+/** android.lens.facing enumeration values
+ * @see ANDROID_LENS_FACING
+ */
 enum CameraMetadataEnumAndroidLensFacing : uint32_t {
     ANDROID_LENS_FACING_FRONT,
-
     ANDROID_LENS_FACING_BACK,
-
     ANDROID_LENS_FACING_EXTERNAL,
-
 };
 
+/** android.lens.state enumeration values
+ * @see ANDROID_LENS_STATE
+ */
 enum CameraMetadataEnumAndroidLensState : uint32_t {
     ANDROID_LENS_STATE_STATIONARY,
-
     ANDROID_LENS_STATE_MOVING,
-
 };
 
+/** android.lens.info.focusDistanceCalibration enumeration values
+ * @see ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION
+ */
 enum CameraMetadataEnumAndroidLensInfoFocusDistanceCalibration : uint32_t {
     ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION_UNCALIBRATED,
-
     ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION_APPROXIMATE,
-
     ANDROID_LENS_INFO_FOCUS_DISTANCE_CALIBRATION_CALIBRATED,
-
 };
 
+/** android.noiseReduction.mode enumeration values
+ * @see ANDROID_NOISE_REDUCTION_MODE
+ */
 enum CameraMetadataEnumAndroidNoiseReductionMode : uint32_t {
     ANDROID_NOISE_REDUCTION_MODE_OFF,
-
     ANDROID_NOISE_REDUCTION_MODE_FAST,
-
     ANDROID_NOISE_REDUCTION_MODE_HIGH_QUALITY,
-
     ANDROID_NOISE_REDUCTION_MODE_MINIMAL,
-
     ANDROID_NOISE_REDUCTION_MODE_ZERO_SHUTTER_LAG,
-
 };
 
+/** android.quirks.partialResult enumeration values
+ * @see ANDROID_QUIRKS_PARTIAL_RESULT
+ */
 enum CameraMetadataEnumAndroidQuirksPartialResult : uint32_t {
     ANDROID_QUIRKS_PARTIAL_RESULT_FINAL,
-
     ANDROID_QUIRKS_PARTIAL_RESULT_PARTIAL,
-
 };
 
+/** android.request.metadataMode enumeration values
+ * @see ANDROID_REQUEST_METADATA_MODE
+ */
 enum CameraMetadataEnumAndroidRequestMetadataMode : uint32_t {
     ANDROID_REQUEST_METADATA_MODE_NONE,
-
     ANDROID_REQUEST_METADATA_MODE_FULL,
-
 };
 
+/** android.request.type enumeration values
+ * @see ANDROID_REQUEST_TYPE
+ */
 enum CameraMetadataEnumAndroidRequestType : uint32_t {
     ANDROID_REQUEST_TYPE_CAPTURE,
-
     ANDROID_REQUEST_TYPE_REPROCESS,
-
 };
 
+/** android.request.availableCapabilities enumeration values
+ * @see ANDROID_REQUEST_AVAILABLE_CAPABILITIES
+ */
 enum CameraMetadataEnumAndroidRequestAvailableCapabilities : uint32_t {
     ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE,
-
     ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_SENSOR,
-
     ANDROID_REQUEST_AVAILABLE_CAPABILITIES_MANUAL_POST_PROCESSING,
-
     ANDROID_REQUEST_AVAILABLE_CAPABILITIES_RAW,
-
     ANDROID_REQUEST_AVAILABLE_CAPABILITIES_PRIVATE_REPROCESSING,
-
     ANDROID_REQUEST_AVAILABLE_CAPABILITIES_READ_SENSOR_SETTINGS,
-
     ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BURST_CAPTURE,
-
     ANDROID_REQUEST_AVAILABLE_CAPABILITIES_YUV_REPROCESSING,
-
     ANDROID_REQUEST_AVAILABLE_CAPABILITIES_DEPTH_OUTPUT,
-
     ANDROID_REQUEST_AVAILABLE_CAPABILITIES_CONSTRAINED_HIGH_SPEED_VIDEO,
-
 };
 
+/** android.scaler.availableFormats enumeration values
+ * @see ANDROID_SCALER_AVAILABLE_FORMATS
+ */
 enum CameraMetadataEnumAndroidScalerAvailableFormats : uint32_t {
-    ANDROID_SCALER_AVAILABLE_FORMATS_RAW16 = 0x20,
-
-    ANDROID_SCALER_AVAILABLE_FORMATS_RAW_OPAQUE = 0x24,
-
-    ANDROID_SCALER_AVAILABLE_FORMATS_YV12 = 0x32315659,
-
-    ANDROID_SCALER_AVAILABLE_FORMATS_YCrCb_420_SP = 0x11,
-
-    ANDROID_SCALER_AVAILABLE_FORMATS_IMPLEMENTATION_DEFINED = 0x22,
-
-    ANDROID_SCALER_AVAILABLE_FORMATS_YCbCr_420_888 = 0x23,
-
-    ANDROID_SCALER_AVAILABLE_FORMATS_BLOB = 0x21,
-
+    ANDROID_SCALER_AVAILABLE_FORMATS_RAW16                      = 0x20,
+    ANDROID_SCALER_AVAILABLE_FORMATS_RAW_OPAQUE                 = 0x24,
+    ANDROID_SCALER_AVAILABLE_FORMATS_YV12                       = 0x32315659,
+    ANDROID_SCALER_AVAILABLE_FORMATS_YCrCb_420_SP               = 0x11,
+    ANDROID_SCALER_AVAILABLE_FORMATS_IMPLEMENTATION_DEFINED     = 0x22,
+    ANDROID_SCALER_AVAILABLE_FORMATS_YCbCr_420_888              = 0x23,
+    ANDROID_SCALER_AVAILABLE_FORMATS_BLOB                       = 0x21,
 };
 
+/** android.scaler.availableStreamConfigurations enumeration values
+ * @see ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS
+ */
 enum CameraMetadataEnumAndroidScalerAvailableStreamConfigurations : uint32_t {
     ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_OUTPUT,
-
     ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS_INPUT,
-
 };
 
+/** android.scaler.croppingType enumeration values
+ * @see ANDROID_SCALER_CROPPING_TYPE
+ */
 enum CameraMetadataEnumAndroidScalerCroppingType : uint32_t {
     ANDROID_SCALER_CROPPING_TYPE_CENTER_ONLY,
-
     ANDROID_SCALER_CROPPING_TYPE_FREEFORM,
-
 };
 
+/** android.sensor.referenceIlluminant1 enumeration values
+ * @see ANDROID_SENSOR_REFERENCE_ILLUMINANT1
+ */
 enum CameraMetadataEnumAndroidSensorReferenceIlluminant1 : uint32_t {
-    ANDROID_SENSOR_REFERENCE_ILLUMINANT1_DAYLIGHT = 1,
-
-    ANDROID_SENSOR_REFERENCE_ILLUMINANT1_FLUORESCENT = 2,
-
-    ANDROID_SENSOR_REFERENCE_ILLUMINANT1_TUNGSTEN = 3,
-
-    ANDROID_SENSOR_REFERENCE_ILLUMINANT1_FLASH = 4,
-
-    ANDROID_SENSOR_REFERENCE_ILLUMINANT1_FINE_WEATHER = 9,
-
-    ANDROID_SENSOR_REFERENCE_ILLUMINANT1_CLOUDY_WEATHER = 10,
-
-    ANDROID_SENSOR_REFERENCE_ILLUMINANT1_SHADE = 11,
-
-    ANDROID_SENSOR_REFERENCE_ILLUMINANT1_DAYLIGHT_FLUORESCENT = 12,
-
-    ANDROID_SENSOR_REFERENCE_ILLUMINANT1_DAY_WHITE_FLUORESCENT = 13,
-
+    ANDROID_SENSOR_REFERENCE_ILLUMINANT1_DAYLIGHT               = 1,
+    ANDROID_SENSOR_REFERENCE_ILLUMINANT1_FLUORESCENT            = 2,
+    ANDROID_SENSOR_REFERENCE_ILLUMINANT1_TUNGSTEN               = 3,
+    ANDROID_SENSOR_REFERENCE_ILLUMINANT1_FLASH                  = 4,
+    ANDROID_SENSOR_REFERENCE_ILLUMINANT1_FINE_WEATHER           = 9,
+    ANDROID_SENSOR_REFERENCE_ILLUMINANT1_CLOUDY_WEATHER         = 10,
+    ANDROID_SENSOR_REFERENCE_ILLUMINANT1_SHADE                  = 11,
+    ANDROID_SENSOR_REFERENCE_ILLUMINANT1_DAYLIGHT_FLUORESCENT   = 12,
+    ANDROID_SENSOR_REFERENCE_ILLUMINANT1_DAY_WHITE_FLUORESCENT  = 13,
     ANDROID_SENSOR_REFERENCE_ILLUMINANT1_COOL_WHITE_FLUORESCENT = 14,
-
-    ANDROID_SENSOR_REFERENCE_ILLUMINANT1_WHITE_FLUORESCENT = 15,
-
-    ANDROID_SENSOR_REFERENCE_ILLUMINANT1_STANDARD_A = 17,
-
-    ANDROID_SENSOR_REFERENCE_ILLUMINANT1_STANDARD_B = 18,
-
-    ANDROID_SENSOR_REFERENCE_ILLUMINANT1_STANDARD_C = 19,
-
-    ANDROID_SENSOR_REFERENCE_ILLUMINANT1_D55 = 20,
-
-    ANDROID_SENSOR_REFERENCE_ILLUMINANT1_D65 = 21,
-
-    ANDROID_SENSOR_REFERENCE_ILLUMINANT1_D75 = 22,
-
-    ANDROID_SENSOR_REFERENCE_ILLUMINANT1_D50 = 23,
-
-    ANDROID_SENSOR_REFERENCE_ILLUMINANT1_ISO_STUDIO_TUNGSTEN = 24,
-
+    ANDROID_SENSOR_REFERENCE_ILLUMINANT1_WHITE_FLUORESCENT      = 15,
+    ANDROID_SENSOR_REFERENCE_ILLUMINANT1_STANDARD_A             = 17,
+    ANDROID_SENSOR_REFERENCE_ILLUMINANT1_STANDARD_B             = 18,
+    ANDROID_SENSOR_REFERENCE_ILLUMINANT1_STANDARD_C             = 19,
+    ANDROID_SENSOR_REFERENCE_ILLUMINANT1_D55                    = 20,
+    ANDROID_SENSOR_REFERENCE_ILLUMINANT1_D65                    = 21,
+    ANDROID_SENSOR_REFERENCE_ILLUMINANT1_D75                    = 22,
+    ANDROID_SENSOR_REFERENCE_ILLUMINANT1_D50                    = 23,
+    ANDROID_SENSOR_REFERENCE_ILLUMINANT1_ISO_STUDIO_TUNGSTEN    = 24,
 };
 
+/** android.sensor.testPatternMode enumeration values
+ * @see ANDROID_SENSOR_TEST_PATTERN_MODE
+ */
 enum CameraMetadataEnumAndroidSensorTestPatternMode : uint32_t {
     ANDROID_SENSOR_TEST_PATTERN_MODE_OFF,
-
     ANDROID_SENSOR_TEST_PATTERN_MODE_SOLID_COLOR,
-
     ANDROID_SENSOR_TEST_PATTERN_MODE_COLOR_BARS,
-
     ANDROID_SENSOR_TEST_PATTERN_MODE_COLOR_BARS_FADE_TO_GRAY,
-
     ANDROID_SENSOR_TEST_PATTERN_MODE_PN9,
-
-    ANDROID_SENSOR_TEST_PATTERN_MODE_CUSTOM1 = 256,
-
+    ANDROID_SENSOR_TEST_PATTERN_MODE_CUSTOM1                    = 256,
 };
 
+/** android.sensor.info.colorFilterArrangement enumeration values
+ * @see ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT
+ */
 enum CameraMetadataEnumAndroidSensorInfoColorFilterArrangement : uint32_t {
     ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGGB,
-
     ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GRBG,
-
     ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GBRG,
-
     ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_BGGR,
-
     ANDROID_SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGB,
-
 };
 
+/** android.sensor.info.timestampSource enumeration values
+ * @see ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE
+ */
 enum CameraMetadataEnumAndroidSensorInfoTimestampSource : uint32_t {
     ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE_UNKNOWN,
-
     ANDROID_SENSOR_INFO_TIMESTAMP_SOURCE_REALTIME,
-
 };
 
+/** android.sensor.info.lensShadingApplied enumeration values
+ * @see ANDROID_SENSOR_INFO_LENS_SHADING_APPLIED
+ */
 enum CameraMetadataEnumAndroidSensorInfoLensShadingApplied : uint32_t {
     ANDROID_SENSOR_INFO_LENS_SHADING_APPLIED_FALSE,
-
     ANDROID_SENSOR_INFO_LENS_SHADING_APPLIED_TRUE,
-
 };
 
+/** android.shading.mode enumeration values
+ * @see ANDROID_SHADING_MODE
+ */
 enum CameraMetadataEnumAndroidShadingMode : uint32_t {
     ANDROID_SHADING_MODE_OFF,
-
     ANDROID_SHADING_MODE_FAST,
-
     ANDROID_SHADING_MODE_HIGH_QUALITY,
-
 };
 
+/** android.statistics.faceDetectMode enumeration values
+ * @see ANDROID_STATISTICS_FACE_DETECT_MODE
+ */
 enum CameraMetadataEnumAndroidStatisticsFaceDetectMode : uint32_t {
     ANDROID_STATISTICS_FACE_DETECT_MODE_OFF,
-
     ANDROID_STATISTICS_FACE_DETECT_MODE_SIMPLE,
-
     ANDROID_STATISTICS_FACE_DETECT_MODE_FULL,
-
 };
 
+/** android.statistics.histogramMode enumeration values
+ * @see ANDROID_STATISTICS_HISTOGRAM_MODE
+ */
 enum CameraMetadataEnumAndroidStatisticsHistogramMode : uint32_t {
     ANDROID_STATISTICS_HISTOGRAM_MODE_OFF,
-
     ANDROID_STATISTICS_HISTOGRAM_MODE_ON,
-
 };
 
+/** android.statistics.sharpnessMapMode enumeration values
+ * @see ANDROID_STATISTICS_SHARPNESS_MAP_MODE
+ */
 enum CameraMetadataEnumAndroidStatisticsSharpnessMapMode : uint32_t {
     ANDROID_STATISTICS_SHARPNESS_MAP_MODE_OFF,
-
     ANDROID_STATISTICS_SHARPNESS_MAP_MODE_ON,
-
 };
 
+/** android.statistics.hotPixelMapMode enumeration values
+ * @see ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE
+ */
 enum CameraMetadataEnumAndroidStatisticsHotPixelMapMode : uint32_t {
     ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE_OFF,
-
     ANDROID_STATISTICS_HOT_PIXEL_MAP_MODE_ON,
-
 };
 
+/** android.statistics.sceneFlicker enumeration values
+ * @see ANDROID_STATISTICS_SCENE_FLICKER
+ */
 enum CameraMetadataEnumAndroidStatisticsSceneFlicker : uint32_t {
     ANDROID_STATISTICS_SCENE_FLICKER_NONE,
-
     ANDROID_STATISTICS_SCENE_FLICKER_50HZ,
-
     ANDROID_STATISTICS_SCENE_FLICKER_60HZ,
-
 };
 
+/** android.statistics.lensShadingMapMode enumeration values
+ * @see ANDROID_STATISTICS_LENS_SHADING_MAP_MODE
+ */
 enum CameraMetadataEnumAndroidStatisticsLensShadingMapMode : uint32_t {
     ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_OFF,
-
     ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_ON,
-
 };
 
+/** android.tonemap.mode enumeration values
+ * @see ANDROID_TONEMAP_MODE
+ */
 enum CameraMetadataEnumAndroidTonemapMode : uint32_t {
     ANDROID_TONEMAP_MODE_CONTRAST_CURVE,
-
     ANDROID_TONEMAP_MODE_FAST,
-
     ANDROID_TONEMAP_MODE_HIGH_QUALITY,
-
     ANDROID_TONEMAP_MODE_GAMMA_VALUE,
-
     ANDROID_TONEMAP_MODE_PRESET_CURVE,
-
 };
 
+/** android.tonemap.presetCurve enumeration values
+ * @see ANDROID_TONEMAP_PRESET_CURVE
+ */
 enum CameraMetadataEnumAndroidTonemapPresetCurve : uint32_t {
     ANDROID_TONEMAP_PRESET_CURVE_SRGB,
-
     ANDROID_TONEMAP_PRESET_CURVE_REC709,
-
 };
 
+/** android.led.transmit enumeration values
+ * @see ANDROID_LED_TRANSMIT
+ */
 enum CameraMetadataEnumAndroidLedTransmit : uint32_t {
     ANDROID_LED_TRANSMIT_OFF,
-
     ANDROID_LED_TRANSMIT_ON,
-
 };
 
+/** android.led.availableLeds enumeration values
+ * @see ANDROID_LED_AVAILABLE_LEDS
+ */
 enum CameraMetadataEnumAndroidLedAvailableLeds : uint32_t {
     ANDROID_LED_AVAILABLE_LEDS_TRANSMIT,
-
 };
 
+/** android.info.supportedHardwareLevel enumeration values
+ * @see ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL
+ */
 enum CameraMetadataEnumAndroidInfoSupportedHardwareLevel : uint32_t {
     ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED,
-
     ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL,
-
     ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY,
-
     ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_3,
-
 };
 
+/** android.blackLevel.lock enumeration values
+ * @see ANDROID_BLACK_LEVEL_LOCK
+ */
 enum CameraMetadataEnumAndroidBlackLevelLock : uint32_t {
     ANDROID_BLACK_LEVEL_LOCK_OFF,
-
     ANDROID_BLACK_LEVEL_LOCK_ON,
-
 };
 
+/** android.sync.frameNumber enumeration values
+ * @see ANDROID_SYNC_FRAME_NUMBER
+ */
 enum CameraMetadataEnumAndroidSyncFrameNumber : uint32_t {
-    ANDROID_SYNC_FRAME_NUMBER_CONVERGING = -1,
-
-    ANDROID_SYNC_FRAME_NUMBER_UNKNOWN = -2,
-
+    ANDROID_SYNC_FRAME_NUMBER_CONVERGING                        = -1,
+    ANDROID_SYNC_FRAME_NUMBER_UNKNOWN                           = -2,
 };
 
+/** android.sync.maxLatency enumeration values
+ * @see ANDROID_SYNC_MAX_LATENCY
+ */
 enum CameraMetadataEnumAndroidSyncMaxLatency : uint32_t {
-    ANDROID_SYNC_MAX_LATENCY_PER_FRAME_CONTROL = 0,
-
-    ANDROID_SYNC_MAX_LATENCY_UNKNOWN = -1,
-
+    ANDROID_SYNC_MAX_LATENCY_PER_FRAME_CONTROL                  = 0,
+    ANDROID_SYNC_MAX_LATENCY_UNKNOWN                            = -1,
 };
 
+/** android.depth.availableDepthStreamConfigurations enumeration values
+ * @see ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS
+ */
 enum CameraMetadataEnumAndroidDepthAvailableDepthStreamConfigurations : uint32_t {
     ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS_OUTPUT,
-
     ANDROID_DEPTH_AVAILABLE_DEPTH_STREAM_CONFIGURATIONS_INPUT,
-
 };
 
+/** android.depth.depthIsExclusive enumeration values
+ * @see ANDROID_DEPTH_DEPTH_IS_EXCLUSIVE
+ */
 enum CameraMetadataEnumAndroidDepthDepthIsExclusive : uint32_t {
     ANDROID_DEPTH_DEPTH_IS_EXCLUSIVE_FALSE,
-
     ANDROID_DEPTH_DEPTH_IS_EXCLUSIVE_TRUE,
-
 };
diff --git a/camera/provider/2.4/default/android.hardware.camera.provider@2.4-service.rc b/camera/provider/2.4/default/android.hardware.camera.provider@2.4-service.rc
index 2bf309b..c919628 100644
--- a/camera/provider/2.4/default/android.hardware.camera.provider@2.4-service.rc
+++ b/camera/provider/2.4/default/android.hardware.camera.provider@2.4-service.rc
@@ -1,4 +1,4 @@
-service camera-provider-2-4 /vendor/bin/hw/android.hardware.camera.provider@2.4-service
+service vendor.camera-provider-2-4 /vendor/bin/hw/android.hardware.camera.provider@2.4-service
     class hal
     user cameraserver
     group audio camera input drmrpc
diff --git a/cas/1.0/CasHal.mk b/cas/1.0/CasHal.mk
deleted file mode 100644
index 3cae6bf..0000000
--- a/cas/1.0/CasHal.mk
+++ /dev/null
@@ -1,192 +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.
-
-
-########################################################################
-# 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/default/CasImpl.cpp b/cas/1.0/default/CasImpl.cpp
index 9d1f4a3..2ac1c4f 100644
--- a/cas/1.0/default/CasImpl.cpp
+++ b/cas/1.0/default/CasImpl.cpp
@@ -103,6 +103,7 @@
     status_t err = INVALID_OPERATION;
     if (holder != NULL) {
         err = holder->get()->openSession(&sessionId);
+        holder.clear();
     }
 
     _hidl_cb(toStatus(err), sessionId);
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
index 93de794..74f2f96 100644
--- a/cas/1.0/default/android.hardware.cas@1.0-service.rc
+++ b/cas/1.0/default/android.hardware.cas@1.0-service.rc
@@ -1,4 +1,4 @@
-service cas-hal-1-0 /vendor/bin/hw/android.hardware.cas@1.0-service
+service vendor.cas-hal-1-0 /vendor/bin/hw/android.hardware.cas@1.0-service
     class hal
     user media
     group mediadrm drmrpc
diff --git a/cas/1.0/vts/functional/VtsHalCasV1_0TargetTest.cpp b/cas/1.0/vts/functional/VtsHalCasV1_0TargetTest.cpp
index d3b0f1d..193253a 100644
--- a/cas/1.0/vts/functional/VtsHalCasV1_0TargetTest.cpp
+++ b/cas/1.0/vts/functional/VtsHalCasV1_0TargetTest.cpp
@@ -223,12 +223,26 @@
     sp<ICas> mMediaCas;
     sp<IDescramblerBase> mDescramblerBase;
     sp<MediaCasListener> mCasListener;
+    typedef struct _OobInputTestParams {
+        const SubSample* subSamples;
+        uint32_t numSubSamples;
+        size_t imemSizeActual;
+        uint64_t imemOffset;
+        uint64_t imemSize;
+        uint64_t srcOffset;
+        uint64_t dstOffset;
+    } OobInputTestParams;
 
     ::testing::AssertionResult createCasPlugin(int32_t caSystemId);
     ::testing::AssertionResult openCasSession(std::vector<uint8_t>* sessionId);
-    ::testing::AssertionResult descrambleTestInputBuffer(const sp<IDescrambler>& descrambler,
-                                                         Status* descrambleStatus,
-                                                         sp<IMemory>* hidlInMemory);
+    ::testing::AssertionResult descrambleTestInputBuffer(
+            const sp<IDescrambler>& descrambler,
+            Status* descrambleStatus,
+            sp<IMemory>* hidlInMemory);
+    ::testing::AssertionResult descrambleTestOobInput(
+            const sp<IDescrambler>& descrambler,
+            Status* descrambleStatus,
+            const OobInputTestParams& params);
 };
 
 ::testing::AssertionResult MediaCasHidlTest::createCasPlugin(int32_t caSystemId) {
@@ -332,6 +346,72 @@
     return ::testing::AssertionResult(returnVoid.isOk());
 }
 
+::testing::AssertionResult MediaCasHidlTest::descrambleTestOobInput(
+        const sp<IDescrambler>& descrambler,
+        Status* descrambleStatus,
+        const OobInputTestParams& params) {
+    hidl_vec<SubSample> hidlSubSamples;
+    hidlSubSamples.setToExternal(
+            const_cast<SubSample*>(params.subSamples), params.numSubSamples, false /*own*/);
+
+    sp<MemoryDealer> dealer = new MemoryDealer(params.imemSizeActual, "vts-cas");
+    if (nullptr == dealer.get()) {
+        ALOGE("couldn't get MemoryDealer!");
+        return ::testing::AssertionFailure();
+    }
+
+    sp<IMemory> mem = dealer->allocate(params.imemSizeActual);
+    if (nullptr == mem.get()) {
+        ALOGE("couldn't allocate IMemory!");
+        return ::testing::AssertionFailure();
+    }
+
+    // build hidl_memory from memory heap
+    ssize_t offset;
+    size_t size;
+    sp<IMemoryHeap> heap = mem->getMemory(&offset, &size);
+    if (nullptr == heap.get()) {
+        ALOGE("couldn't get memory heap!");
+        return ::testing::AssertionFailure();
+    }
+
+    native_handle_t* nativeHandle = native_handle_create(1, 0);
+    if (!nativeHandle) {
+        ALOGE("failed to create native handle!");
+        return ::testing::AssertionFailure();
+    }
+    nativeHandle->data[0] = heap->getHeapID();
+
+    SharedBuffer srcBuffer = {
+            .heapBase = hidl_memory("ashmem", hidl_handle(nativeHandle), heap->getSize()),
+            .offset = (uint64_t) offset + params.imemOffset,
+            .size = (uint64_t) params.imemSize,
+    };
+
+    DestinationBuffer dstBuffer;
+    dstBuffer.type = BufferType::SHARED_MEMORY;
+    dstBuffer.nonsecureMemory = srcBuffer;
+
+    uint32_t outBytes;
+    hidl_string detailedError;
+    auto returnVoid = descrambler->descramble(
+        ScramblingControl::EVENKEY /*2*/, hidlSubSamples,
+        srcBuffer,
+        params.srcOffset,
+        dstBuffer,
+        params.dstOffset,
+        [&](Status status, uint32_t bytesWritten, const hidl_string& detailedErr) {
+            *descrambleStatus = status;
+            outBytes = bytesWritten;
+            detailedError = detailedErr;
+        });
+    if (!returnVoid.isOk() || *descrambleStatus != Status::OK) {
+        ALOGI("descramble failed, trans=%s, status=%d, outBytes=%u, error=%s",
+              returnVoid.description().c_str(), *descrambleStatus, outBytes, detailedError.c_str());
+    }
+    return ::testing::AssertionResult(returnVoid.isOk());
+}
+
 TEST_F(MediaCasHidlTest, EnumeratePlugins) {
     description("Test enumerate plugins");
     hidl_vec<HidlCasPluginDescriptor> descriptors;
@@ -613,6 +693,153 @@
     EXPECT_FALSE(mDescramblerBase->requiresSecureDecoderComponent("bad"));
 }
 
+TEST_F(MediaCasHidlTest, TestClearKeyOobFails) {
+    description("Test that oob descramble request fails with expected error");
+
+    ASSERT_TRUE(createCasPlugin(CLEAR_KEY_SYSTEM_ID));
+
+    auto returnStatus = mMediaCas->provision(hidl_string(PROVISION_STR));
+    EXPECT_TRUE(returnStatus.isOk());
+    EXPECT_EQ(Status::OK, returnStatus);
+
+    std::vector<uint8_t> sessionId;
+    ASSERT_TRUE(openCasSession(&sessionId));
+
+    returnStatus = mDescramblerBase->setMediaCasSession(sessionId);
+    EXPECT_TRUE(returnStatus.isOk());
+    EXPECT_EQ(Status::OK, returnStatus);
+
+    hidl_vec<uint8_t> hidlEcm;
+    hidlEcm.setToExternal(const_cast<uint8_t*>(kEcmBinaryBuffer), sizeof(kEcmBinaryBuffer));
+    returnStatus = mMediaCas->processEcm(sessionId, hidlEcm);
+    EXPECT_TRUE(returnStatus.isOk());
+    EXPECT_EQ(Status::OK, returnStatus);
+
+    sp<IDescrambler> descrambler = IDescrambler::castFrom(mDescramblerBase);
+    ASSERT_NE(nullptr, descrambler.get());
+
+    Status descrambleStatus = Status::OK;
+
+    // test invalid src buffer offset
+    ASSERT_TRUE(descrambleTestOobInput(
+            descrambler,
+            &descrambleStatus,
+            {
+                .subSamples     = kSubSamples,
+                .numSubSamples  = sizeof(kSubSamples)/sizeof(SubSample),
+                .imemSizeActual = sizeof(kInBinaryBuffer),
+                .imemOffset     = 0xcccccc,
+                .imemSize       = sizeof(kInBinaryBuffer),
+                .srcOffset      = 0,
+                .dstOffset      = 0
+            }));
+    EXPECT_EQ(Status::BAD_VALUE, descrambleStatus);
+
+    // test invalid src buffer size
+    ASSERT_TRUE(descrambleTestOobInput(
+            descrambler,
+            &descrambleStatus,
+            {
+                .subSamples     = kSubSamples,
+                .numSubSamples  = sizeof(kSubSamples)/sizeof(SubSample),
+                .imemSizeActual = sizeof(kInBinaryBuffer),
+                .imemOffset     = 0,
+                .imemSize       = 0xcccccc,
+                .srcOffset      = 0,
+                .dstOffset      = 0
+            }));
+    EXPECT_EQ(Status::BAD_VALUE, descrambleStatus);
+
+    // test invalid src buffer size
+    ASSERT_TRUE(descrambleTestOobInput(
+            descrambler,
+            &descrambleStatus,
+            {
+                .subSamples     = kSubSamples,
+                .numSubSamples  = sizeof(kSubSamples)/sizeof(SubSample),
+                .imemSizeActual = sizeof(kInBinaryBuffer),
+                .imemOffset     = 1,
+                .imemSize       = (uint64_t)-1,
+                .srcOffset      = 0,
+                .dstOffset      = 0
+            }));
+    EXPECT_EQ(Status::BAD_VALUE, descrambleStatus);
+
+    // test invalid srcOffset
+    ASSERT_TRUE(descrambleTestOobInput(
+            descrambler,
+            &descrambleStatus,
+            {
+                .subSamples     = kSubSamples,
+                .numSubSamples  = sizeof(kSubSamples)/sizeof(SubSample),
+                .imemSizeActual = sizeof(kInBinaryBuffer),
+                .imemOffset     = 0,
+                .imemSize       = sizeof(kInBinaryBuffer),
+                .srcOffset      = 0xcccccc,
+                .dstOffset      = 0
+            }));
+    EXPECT_EQ(Status::BAD_VALUE, descrambleStatus);
+
+    // test invalid dstOffset
+    ASSERT_TRUE(descrambleTestOobInput(
+            descrambler,
+            &descrambleStatus,
+            {
+                .subSamples     = kSubSamples,
+                .numSubSamples  = sizeof(kSubSamples)/sizeof(SubSample),
+                .imemSizeActual = sizeof(kInBinaryBuffer),
+                .imemOffset     = 0,
+                .imemSize       = sizeof(kInBinaryBuffer),
+                .srcOffset      = 0,
+                .dstOffset      = 0xcccccc
+            }));
+    EXPECT_EQ(Status::BAD_VALUE, descrambleStatus);
+
+    // test detection of oob subsample sizes
+    const SubSample invalidSubSamples1[] =
+        {{162, 0}, {0, 184}, {0, 0xdddddd}};
+
+    ASSERT_TRUE(descrambleTestOobInput(
+            descrambler,
+            &descrambleStatus,
+            {
+                .subSamples     = invalidSubSamples1,
+                .numSubSamples  = sizeof(invalidSubSamples1)/sizeof(SubSample),
+                .imemSizeActual = sizeof(kInBinaryBuffer),
+                .imemOffset     = 0,
+                .imemSize       = sizeof(kInBinaryBuffer),
+                .srcOffset      = 0,
+                .dstOffset      = 0
+            }));
+    EXPECT_EQ(Status::BAD_VALUE, descrambleStatus);
+
+    // test detection of overflowing subsample sizes
+    const SubSample invalidSubSamples2[] =
+        {{162, 0}, {0, 184}, {2, (uint32_t)-1}};
+
+    ASSERT_TRUE(descrambleTestOobInput(
+            descrambler,
+            &descrambleStatus,
+            {
+                .subSamples     = invalidSubSamples2,
+                .numSubSamples  = sizeof(invalidSubSamples2)/sizeof(SubSample),
+                .imemSizeActual = sizeof(kInBinaryBuffer),
+                .imemOffset     = 0,
+                .imemSize       = sizeof(kInBinaryBuffer),
+                .srcOffset      = 0,
+                .dstOffset      = 0
+            }));
+    EXPECT_EQ(Status::BAD_VALUE, descrambleStatus);
+
+    returnStatus = mDescramblerBase->release();
+    EXPECT_TRUE(returnStatus.isOk());
+    EXPECT_EQ(Status::OK, returnStatus);
+
+    returnStatus = mMediaCas->release();
+    EXPECT_TRUE(returnStatus.isOk());
+    EXPECT_EQ(Status::OK, returnStatus);
+}
+
 }  // anonymous namespace
 
 int main(int argc, char** argv) {
diff --git a/compatibility_matrix.26.xml b/compatibility_matrix.1.xml
similarity index 100%
rename from compatibility_matrix.26.xml
rename to compatibility_matrix.1.xml
diff --git a/compatibility_matrix.27.xml b/compatibility_matrix.2.xml
similarity index 100%
rename from compatibility_matrix.27.xml
rename to compatibility_matrix.2.xml
diff --git a/compatibility_matrix.current.xml b/compatibility_matrix.current.xml
index 5296142..5b033e7 100644
--- a/compatibility_matrix.current.xml
+++ b/compatibility_matrix.current.xml
@@ -81,7 +81,7 @@
     </hal>
     <hal format="hidl" optional="false">
         <name>android.hardware.configstore</name>
-        <version>1.0</version>
+        <version>1.0-1</version>
         <interface>
             <name>ISurfaceFlingerConfigs</name>
             <instance>default</instance>
@@ -155,9 +155,9 @@
             <instance>default</instance>
         </interface>
     </hal>
-    <hal format="hidl" optional="true">
+    <hal format="hidl" optional="false">
         <name>android.hardware.health</name>
-        <version>1.0</version>
+        <version>2.0</version>
         <interface>
             <name>IHealth</name>
             <instance>default</instance>
diff --git a/configstore/1.0/default/android.hardware.configstore@1.0-service.rc b/configstore/1.0/default/android.hardware.configstore@1.0-service.rc
deleted file mode 100644
index 563d854..0000000
--- a/configstore/1.0/default/android.hardware.configstore@1.0-service.rc
+++ /dev/null
@@ -1,4 +0,0 @@
-service configstore-hal-1-0 /vendor/bin/hw/android.hardware.configstore@1.0-service
-    class hal animation
-    user system
-    group system
diff --git a/configstore/1.1/Android.bp b/configstore/1.1/Android.bp
new file mode 100644
index 0000000..f0a1748
--- /dev/null
+++ b/configstore/1.1/Android.bp
@@ -0,0 +1,18 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.configstore@1.1",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "ISurfaceFlingerConfigs.hal",
+    ],
+    interfaces: [
+        "android.hardware.configstore@1.0",
+        "android.hidl.base@1.0",
+    ],
+    gen_java: true,
+}
+
diff --git a/configstore/1.1/ISurfaceFlingerConfigs.hal b/configstore/1.1/ISurfaceFlingerConfigs.hal
new file mode 100644
index 0000000..5eacbe0
--- /dev/null
+++ b/configstore/1.1/ISurfaceFlingerConfigs.hal
@@ -0,0 +1,25 @@
+/*
+ * 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.configstore@1.1;
+
+import @1.0::ISurfaceFlingerConfigs;
+
+/**
+ * New revision of ISurfaceFlingerConfigs
+ */
+
+interface ISurfaceFlingerConfigs extends @1.0::ISurfaceFlingerConfigs {
+};
diff --git a/configstore/1.0/default/Android.mk b/configstore/1.1/default/Android.mk
similarity index 70%
rename from configstore/1.0/default/Android.mk
rename to configstore/1.1/default/Android.mk
index 240b2a2..53e454b 100644
--- a/configstore/1.0/default/Android.mk
+++ b/configstore/1.1/default/Android.mk
@@ -2,12 +2,12 @@
 
 ################################################################################
 include $(CLEAR_VARS)
-LOCAL_MODULE := android.hardware.configstore@1.0-service
-LOCAL_REQUIRED_MODULES_arm64 := configstore@1.0.policy
+LOCAL_MODULE := android.hardware.configstore@1.1-service
+LOCAL_REQUIRED_MODULES_arm64 := configstore@1.1.policy
 LOCAL_PROPRIETARY_MODULE := true
 LOCAL_MODULE_CLASS := EXECUTABLES
 LOCAL_MODULE_RELATIVE_PATH := hw
-LOCAL_INIT_RC := android.hardware.configstore@1.0-service.rc
+LOCAL_INIT_RC := android.hardware.configstore@1.1-service.rc
 LOCAL_SRC_FILES:= service.cpp
 
 include $(LOCAL_PATH)/surfaceflinger.mk
@@ -20,15 +20,16 @@
     liblog \
     libutils \
     android.hardware.configstore@1.0 \
+    android.hardware.configstore@1.1
 
 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 := configstore@1.1.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
+LOCAL_SRC_FILES := seccomp_policy/configstore@1.1-$(TARGET_ARCH).policy
 include $(BUILD_PREBUILT)
 endif
diff --git a/configstore/1.0/default/SurfaceFlingerConfigs.cpp b/configstore/1.1/default/SurfaceFlingerConfigs.cpp
similarity index 96%
rename from configstore/1.0/default/SurfaceFlingerConfigs.cpp
rename to configstore/1.1/default/SurfaceFlingerConfigs.cpp
index 3239274..5a040f2 100644
--- a/configstore/1.0/default/SurfaceFlingerConfigs.cpp
+++ b/configstore/1.1/default/SurfaceFlingerConfigs.cpp
@@ -19,7 +19,7 @@
 namespace android {
 namespace hardware {
 namespace configstore {
-namespace V1_0 {
+namespace V1_1 {
 namespace implementation {
 
 // Methods from ::android::hardware::configstore::V1_0::ISurfaceFlingerConfigs
@@ -139,10 +139,13 @@
     return Void();
 }
 
+// Methods from ::android::hardware::configstore::V1_1::ISurfaceFlingerConfigs
+// follow.
+
 // Methods from ::android::hidl::base::V1_0::IBase follow.
 
 }  // namespace implementation
-}  // namespace V1_0
+}  // namespace V1_1
 }  // namespace configstore
 }  // namespace hardware
 }  // namespace android
diff --git a/configstore/1.0/default/SurfaceFlingerConfigs.h b/configstore/1.1/default/SurfaceFlingerConfigs.h
similarity index 77%
rename from configstore/1.0/default/SurfaceFlingerConfigs.h
rename to configstore/1.1/default/SurfaceFlingerConfigs.h
index 32e5fc3..53e8ae8 100644
--- a/configstore/1.0/default/SurfaceFlingerConfigs.h
+++ b/configstore/1.1/default/SurfaceFlingerConfigs.h
@@ -1,17 +1,17 @@
-#ifndef ANDROID_HARDWARE_CONFIGSTORE_V1_0_SURFACEFLINGERCONFIGS_H
-#define ANDROID_HARDWARE_CONFIGSTORE_V1_0_SURFACEFLINGERCONFIGS_H
+#ifndef ANDROID_HARDWARE_CONFIGSTORE_V1_1_SURFACEFLINGERCONFIGS_H
+#define ANDROID_HARDWARE_CONFIGSTORE_V1_1_SURFACEFLINGERCONFIGS_H
 
-#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
+#include <android/hardware/configstore/1.1/ISurfaceFlingerConfigs.h>
 #include <hidl/MQDescriptor.h>
 #include <hidl/Status.h>
 
 namespace android {
 namespace hardware {
 namespace configstore {
-namespace V1_0 {
+namespace V1_1 {
 namespace implementation {
 
-using ::android::hardware::configstore::V1_0::ISurfaceFlingerConfigs;
+using ::android::hardware::configstore::V1_1::ISurfaceFlingerConfigs;
 using ::android::hardware::Return;
 using ::android::hardware::Void;
 using ::android::sp;
@@ -32,13 +32,16 @@
     Return<void> maxFrameBufferAcquiredBuffers(maxFrameBufferAcquiredBuffers_cb _hidl_cb) override;
     Return<void> startGraphicsAllocatorService(startGraphicsAllocatorService_cb _hidl_cb) override;
 
+    // Methods from
+    // ::android::hardware::configstore::V1_1::ISurfaceFlingerConfigs follow.
+
     // Methods from ::android::hidl::base::V1_0::IBase follow.
 };
 
 }  // namespace implementation
-}  // namespace V1_0
+}  // namespace V1_1
 }  // namespace configstore
 }  // namespace hardware
 }  // namespace android
 
-#endif  // ANDROID_HARDWARE_CONFIGSTORE_V1_0_SURFACEFLINGERCONFIGS_H
+#endif  // ANDROID_HARDWARE_CONFIGSTORE_V1_1_SURFACEFLINGERCONFIGS_H
diff --git a/configstore/1.1/default/android.hardware.configstore@1.1-service.rc b/configstore/1.1/default/android.hardware.configstore@1.1-service.rc
new file mode 100644
index 0000000..105678a
--- /dev/null
+++ b/configstore/1.1/default/android.hardware.configstore@1.1-service.rc
@@ -0,0 +1,4 @@
+service vendor.configstore-hal /vendor/bin/hw/android.hardware.configstore@1.1-service
+    class hal animation
+    user system
+    group system
diff --git a/configstore/1.0/default/seccomp_policy/configstore@1.0-arm64.policy b/configstore/1.1/default/seccomp_policy/configstore@1.1-arm64.policy
similarity index 88%
rename from configstore/1.0/default/seccomp_policy/configstore@1.0-arm64.policy
rename to configstore/1.1/default/seccomp_policy/configstore@1.1-arm64.policy
index 43bf1fa..f2dd892 100644
--- a/configstore/1.0/default/seccomp_policy/configstore@1.0-arm64.policy
+++ b/configstore/1.1/default/seccomp_policy/configstore@1.1-arm64.policy
@@ -17,7 +17,9 @@
 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
+# prctl: arg0 == 15 || arg0 == 0x53564d41 || arg0 == 29 || arg0 == 39
+# TODO(b/68162846) reduce scope of prctl() based on arguments
+prctl: 1
 openat: 1
 mmap: 1
 mprotect: 1
@@ -28,6 +30,7 @@
 write: 1
 fstat: 1
 clone: 1
+sched_setscheduler: 1
 munmap: 1
 lseek: 1
 sigaltstack: 1
diff --git a/configstore/1.0/default/service.cpp b/configstore/1.1/default/service.cpp
similarity index 80%
rename from configstore/1.0/default/service.cpp
rename to configstore/1.1/default/service.cpp
index c9c81a0..535e0cd 100644
--- a/configstore/1.0/default/service.cpp
+++ b/configstore/1.1/default/service.cpp
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "android.hardware.configstore@1.0-service"
+#define LOG_TAG "android.hardware.configstore@1.1-service"
 
-#include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
+#include <android/hardware/configstore/1.1/ISurfaceFlingerConfigs.h>
 #include <hidl/HidlTransportSupport.h>
 #include <hwminijail/HardwareMinijail.h>
 
@@ -24,8 +24,8 @@
 
 using android::hardware::configureRpcThreadpool;
 using android::hardware::joinRpcThreadpool;
-using android::hardware::configstore::V1_0::ISurfaceFlingerConfigs;
-using android::hardware::configstore::V1_0::implementation::SurfaceFlingerConfigs;
+using android::hardware::configstore::V1_1::ISurfaceFlingerConfigs;
+using android::hardware::configstore::V1_1::implementation::SurfaceFlingerConfigs;
 using android::hardware::SetupMinijail;
 using android::sp;
 using android::status_t;
@@ -34,7 +34,7 @@
 int main() {
     configureRpcThreadpool(10, true);
 
-    SetupMinijail("/vendor/etc/seccomp_policy/configstore@1.0.policy");
+    SetupMinijail("/vendor/etc/seccomp_policy/configstore@1.1.policy");
 
     sp<ISurfaceFlingerConfigs> surfaceFlingerConfigs = new SurfaceFlingerConfigs;
     status_t status = surfaceFlingerConfigs->registerAsService();
diff --git a/configstore/1.0/default/surfaceflinger.mk b/configstore/1.1/default/surfaceflinger.mk
similarity index 100%
rename from configstore/1.0/default/surfaceflinger.mk
rename to configstore/1.1/default/surfaceflinger.mk
diff --git a/broadcastradio/1.1/vts/utils/Android.bp b/configstore/1.1/vts/functional/Android.bp
similarity index 70%
copy from broadcastradio/1.1/vts/utils/Android.bp
copy to configstore/1.1/vts/functional/Android.bp
index 0c7e2a4..59beb09 100644
--- a/broadcastradio/1.1/vts/utils/Android.bp
+++ b/configstore/1.1/vts/functional/Android.bp
@@ -14,15 +14,13 @@
 // 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",
+cc_test {
+    name: "VtsHalConfigstoreV1_1TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: ["VtsHalConfigstoreV1_1TargetTest.cpp"],
+    static_libs: [
+        "android.hardware.configstore@1.0",
+        "android.hardware.configstore@1.1",
     ],
 }
+
diff --git a/configstore/1.1/vts/functional/VtsHalConfigstoreV1_1TargetTest.cpp b/configstore/1.1/vts/functional/VtsHalConfigstoreV1_1TargetTest.cpp
new file mode 100644
index 0000000..bd3da4c
--- /dev/null
+++ b/configstore/1.1/vts/functional/VtsHalConfigstoreV1_1TargetTest.cpp
@@ -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.
+ */
+
+#define LOG_TAG "ConfigstoreHidlHalTest"
+
+#include <VtsHalHidlTargetTestBase.h>
+#include <android-base/logging.h>
+#include <android/hardware/configstore/1.0/types.h>
+#include <android/hardware/configstore/1.1/ISurfaceFlingerConfigs.h>
+#include <unistd.h>
+
+using ::android::hardware::configstore::V1_1::ISurfaceFlingerConfigs;
+using ::android::sp;
+
+#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
+#define EXPECT_OK(ret) EXPECT_TRUE(ret.isOk())
+
+class ConfigstoreHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+   public:
+    sp<ISurfaceFlingerConfigs> sfConfigs;
+
+    virtual void SetUp() override {
+        sfConfigs = ::testing::VtsHalHidlTargetTestBase::getService<ISurfaceFlingerConfigs>();
+        ASSERT_NE(sfConfigs, nullptr);
+    }
+
+    virtual void TearDown() override {}
+};
+
+/**
+ * Placeholder testcase.
+ */
+TEST_F(ConfigstoreHidlTest, Test) {
+    ASSERT_TRUE(true);
+}
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    int status = RUN_ALL_TESTS();
+    LOG(INFO) << "Test result = " << status;
+    return status;
+}
diff --git a/contexthub/1.0/default/Contexthub.cpp b/contexthub/1.0/default/Contexthub.cpp
index 3626a09..5f83a22 100644
--- a/contexthub/1.0/default/Contexthub.cpp
+++ b/contexthub/1.0/default/Contexthub.cpp
@@ -155,6 +155,12 @@
         .message = static_cast<const uint8_t *>(msg.msg.data()),
     };
 
+    // Use a dummy to prevent send_message with empty message from failing prematurely
+    static uint8_t dummy;
+    if (txMsg.message_len == 0 && txMsg.message == nullptr) {
+        txMsg.message = &dummy;
+    }
+
     ALOGI("Sending msg of type %" PRIu32 ", size %" PRIu32 " to app 0x%" PRIx64,
           txMsg.message_type,
           txMsg.message_len,
@@ -275,11 +281,11 @@
                 result = TransactionResult::FAILURE;
             }
 
+            mIsTransactionPending = false;
             if (cb != nullptr) {
                 cb->handleTxnResult(mTransactionId, result);
             }
             retVal = 0;
-            mIsTransactionPending = false;
             break;
         }
 
@@ -377,6 +383,7 @@
 
         msg.appName = rxMsg->app_name.id;
         msg.msgType = rxMsg->message_type;
+        msg.hostEndPoint = static_cast<uint16_t>(HostEndPoint::BROADCAST);
         msg.msg = std::vector<uint8_t>(static_cast<const uint8_t *>(rxMsg->message),
                                        static_cast<const uint8_t *>(rxMsg->message) +
                                        rxMsg->message_len);
diff --git a/contexthub/1.0/default/OWNERS b/contexthub/1.0/default/OWNERS
new file mode 100644
index 0000000..49a3204
--- /dev/null
+++ b/contexthub/1.0/default/OWNERS
@@ -0,0 +1,2 @@
+ashutoshj@google.com
+bduddie@google.com
diff --git a/contexthub/1.0/default/android.hardware.contexthub@1.0-service.rc b/contexthub/1.0/default/android.hardware.contexthub@1.0-service.rc
index 5677ec2..a8c9487 100644
--- a/contexthub/1.0/default/android.hardware.contexthub@1.0-service.rc
+++ b/contexthub/1.0/default/android.hardware.contexthub@1.0-service.rc
@@ -1,4 +1,4 @@
-service contexthub-hal-1-0 /vendor/bin/hw/android.hardware.contexthub@1.0-service
+service vendor.contexthub-hal-1-0 /vendor/bin/hw/android.hardware.contexthub@1.0-service
     class hal
     user system
     group system
diff --git a/contexthub/1.0/vts/functional/OWNERS b/contexthub/1.0/vts/functional/OWNERS
new file mode 100644
index 0000000..ad036b4
--- /dev/null
+++ b/contexthub/1.0/vts/functional/OWNERS
@@ -0,0 +1,7 @@
+#Context Hub team
+ashutoshj@google.com
+bduddie@google.com
+
+#VTS team
+yim@google.com
+trong@google.com
diff --git a/current.txt b/current.txt
index c81e01b..4a943b9 100644
--- a/current.txt
+++ b/current.txt
@@ -199,6 +199,7 @@
 c2c50ec74c87a583c683b4493f8f9f2e454a8d41c57af5b3eb88823a999f0ea4 android.hardware.radio@1.0::IRadioResponse # Added for b/65230472 for Android O
 4922dd58e89a03181ed1c48a6e118e47633b73b11090bdfed5aa920d25a7592b android.hardware.radio@1.0::IRadioResponse # Added for b/65230472 for Android O DR
 28e929b453df3d9f5060af2764e6cdb123ddb893e3e86923c877f6ff7e5f02c9 android.hardware.wifi@1.0::types
+bfd81bcafa3c97519cd56ad29e9fa48e23d1d323b89dbcc85899282a8c628194 android.hardware.automotive.vehicle@2.0::types
 df1d7b27e644bfed0a4f606a8c44d35d45cafce82c7c648494c8a25c7cd4a949 android.hardware.wifi@1.0::types
 
 # HALs released in Android O MR1 (Initial Set)
@@ -230,7 +231,9 @@
 b056e1defab4071584214584057d0bc73a613081bf1152590549649d4582c13c android.hardware.wifi@1.1::IWifiChip
 
 # ABI preserving changes to HALs during Android O MR1 (Final Set)
+09342041e17c429fce0034b9096d17849122111436a5f0053e7e59500e1cb89c android.hardware.media.omx@1.0::IOmxStore
 2d833aeed0cd1d59437aca210be590a953cf32bcb6683cd63d089762a643fb49 android.hardware.radio@1.0::IRadioResponse
+0a159f81359cd4f71bbe00972ee8403ea79351fb7c0cd48be72ebb3e424dbaef android.hardware.radio@1.0::types
 05aa3de6130a9788fdb6f4d3cc57c3ea90f067e77a5e09d6a772ec7f6bca33d2 android.hardware.radio@1.1::IRadioResponse
 
 # HALs released in Android O MR1 (Final Set)
@@ -248,8 +251,6 @@
 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
-09342041e17c429fce0034b9096d17849122111436a5f0053e7e59500e1cb89c android.hardware.media.omx@1.0::IOmxStore
 246a56d37d57a47224562c9d077b4a2886ce6242b9311bd98a17325944c280d7 android.hardware.neuralnetworks@1.0::types
 93eb3757ceaf21590fa4cd1d4a7dfe3b3794af5396100a6d25630879352abce9 android.hardware.neuralnetworks@1.0::IDevice
 f66f9a38541bf92001d3adcce678cd7e3da2262124befb460b1c9aea9492813b android.hardware.neuralnetworks@1.0::IExecutionCallback
@@ -257,3 +258,8 @@
 73e03573494ba96f0e711ab7f1956c5b2d54c3da690cd7ecf4d6d0f287447730 android.hardware.neuralnetworks@1.0::IPreparedModelCallback
 f4945e397b5dea41bb64518dfde59be71245d8a125fd1e0acffeb57ac7b08fed android.hardware.thermal@1.1::IThermal
 c8bc853546dd55584611def2a9fa1d99f657e3366c976d2f60fe6b8aa6d2cb87 android.hardware.thermal@1.1::IThermalCallback
+
+# ABI preserving changes to HALs during Android P
+fb92e2b40f8e9d494e8fd3b4ac18499a3216342e7cff160714c3bbf3660b6e79 android.hardware.gnss@1.0::IGnssConfiguration
+d4c10cb28318dba8efb22231a8c23e86ad8853f85775187c40b42a878a5ef4d5 android.hardware.automotive.vehicle@2.0::types
+cf72ff5a52bfa4d08e9e1000cf3ab5952a2d280c7f13cdad5ab7905c08050766 android.hardware.camera.metadata@3.2::types
diff --git a/drm/1.0/default/android.hardware.drm@1.0-service.rc b/drm/1.0/default/android.hardware.drm@1.0-service.rc
index e7beca3..a3457b5 100644
--- a/drm/1.0/default/android.hardware.drm@1.0-service.rc
+++ b/drm/1.0/default/android.hardware.drm@1.0-service.rc
@@ -1,4 +1,4 @@
-service drm-hal-1-0 /vendor/bin/hw/android.hardware.drm@1.0-service
+service vendor.drm-hal-1-0 /vendor/bin/hw/android.hardware.drm@1.0-service
     class hal
     user media
     group mediadrm drmrpc
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 a110eb1..4a1892b 100644
--- a/drm/1.0/vts/functional/drm_hal_clearkey_test.cpp
+++ b/drm/1.0/vts/functional/drm_hal_clearkey_test.cpp
@@ -89,10 +89,6 @@
     0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80,
     0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80};
 
-static const uint32_t k256SubSampleByteCount = 256;
-static const uint32_t k512SubSampleClearBytes = 512;
-static const uint32_t k512SubSampleEncryptedBytes = 512;
-
 class DrmHalClearkeyFactoryTest : public ::testing::VtsHalHidlTargetTestBase {
    public:
     virtual void SetUp() override {
@@ -349,8 +345,7 @@
  * Helper method to close a session
  */
 void DrmHalClearkeyPluginTest::closeSession(const SessionId& sessionId) {
-    auto result = drmPlugin->closeSession(sessionId);
-    EXPECT_EQ(Status::OK, result);
+    EXPECT_TRUE(drmPlugin->closeSession(sessionId).isOk());
 }
 
 /**
@@ -793,7 +788,7 @@
  */
 TEST_F(DrmHalClearkeyPluginTest, GenericEncryptNotSupported) {
     SessionId session = openSession();
-    ;
+
     hidl_vec<uint8_t> keyId = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
     hidl_vec<uint8_t> input = {1, 2, 3, 4, 5};
     hidl_vec<uint8_t> iv = std::vector<uint8_t>(AES_BLOCK_SIZE, 0);
@@ -822,7 +817,7 @@
 
 TEST_F(DrmHalClearkeyPluginTest, GenericSignNotSupported) {
     SessionId session = openSession();
-    ;
+
     hidl_vec<uint8_t> keyId = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
     hidl_vec<uint8_t> message = {1, 2, 3, 4, 5};
     auto res = drmPlugin->sign(session, keyId, message,
@@ -836,7 +831,7 @@
 
 TEST_F(DrmHalClearkeyPluginTest, GenericVerifyNotSupported) {
     SessionId session = openSession();
-    ;
+
     hidl_vec<uint8_t> keyId = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
     hidl_vec<uint8_t> message = {1, 2, 3, 4, 5};
     hidl_vec<uint8_t> signature = {0, 0, 0, 0, 0, 0, 0, 0,
@@ -926,8 +921,7 @@
  */
 TEST_F(DrmHalClearkeyPluginTest, SetMediaDrmSession) {
     auto sessionId = openSession();
-    Status status = cryptoPlugin->setMediaDrmSession(sessionId);
-    EXPECT_EQ(Status::OK, status);
+    EXPECT_TRUE(cryptoPlugin->setMediaDrmSession(sessionId).isOk());
     closeSession(sessionId);
 }
 
@@ -948,8 +942,7 @@
  */
 TEST_F(DrmHalClearkeyPluginTest, SetMediaDrmSessionEmptySession) {
     SessionId sessionId;
-    Status status = cryptoPlugin->setMediaDrmSession(sessionId);
-    EXPECT_EQ(Status::OK, status);
+    EXPECT_TRUE(cryptoPlugin->setMediaDrmSession(sessionId).isOk());
 }
 
 /**
@@ -1131,18 +1124,17 @@
 TEST_F(DrmHalClearkeyDecryptTest, ClearSegmentTest) {
     vector<uint8_t> iv(AES_BLOCK_SIZE, 0);
     const Pattern noPattern = {0, 0};
+    const uint32_t kByteCount = 256;
     const vector<SubSample> subSamples = {
-        {.numBytesOfClearData = k256SubSampleByteCount,
+        {.numBytesOfClearData = kByteCount,
          .numBytesOfEncryptedData = 0}};
     auto sessionId = openSession();
     loadKeys(sessionId);
-
-    Status status = cryptoPlugin->setMediaDrmSession(sessionId);
-    EXPECT_EQ(Status::OK, status);
+    EXPECT_TRUE(cryptoPlugin->setMediaDrmSession(sessionId).isOk());
 
     uint32_t byteCount = decrypt(Mode::UNENCRYPTED, &iv[0], subSamples,
             noPattern, Status::OK);
-    EXPECT_EQ(k256SubSampleByteCount, byteCount);
+    EXPECT_EQ(kByteCount, byteCount);
 
     closeSession(sessionId);
 }
@@ -1154,18 +1146,18 @@
 TEST_F(DrmHalClearkeyDecryptTest, EncryptedAesCtrSegmentTest) {
     vector<uint8_t> iv(AES_BLOCK_SIZE, 0);
     const Pattern noPattern = {0, 0};
+    const uint32_t kClearBytes = 512;
+    const uint32_t kEncryptedBytes = 512;
     const vector<SubSample> subSamples = {
-        {.numBytesOfClearData = k512SubSampleClearBytes,
-         .numBytesOfEncryptedData = k512SubSampleEncryptedBytes}};
+        {.numBytesOfClearData = kClearBytes,
+         .numBytesOfEncryptedData = kEncryptedBytes}};
     auto sessionId = openSession();
     loadKeys(sessionId);
-
-    Status status = cryptoPlugin->setMediaDrmSession(sessionId);
-    EXPECT_EQ(Status::OK, status);
+    EXPECT_TRUE(cryptoPlugin->setMediaDrmSession(sessionId).isOk());
 
     uint32_t byteCount = decrypt(Mode::AES_CTR, &iv[0], subSamples,
             noPattern, Status::OK);
-    EXPECT_EQ(k512SubSampleClearBytes + k512SubSampleEncryptedBytes, byteCount);
+    EXPECT_EQ(kClearBytes + kEncryptedBytes, byteCount);
 
     closeSession(sessionId);
 }
@@ -1177,12 +1169,10 @@
     vector<uint8_t> iv(AES_BLOCK_SIZE, 0);
     const Pattern noPattern = {0, 0};
     const vector<SubSample> subSamples = {
-        {.numBytesOfClearData = k256SubSampleByteCount,
-         .numBytesOfEncryptedData = k256SubSampleByteCount}};
+        {.numBytesOfClearData = 256,
+         .numBytesOfEncryptedData = 256}};
     auto sessionId = openSession();
-
-    Status status = cryptoPlugin->setMediaDrmSession(sessionId);
-    EXPECT_EQ(Status::OK, status);
+    EXPECT_TRUE(cryptoPlugin->setMediaDrmSession(sessionId).isOk());
 
     uint32_t byteCount = decrypt(Mode::AES_CTR, &iv[0], subSamples,
             noPattern, Status::ERROR_DRM_NO_LICENSE);
@@ -1207,9 +1197,9 @@
             EXPECT_EQ(Status::OK, status);
             EXPECT_EQ(0u, myKeySetId.size());
         });
-    ASSERT_OK(res);
+    EXPECT_OK(res);
 
-    ASSERT_TRUE(cryptoPlugin->setMediaDrmSession(sessionId).isOk());
+    EXPECT_TRUE(cryptoPlugin->setMediaDrmSession(sessionId).isOk());
 
     uint32_t byteCount = decrypt(Mode::AES_CTR, &iv[0], subSamples,
             noPattern, Status::ERROR_DRM_NO_LICENSE);
@@ -1224,9 +1214,11 @@
 TEST_F(DrmHalClearkeyDecryptTest, DecryptWithEmptyKey) {
     vector<uint8_t> iv(AES_BLOCK_SIZE, 0);
     const Pattern noPattern = {0, 0};
+    const uint32_t kClearBytes = 512;
+    const uint32_t kEncryptedBytes = 512;
     const vector<SubSample> subSamples = {
-        {.numBytesOfClearData = k512SubSampleClearBytes,
-         .numBytesOfEncryptedData = k512SubSampleEncryptedBytes}};
+        {.numBytesOfClearData = kClearBytes,
+         .numBytesOfEncryptedData = kEncryptedBytes}};
 
     // base 64 encoded JSON response string, must not contain padding character '='
     const hidl_string emptyKeyResponse =
@@ -1259,9 +1251,11 @@
 TEST_F(DrmHalClearkeyDecryptTest, DecryptWithKeyTooLong) {
     vector<uint8_t> iv(AES_BLOCK_SIZE, 0);
     const Pattern noPattern = {0, 0};
+    const uint32_t kClearBytes = 512;
+    const uint32_t kEncryptedBytes = 512;
     const vector<SubSample> subSamples = {
-        {.numBytesOfClearData = k512SubSampleClearBytes,
-         .numBytesOfEncryptedData = k512SubSampleEncryptedBytes}};
+        {.numBytesOfClearData = kClearBytes,
+         .numBytesOfEncryptedData = kEncryptedBytes}};
 
     // base 64 encoded JSON response string, must not contain padding character '='
     const hidl_string keyTooLongResponse =
diff --git a/dumpstate/1.0/default/android.hardware.dumpstate@1.0-service.rc b/dumpstate/1.0/default/android.hardware.dumpstate@1.0-service.rc
index 0f27248..f626f70 100644
--- a/dumpstate/1.0/default/android.hardware.dumpstate@1.0-service.rc
+++ b/dumpstate/1.0/default/android.hardware.dumpstate@1.0-service.rc
@@ -1,4 +1,4 @@
-service dumpstate-1-0 /vendor/bin/hw/android.hardware.dumpstate@1.0-service
+service vendor.dumpstate-1-0 /vendor/bin/hw/android.hardware.dumpstate@1.0-service
     class hal
     user system
     group system
diff --git a/dumpstate/1.0/vts/functional/VtsHalDumpstateV1_0TargetTest.cpp b/dumpstate/1.0/vts/functional/VtsHalDumpstateV1_0TargetTest.cpp
index 046bf56..9e866e7 100644
--- a/dumpstate/1.0/vts/functional/VtsHalDumpstateV1_0TargetTest.cpp
+++ b/dumpstate/1.0/vts/functional/VtsHalDumpstateV1_0TargetTest.cpp
@@ -16,6 +16,9 @@
 
 #define LOG_TAG "dumpstate_hidl_hal_test"
 
+#include <fcntl.h>
+#include <unistd.h>
+
 #include <android/hardware/dumpstate/1.0/IDumpstateDevice.h>
 #include <cutils/native_handle.h>
 #include <log/log.h>
@@ -58,50 +61,40 @@
 
 // Positive test: make sure dumpstateBoard() writes something to the FD.
 TEST_F(DumpstateHidlTest, TestOk) {
-    FILE* file = tmpfile();
-
-    ASSERT_NE(nullptr, file) << "Could not create temp file: " << strerror(errno);
+    // Index 0 corresponds to the read end of the pipe; 1 to the write end.
+    int fds[2];
+    ASSERT_EQ(0, pipe2(fds, O_NONBLOCK)) << errno;
 
     native_handle_t* handle = native_handle_create(1, 0);
     ASSERT_NE(handle, nullptr) << "Could not create native_handle";
-    handle->data[0] = fileno(file);
+    handle->data[0] = fds[1];
 
     Return<void> status = dumpstate->dumpstateBoard(handle);
     ASSERT_TRUE(status.isOk()) << "Status should be ok: " << status.description();
 
     // Check that at least one byte was written
-    rewind(file);  // can not fail
     char buff;
-    int read = fread(&buff, sizeof(buff), 1, file);
-    ASSERT_EQ(1, read) << "dumped nothing";
-
-    EXPECT_EQ(0, fclose(file)) << errno;
+    ASSERT_EQ(1, read(fds[0], &buff, 1)) << "dumped nothing";
 
     native_handle_close(handle);
-    native_handle_delete(handle);
 }
 
 // Positive test: make sure dumpstateBoard() doesn't crash with two FDs.
 TEST_F(DumpstateHidlTest, TestHandleWithTwoFds) {
-    FILE* file1 = tmpfile();
-    FILE* file2 = tmpfile();
-
-    ASSERT_NE(nullptr, file1) << "Could not create temp file #1: " << strerror(errno);
-    ASSERT_NE(nullptr, file2) << "Could not create temp file #2: " << strerror(errno);
+    int fds1[2];
+    int fds2[2];
+    ASSERT_EQ(0, pipe2(fds1, O_NONBLOCK)) << errno;
+    ASSERT_EQ(0, pipe2(fds2, O_NONBLOCK)) << errno;
 
     native_handle_t* handle = native_handle_create(2, 0);
     ASSERT_NE(handle, nullptr) << "Could not create native_handle";
-    handle->data[0] = fileno(file1);
-    handle->data[1] = fileno(file2);
+    handle->data[0] = fds1[1];
+    handle->data[1] = fds2[1];
 
     Return<void> status = dumpstate->dumpstateBoard(handle);
     ASSERT_TRUE(status.isOk()) << "Status should be ok: " << status.description();
 
-    EXPECT_EQ(0, fclose(file1)) << errno;
-    EXPECT_EQ(0, fclose(file2)) << errno;
-
     native_handle_close(handle);
-    native_handle_delete(handle);
 }
 
 int main(int argc, char** argv) {
diff --git a/gatekeeper/1.0/default/android.hardware.gatekeeper@1.0-service.rc b/gatekeeper/1.0/default/android.hardware.gatekeeper@1.0-service.rc
index d3f5e9d..da332c7 100644
--- a/gatekeeper/1.0/default/android.hardware.gatekeeper@1.0-service.rc
+++ b/gatekeeper/1.0/default/android.hardware.gatekeeper@1.0-service.rc
@@ -1,4 +1,4 @@
-service gatekeeper-1-0 /vendor/bin/hw/android.hardware.gatekeeper@1.0-service
+service vendor.gatekeeper-1-0 /vendor/bin/hw/android.hardware.gatekeeper@1.0-service
     class hal
     user system
     group system
diff --git a/gnss/1.0/IGnssConfiguration.hal b/gnss/1.0/IGnssConfiguration.hal
index e315286..75aee7c 100644
--- a/gnss/1.0/IGnssConfiguration.hal
+++ b/gnss/1.0/IGnssConfiguration.hal
@@ -78,9 +78,13 @@
      */
 
      /**
-      * This method enables or disables emergency SUPL.
+      * This method enables or disables NI emergency SUPL restrictions.
       *
-      * @param enabled True if emergency SUPL is to be enabled.
+      * @param enabled True if the device must only accept NI Emergency SUPL requests when the
+      *                     device is truly in emergency mode (e.g. the user has dialed 911, 112,
+      *                     etc...)
+      *                False if the device must accept NI Emergency SUPL any time they are
+      *                      received
       *
       * @return success True if operation was successful.
       */
diff --git a/gnss/1.0/default/Gnss.cpp b/gnss/1.0/default/Gnss.cpp
index cfcee24..f362749 100644
--- a/gnss/1.0/default/Gnss.cpp
+++ b/gnss/1.0/default/Gnss.cpp
@@ -508,7 +508,7 @@
         const AGpsRilInterface* agpsRilIface = static_cast<const AGpsRilInterface*>(
                 mGnssIface->get_extension(AGPS_RIL_INTERFACE));
         if (agpsRilIface == nullptr) {
-            ALOGE("%s GnssRil interface not implemented by GNSS HAL", __func__);
+            ALOGI("%s: GnssRil interface not implemented by HAL", __func__);
         } else {
             mGnssRil = new AGnssRil(agpsRilIface);
         }
@@ -528,7 +528,7 @@
                         mGnssIface->get_extension(GNSS_CONFIGURATION_INTERFACE));
 
         if (gnssConfigIface == nullptr) {
-            ALOGE("%s GnssConfiguration interface not implemented by GNSS HAL", __func__);
+            ALOGE("%s: GnssConfiguration interface not implemented by HAL", __func__);
         } else {
             mGnssConfig = new GnssConfiguration(gnssConfigIface);
         }
@@ -548,7 +548,7 @@
                         mGnssIface->get_extension(GPS_GEOFENCING_INTERFACE));
 
         if (gpsGeofencingIface == nullptr) {
-            ALOGE("%s GnssGeofencing interface not implemented by GNSS HAL", __func__);
+            ALOGE("%s: GnssGeofencing interface not implemented by HAL", __func__);
         } else {
             mGnssGeofencingIface = new GnssGeofencing(gpsGeofencingIface);
         }
@@ -567,7 +567,7 @@
         const AGpsInterface* agpsIface = static_cast<const AGpsInterface*>(
                 mGnssIface->get_extension(AGPS_INTERFACE));
         if (agpsIface == nullptr) {
-            ALOGE("%s AGnss interface not implemented by GNSS HAL", __func__);
+            ALOGE("%s: AGnss interface not implemented by HAL", __func__);
         } else {
             mAGnssIface = new AGnss(agpsIface);
         }
@@ -585,7 +585,7 @@
         const GpsNiInterface* gpsNiIface = static_cast<const GpsNiInterface*>(
                 mGnssIface->get_extension(GPS_NI_INTERFACE));
         if (gpsNiIface == nullptr) {
-            ALOGE("%s GnssNi interface not implemented by GNSS HAL", __func__);
+            ALOGI("%s: GnssNi interface not implemented by HAL", __func__);
         } else {
             mGnssNi = new GnssNi(gpsNiIface);
         }
@@ -605,7 +605,7 @@
                         mGnssIface->get_extension(GPS_MEASUREMENT_INTERFACE));
 
         if (gpsMeasurementIface == nullptr) {
-            ALOGE("%s GnssMeasurement interface not implemented by GNSS HAL", __func__);
+            ALOGE("%s: GnssMeasurement interface not implemented by HAL", __func__);
         } else {
             mGnssMeasurement = new GnssMeasurement(gpsMeasurementIface);
         }
@@ -625,8 +625,7 @@
                         mGnssIface->get_extension(GPS_NAVIGATION_MESSAGE_INTERFACE));
 
         if (gpsNavigationMessageIface == nullptr) {
-            ALOGE("%s GnssNavigationMessage interface not implemented by GNSS HAL",
-                  __func__);
+            ALOGI("%s: GnssNavigationMessage interface not implemented by HAL", __func__);
         } else {
             mGnssNavigationMessage = new GnssNavigationMessage(gpsNavigationMessageIface);
         }
@@ -646,7 +645,7 @@
                 mGnssIface->get_extension(GPS_XTRA_INTERFACE));
 
         if (gpsXtraIface == nullptr) {
-            ALOGE("%s GnssXtra interface not implemented by HAL", __func__);
+            ALOGI("%s: GnssXtra interface not implemented by HAL", __func__);
         } else {
             mGnssXtraIface = new GnssXtra(gpsXtraIface);
         }
@@ -666,7 +665,7 @@
                 mGnssIface->get_extension(GPS_DEBUG_INTERFACE));
 
         if (gpsDebugIface == nullptr) {
-            ALOGE("%s: GnssDebug interface is not implemented by HAL", __func__);
+            ALOGI("%s: GnssDebug interface not implemented by HAL", __func__);
         } else {
             mGnssDebug = new GnssDebug(gpsDebugIface);
         }
diff --git a/gnss/1.0/default/GnssUtils.cpp b/gnss/1.0/default/GnssUtils.cpp
index d9956d6..4514a21 100644
--- a/gnss/1.0/default/GnssUtils.cpp
+++ b/gnss/1.0/default/GnssUtils.cpp
@@ -51,23 +51,36 @@
     return gnssLocation;
 }
 
-GnssLocation convertToGnssLocation(FlpLocation* location) {
+GnssLocation convertToGnssLocation(FlpLocation* flpLocation) {
     GnssLocation gnssLocation = {};
-    if (location != nullptr) {
-        gnssLocation = {
-            // Bit mask applied (and 0's below) for same reason as above with GpsLocation
-            .gnssLocationFlags = static_cast<uint16_t>(location->flags & 0x1f),
-            .latitudeDegrees = location->latitude,
-            .longitudeDegrees = location->longitude,
-            .altitudeMeters = location->altitude,
-            .speedMetersPerSec = location->speed,
-            .bearingDegrees = location->bearing,
-            .horizontalAccuracyMeters = location->accuracy,
-            .verticalAccuracyMeters = 0,
-            .speedAccuracyMetersPerSecond = 0,
-            .bearingAccuracyDegrees = 0,
-            .timestamp = location->timestamp
-        };
+    if (flpLocation != nullptr) {
+        gnssLocation = {.gnssLocationFlags = 0,  // clear here and set below
+                        .latitudeDegrees = flpLocation->latitude,
+                        .longitudeDegrees = flpLocation->longitude,
+                        .altitudeMeters = flpLocation->altitude,
+                        .speedMetersPerSec = flpLocation->speed,
+                        .bearingDegrees = flpLocation->bearing,
+                        .horizontalAccuracyMeters = flpLocation->accuracy,
+                        .verticalAccuracyMeters = 0,
+                        .speedAccuracyMetersPerSecond = 0,
+                        .bearingAccuracyDegrees = 0,
+                        .timestamp = flpLocation->timestamp};
+        // FlpLocation flags different from GnssLocation flags
+        if (flpLocation->flags & FLP_LOCATION_HAS_LAT_LONG) {
+            gnssLocation.gnssLocationFlags |= GPS_LOCATION_HAS_LAT_LONG;
+        }
+        if (flpLocation->flags & FLP_LOCATION_HAS_ALTITUDE) {
+            gnssLocation.gnssLocationFlags |= GPS_LOCATION_HAS_ALTITUDE;
+        }
+        if (flpLocation->flags & FLP_LOCATION_HAS_SPEED) {
+            gnssLocation.gnssLocationFlags |= GPS_LOCATION_HAS_SPEED;
+        }
+        if (flpLocation->flags & FLP_LOCATION_HAS_BEARING) {
+            gnssLocation.gnssLocationFlags |= GPS_LOCATION_HAS_BEARING;
+        }
+        if (flpLocation->flags & FLP_LOCATION_HAS_ACCURACY) {
+            gnssLocation.gnssLocationFlags |= GPS_LOCATION_HAS_HORIZONTAL_ACCURACY;
+        }
     }
 
     return gnssLocation;
diff --git a/gnss/1.0/default/android.hardware.gnss@1.0-service.rc b/gnss/1.0/default/android.hardware.gnss@1.0-service.rc
index e629955..1a44d34 100644
--- a/gnss/1.0/default/android.hardware.gnss@1.0-service.rc
+++ b/gnss/1.0/default/android.hardware.gnss@1.0-service.rc
@@ -1,4 +1,4 @@
-service gnss_service /vendor/bin/hw/android.hardware.gnss@1.0-service
+service vendor.gnss_service /vendor/bin/hw/android.hardware.gnss@1.0-service
     class hal
     user gps
     group system gps radio
diff --git a/gnss/1.1/Android.bp b/gnss/1.1/Android.bp
new file mode 100644
index 0000000..6909807
--- /dev/null
+++ b/gnss/1.1/Android.bp
@@ -0,0 +1,20 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.gnss@1.1",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "IGnss.hal",
+        "IGnssCallback.hal",
+        "IGnssMeasurement.hal",
+    ],
+    interfaces: [
+        "android.hardware.gnss@1.0",
+        "android.hidl.base@1.0",
+    ],
+    gen_java: true,
+}
+
diff --git a/gnss/1.1/IGnss.hal b/gnss/1.1/IGnss.hal
new file mode 100644
index 0000000..d5e0c3e
--- /dev/null
+++ b/gnss/1.1/IGnss.hal
@@ -0,0 +1,73 @@
+/*
+ * 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.gnss@1.1;
+
+import @1.0::IGnss;
+
+import IGnssMeasurement;
+import IGnssCallback;
+
+/** Represents the standard GNSS (Global Navigation Satellite System) interface. */
+interface IGnss extends @1.0::IGnss {
+    /**
+     * Opens the interface and provides the callback routines to the implementation of this
+     * interface.
+     *
+     * @param callback Callback interface for IGnss.
+     *
+     * @return success Returns true on success.
+     */
+    setCallback_1_1(IGnssCallback callback) generates (bool success);
+
+    /**
+     * Sets the GnssPositionMode parameter, its associated recurrence value,
+     * the time between fixes, requested fix accuracy, time to first fix.
+     *
+     * @param mode Parameter must be one of MS_BASED or STANDALONE. It is allowed by the platform
+     *     (and it is recommended) to fallback to MS_BASED if MS_ASSISTED is passed in, and MS_BASED
+     *     is supported.
+     * @param recurrence GNSS postion recurrence value, either periodic or single.
+     * @param minIntervalMs Represents the time between fixes in milliseconds.
+     * @param preferredAccuracyMeters Represents the requested fix accuracy in meters.
+     * @param preferredTimeMs Represents the requested time to first fix in milliseconds.
+     * @param lowPowerMode When true, HAL must make strong tradeoffs to substantially restrict power
+     *     use. Specifically, in the case of a several second long minIntervalMs, the GNSS chipset
+     *     must not, on average, run power hungry operations like RF and signal searches for more
+     *     than one second per interval, and must make exactly one call to gnssSvStatusCb(), and
+     *     either zero or one call to GnssLocationCb() at each interval. When false, HAL must
+     *     operate in the nominal mode (similar to V1.0 where this flag wasn't present) and is
+     *     expected to make power and performance tradoffs such as duty-cycling when signal
+     *     conditions are good and more active searches to reacquire GNSS signals when no signals
+     *     are present.
+     *
+     * @return success Returns true if successful.
+     */
+    setPositionMode_1_1(GnssPositionMode mode,
+                        GnssPositionRecurrence recurrence,
+                        uint32_t minIntervalMs,
+                        uint32_t preferredAccuracyMeters,
+                        uint32_t preferredTimeMs,
+                        bool lowPowerMode)
+             generates (bool success);
+
+   /**
+    * This method returns the IGnssMeasurement interface.
+    *
+    * @return gnssMeasurementIface Handle to the IGnssMeasurement interface.
+    */
+    getExtensionGnssMeasurement_1_1() generates (IGnssMeasurement gnssMeasurementIface);
+};
\ No newline at end of file
diff --git a/gnss/1.1/IGnssCallback.hal b/gnss/1.1/IGnssCallback.hal
new file mode 100644
index 0000000..7a2849e
--- /dev/null
+++ b/gnss/1.1/IGnssCallback.hal
@@ -0,0 +1,38 @@
+/*
+ * 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.gnss@1.1;
+
+import @1.0::IGnssCallback;
+
+/**
+ * The interface is required for the HAL to communicate certain information
+ * like status and location info back to the platform, the platform implements
+ * the interfaces and passes a handle to the HAL.
+ */
+interface IGnssCallback extends @1.0::IGnssCallback {
+    /**
+     * Callback to inform framework of the GNSS HAL implementation model & version name.
+     *
+     * This is a user-visible string that identifies the model and version of the GNSS HAL.
+     * For example "ABC Co., Baseband Part 1234, RF Part 567, Software version 3.14.159"
+     *
+     * This must be called in response to IGnss::setCallback
+     *
+     * @param name String providing the name of the GNSS HAL implementation
+     */
+    gnssNameCb(string name);
+};
\ No newline at end of file
diff --git a/gnss/1.1/IGnssMeasurement.hal b/gnss/1.1/IGnssMeasurement.hal
new file mode 100644
index 0000000..75df5a8
--- /dev/null
+++ b/gnss/1.1/IGnssMeasurement.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.gnss@1.1;
+
+import @1.0::IGnssMeasurement;
+import @1.0::IGnssMeasurementCallback;
+
+/**
+ * Extended interface for GNSS Measurements support.
+ */
+interface IGnssMeasurement extends @1.0::IGnssMeasurement {
+
+    /**
+     * Initializes the interface and registers the callback routines with the HAL. After a
+     * successful call to 'setCallback_1_1' the HAL must begin to provide updates at an average
+     * output rate of 1Hz (occasional intra-measurement time offsets in the range from 0-2000msec
+     * can be tolerated.)
+     *
+     * @param callback Handle to GnssMeasurement callback interface.
+     * @param enableFullTracking If true, GNSS chipset must switch off duty cycling. In such mode
+     *     no clock discontinuities are expected and, when supported, carrier phase should be
+     *     continuous in good signal conditions. All constellations and frequency bands that the
+     *     chipset supports must be reported in this mode. The GNSS chipset is allowed to consume
+     *     more power in this mode. If false, API must behave as in HAL V1_0, optimizing power via
+     *     duty cycling, constellations and frequency limits, etc.
+     *
+     * @return initRet Returns SUCCESS if successful. Returns ERROR_ALREADY_INIT if a callback has
+     *     already been registered without a corresponding call to 'close'. Returns ERROR_GENERIC
+     *     for any other error. The HAL must not generate any other updates upon returning this
+     *     error code.
+     */
+    setCallback_1_1(IGnssMeasurementCallback callback, bool enableFullTracking)
+         generates (GnssMeasurementStatus initRet);
+
+};
diff --git a/gnss/1.1/vts/OWNERS b/gnss/1.1/vts/OWNERS
new file mode 100644
index 0000000..56648ad
--- /dev/null
+++ b/gnss/1.1/vts/OWNERS
@@ -0,0 +1,6 @@
+wyattriley@google.com
+gomo@google.com
+smalkos@google.com
+
+# VTS team
+yim@google.com
diff --git a/broadcastradio/1.1/tests/Android.bp b/gnss/1.1/vts/functional/Android.bp
similarity index 70%
copy from broadcastradio/1.1/tests/Android.bp
copy to gnss/1.1/vts/functional/Android.bp
index fa1fd94..67ef486 100644
--- a/broadcastradio/1.1/tests/Android.bp
+++ b/gnss/1.1/vts/functional/Android.bp
@@ -15,15 +15,15 @@
 //
 
 cc_test {
-    name: "android.hardware.broadcastradio@1.1-utils-tests",
-    vendor: true,
-    cflags: [
-        "-Wall",
-        "-Wextra",
-        "-Werror",
-    ],
+    name: "VtsHalGnssV1_1TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: [
-        "WorkerThread_test.cpp",
+        "gnss_hal_test.cpp",
+        "gnss_hal_test_cases.cpp",
+        "VtsHalGnssV1_1TargetTest.cpp",
     ],
-    static_libs: ["android.hardware.broadcastradio@1.1-utils-lib"],
+    static_libs: [
+        "android.hardware.gnss@1.0",
+        "android.hardware.gnss@1.1",
+    ],
 }
diff --git a/gnss/1.1/vts/functional/VtsHalGnssV1_1TargetTest.cpp b/gnss/1.1/vts/functional/VtsHalGnssV1_1TargetTest.cpp
new file mode 100644
index 0000000..9b805e4
--- /dev/null
+++ b/gnss/1.1/vts/functional/VtsHalGnssV1_1TargetTest.cpp
@@ -0,0 +1,24 @@
+/*
+ * 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 <VtsHalHidlTargetTestBase.h>
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    int status = RUN_ALL_TESTS();
+    ALOGI("Test result = %d", status);
+    return status;
+}
\ No newline at end of file
diff --git a/gnss/1.1/vts/functional/gnss_hal_test.cpp b/gnss/1.1/vts/functional/gnss_hal_test.cpp
new file mode 100644
index 0000000..2f4dd93
--- /dev/null
+++ b/gnss/1.1/vts/functional/gnss_hal_test.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_TAG "VtsHalGnssV1_1TargetTest"
+#include <log/log.h>
+
+#include <gnss_hal_test.h>
+
+#include <chrono>
+
+// Implementations for the main test class for GNSS HAL
+GnssHalTest::GnssHalTest()
+    : info_called_count_(0),
+      capabilities_called_count_(0),
+      location_called_count_(0),
+      name_called_count_(0),
+      notify_count_(0) {}
+
+void GnssHalTest::SetUp() {
+    gnss_hal_ = ::testing::VtsHalHidlTargetTestBase::getService<IGnss>();
+    ASSERT_NE(gnss_hal_, nullptr);
+}
+
+void GnssHalTest::TearDown() {
+    if (gnss_hal_ != nullptr) {
+        gnss_hal_->cleanup();
+    }
+    if (notify_count_ > 0) {
+        ALOGW("%d unprocessed callbacks discarded", notify_count_);
+    }
+}
+
+void GnssHalTest::notify() {
+    std::unique_lock<std::mutex> lock(mtx_);
+    notify_count_++;
+    cv_.notify_one();
+}
+
+std::cv_status GnssHalTest::wait(int timeoutSeconds) {
+    std::unique_lock<std::mutex> lock(mtx_);
+
+    auto status = std::cv_status::no_timeout;
+    while (notify_count_ == 0) {
+        status = cv_.wait_for(lock, std::chrono::seconds(timeoutSeconds));
+        if (status == std::cv_status::timeout) return status;
+    }
+    notify_count_--;
+    return status;
+}
+
+Return<void> GnssHalTest::GnssCallback::gnssSetSystemInfoCb(
+    const IGnssCallback::GnssSystemInfo& info) {
+    ALOGI("Info received, year %d", info.yearOfHw);
+    parent_.info_called_count_++;
+    parent_.last_info_ = info;
+    parent_.notify();
+    return Void();
+}
+
+Return<void> GnssHalTest::GnssCallback::gnssSetCapabilitesCb(uint32_t capabilities) {
+    ALOGI("Capabilities received %d", capabilities);
+    parent_.capabilities_called_count_++;
+    parent_.last_capabilities_ = capabilities;
+    parent_.notify();
+    return Void();
+}
+
+Return<void> GnssHalTest::GnssCallback::gnssNameCb(const android::hardware::hidl_string& name) {
+    ALOGI("Name received: %s", name.c_str());
+    parent_.name_called_count_++;
+    parent_.last_name_ = name;
+    parent_.notify();
+    return Void();
+}
+
+Return<void> GnssHalTest::GnssCallback::gnssLocationCb(const GnssLocation& location) {
+    ALOGI("Location received");
+    parent_.location_called_count_++;
+    parent_.last_location_ = location;
+    parent_.notify();
+    return Void();
+}
diff --git a/gnss/1.1/vts/functional/gnss_hal_test.h b/gnss/1.1/vts/functional/gnss_hal_test.h
new file mode 100644
index 0000000..bbc8d9f
--- /dev/null
+++ b/gnss/1.1/vts/functional/gnss_hal_test.h
@@ -0,0 +1,226 @@
+/*
+ * 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 GNSS_HAL_TEST_H_
+#define GNSS_HAL_TEST_H_
+
+#include <android/hardware/gnss/1.1/IGnss.h>
+
+#include <VtsHalHidlTargetTestBase.h>
+
+#include <condition_variable>
+#include <mutex>
+
+using android::hardware::Return;
+using android::hardware::Void;
+
+using android::hardware::gnss::V1_0::GnssLocation;
+
+using android::hardware::gnss::V1_1::IGnss;
+using android::hardware::gnss::V1_1::IGnssCallback;
+using android::hardware::gnss::V1_0::GnssLocationFlags;
+using android::sp;
+#define TIMEOUT_SEC 2  // for basic commands/responses
+
+// The main test class for GNSS HAL.
+class GnssHalTest : public ::testing::VtsHalHidlTargetTestBase {
+   public:
+    GnssHalTest();
+
+    virtual void SetUp() override;
+
+    virtual void TearDown() override;
+
+    /* Used as a mechanism to inform the test that a callback has occurred */
+    void notify();
+
+    /* Test code calls this function to wait for a callback */
+    std::cv_status wait(int timeoutSeconds);
+
+    /* Callback class for data & Event. */
+    class GnssCallback : public IGnssCallback {
+       public:
+        GnssHalTest& parent_;
+
+        GnssCallback(GnssHalTest& parent) : parent_(parent){};
+
+        virtual ~GnssCallback() = default;
+
+        // Dummy callback handlers
+        Return<void> gnssStatusCb(const IGnssCallback::GnssStatusValue /* status */) override {
+            return Void();
+        }
+        Return<void> gnssSvStatusCb(const IGnssCallback::GnssSvStatus& /* svStatus */) override {
+            return Void();
+        }
+        Return<void> gnssNmeaCb(int64_t /* timestamp */,
+                                const android::hardware::hidl_string& /* nmea */) override {
+            return Void();
+        }
+        Return<void> gnssAcquireWakelockCb() override { return Void(); }
+        Return<void> gnssReleaseWakelockCb() override { return Void(); }
+        Return<void> gnssRequestTimeCb() override { return Void(); }
+        // Actual (test) callback handlers
+        Return<void> gnssLocationCb(const GnssLocation& location) override;
+        Return<void> gnssSetCapabilitesCb(uint32_t capabilities) override;
+        Return<void> gnssSetSystemInfoCb(const IGnssCallback::GnssSystemInfo& info) override;
+        Return<void> gnssNameCb(const android::hardware::hidl_string& name) override;
+    };
+
+    /*
+     * StartAndGetSingleLocation:
+     * Helper function to get one Location and check fields
+     *
+     * returns  true if a location was successfully generated
+     */
+    bool StartAndGetSingleLocation(bool checkAccuracies) {
+        auto result = gnss_hal_->start();
+
+        EXPECT_TRUE(result.isOk());
+        EXPECT_TRUE(result);
+
+        /*
+         * GPS signals initially optional for this test, so don't expect fast fix,
+         * or no timeout, unless signal is present
+         */
+        int firstGnssLocationTimeoutSeconds = 15;
+
+        wait(firstGnssLocationTimeoutSeconds);
+        EXPECT_EQ(location_called_count_, 1);
+
+        if (location_called_count_ > 0) {
+            // don't require speed on first fix
+            CheckLocation(last_location_, checkAccuracies, false);
+            return true;
+        }
+        return false;
+    }
+
+    /*
+     * CheckLocation:
+     *   Helper function to vet Location fields when calling setPositionMode_1_1()
+     */
+    void CheckLocation(GnssLocation& location, bool checkAccuracies, bool checkSpeed) {
+        EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_LAT_LONG);
+        EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_ALTITUDE);
+        if (checkSpeed) {
+            EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_SPEED);
+        }
+        EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_HORIZONTAL_ACCURACY);
+        // New uncertainties available in O must be provided,
+        // at least when paired with modern hardware (2017+)
+        if (checkAccuracies) {
+            EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_VERTICAL_ACCURACY);
+            if (checkSpeed) {
+                EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_SPEED_ACCURACY);
+                if (location.gnssLocationFlags & GnssLocationFlags::HAS_BEARING) {
+                    EXPECT_TRUE(location.gnssLocationFlags &
+                                GnssLocationFlags::HAS_BEARING_ACCURACY);
+                }
+            }
+        }
+        EXPECT_GE(location.latitudeDegrees, -90.0);
+        EXPECT_LE(location.latitudeDegrees, 90.0);
+        EXPECT_GE(location.longitudeDegrees, -180.0);
+        EXPECT_LE(location.longitudeDegrees, 180.0);
+        EXPECT_GE(location.altitudeMeters, -1000.0);
+        EXPECT_LE(location.altitudeMeters, 30000.0);
+        if (checkSpeed) {
+            EXPECT_GE(location.speedMetersPerSec, 0.0);
+            EXPECT_LE(location.speedMetersPerSec, 5.0);  // VTS tests are stationary.
+
+            // Non-zero speeds must be reported with an associated bearing
+            if (location.speedMetersPerSec > 0.0) {
+                EXPECT_TRUE(location.gnssLocationFlags & GnssLocationFlags::HAS_BEARING);
+            }
+        }
+
+        /*
+         * Tolerating some especially high values for accuracy estimate, in case of
+         * first fix with especially poor geometry (happens occasionally)
+         */
+        EXPECT_GT(location.horizontalAccuracyMeters, 0.0);
+        EXPECT_LE(location.horizontalAccuracyMeters, 250.0);
+
+        /*
+         * Some devices may define bearing as -180 to +180, others as 0 to 360.
+         * Both are okay & understandable.
+         */
+        if (location.gnssLocationFlags & GnssLocationFlags::HAS_BEARING) {
+            EXPECT_GE(location.bearingDegrees, -180.0);
+            EXPECT_LE(location.bearingDegrees, 360.0);
+        }
+        if (location.gnssLocationFlags & GnssLocationFlags::HAS_VERTICAL_ACCURACY) {
+            EXPECT_GT(location.verticalAccuracyMeters, 0.0);
+            EXPECT_LE(location.verticalAccuracyMeters, 500.0);
+        }
+        if (location.gnssLocationFlags & GnssLocationFlags::HAS_SPEED_ACCURACY) {
+            EXPECT_GT(location.speedAccuracyMetersPerSecond, 0.0);
+            EXPECT_LE(location.speedAccuracyMetersPerSecond, 50.0);
+        }
+        if (location.gnssLocationFlags & GnssLocationFlags::HAS_BEARING_ACCURACY) {
+            EXPECT_GT(location.bearingAccuracyDegrees, 0.0);
+            EXPECT_LE(location.bearingAccuracyDegrees, 360.0);
+        }
+
+        // Check timestamp > 1.48e12 (47 years in msec - 1970->2017+)
+        EXPECT_GT(location.timestamp, 1.48e12);
+    }
+
+    /*
+     * StopAndClearLocations:
+     * Helper function to stop locations
+     *
+     * returns  true if a location was successfully generated
+     */
+    void StopAndClearLocations() {
+        auto result = gnss_hal_->stop();
+
+        EXPECT_TRUE(result.isOk());
+        EXPECT_TRUE(result);
+
+        /*
+         * Clear notify/waiting counter, allowing up till the timeout after
+         * the last reply for final startup messages to arrive (esp. system
+         * info.)
+         */
+        while (wait(TIMEOUT_SEC) == std::cv_status::no_timeout) {
+        }
+    }
+
+    sp<IGnss> gnss_hal_;         // GNSS HAL to call into
+    sp<IGnssCallback> gnss_cb_;  // Primary callback interface
+
+    /* Count of calls to set the following items, and the latest item (used by
+     * test.)
+     */
+    int info_called_count_;
+    IGnssCallback::GnssSystemInfo last_info_;
+    uint32_t last_capabilities_;
+    int capabilities_called_count_;
+    int location_called_count_;
+    GnssLocation last_location_;
+
+    int name_called_count_;
+    android::hardware::hidl_string last_name_;
+
+   private:
+    std::mutex mtx_;
+    std::condition_variable cv_;
+    int notify_count_;
+};
+
+#endif  // GNSS_HAL_TEST_H_
diff --git a/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp b/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp
new file mode 100644
index 0000000..47bad34
--- /dev/null
+++ b/gnss/1.1/vts/functional/gnss_hal_test_cases.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.
+ */
+
+#include <gnss_hal_test.h>
+
+#include <VtsHalHidlTargetTestBase.h>
+
+using android::hardware::gnss::V1_1::IGnssMeasurement;
+
+/*
+ * SetupTeardownCreateCleanup:
+ * Requests the gnss HAL then calls cleanup
+ *
+ * Empty test fixture to verify basic Setup & Teardown
+ */
+TEST_F(GnssHalTest, SetupTeardownCreateCleanup) {}
+
+/*
+ * SetCallbackResponses:
+ * Sets up the callback, awaits the capability, info & name
+ */
+TEST_F(GnssHalTest, SetCallbackResponses) {
+    gnss_cb_ = new GnssCallback(*this);
+    ASSERT_NE(gnss_cb_, nullptr);
+
+    auto result = gnss_hal_->setCallback_1_1(gnss_cb_);
+    if (!result.isOk()) {
+        ALOGE("result of failed setCallback %s", result.description().c_str());
+    }
+
+    ASSERT_TRUE(result.isOk());
+    ASSERT_TRUE(result);
+
+    /*
+     * All capabilities, name and systemInfo callbacks should trigger
+     */
+    EXPECT_EQ(std::cv_status::no_timeout, wait(TIMEOUT_SEC));
+    EXPECT_EQ(std::cv_status::no_timeout, wait(TIMEOUT_SEC));
+    EXPECT_EQ(std::cv_status::no_timeout, wait(TIMEOUT_SEC));
+
+    EXPECT_EQ(capabilities_called_count_, 1);
+    EXPECT_EQ(info_called_count_, 1);
+    EXPECT_EQ(name_called_count_, 1);
+}
+
+/*
+ * TestGnssMeasurementCallback:
+ * Gets the GnssMeasurementExtension and verify that it returns an actual extension.
+ */
+TEST_F(GnssHalTest, TestGnssMeasurementCallback) {
+    auto gnssMeasurement = gnss_hal_->getExtensionGnssMeasurement_1_1();
+    ASSERT_TRUE(gnssMeasurement.isOk());
+    if (last_capabilities_ & IGnssCallback::Capabilities::MEASUREMENTS) {
+        sp<IGnssMeasurement> iGnssMeas = gnssMeasurement;
+        EXPECT_NE(iGnssMeas, nullptr);
+    }
+}
+
+/*
+ * GetLocation:
+ * Turns on location, waits for at least 5 locations allowing max of LOCATION_TIMEOUT_SUBSEQUENT_SEC
+ * between one location and the next. Also ensure that MIN_INTERVAL_MSEC is respected by waiting
+ * NO_LOCATION_PERIOD_SEC and verfiy that no location is received. Also perform validity checks on
+ * each received location.
+ */
+TEST_F(GnssHalTest, GetLocationLowPower) {
+#define MIN_INTERVAL_MSEC 5000
+#define PREFERRED_ACCURACY 0   // Ideally perfect (matches GnssLocationProvider)
+#define PREFERRED_TIME_MSEC 0  // Ideally immediate
+
+#define LOCATION_TIMEOUT_SUBSEQUENT_SEC (MIN_INTERVAL_MSEC + 1000) / 1000
+#define NO_LOCATION_PERIOD_SEC 2
+#define LOCATIONS_TO_CHECK 5
+#define LOW_POWER_MODE true
+
+    bool checkMoreAccuracies = (info_called_count_ > 0 && last_info_.yearOfHw >= 2017);
+
+    auto result = gnss_hal_->setPositionMode_1_1(
+        IGnss::GnssPositionMode::MS_BASED, IGnss::GnssPositionRecurrence::RECURRENCE_PERIODIC,
+        MIN_INTERVAL_MSEC, PREFERRED_ACCURACY, PREFERRED_TIME_MSEC, LOW_POWER_MODE);
+
+    ASSERT_TRUE(result.isOk());
+    EXPECT_TRUE(result);
+
+    EXPECT_TRUE(StartAndGetSingleLocation(checkMoreAccuracies));
+
+    for (int i = 1; i < LOCATIONS_TO_CHECK; i++) {
+        // Verify that MIN_INTERVAL_MSEC is respected by waiting NO_LOCATION_PERIOD_SEC and
+        // ensure that no location is received yet
+        wait(NO_LOCATION_PERIOD_SEC);
+        EXPECT_EQ(location_called_count_, i);
+        EXPECT_EQ(std::cv_status::no_timeout,
+                  wait(LOCATION_TIMEOUT_SUBSEQUENT_SEC - NO_LOCATION_PERIOD_SEC));
+        EXPECT_EQ(location_called_count_, i + 1);
+        CheckLocation(last_location_, checkMoreAccuracies, true);
+    }
+
+    StopAndClearLocations();
+}
\ No newline at end of file
diff --git a/graphics/allocator/2.0/Android.bp b/graphics/allocator/2.0/Android.bp
index 0b0722e..50b474e 100644
--- a/graphics/allocator/2.0/Android.bp
+++ b/graphics/allocator/2.0/Android.bp
@@ -5,7 +5,6 @@
     root: "android.hardware",
     vndk: {
         enabled: true,
-        support_system_process: true,
     },
     srcs: [
         "IAllocator.hal",
diff --git a/graphics/allocator/2.0/default/android.hardware.graphics.allocator@2.0-service.rc b/graphics/allocator/2.0/default/android.hardware.graphics.allocator@2.0-service.rc
index 70f2ef8..6eee71f 100644
--- a/graphics/allocator/2.0/default/android.hardware.graphics.allocator@2.0-service.rc
+++ b/graphics/allocator/2.0/default/android.hardware.graphics.allocator@2.0-service.rc
@@ -1,4 +1,4 @@
-service gralloc-2-0 /vendor/bin/hw/android.hardware.graphics.allocator@2.0-service
+service vendor.gralloc-2-0 /vendor/bin/hw/android.hardware.graphics.allocator@2.0-service
     class hal animation
     user system
     group graphics drmrpc
diff --git a/graphics/composer/2.1/default/IComposerCommandBuffer.h b/graphics/composer/2.1/default/IComposerCommandBuffer.h
index 058709c..c752f8a 100644
--- a/graphics/composer/2.1/default/IComposerCommandBuffer.h
+++ b/graphics/composer/2.1/default/IComposerCommandBuffer.h
@@ -92,6 +92,13 @@
     bool writeQueue(bool* outQueueChanged, uint32_t* outCommandLength,
             hidl_vec<hidl_handle>* outCommandHandles)
     {
+        if (mDataWritten == 0) {
+            *outQueueChanged = false;
+            *outCommandLength = 0;
+            outCommandHandles->setToExternal(nullptr, 0);
+            return true;
+        }
+
         // After data are written to the queue, it may not be read by the
         // remote reader when
         //
diff --git a/graphics/composer/2.1/default/android.hardware.graphics.composer@2.1-service.rc b/graphics/composer/2.1/default/android.hardware.graphics.composer@2.1-service.rc
index 51b0e3b..3b6710b 100644
--- a/graphics/composer/2.1/default/android.hardware.graphics.composer@2.1-service.rc
+++ b/graphics/composer/2.1/default/android.hardware.graphics.composer@2.1-service.rc
@@ -1,4 +1,4 @@
-service hwcomposer-2-1 /vendor/bin/hw/android.hardware.graphics.composer@2.1-service
+service vendor.hwcomposer-2-1 /vendor/bin/hw/android.hardware.graphics.composer@2.1-service
     class hal animation
     user system
     group graphics drmrpc
diff --git a/graphics/composer/2.1/vts/OWNERS b/graphics/composer/2.1/vts/OWNERS
new file mode 100644
index 0000000..ef69d7c
--- /dev/null
+++ b/graphics/composer/2.1/vts/OWNERS
@@ -0,0 +1,6 @@
+# Graphics team
+olv@google.com
+
+# VTS team
+yim@google.com
+zhuoyao@google.com
\ No newline at end of file
diff --git a/graphics/mapper/2.0/vts/OWNERS b/graphics/mapper/2.0/vts/OWNERS
new file mode 100644
index 0000000..ef69d7c
--- /dev/null
+++ b/graphics/mapper/2.0/vts/OWNERS
@@ -0,0 +1,6 @@
+# Graphics team
+olv@google.com
+
+# VTS team
+yim@google.com
+zhuoyao@google.com
\ No newline at end of file
diff --git a/graphics/mapper/2.1/Android.bp b/graphics/mapper/2.1/Android.bp
new file mode 100644
index 0000000..7438d64
--- /dev/null
+++ b/graphics/mapper/2.1/Android.bp
@@ -0,0 +1,20 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.graphics.mapper@2.1",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+        support_system_process: true,
+    },
+    srcs: [
+        "IMapper.hal",
+    ],
+    interfaces: [
+        "android.hardware.graphics.common@1.0",
+        "android.hardware.graphics.mapper@2.0",
+        "android.hidl.base@1.0",
+    ],
+    gen_java: false,
+}
+
diff --git a/graphics/mapper/2.1/IMapper.hal b/graphics/mapper/2.1/IMapper.hal
new file mode 100644
index 0000000..a23656d
--- /dev/null
+++ b/graphics/mapper/2.1/IMapper.hal
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ */
+
+package android.hardware.graphics.mapper@2.1;
+
+import android.hardware.graphics.mapper@2.0::Error;
+import android.hardware.graphics.mapper@2.0::IMapper;
+
+interface IMapper extends android.hardware.graphics.mapper@2.0::IMapper {
+    /**
+     * Validate that the buffer can be safely accessed by a caller who assumes
+     * the specified descriptorInfo and stride. This must at least validate
+     * that the buffer size is large enough. Validating the buffer against
+     * individual buffer attributes is optional.
+     *
+     * @param buffer is the buffer to validate against.
+     * @param descriptorInfo specifies the attributes of the buffer.
+     * @param stride is the buffer stride returned by IAllocator::allocate.
+     * @return error is NONE upon success. Otherwise,
+     *                  BAD_BUFFER when the buffer is invalid.
+     *                  BAD_VALUE when buffer cannot be safely accessed
+     */
+    validateBufferSize(pointer buffer,
+                       BufferDescriptorInfo descriptorInfo,
+                       uint32_t stride)
+            generates (Error error);
+
+    /**
+     * Get the transport size of a buffer. An imported buffer handle is a raw
+     * buffer handle with the process-local runtime data appended. This
+     * function, for example, allows a caller to omit the process-local
+     * runtime data at the tail when serializing the imported buffer handle.
+     *
+     * Note that a client might or might not omit the process-local runtime
+     * data when sending an imported buffer handle. The mapper must support
+     * both cases on the receiving end.
+     *
+     * @param buffer is the buffer to get the transport size from.
+     * @return error is NONE upon success. Otherwise,
+     *                  BAD_BUFFER when the buffer is invalid.
+     * @return numFds is the number of file descriptors needed for transport.
+     * @return numInts is the number of integers needed for transport.
+     */
+    getTransportSize(pointer buffer)
+            generates (Error error,
+                       uint32_t numFds,
+                       uint32_t numInts);
+};
diff --git a/graphics/mapper/2.1/vts/OWNERS b/graphics/mapper/2.1/vts/OWNERS
new file mode 100644
index 0000000..ef69d7c
--- /dev/null
+++ b/graphics/mapper/2.1/vts/OWNERS
@@ -0,0 +1,6 @@
+# Graphics team
+olv@google.com
+
+# VTS team
+yim@google.com
+zhuoyao@google.com
\ No newline at end of file
diff --git a/graphics/mapper/2.1/vts/functional/Android.bp b/graphics/mapper/2.1/vts/functional/Android.bp
new file mode 100644
index 0000000..578d298
--- /dev/null
+++ b/graphics/mapper/2.1/vts/functional/Android.bp
@@ -0,0 +1,32 @@
+//
+// Copyright (C) 2016 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_test {
+    name: "VtsHalGraphicsMapperV2_1TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: ["VtsHalGraphicsMapperV2_1TargetTest.cpp"],
+    shared_libs: [
+        "libsync",
+    ],
+    static_libs: [
+        "android.hardware.graphics.allocator@2.0",
+        "android.hardware.graphics.common@1.0",
+        "android.hardware.graphics.mapper@2.0",
+        "android.hardware.graphics.mapper@2.1",
+        "libVtsHalGraphicsMapperTestUtils",
+        "libnativehelper",
+    ],
+}
diff --git a/graphics/mapper/2.1/vts/functional/VtsHalGraphicsMapperV2_1TargetTest.cpp b/graphics/mapper/2.1/vts/functional/VtsHalGraphicsMapperV2_1TargetTest.cpp
new file mode 100644
index 0000000..4067c8d
--- /dev/null
+++ b/graphics/mapper/2.1/vts/functional/VtsHalGraphicsMapperV2_1TargetTest.cpp
@@ -0,0 +1,247 @@
+/*
+ * 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 "VtsHalGraphicsMapperV2_1TargetTest"
+
+#include <VtsHalHidlTargetTestBase.h>
+#include <android-base/logging.h>
+#include <android/hardware/graphics/mapper/2.1/IMapper.h>
+#include <sync/sync.h>
+#include "VtsHalGraphicsMapperTestUtils.h"
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace mapper {
+namespace V2_1 {
+namespace tests {
+namespace {
+
+using android::hardware::graphics::mapper::V2_0::Error;
+
+using android::hardware::graphics::common::V1_0::BufferUsage;
+using android::hardware::graphics::common::V1_0::PixelFormat;
+
+class Gralloc : public V2_0::tests::Gralloc {
+   public:
+    Gralloc() : V2_0::tests::Gralloc() {
+        if (::testing::Test::HasFatalFailure()) {
+            return;
+        }
+
+        init();
+    }
+
+    sp<IMapper> getMapper() const { return mMapper; }
+
+    bool validateBufferSize(const native_handle_t* bufferHandle,
+                            const IMapper::BufferDescriptorInfo& descriptorInfo, uint32_t stride) {
+        auto buffer = const_cast<native_handle_t*>(bufferHandle);
+
+        Error error = mMapper->validateBufferSize(buffer, descriptorInfo, stride);
+        return error == Error::NONE;
+    }
+
+    void getTransportSize(const native_handle_t* bufferHandle, uint32_t* numFds,
+                          uint32_t* numInts) {
+        auto buffer = const_cast<native_handle_t*>(bufferHandle);
+
+        *numFds = 0;
+        *numInts = 0;
+        mMapper->getTransportSize(buffer, [&](const auto& tmpError, const auto& tmpNumFds,
+                                              const auto& tmpNumInts) {
+            ASSERT_EQ(Error::NONE, tmpError) << "failed to get transport size";
+            ASSERT_GE(bufferHandle->numFds, int(tmpNumFds)) << "invalid numFds " << tmpNumFds;
+            ASSERT_GE(bufferHandle->numInts, int(tmpNumInts)) << "invalid numInts " << tmpNumInts;
+
+            *numFds = tmpNumFds;
+            *numInts = tmpNumInts;
+        });
+    }
+
+   private:
+    void init() {
+        mMapper = IMapper::castFrom(V2_0::tests::Gralloc::getMapper());
+        ASSERT_NE(nullptr, mMapper.get()) << "failed to find IMapper 2.1";
+    }
+
+    sp<IMapper> mMapper;
+};
+
+class GraphicsMapperHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+   protected:
+    void SetUp() override {
+        ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique<Gralloc>());
+
+        mDummyDescriptorInfo.width = 64;
+        mDummyDescriptorInfo.height = 64;
+        mDummyDescriptorInfo.layerCount = 1;
+        mDummyDescriptorInfo.format = PixelFormat::RGBA_8888;
+        mDummyDescriptorInfo.usage =
+            static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN);
+    }
+
+    void TearDown() override {}
+
+    std::unique_ptr<Gralloc> mGralloc;
+    IMapper::BufferDescriptorInfo mDummyDescriptorInfo{};
+};
+
+/**
+ * Test that IMapper::validateBufferSize works.
+ */
+TEST_F(GraphicsMapperHidlTest, ValidateBufferSizeBasic) {
+    const native_handle_t* bufferHandle;
+    uint32_t stride;
+    ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(mDummyDescriptorInfo, true, &stride));
+
+    ASSERT_TRUE(mGralloc->validateBufferSize(bufferHandle, mDummyDescriptorInfo, stride));
+
+    ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(bufferHandle));
+}
+
+/**
+ * Test IMapper::validateBufferSize with invalid buffers.
+ */
+TEST_F(GraphicsMapperHidlTest, ValidateBufferSizeBadBuffer) {
+    native_handle_t* invalidHandle = nullptr;
+    Error ret = mGralloc->getMapper()->validateBufferSize(invalidHandle, mDummyDescriptorInfo,
+                                                          mDummyDescriptorInfo.width);
+    ASSERT_EQ(Error::BAD_BUFFER, ret)
+        << "validateBufferSize with nullptr did not fail with BAD_BUFFER";
+
+    invalidHandle = native_handle_create(0, 0);
+    ret = mGralloc->getMapper()->validateBufferSize(invalidHandle, mDummyDescriptorInfo,
+                                                    mDummyDescriptorInfo.width);
+    ASSERT_EQ(Error::BAD_BUFFER, ret)
+        << "validateBufferSize with invalid handle did not fail with BAD_BUFFER";
+    native_handle_delete(invalidHandle);
+
+    native_handle_t* rawBufferHandle;
+    ASSERT_NO_FATAL_FAILURE(rawBufferHandle = const_cast<native_handle_t*>(
+                                mGralloc->allocate(mDummyDescriptorInfo, false)));
+    ret = mGralloc->getMapper()->validateBufferSize(rawBufferHandle, mDummyDescriptorInfo,
+                                                    mDummyDescriptorInfo.width);
+    ASSERT_EQ(Error::BAD_BUFFER, ret)
+        << "validateBufferSize with raw buffer handle did not fail with BAD_BUFFER";
+    native_handle_delete(rawBufferHandle);
+}
+
+/**
+ * Test IMapper::validateBufferSize with invalid descriptor and/or stride.
+ */
+TEST_F(GraphicsMapperHidlTest, ValidateBufferSizeBadValue) {
+    auto info = mDummyDescriptorInfo;
+    info.width = 1024;
+    info.height = 1024;
+    info.layerCount = 1;
+    info.format = PixelFormat::RGBA_8888;
+
+    native_handle_t* bufferHandle;
+    uint32_t stride;
+    ASSERT_NO_FATAL_FAILURE(
+        bufferHandle = const_cast<native_handle_t*>(mGralloc->allocate(info, true, &stride)));
+
+    // All checks below test if a 8MB buffer can fit in a 4MB buffer.
+    info.width *= 2;
+    Error ret = mGralloc->getMapper()->validateBufferSize(bufferHandle, info, stride);
+    ASSERT_EQ(Error::BAD_VALUE, ret)
+        << "validateBufferSize with bad width did not fail with BAD_VALUE";
+    info.width /= 2;
+
+    info.height *= 2;
+    ret = mGralloc->getMapper()->validateBufferSize(bufferHandle, info, stride);
+    ASSERT_EQ(Error::BAD_VALUE, ret)
+        << "validateBufferSize with bad height did not fail with BAD_VALUE";
+    info.height /= 2;
+
+    info.layerCount *= 2;
+    ret = mGralloc->getMapper()->validateBufferSize(bufferHandle, info, stride);
+    ASSERT_EQ(Error::BAD_VALUE, ret)
+        << "validateBufferSize with bad layer count did not fail with BAD_VALUE";
+    info.layerCount /= 2;
+
+    info.format = PixelFormat::RGBA_FP16;
+    ret = mGralloc->getMapper()->validateBufferSize(bufferHandle, info, stride);
+    ASSERT_EQ(Error::BAD_VALUE, ret)
+        << "validateBufferSize with bad format did not fail with BAD_VALUE";
+    info.format = PixelFormat::RGBA_8888;
+
+    ret = mGralloc->getMapper()->validateBufferSize(bufferHandle, mDummyDescriptorInfo, stride * 2);
+    ASSERT_EQ(Error::BAD_VALUE, ret)
+        << "validateBufferSize with bad stride did not fail with BAD_VALUE";
+
+    ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(bufferHandle));
+}
+
+/**
+ * Test IMapper::getTransportSize.
+ */
+TEST_F(GraphicsMapperHidlTest, GetTransportSizeBasic) {
+    const native_handle_t* bufferHandle;
+    uint32_t numFds;
+    uint32_t numInts;
+    ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(mDummyDescriptorInfo, true));
+    ASSERT_NO_FATAL_FAILURE(mGralloc->getTransportSize(bufferHandle, &numFds, &numInts));
+    ASSERT_NO_FATAL_FAILURE(mGralloc->freeBuffer(bufferHandle));
+}
+
+/**
+ * Test IMapper::getTransportSize with invalid buffers.
+ */
+TEST_F(GraphicsMapperHidlTest, GetTransportSizeBadBuffer) {
+    native_handle_t* invalidHandle = nullptr;
+    mGralloc->getMapper()->getTransportSize(
+        invalidHandle, [&](const auto& tmpError, const auto&, const auto&) {
+            ASSERT_EQ(Error::BAD_BUFFER, tmpError)
+                << "getTransportSize with nullptr did not fail with BAD_BUFFER";
+        });
+
+    invalidHandle = native_handle_create(0, 0);
+    mGralloc->getMapper()->getTransportSize(
+        invalidHandle, [&](const auto& tmpError, const auto&, const auto&) {
+            ASSERT_EQ(Error::BAD_BUFFER, tmpError)
+                << "getTransportSize with invalid handle did not fail with BAD_BUFFER";
+        });
+    native_handle_delete(invalidHandle);
+
+    native_handle_t* rawBufferHandle;
+    ASSERT_NO_FATAL_FAILURE(rawBufferHandle = const_cast<native_handle_t*>(
+                                mGralloc->allocate(mDummyDescriptorInfo, false)));
+    mGralloc->getMapper()->getTransportSize(
+        invalidHandle, [&](const auto& tmpError, const auto&, const auto&) {
+            ASSERT_EQ(Error::BAD_BUFFER, tmpError)
+                << "getTransportSize with raw buffer handle did not fail with BAD_BUFFER";
+        });
+    native_handle_delete(rawBufferHandle);
+}
+
+}  // namespace
+}  // namespace tests
+}  // namespace V2_1
+}  // namespace mapper
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+
+    int status = RUN_ALL_TESTS();
+    LOG(INFO) << "Test result = " << status;
+
+    return status;
+}
diff --git a/health/1.0/default/android.hardware.health@1.0-service.rc b/health/1.0/default/android.hardware.health@1.0-service.rc
index 13cd7a5..d74a07e 100644
--- a/health/1.0/default/android.hardware.health@1.0-service.rc
+++ b/health/1.0/default/android.hardware.health@1.0-service.rc
@@ -1,4 +1,4 @@
-service health-hal-1-0 /vendor/bin/hw/android.hardware.health@1.0-service
+service vendor.health-hal-1-0 /vendor/bin/hw/android.hardware.health@1.0-service
     class hal
     user system
     group system
diff --git a/health/2.0/Android.bp b/health/2.0/Android.bp
index 4a4f24b..1080df1 100644
--- a/health/2.0/Android.bp
+++ b/health/2.0/Android.bp
@@ -16,7 +16,6 @@
         "android.hidl.base@1.0",
     ],
     types: [
-        "HealthInfo",
         "Result",
     ],
     gen_java: true,
diff --git a/health/2.0/IHealthInfoCallback.hal b/health/2.0/IHealthInfoCallback.hal
index 15352ee..8e17bb9 100644
--- a/health/2.0/IHealthInfoCallback.hal
+++ b/health/2.0/IHealthInfoCallback.hal
@@ -16,6 +16,8 @@
 
 package android.hardware.health@2.0;
 
+import @1.0::HealthInfo;
+
 /**
  * IHealthInfoCallback is the callback interface to
  * {@link IHealthInfoBus.registerCallback}.
diff --git a/health/2.0/default/Android.bp b/health/2.0/default/Android.bp
new file mode 100644
index 0000000..8eb02e0
--- /dev/null
+++ b/health/2.0/default/Android.bp
@@ -0,0 +1,28 @@
+cc_library_static {
+    name: "android.hardware.health@2.0-impl",
+    vendor_available: true,
+    srcs: [
+        "Health.cpp",
+        "healthd_common.cpp",
+    ],
+
+    cflags: ["-DHEALTHD_USE_HEALTH_2_0"],
+
+    export_include_dirs: ["include"],
+
+    shared_libs: [
+        "libbase",
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+        "libcutils",
+        "android.hardware.health@2.0",
+    ],
+
+    static_libs: [
+        "libbatterymonitor",
+        "android.hardware.health@1.0-convert",
+    ],
+}
diff --git a/health/2.0/default/Health.cpp b/health/2.0/default/Health.cpp
new file mode 100644
index 0000000..4710c90
--- /dev/null
+++ b/health/2.0/default/Health.cpp
@@ -0,0 +1,183 @@
+#define LOG_TAG "android.hardware.health@2.0-impl"
+#include <android-base/logging.h>
+
+#include <health2/Health.h>
+
+#include <hidl/HidlTransportSupport.h>
+
+extern void healthd_battery_update_internal(bool);
+
+namespace android {
+namespace hardware {
+namespace health {
+namespace V2_0 {
+namespace implementation {
+
+sp<Health> Health::instance_;
+
+Health::Health(struct healthd_config* c) {
+    // TODO(b/69268160): remove when libhealthd is removed.
+    healthd_board_init(c);
+    battery_monitor_ = std::make_unique<BatteryMonitor>();
+    battery_monitor_->init(c);
+}
+
+// Methods from IHealth follow.
+Return<Result> Health::registerCallback(const sp<IHealthInfoCallback>& callback) {
+    if (callback == nullptr) {
+        return Result::SUCCESS;
+    }
+
+    {
+        std::lock_guard<std::mutex> _lock(callbacks_lock_);
+        callbacks_.push_back(callback);
+        // unlock
+    }
+
+    auto linkRet = callback->linkToDeath(this, 0u /* cookie */);
+    if (!linkRet.withDefault(false)) {
+        LOG(WARNING) << __func__ << "Cannot link to death: "
+                     << (linkRet.isOk() ? "linkToDeath returns false" : linkRet.description());
+        // ignore the error
+    }
+
+    return update();
+}
+
+bool Health::unregisterCallbackInternal(const sp<IBase>& callback) {
+    if (callback == nullptr) return false;
+
+    bool removed = false;
+    std::lock_guard<std::mutex> _lock(callbacks_lock_);
+    for (auto it = callbacks_.begin(); it != callbacks_.end();) {
+        if (interfacesEqual(*it, callback)) {
+            it = callbacks_.erase(it);
+            removed = true;
+        } else {
+            ++it;
+        }
+    }
+    (void)callback->unlinkToDeath(this).isOk();  // ignore errors
+    return removed;
+}
+
+Return<Result> Health::unregisterCallback(const sp<IHealthInfoCallback>& callback) {
+    return unregisterCallbackInternal(callback) ? Result::SUCCESS : Result::NOT_FOUND;
+}
+
+template <typename T>
+void getProperty(const std::unique_ptr<BatteryMonitor>& monitor, int id, T defaultValue,
+                 const std::function<void(Result, T)>& callback) {
+    struct BatteryProperty prop;
+    T ret = defaultValue;
+    Result result = Result::SUCCESS;
+    status_t err = monitor->getProperty(static_cast<int>(id), &prop);
+    if (err != OK) {
+        LOG(DEBUG) << "getProperty(" << id << ")"
+                   << " fails: (" << err << ") " << strerror(-err);
+    } else {
+        ret = static_cast<T>(prop.valueInt64);
+    }
+    switch (err) {
+        case OK:
+            result = Result::SUCCESS;
+            break;
+        case NAME_NOT_FOUND:
+            result = Result::NOT_SUPPORTED;
+            break;
+        default:
+            result = Result::UNKNOWN;
+            break;
+    }
+    callback(result, static_cast<T>(ret));
+}
+
+Return<void> Health::getChargeCounter(getChargeCounter_cb _hidl_cb) {
+    getProperty(battery_monitor_, BATTERY_PROP_CHARGE_COUNTER, INT32_MIN, _hidl_cb);
+    return Void();
+}
+
+Return<void> Health::getCurrentNow(getCurrentNow_cb _hidl_cb) {
+    getProperty(battery_monitor_, BATTERY_PROP_CURRENT_NOW, INT32_MIN, _hidl_cb);
+    return Void();
+}
+
+Return<void> Health::getCurrentAverage(getCurrentAverage_cb _hidl_cb) {
+    getProperty(battery_monitor_, BATTERY_PROP_CURRENT_AVG, INT32_MIN, _hidl_cb);
+    return Void();
+}
+
+Return<void> Health::getCapacity(getCapacity_cb _hidl_cb) {
+    getProperty(battery_monitor_, BATTERY_PROP_CAPACITY, INT32_MIN, _hidl_cb);
+    return Void();
+}
+
+Return<void> Health::getEnergyCounter(getEnergyCounter_cb _hidl_cb) {
+    getProperty(battery_monitor_, BATTERY_PROP_ENERGY_COUNTER, INT64_MIN, _hidl_cb);
+    return Void();
+}
+
+Return<void> Health::getChargeStatus(getChargeStatus_cb _hidl_cb) {
+    getProperty(battery_monitor_, BATTERY_PROP_BATTERY_STATUS, BatteryStatus::UNKNOWN, _hidl_cb);
+    return Void();
+}
+
+Return<Result> Health::update() {
+    if (!healthd_mode_ops || !healthd_mode_ops->battery_update) {
+        LOG(WARNING) << "health@2.0: update: not initialized. "
+                     << "update() should not be called in charger / recovery.";
+        return Result::UNKNOWN;
+    }
+
+    // Retrieve all information and call healthd_mode_ops->battery_update, which calls
+    // notifyListeners.
+    bool chargerOnline = battery_monitor_->update();
+
+    // adjust uevent / wakealarm periods
+    healthd_battery_update_internal(chargerOnline);
+
+    return Result::SUCCESS;
+}
+
+void Health::notifyListeners(const HealthInfo& info) {
+    std::lock_guard<std::mutex> _lock(callbacks_lock_);
+    for (auto it = callbacks_.begin(); it != callbacks_.end();) {
+        auto ret = (*it)->healthInfoChanged(info);
+        if (!ret.isOk() && ret.isDeadObject()) {
+            it = callbacks_.erase(it);
+        } else {
+            ++it;
+        }
+    }
+}
+
+Return<void> Health::debug(const hidl_handle& handle, const hidl_vec<hidl_string>&) {
+    if (handle != nullptr && handle->numFds >= 1) {
+        int fd = handle->data[0];
+        battery_monitor_->dumpState(fd);
+        fsync(fd);
+    }
+    return Void();
+}
+
+void Health::serviceDied(uint64_t /* cookie */, const wp<IBase>& who) {
+    (void)unregisterCallbackInternal(who.promote());
+}
+
+sp<IHealth> Health::initInstance(struct healthd_config* c) {
+    if (instance_ == nullptr) {
+        instance_ = new Health(c);
+    }
+    return instance_;
+}
+
+sp<Health> Health::getImplementation() {
+    CHECK(instance_ != nullptr);
+    return instance_;
+}
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace health
+}  // namespace hardware
+}  // namespace android
diff --git a/health/2.0/default/healthd_common.cpp b/health/2.0/default/healthd_common.cpp
new file mode 100644
index 0000000..8ff409d
--- /dev/null
+++ b/health/2.0/default/healthd_common.cpp
@@ -0,0 +1,275 @@
+/*
+ * Copyright (C) 2013 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.health@2.0-impl"
+#define KLOG_LEVEL 6
+
+#include <healthd/BatteryMonitor.h>
+#include <healthd/healthd.h>
+
+#include <batteryservice/BatteryService.h>
+#include <cutils/klog.h>
+#include <cutils/uevent.h>
+#include <errno.h>
+#include <libgen.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/epoll.h>
+#include <sys/timerfd.h>
+#include <unistd.h>
+#include <utils/Errors.h>
+
+#include <health2/Health.h>
+
+using namespace android;
+
+// Periodic chores fast interval in seconds
+#define DEFAULT_PERIODIC_CHORES_INTERVAL_FAST (60 * 1)
+// Periodic chores fast interval in seconds
+#define DEFAULT_PERIODIC_CHORES_INTERVAL_SLOW (60 * 10)
+
+static struct healthd_config healthd_config = {
+    .periodic_chores_interval_fast = DEFAULT_PERIODIC_CHORES_INTERVAL_FAST,
+    .periodic_chores_interval_slow = DEFAULT_PERIODIC_CHORES_INTERVAL_SLOW,
+    .batteryStatusPath = String8(String8::kEmptyString),
+    .batteryHealthPath = String8(String8::kEmptyString),
+    .batteryPresentPath = String8(String8::kEmptyString),
+    .batteryCapacityPath = String8(String8::kEmptyString),
+    .batteryVoltagePath = String8(String8::kEmptyString),
+    .batteryTemperaturePath = String8(String8::kEmptyString),
+    .batteryTechnologyPath = String8(String8::kEmptyString),
+    .batteryCurrentNowPath = String8(String8::kEmptyString),
+    .batteryCurrentAvgPath = String8(String8::kEmptyString),
+    .batteryChargeCounterPath = String8(String8::kEmptyString),
+    .batteryFullChargePath = String8(String8::kEmptyString),
+    .batteryCycleCountPath = String8(String8::kEmptyString),
+    .energyCounter = NULL,
+    .boot_min_cap = 0,
+    .screen_on = NULL,
+};
+
+static int eventct;
+static int epollfd;
+
+#define POWER_SUPPLY_SUBSYSTEM "power_supply"
+
+// epoll_create() parameter is actually unused
+#define MAX_EPOLL_EVENTS 40
+static int uevent_fd;
+static int wakealarm_fd;
+
+// -1 for no epoll timeout
+static int awake_poll_interval = -1;
+
+static int wakealarm_wake_interval = DEFAULT_PERIODIC_CHORES_INTERVAL_FAST;
+
+using ::android::hardware::health::V2_0::implementation::Health;
+
+struct healthd_mode_ops* healthd_mode_ops = nullptr;
+
+int healthd_register_event(int fd, void (*handler)(uint32_t), EventWakeup wakeup) {
+    struct epoll_event ev;
+
+    ev.events = EPOLLIN;
+
+    if (wakeup == EVENT_WAKEUP_FD) ev.events |= EPOLLWAKEUP;
+
+    ev.data.ptr = (void*)handler;
+    if (epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &ev) == -1) {
+        KLOG_ERROR(LOG_TAG, "epoll_ctl failed; errno=%d\n", errno);
+        return -1;
+    }
+
+    eventct++;
+    return 0;
+}
+
+static void wakealarm_set_interval(int interval) {
+    struct itimerspec itval;
+
+    if (wakealarm_fd == -1) return;
+
+    wakealarm_wake_interval = interval;
+
+    if (interval == -1) interval = 0;
+
+    itval.it_interval.tv_sec = interval;
+    itval.it_interval.tv_nsec = 0;
+    itval.it_value.tv_sec = interval;
+    itval.it_value.tv_nsec = 0;
+
+    if (timerfd_settime(wakealarm_fd, 0, &itval, NULL) == -1)
+        KLOG_ERROR(LOG_TAG, "wakealarm_set_interval: timerfd_settime failed\n");
+}
+
+void healthd_battery_update_internal(bool charger_online) {
+    // Fast wake interval when on charger (watch for overheat);
+    // slow wake interval when on battery (watch for drained battery).
+
+    int new_wake_interval = charger_online ? healthd_config.periodic_chores_interval_fast
+                                           : healthd_config.periodic_chores_interval_slow;
+
+    if (new_wake_interval != wakealarm_wake_interval) wakealarm_set_interval(new_wake_interval);
+
+    // During awake periods poll at fast rate.  If wake alarm is set at fast
+    // rate then just use the alarm; if wake alarm is set at slow rate then
+    // poll at fast rate while awake and let alarm wake up at slow rate when
+    // asleep.
+
+    if (healthd_config.periodic_chores_interval_fast == -1)
+        awake_poll_interval = -1;
+    else
+        awake_poll_interval = new_wake_interval == healthd_config.periodic_chores_interval_fast
+                                  ? -1
+                                  : healthd_config.periodic_chores_interval_fast * 1000;
+}
+
+static void healthd_battery_update(void) {
+    Health::getImplementation()->update();
+}
+
+static void periodic_chores() {
+    healthd_battery_update();
+}
+
+#define UEVENT_MSG_LEN 2048
+static void uevent_event(uint32_t /*epevents*/) {
+    char msg[UEVENT_MSG_LEN + 2];
+    char* cp;
+    int n;
+
+    n = uevent_kernel_multicast_recv(uevent_fd, msg, UEVENT_MSG_LEN);
+    if (n <= 0) return;
+    if (n >= UEVENT_MSG_LEN) /* overflow -- discard */
+        return;
+
+    msg[n] = '\0';
+    msg[n + 1] = '\0';
+    cp = msg;
+
+    while (*cp) {
+        if (!strcmp(cp, "SUBSYSTEM=" POWER_SUPPLY_SUBSYSTEM)) {
+            healthd_battery_update();
+            break;
+        }
+
+        /* advance to after the next \0 */
+        while (*cp++)
+            ;
+    }
+}
+
+static void uevent_init(void) {
+    uevent_fd = uevent_open_socket(64 * 1024, true);
+
+    if (uevent_fd < 0) {
+        KLOG_ERROR(LOG_TAG, "uevent_init: uevent_open_socket failed\n");
+        return;
+    }
+
+    fcntl(uevent_fd, F_SETFL, O_NONBLOCK);
+    if (healthd_register_event(uevent_fd, uevent_event, EVENT_WAKEUP_FD))
+        KLOG_ERROR(LOG_TAG, "register for uevent events failed\n");
+}
+
+static void wakealarm_event(uint32_t /*epevents*/) {
+    unsigned long long wakeups;
+
+    if (read(wakealarm_fd, &wakeups, sizeof(wakeups)) == -1) {
+        KLOG_ERROR(LOG_TAG, "wakealarm_event: read wakealarm fd failed\n");
+        return;
+    }
+
+    periodic_chores();
+}
+
+static void wakealarm_init(void) {
+    wakealarm_fd = timerfd_create(CLOCK_BOOTTIME_ALARM, TFD_NONBLOCK);
+    if (wakealarm_fd == -1) {
+        KLOG_ERROR(LOG_TAG, "wakealarm_init: timerfd_create failed\n");
+        return;
+    }
+
+    if (healthd_register_event(wakealarm_fd, wakealarm_event, EVENT_WAKEUP_FD))
+        KLOG_ERROR(LOG_TAG, "Registration of wakealarm event failed\n");
+
+    wakealarm_set_interval(healthd_config.periodic_chores_interval_fast);
+}
+
+static void healthd_mainloop(void) {
+    int nevents = 0;
+    while (1) {
+        struct epoll_event events[eventct];
+        int timeout = awake_poll_interval;
+        int mode_timeout;
+
+        /* Don't wait for first timer timeout to run periodic chores */
+        if (!nevents) periodic_chores();
+
+        healthd_mode_ops->heartbeat();
+
+        mode_timeout = healthd_mode_ops->preparetowait();
+        if (timeout < 0 || (mode_timeout > 0 && mode_timeout < timeout)) timeout = mode_timeout;
+        nevents = epoll_wait(epollfd, events, eventct, timeout);
+        if (nevents == -1) {
+            if (errno == EINTR) continue;
+            KLOG_ERROR(LOG_TAG, "healthd_mainloop: epoll_wait failed\n");
+            break;
+        }
+
+        for (int n = 0; n < nevents; ++n) {
+            if (events[n].data.ptr) (*(void (*)(int))events[n].data.ptr)(events[n].events);
+        }
+    }
+
+    return;
+}
+
+static int healthd_init() {
+    epollfd = epoll_create(MAX_EPOLL_EVENTS);
+    if (epollfd == -1) {
+        KLOG_ERROR(LOG_TAG, "epoll_create failed; errno=%d\n", errno);
+        return -1;
+    }
+
+    healthd_mode_ops->init(&healthd_config);
+    wakealarm_init();
+    uevent_init();
+
+    return 0;
+}
+
+int healthd_main() {
+    int ret;
+
+    klog_set_level(KLOG_LEVEL);
+
+    if (!healthd_mode_ops) {
+        KLOG_ERROR("healthd ops not set, exiting\n");
+        exit(1);
+    }
+
+    ret = healthd_init();
+    if (ret) {
+        KLOG_ERROR("Initialization failed, exiting\n");
+        exit(2);
+    }
+
+    healthd_mainloop();
+    KLOG_ERROR("Main loop terminated, exiting\n");
+    return 3;
+}
diff --git a/health/2.0/default/include/health2/Health.h b/health/2.0/default/include/health2/Health.h
new file mode 100644
index 0000000..ab42ae7
--- /dev/null
+++ b/health/2.0/default/include/health2/Health.h
@@ -0,0 +1,69 @@
+#ifndef ANDROID_HARDWARE_HEALTH_V2_0_HEALTH_H
+#define ANDROID_HARDWARE_HEALTH_V2_0_HEALTH_H
+
+#include <memory>
+#include <vector>
+
+#include <android/hardware/health/1.0/types.h>
+#include <android/hardware/health/2.0/IHealth.h>
+#include <healthd/BatteryMonitor.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace health {
+namespace V2_0 {
+namespace implementation {
+
+using V1_0::BatteryStatus;
+using V1_0::HealthInfo;
+
+using ::android::hidl::base::V1_0::IBase;
+
+struct Health : public IHealth, hidl_death_recipient {
+   public:
+    static sp<IHealth> initInstance(struct healthd_config* c);
+    // Should only be called by implementation itself (-impl, -service).
+    // Clients should not call this function. Instead, initInstance() initializes and returns the
+    // global instance that has fewer functions.
+    // TODO(b/62229583): clean up and hide these functions after update() logic is simplified.
+    static sp<Health> getImplementation();
+
+    Health(struct healthd_config* c);
+
+    // TODO(b/62229583): clean up and hide these functions after update() logic is simplified.
+    void notifyListeners(const HealthInfo& info);
+
+    // Methods from IHealth follow.
+    Return<Result> registerCallback(const sp<IHealthInfoCallback>& callback) override;
+    Return<Result> unregisterCallback(const sp<IHealthInfoCallback>& callback) override;
+    Return<Result> update() override;
+    Return<void> getChargeCounter(getChargeCounter_cb _hidl_cb) override;
+    Return<void> getCurrentNow(getCurrentNow_cb _hidl_cb) override;
+    Return<void> getCurrentAverage(getCurrentAverage_cb _hidl_cb) override;
+    Return<void> getCapacity(getCapacity_cb _hidl_cb) override;
+    Return<void> getEnergyCounter(getEnergyCounter_cb _hidl_cb) override;
+    Return<void> getChargeStatus(getChargeStatus_cb _hidl_cb) override;
+
+    // Methods from ::android::hidl::base::V1_0::IBase follow.
+    Return<void> debug(const hidl_handle& fd, const hidl_vec<hidl_string>& args) override;
+
+    void serviceDied(uint64_t cookie, const wp<IBase>& /* who */) override;
+
+   private:
+    static sp<Health> instance_;
+
+    std::mutex callbacks_lock_;
+    std::vector<sp<IHealthInfoCallback>> callbacks_;
+    std::unique_ptr<BatteryMonitor> battery_monitor_;
+
+    bool unregisterCallbackInternal(const sp<IBase>& cb);
+};
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace health
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_HEALTH_V2_0_HEALTH_H
diff --git a/health/2.0/types.hal b/health/2.0/types.hal
index 0d17f9f..8c6d88f 100644
--- a/health/2.0/types.hal
+++ b/health/2.0/types.hal
@@ -26,40 +26,3 @@
     NOT_FOUND,
     CALLBACK_DIED,
 };
-
-struct HealthInfo {
-    /**
-     * Legacy information from 1.0 HAL.
-     *
-     * If a value is not available, it must be set to 0, UNKNOWN, or empty
-     * string.
-     */
-    @1.0::HealthInfo legacy;
-
-    /**
-     * Average battery current in microamperes. Positive
-     * values indicate net current entering the battery from a charge source,
-     * negative values indicate net current discharging from the battery.
-     * The time period over which the average is computed may depend on the
-     * fuel gauge hardware and its configuration.
-     *
-     * If this value is not available, it must be set to 0.
-     */
-    int32_t batteryCurrentAverage;
-
-    /**
-     * Remaining battery capacity percentage of total capacity
-     * (with no fractional part). This value must be in the range 0-100
-     * (inclusive).
-     *
-     * If this value is not available, it must be set to 0.
-     */
-    int32_t batteryCapacity;
-
-    /**
-     * Battery remaining energy in nanowatt-hours.
-     *
-     * If this value is not available, it must be set to 0.
-     */
-    int64_t energyCounter;
-};
\ No newline at end of file
diff --git a/broadcastradio/1.1/vts/utils/Android.bp b/health/2.0/vts/functional/Android.bp
similarity index 72%
copy from broadcastradio/1.1/vts/utils/Android.bp
copy to health/2.0/vts/functional/Android.bp
index 0c7e2a4..4ad01b9 100644
--- a/broadcastradio/1.1/vts/utils/Android.bp
+++ b/health/2.0/vts/functional/Android.bp
@@ -14,15 +14,12 @@
 // 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",
+cc_test {
+    name: "VtsHalHealthV2_0TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: ["VtsHalHealthV2_0TargetTest.cpp"],
+    static_libs: [
+        "android.hardware.health@1.0",
+        "android.hardware.health@2.0",
     ],
 }
diff --git a/health/2.0/vts/functional/VtsHalHealthV2_0TargetTest.cpp b/health/2.0/vts/functional/VtsHalHealthV2_0TargetTest.cpp
new file mode 100644
index 0000000..bf8548c
--- /dev/null
+++ b/health/2.0/vts/functional/VtsHalHealthV2_0TargetTest.cpp
@@ -0,0 +1,220 @@
+/*
+ * 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 "health_hidl_hal_test"
+
+#include <mutex>
+
+#include <VtsHalHidlTargetTestBase.h>
+#include <android-base/logging.h>
+#include <android/hardware/health/2.0/IHealth.h>
+#include <android/hardware/health/2.0/types.h>
+
+using ::testing::AssertionFailure;
+using ::testing::AssertionResult;
+using ::testing::AssertionSuccess;
+using ::testing::VtsHalHidlTargetTestBase;
+using ::testing::VtsHalHidlTargetTestEnvBase;
+
+namespace android {
+namespace hardware {
+namespace health {
+namespace V2_0 {
+
+using V1_0::BatteryStatus;
+using V1_0::HealthInfo;
+
+// Test environment for graphics.composer
+class HealthHidlEnvironment : public VtsHalHidlTargetTestEnvBase {
+   public:
+    // get the test environment singleton
+    static HealthHidlEnvironment* Instance() {
+        static HealthHidlEnvironment* instance = new HealthHidlEnvironment;
+        return instance;
+    }
+
+    virtual void registerTestServices() override { registerTestService<IHealth>(); }
+
+   private:
+    HealthHidlEnvironment() {}
+
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(HealthHidlEnvironment);
+};
+
+class HealthHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+   public:
+    virtual void SetUp() override {
+        std::string serviceName = HealthHidlEnvironment::Instance()->getServiceName<IHealth>();
+        LOG(INFO) << "get service with name:" << serviceName;
+        ASSERT_FALSE(serviceName.empty());
+        mHealth = ::testing::VtsHalHidlTargetTestBase::getService<IHealth>(serviceName);
+        ASSERT_NE(mHealth, nullptr);
+    }
+
+    sp<IHealth> mHealth;
+};
+
+class Callback : public IHealthInfoCallback {
+   public:
+    Return<void> healthInfoChanged(const HealthInfo&) override {
+        std::lock_guard<std::mutex> lock(mMutex);
+        mInvoked = true;
+        mInvokedNotify.notify_all();
+        return Void();
+    }
+    template <typename R, typename P>
+    bool waitInvoke(std::chrono::duration<R, P> duration) {
+        std::unique_lock<std::mutex> lock(mMutex);
+        bool r = mInvokedNotify.wait_for(lock, duration, [this] { return this->mInvoked; });
+        mInvoked = false;
+        return r;
+    }
+   private:
+    std::mutex mMutex;
+    std::condition_variable mInvokedNotify;
+    bool mInvoked = false;
+};
+
+#define ASSERT_OK(r) ASSERT_TRUE(isOk(r))
+#define EXPECT_OK(r) EXPECT_TRUE(isOk(r))
+template <typename T>
+AssertionResult isOk(const Return<T>& r) {
+    return r.isOk() ? AssertionSuccess() : (AssertionFailure() << r.description());
+}
+
+#define ASSERT_ALL_OK(r) ASSERT_TRUE(isAllOk(r))
+// Both isOk() and Result::SUCCESS
+AssertionResult isAllOk(const Return<Result>& r) {
+    if (!r.isOk()) {
+        return AssertionFailure() << r.description();
+    }
+    if (static_cast<Result>(r) != Result::SUCCESS) {
+        return AssertionFailure() << toString(static_cast<Result>(r));
+    }
+    return AssertionSuccess();
+}
+
+/**
+ * Test whether callbacks work. Tested functions are IHealth::registerCallback,
+ * unregisterCallback, and update.
+ */
+TEST_F(HealthHidlTest, Callbacks) {
+    using namespace std::chrono_literals;
+    sp<Callback> firstCallback = new Callback();
+    sp<Callback> secondCallback = new Callback();
+
+    ASSERT_ALL_OK(mHealth->registerCallback(firstCallback));
+    ASSERT_ALL_OK(mHealth->registerCallback(secondCallback));
+
+    // registerCallback may or may not invoke the callback immediately, so the test needs
+    // to wait for the invocation. If the implementation chooses not to invoke the callback
+    // immediately, just wait for some time.
+    firstCallback->waitInvoke(200ms);
+    secondCallback->waitInvoke(200ms);
+
+    // assert that the first callback is invoked when update is called.
+    ASSERT_ALL_OK(mHealth->update());
+
+    ASSERT_TRUE(firstCallback->waitInvoke(1s));
+    ASSERT_TRUE(secondCallback->waitInvoke(1s));
+
+    ASSERT_ALL_OK(mHealth->unregisterCallback(firstCallback));
+
+    // clear any potentially pending callbacks result from wakealarm / kernel events
+    // If there is none, just wait for some time.
+    firstCallback->waitInvoke(200ms);
+    secondCallback->waitInvoke(200ms);
+
+    // assert that the second callback is still invoked even though the first is unregistered.
+    ASSERT_ALL_OK(mHealth->update());
+
+    ASSERT_FALSE(firstCallback->waitInvoke(200ms));
+    ASSERT_TRUE(secondCallback->waitInvoke(1s));
+
+    ASSERT_ALL_OK(mHealth->unregisterCallback(secondCallback));
+}
+
+TEST_F(HealthHidlTest, UnregisterNonExistentCallback) {
+    sp<Callback> callback = new Callback();
+    auto ret = mHealth->unregisterCallback(callback);
+    ASSERT_OK(ret);
+    ASSERT_EQ(Result::NOT_FOUND, static_cast<Result>(ret)) << "Actual: " << toString(ret);
+}
+
+/**
+ * Pass the test if:
+ *  - Property is not supported (res == NOT_SUPPORTED)
+ *  - Result is success, and predicate is true
+ * @param res the Result value.
+ * @param valueStr the string representation for actual value (for error message)
+ * @param pred a predicate that test whether the value is valid
+ */
+#define EXPECT_VALID_OR_UNSUPPORTED_PROP(res, valueStr, pred) \
+    EXPECT_TRUE(isPropertyOk(res, valueStr, pred, #pred))
+
+AssertionResult isPropertyOk(Result res, const std::string& valueStr, bool pred,
+                             const std::string& predStr) {
+    if (res == Result::SUCCESS) {
+        if (pred) {
+            return AssertionSuccess();
+        }
+        return AssertionFailure() << "value doesn't match.\nActual: " << valueStr
+                                  << "\nExpected: " << predStr;
+    }
+    if (res == Result::NOT_SUPPORTED) {
+        return AssertionSuccess();
+    }
+    return AssertionFailure() << "Result is not SUCCESS or NOT_SUPPORTED: " << toString(res);
+}
+
+TEST_F(HealthHidlTest, Properties) {
+    EXPECT_OK(mHealth->getChargeCounter([](auto result, auto value) {
+        EXPECT_VALID_OR_UNSUPPORTED_PROP(result, std::to_string(value), value > 0);
+    }));
+    EXPECT_OK(mHealth->getCurrentNow([](auto result, auto value) {
+        EXPECT_VALID_OR_UNSUPPORTED_PROP(result, std::to_string(value), value != INT32_MIN);
+    }));
+    EXPECT_OK(mHealth->getCurrentAverage([](auto result, auto value) {
+        EXPECT_VALID_OR_UNSUPPORTED_PROP(result, std::to_string(value), value != INT32_MIN);
+    }));
+    EXPECT_OK(mHealth->getCapacity([](auto result, auto value) {
+        EXPECT_VALID_OR_UNSUPPORTED_PROP(result, std::to_string(value), 0 <= value && value <= 100);
+    }));
+    EXPECT_OK(mHealth->getEnergyCounter([](auto result, auto value) {
+        EXPECT_VALID_OR_UNSUPPORTED_PROP(result, std::to_string(value), value != INT64_MIN);
+    }));
+    EXPECT_OK(mHealth->getChargeStatus([](auto result, auto value) {
+        EXPECT_VALID_OR_UNSUPPORTED_PROP(
+            result, toString(value),
+            value == BatteryStatus::CHARGING || value == BatteryStatus::DISCHARGING ||
+                value == BatteryStatus::NOT_CHARGING || value == BatteryStatus::FULL);
+    }));
+}
+
+}  // namespace V2_0
+}  // namespace health
+}  // namespace hardware
+}  // namespace android
+
+int main(int argc, char** argv) {
+    using ::android::hardware::health::V2_0::HealthHidlEnvironment;
+    ::testing::AddGlobalTestEnvironment(HealthHidlEnvironment::Instance());
+    ::testing::InitGoogleTest(&argc, argv);
+    HealthHidlEnvironment::Instance()->init(&argc, argv);
+    int status = RUN_ALL_TESTS();
+    LOG(INFO) << "Test result = " << status;
+    return status;
+}
diff --git a/ir/1.0/default/android.hardware.ir@1.0-service.rc b/ir/1.0/default/android.hardware.ir@1.0-service.rc
index 47f34fe..0d06967 100644
--- a/ir/1.0/default/android.hardware.ir@1.0-service.rc
+++ b/ir/1.0/default/android.hardware.ir@1.0-service.rc
@@ -1,4 +1,4 @@
-service ir-hal-1-0 /vendor/bin/hw/android.hardware.ir@1.0-service
+service vendor.ir-hal-1-0 /vendor/bin/hw/android.hardware.ir@1.0-service
     class hal
     user system
-    group system
\ No newline at end of file
+    group system
diff --git a/keymaster/3.0/default/Android.mk b/keymaster/3.0/default/Android.mk
index 87ad245..6b66f7d 100644
--- a/keymaster/3.0/default/Android.mk
+++ b/keymaster/3.0/default/Android.mk
@@ -13,6 +13,8 @@
     libcrypto \
     libkeymaster_portable \
     libkeymaster_staging \
+    libpuresoftkeymasterdevice \
+    libkeymaster3device \
     libhidlbase \
     libhidltransport \
     libutils \
diff --git a/keymaster/3.0/default/KeymasterDevice.cpp b/keymaster/3.0/default/KeymasterDevice.cpp
index d83963f..6fabbde 100644
--- a/keymaster/3.0/default/KeymasterDevice.cpp
+++ b/keymaster/3.0/default/KeymasterDevice.cpp
@@ -21,9 +21,11 @@
 
 #include <cutils/log.h>
 
+#include <AndroidKeymaster3Device.h>
+#include <hardware/keymaster0.h>
+#include <hardware/keymaster1.h>
+#include <hardware/keymaster2.h>
 #include <hardware/keymaster_defs.h>
-#include <keymaster/keymaster_configuration.h>
-#include <keymaster/soft_keymaster_device.h>
 
 namespace android {
 namespace hardware {
@@ -31,717 +33,77 @@
 namespace V3_0 {
 namespace implementation {
 
-using ::keymaster::SoftKeymasterDevice;
-
-class SoftwareOnlyHidlKeymasterEnforcement : public ::keymaster::KeymasterEnforcement {
-  public:
-    SoftwareOnlyHidlKeymasterEnforcement() : KeymasterEnforcement(64, 64) {}
-
-    uint32_t get_current_time() const override {
-        struct timespec tp;
-        int err = clock_gettime(CLOCK_MONOTONIC, &tp);
-        if (err || tp.tv_sec < 0) return 0;
-        return static_cast<uint32_t>(tp.tv_sec);
-    }
-
-    bool activation_date_valid(uint64_t) const override { return true; }
-    bool expiration_date_passed(uint64_t) const override { return false; }
-    bool auth_token_timed_out(const hw_auth_token_t&, uint32_t) const override { return false; }
-    bool ValidateTokenSignature(const hw_auth_token_t&) const override { return true; }
-};
-
-class SoftwareOnlyHidlKeymasterContext : public ::keymaster::SoftKeymasterContext {
-  public:
-    SoftwareOnlyHidlKeymasterContext() : enforcement_(new SoftwareOnlyHidlKeymasterEnforcement) {}
-
-    ::keymaster::KeymasterEnforcement* enforcement_policy() override { return enforcement_.get(); }
-
-  private:
-    std::unique_ptr<::keymaster::KeymasterEnforcement> enforcement_;
-};
-
-static int keymaster0_device_initialize(const hw_module_t* mod, keymaster2_device_t** dev) {
-    assert(mod->module_api_version < KEYMASTER_MODULE_API_VERSION_1_0);
-    ALOGI("Found keymaster0 module %s, version %x", mod->name, mod->module_api_version);
-
-    std::unique_ptr<SoftKeymasterDevice> soft_keymaster(new SoftKeymasterDevice);
-    keymaster0_device_t* km0_device = NULL;
-    keymaster_error_t error = KM_ERROR_OK;
-
-    int rc = keymaster0_open(mod, &km0_device);
+static int get_keymaster0_dev(keymaster0_device_t** dev, const hw_module_t* mod) {
+    int rc = keymaster0_open(mod, dev);
     if (rc) {
         ALOGE("Error opening keystore keymaster0 device.");
-        goto err;
+        *dev = nullptr;
+        return rc;
     }
-
-    if (km0_device->flags & KEYMASTER_SOFTWARE_ONLY) {
-        ALOGI("Keymaster0 module is software-only.  Using SoftKeymasterDevice instead.");
-        km0_device->common.close(&km0_device->common);
-        km0_device = NULL;
-        // SoftKeymasterDevice will be deleted by keymaster_device_release()
-        *dev = soft_keymaster.release()->keymaster2_device();
-        return 0;
-    }
-
-    ALOGD("Wrapping keymaster0 module %s with SoftKeymasterDevice", mod->name);
-    error = soft_keymaster->SetHardwareDevice(km0_device);
-    km0_device = NULL;  // SoftKeymasterDevice has taken ownership.
-    if (error != KM_ERROR_OK) {
-        ALOGE("Got error %d from SetHardwareDevice", error);
-        rc = error;
-        goto err;
-    }
-
-    // SoftKeymasterDevice will be deleted by  keymaster_device_release()
-    *dev = soft_keymaster.release()->keymaster2_device();
     return 0;
-
-err:
-    if (km0_device) km0_device->common.close(&km0_device->common);
-    *dev = NULL;
-    return rc;
 }
 
-static int keymaster1_device_initialize(const hw_module_t* mod, keymaster2_device_t** dev,
-                                        bool* supports_all_digests) {
-    assert(mod->module_api_version >= KEYMASTER_MODULE_API_VERSION_1_0);
-    ALOGI("Found keymaster1 module %s, version %x", mod->name, mod->module_api_version);
-
-    std::unique_ptr<SoftKeymasterDevice> soft_keymaster(new SoftKeymasterDevice);
-    keymaster1_device_t* km1_device = nullptr;
-    keymaster_error_t error = KM_ERROR_OK;
-
-    int rc = keymaster1_open(mod, &km1_device);
+static int get_keymaster1_dev(keymaster1_device_t** dev, const hw_module_t* mod) {
+    int rc = keymaster1_open(mod, dev);
     if (rc) {
         ALOGE("Error %d opening keystore keymaster1 device", rc);
-        goto err;
+        if (*dev) {
+            (*dev)->common.close(&(*dev)->common);
+            *dev = nullptr;
+        }
     }
-
-    ALOGD("Wrapping keymaster1 module %s with SofKeymasterDevice", mod->name);
-    error = soft_keymaster->SetHardwareDevice(km1_device);
-    km1_device = nullptr;  // SoftKeymasterDevice has taken ownership.
-    if (error != KM_ERROR_OK) {
-        ALOGE("Got error %d from SetHardwareDevice", error);
-        rc = error;
-        goto err;
-    }
-
-    // SoftKeymasterDevice will be deleted by keymaster_device_release()
-    *supports_all_digests = soft_keymaster->supports_all_digests();
-    *dev = soft_keymaster.release()->keymaster2_device();
-    return 0;
-
-err:
-    if (km1_device) km1_device->common.close(&km1_device->common);
-    *dev = NULL;
     return rc;
 }
 
-static int keymaster2_device_initialize(const hw_module_t* mod, keymaster2_device_t** dev) {
-    assert(mod->module_api_version >= KEYMASTER_MODULE_API_VERSION_2_0);
-    ALOGI("Found keymaster2 module %s, version %x", mod->name, mod->module_api_version);
-
-    keymaster2_device_t* km2_device = nullptr;
-
-    int rc = keymaster2_open(mod, &km2_device);
+static int get_keymaster2_dev(keymaster2_device_t** dev, const hw_module_t* mod) {
+    int rc = keymaster2_open(mod, dev);
     if (rc) {
         ALOGE("Error %d opening keystore keymaster2 device", rc);
-        goto err;
+        *dev = nullptr;
     }
-
-    *dev = km2_device;
-    return 0;
-
-err:
-    if (km2_device) km2_device->common.close(&km2_device->common);
-    *dev = nullptr;
     return rc;
 }
 
-static int keymaster_device_initialize(keymaster2_device_t** dev, uint32_t* version,
-                                       bool* supports_ec, bool* supports_all_digests) {
-    const hw_module_t* mod;
-
-    *supports_ec = true;
+static IKeymasterDevice* createKeymaster3Device() {
+    const hw_module_t* mod = nullptr;
 
     int rc = hw_get_module_by_class(KEYSTORE_HARDWARE_MODULE_ID, NULL, &mod);
     if (rc) {
         ALOGI("Could not find any keystore module, using software-only implementation.");
         // SoftKeymasterDevice will be deleted by keymaster_device_release()
-        *dev = (new SoftKeymasterDevice(new SoftwareOnlyHidlKeymasterContext))->keymaster2_device();
-        *version = -1;
-        return 0;
+        return ::keymaster::ng::CreateKeymasterDevice();
     }
 
     if (mod->module_api_version < KEYMASTER_MODULE_API_VERSION_1_0) {
-        *version = 0;
-        *supports_all_digests = false;
-        int rc = keymaster0_device_initialize(mod, dev);
-        if (rc == 0 && ((*dev)->flags & KEYMASTER_SUPPORTS_EC) == 0) {
-            *supports_ec = false;
+        keymaster0_device_t* dev = nullptr;
+        if (get_keymaster0_dev(&dev, mod)) {
+            return nullptr;
         }
-        return rc;
+        return ::keymaster::ng::CreateKeymasterDevice(dev);
     } else if (mod->module_api_version == KEYMASTER_MODULE_API_VERSION_1_0) {
-        *version = 1;
-        return keymaster1_device_initialize(mod, dev, supports_all_digests);
+        keymaster1_device_t* dev = nullptr;
+        if (get_keymaster1_dev(&dev, mod)) {
+            return nullptr;
+        }
+        return ::keymaster::ng::CreateKeymasterDevice(dev);
     } else {
-        *version = 2;
-        *supports_all_digests = true;
-        return keymaster2_device_initialize(mod, dev);
-    }
-}
-
-KeymasterDevice::~KeymasterDevice() {
-    if (keymaster_device_) keymaster_device_->common.close(&keymaster_device_->common);
-}
-
-static inline keymaster_tag_type_t typeFromTag(const keymaster_tag_t tag) {
-    return keymaster_tag_get_type(tag);
-}
-
-/**
- * legacy_enum_conversion converts enums from hidl to keymaster and back. Currently, this is just a
- * cast to make the compiler happy. One of two thigs should happen though:
- * TODO The keymaster enums should become aliases for the hidl generated enums so that we have a
- *      single point of truth. Then this cast function can go away.
- */
-inline static keymaster_tag_t legacy_enum_conversion(const Tag value) {
-    return keymaster_tag_t(value);
-}
-inline static Tag legacy_enum_conversion(const keymaster_tag_t value) {
-    return Tag(value);
-}
-inline static keymaster_purpose_t legacy_enum_conversion(const KeyPurpose value) {
-    return keymaster_purpose_t(value);
-}
-inline static keymaster_key_format_t legacy_enum_conversion(const KeyFormat value) {
-    return keymaster_key_format_t(value);
-}
-inline static ErrorCode legacy_enum_conversion(const keymaster_error_t value) {
-    return ErrorCode(value);
-}
-
-class KmParamSet : public keymaster_key_param_set_t {
-  public:
-    KmParamSet(const hidl_vec<KeyParameter>& keyParams) {
-        params = new keymaster_key_param_t[keyParams.size()];
-        length = keyParams.size();
-        for (size_t i = 0; i < keyParams.size(); ++i) {
-            auto tag = legacy_enum_conversion(keyParams[i].tag);
-            switch (typeFromTag(tag)) {
-            case KM_ENUM:
-            case KM_ENUM_REP:
-                params[i] = keymaster_param_enum(tag, keyParams[i].f.integer);
-                break;
-            case KM_UINT:
-            case KM_UINT_REP:
-                params[i] = keymaster_param_int(tag, keyParams[i].f.integer);
-                break;
-            case KM_ULONG:
-            case KM_ULONG_REP:
-                params[i] = keymaster_param_long(tag, keyParams[i].f.longInteger);
-                break;
-            case KM_DATE:
-                params[i] = keymaster_param_date(tag, keyParams[i].f.dateTime);
-                break;
-            case KM_BOOL:
-                if (keyParams[i].f.boolValue)
-                    params[i] = keymaster_param_bool(tag);
-                else
-                    params[i].tag = KM_TAG_INVALID;
-                break;
-            case KM_BIGNUM:
-            case KM_BYTES:
-                params[i] =
-                    keymaster_param_blob(tag, &keyParams[i].blob[0], keyParams[i].blob.size());
-                break;
-            case KM_INVALID:
-            default:
-                params[i].tag = KM_TAG_INVALID;
-                /* just skip */
-                break;
-            }
+        keymaster2_device_t* dev = nullptr;
+        if (get_keymaster2_dev(&dev, mod)) {
+            return nullptr;
         }
+        return ::keymaster::ng::CreateKeymasterDevice(dev);
     }
-    KmParamSet(KmParamSet&& other) : keymaster_key_param_set_t{other.params, other.length} {
-        other.length = 0;
-        other.params = nullptr;
-    }
-    KmParamSet(const KmParamSet&) = delete;
-    ~KmParamSet() { delete[] params; }
-};
-
-inline static KmParamSet hidlParams2KmParamSet(const hidl_vec<KeyParameter>& params) {
-    return KmParamSet(params);
-}
-
-inline static keymaster_blob_t hidlVec2KmBlob(const hidl_vec<uint8_t>& blob) {
-    /* hidl unmarshals funny pointers if the the blob is empty */
-    if (blob.size()) return {&blob[0], blob.size()};
-    return {nullptr, 0};
-}
-
-inline static keymaster_key_blob_t hidlVec2KmKeyBlob(const hidl_vec<uint8_t>& blob) {
-    /* hidl unmarshals funny pointers if the the blob is empty */
-    if (blob.size()) return {&blob[0], blob.size()};
-    return {nullptr, 0};
-}
-
-inline static hidl_vec<uint8_t> kmBlob2hidlVec(const keymaster_key_blob_t& blob) {
-    hidl_vec<uint8_t> result;
-    result.setToExternal(const_cast<unsigned char*>(blob.key_material), blob.key_material_size);
-    return result;
-}
-inline static hidl_vec<uint8_t> kmBlob2hidlVec(const keymaster_blob_t& blob) {
-    hidl_vec<uint8_t> result;
-    result.setToExternal(const_cast<unsigned char*>(blob.data), blob.data_length);
-    return result;
-}
-
-inline static hidl_vec<hidl_vec<uint8_t>>
-kmCertChain2Hidl(const keymaster_cert_chain_t* cert_chain) {
-    hidl_vec<hidl_vec<uint8_t>> result;
-    if (!cert_chain || cert_chain->entry_count == 0 || !cert_chain->entries) return result;
-
-    result.resize(cert_chain->entry_count);
-    for (size_t i = 0; i < cert_chain->entry_count; ++i) {
-        auto& entry = cert_chain->entries[i];
-        result[i] = kmBlob2hidlVec(entry);
-    }
-
-    return result;
-}
-
-static inline hidl_vec<KeyParameter> kmParamSet2Hidl(const keymaster_key_param_set_t& set) {
-    hidl_vec<KeyParameter> result;
-    if (set.length == 0 || set.params == nullptr) return result;
-
-    result.resize(set.length);
-    keymaster_key_param_t* params = set.params;
-    for (size_t i = 0; i < set.length; ++i) {
-        auto tag = params[i].tag;
-        result[i].tag = legacy_enum_conversion(tag);
-        switch (typeFromTag(tag)) {
-        case KM_ENUM:
-        case KM_ENUM_REP:
-            result[i].f.integer = params[i].enumerated;
-            break;
-        case KM_UINT:
-        case KM_UINT_REP:
-            result[i].f.integer = params[i].integer;
-            break;
-        case KM_ULONG:
-        case KM_ULONG_REP:
-            result[i].f.longInteger = params[i].long_integer;
-            break;
-        case KM_DATE:
-            result[i].f.dateTime = params[i].date_time;
-            break;
-        case KM_BOOL:
-            result[i].f.boolValue = params[i].boolean;
-            break;
-        case KM_BIGNUM:
-        case KM_BYTES:
-            result[i].blob.setToExternal(const_cast<unsigned char*>(params[i].blob.data),
-                                         params[i].blob.data_length);
-            break;
-        case KM_INVALID:
-        default:
-            params[i].tag = KM_TAG_INVALID;
-            /* just skip */
-            break;
-        }
-    }
-    return result;
-}
-
-// Methods from ::android::hardware::keymaster::V3_0::IKeymasterDevice follow.
-Return<void> KeymasterDevice::getHardwareFeatures(getHardwareFeatures_cb _hidl_cb) {
-    bool is_secure = !(keymaster_device_->flags & KEYMASTER_SOFTWARE_ONLY);
-    bool supports_symmetric_cryptography = false;
-    bool supports_attestation = false;
-
-    switch (hardware_version_) {
-    case 2:
-        supports_attestation = true;
-    /* Falls through */
-    case 1:
-        supports_symmetric_cryptography = true;
-        break;
-    };
-
-    _hidl_cb(is_secure, hardware_supports_ec_, supports_symmetric_cryptography,
-             supports_attestation, hardware_supports_all_digests_,
-             keymaster_device_->common.module->name, keymaster_device_->common.module->author);
-    return Void();
-}
-
-Return<ErrorCode> KeymasterDevice::addRngEntropy(const hidl_vec<uint8_t>& data) {
-    if (!data.size()) return ErrorCode::OK;
-    return legacy_enum_conversion(
-        keymaster_device_->add_rng_entropy(keymaster_device_, &data[0], data.size()));
-}
-
-Return<void> KeymasterDevice::generateKey(const hidl_vec<KeyParameter>& keyParams,
-                                          generateKey_cb _hidl_cb) {
-    // result variables for the wire
-    KeyCharacteristics resultCharacteristics;
-    hidl_vec<uint8_t> resultKeyBlob;
-
-    // result variables the backend understands
-    keymaster_key_blob_t key_blob{nullptr, 0};
-    keymaster_key_characteristics_t key_characteristics{{nullptr, 0}, {nullptr, 0}};
-
-    // convert the parameter set to something our backend understands
-    auto kmParams = hidlParams2KmParamSet(keyParams);
-
-    auto rc = keymaster_device_->generate_key(keymaster_device_, &kmParams, &key_blob,
-                                              &key_characteristics);
-
-    if (rc == KM_ERROR_OK) {
-        // on success convert the result to wire format
-        resultKeyBlob = kmBlob2hidlVec(key_blob);
-        resultCharacteristics.softwareEnforced = kmParamSet2Hidl(key_characteristics.sw_enforced);
-        resultCharacteristics.teeEnforced = kmParamSet2Hidl(key_characteristics.hw_enforced);
-    }
-
-    // send results off to the client
-    _hidl_cb(legacy_enum_conversion(rc), resultKeyBlob, resultCharacteristics);
-
-    // free buffers that we are responsible for
-    if (key_blob.key_material) free(const_cast<uint8_t*>(key_blob.key_material));
-    keymaster_free_characteristics(&key_characteristics);
-
-    return Void();
-}
-
-Return<void> KeymasterDevice::getKeyCharacteristics(const hidl_vec<uint8_t>& keyBlob,
-                                                    const hidl_vec<uint8_t>& clientId,
-                                                    const hidl_vec<uint8_t>& appData,
-                                                    getKeyCharacteristics_cb _hidl_cb) {
-    // result variables for the wire
-    KeyCharacteristics resultCharacteristics;
-
-    // result variables the backend understands
-    keymaster_key_characteristics_t key_characteristics{{nullptr, 0}, {nullptr, 0}};
-
-    auto kmKeyBlob = hidlVec2KmKeyBlob(keyBlob);
-    auto kmClientId = hidlVec2KmBlob(clientId);
-    auto kmAppData = hidlVec2KmBlob(appData);
-
-    auto rc = keymaster_device_->get_key_characteristics(
-        keymaster_device_, keyBlob.size() ? &kmKeyBlob : nullptr,
-        clientId.size() ? &kmClientId : nullptr, appData.size() ? &kmAppData : nullptr,
-        &key_characteristics);
-
-    if (rc == KM_ERROR_OK) {
-        resultCharacteristics.softwareEnforced = kmParamSet2Hidl(key_characteristics.sw_enforced);
-        resultCharacteristics.teeEnforced = kmParamSet2Hidl(key_characteristics.hw_enforced);
-    }
-
-    _hidl_cb(legacy_enum_conversion(rc), resultCharacteristics);
-
-    keymaster_free_characteristics(&key_characteristics);
-
-    return Void();
-}
-
-Return<void> KeymasterDevice::importKey(const hidl_vec<KeyParameter>& params, KeyFormat keyFormat,
-                                        const hidl_vec<uint8_t>& keyData, importKey_cb _hidl_cb) {
-    // result variables for the wire
-    KeyCharacteristics resultCharacteristics;
-    hidl_vec<uint8_t> resultKeyBlob;
-
-    // result variables the backend understands
-    keymaster_key_blob_t key_blob{nullptr, 0};
-    keymaster_key_characteristics_t key_characteristics{{nullptr, 0}, {nullptr, 0}};
-
-    auto kmParams = hidlParams2KmParamSet(params);
-    auto kmKeyData = hidlVec2KmBlob(keyData);
-
-    auto rc = keymaster_device_->import_key(keymaster_device_, &kmParams,
-                                            legacy_enum_conversion(keyFormat), &kmKeyData,
-                                            &key_blob, &key_characteristics);
-
-    if (rc == KM_ERROR_OK) {
-        // on success convert the result to wire format
-        // (Can we assume that key_blob is {nullptr, 0} or a valid buffer description?)
-        resultKeyBlob = kmBlob2hidlVec(key_blob);
-        resultCharacteristics.softwareEnforced = kmParamSet2Hidl(key_characteristics.sw_enforced);
-        resultCharacteristics.teeEnforced = kmParamSet2Hidl(key_characteristics.hw_enforced);
-    }
-
-    _hidl_cb(legacy_enum_conversion(rc), resultKeyBlob, resultCharacteristics);
-
-    // free buffers that we are responsible for
-    if (key_blob.key_material) free(const_cast<uint8_t*>(key_blob.key_material));
-    keymaster_free_characteristics(&key_characteristics);
-
-    return Void();
-}
-
-Return<void> KeymasterDevice::exportKey(KeyFormat exportFormat, const hidl_vec<uint8_t>& keyBlob,
-                                        const hidl_vec<uint8_t>& clientId,
-                                        const hidl_vec<uint8_t>& appData, exportKey_cb _hidl_cb) {
-
-    // result variables for the wire
-    hidl_vec<uint8_t> resultKeyBlob;
-
-    // result variables the backend understands
-    keymaster_blob_t out_blob{nullptr, 0};
-
-    auto kmKeyBlob = hidlVec2KmKeyBlob(keyBlob);
-    auto kmClientId = hidlVec2KmBlob(clientId);
-    auto kmAppData = hidlVec2KmBlob(appData);
-
-    auto rc = keymaster_device_->export_key(keymaster_device_, legacy_enum_conversion(exportFormat),
-                                            keyBlob.size() ? &kmKeyBlob : nullptr,
-                                            clientId.size() ? &kmClientId : nullptr,
-                                            appData.size() ? &kmAppData : nullptr, &out_blob);
-
-    if (rc == KM_ERROR_OK) {
-        // on success convert the result to wire format
-        // (Can we assume that key_blob is {nullptr, 0} or a valid buffer description?)
-        resultKeyBlob = kmBlob2hidlVec(out_blob);
-    }
-
-    _hidl_cb(legacy_enum_conversion(rc), resultKeyBlob);
-
-    // free buffers that we are responsible for
-    if (out_blob.data) free(const_cast<uint8_t*>(out_blob.data));
-
-    return Void();
-}
-
-Return<void> KeymasterDevice::attestKey(const hidl_vec<uint8_t>& keyToAttest,
-                                        const hidl_vec<KeyParameter>& attestParams,
-                                        attestKey_cb _hidl_cb) {
-
-    hidl_vec<hidl_vec<uint8_t>> resultCertChain;
-
-    bool foundAttestationApplicationId = false;
-    for (size_t i = 0; i < attestParams.size(); ++i) {
-        switch (attestParams[i].tag) {
-        case Tag::ATTESTATION_ID_BRAND:
-        case Tag::ATTESTATION_ID_DEVICE:
-        case Tag::ATTESTATION_ID_PRODUCT:
-        case Tag::ATTESTATION_ID_SERIAL:
-        case Tag::ATTESTATION_ID_IMEI:
-        case Tag::ATTESTATION_ID_MEID:
-        case Tag::ATTESTATION_ID_MANUFACTURER:
-        case Tag::ATTESTATION_ID_MODEL:
-            // Device id attestation may only be supported if the device is able to permanently
-            // destroy its knowledge of the ids. This device is unable to do this, so it must
-            // never perform any device id attestation.
-            _hidl_cb(ErrorCode::CANNOT_ATTEST_IDS, resultCertChain);
-            return Void();
-
-        case Tag::ATTESTATION_APPLICATION_ID:
-            foundAttestationApplicationId = true;
-            break;
-
-        default:
-            break;
-        }
-    }
-
-    // KM3 devices reject missing attest application IDs. KM2 devices do not.
-    if (!foundAttestationApplicationId) {
-        _hidl_cb(ErrorCode::ATTESTATION_APPLICATION_ID_MISSING,
-                 resultCertChain);
-        return Void();
-    }
-
-    keymaster_cert_chain_t cert_chain{nullptr, 0};
-
-    auto kmKeyToAttest = hidlVec2KmKeyBlob(keyToAttest);
-    auto kmAttestParams = hidlParams2KmParamSet(attestParams);
-
-    auto rc = keymaster_device_->attest_key(keymaster_device_, &kmKeyToAttest, &kmAttestParams,
-                                            &cert_chain);
-
-    if (rc == KM_ERROR_OK) {
-        resultCertChain = kmCertChain2Hidl(&cert_chain);
-    }
-
-    _hidl_cb(legacy_enum_conversion(rc), resultCertChain);
-
-    keymaster_free_cert_chain(&cert_chain);
-
-    return Void();
-}
-
-Return<void> KeymasterDevice::upgradeKey(const hidl_vec<uint8_t>& keyBlobToUpgrade,
-                                         const hidl_vec<KeyParameter>& upgradeParams,
-                                         upgradeKey_cb _hidl_cb) {
-
-    // result variables for the wire
-    hidl_vec<uint8_t> resultKeyBlob;
-
-    // result variables the backend understands
-    keymaster_key_blob_t key_blob{nullptr, 0};
-
-    auto kmKeyBlobToUpgrade = hidlVec2KmKeyBlob(keyBlobToUpgrade);
-    auto kmUpgradeParams = hidlParams2KmParamSet(upgradeParams);
-
-    auto rc = keymaster_device_->upgrade_key(keymaster_device_, &kmKeyBlobToUpgrade,
-                                             &kmUpgradeParams, &key_blob);
-
-    if (rc == KM_ERROR_OK) {
-        // on success convert the result to wire format
-        resultKeyBlob = kmBlob2hidlVec(key_blob);
-    }
-
-    _hidl_cb(legacy_enum_conversion(rc), resultKeyBlob);
-
-    if (key_blob.key_material) free(const_cast<uint8_t*>(key_blob.key_material));
-
-    return Void();
-}
-
-Return<ErrorCode> KeymasterDevice::deleteKey(const hidl_vec<uint8_t>& keyBlob) {
-    if (keymaster_device_->delete_key == nullptr) {
-        return ErrorCode::UNIMPLEMENTED;
-    }
-    auto kmKeyBlob = hidlVec2KmKeyBlob(keyBlob);
-    auto rc = legacy_enum_conversion(
-        keymaster_device_->delete_key(keymaster_device_, &kmKeyBlob));
-    // Keymaster 3.0 requires deleteKey to return ErrorCode::OK if the key
-    // blob is unusable after the call. This is equally true if the key blob was
-    // unusable before.
-    if (rc == ErrorCode::INVALID_KEY_BLOB) return ErrorCode::OK;
-    return rc;
-}
-
-Return<ErrorCode> KeymasterDevice::deleteAllKeys() {
-    if (keymaster_device_->delete_all_keys == nullptr) {
-        return ErrorCode::UNIMPLEMENTED;
-    }
-    return legacy_enum_conversion(keymaster_device_->delete_all_keys(keymaster_device_));
-}
-
-Return<ErrorCode> KeymasterDevice::destroyAttestationIds() {
-    return ErrorCode::UNIMPLEMENTED;
-}
-
-Return<void> KeymasterDevice::begin(KeyPurpose purpose, const hidl_vec<uint8_t>& key,
-                                    const hidl_vec<KeyParameter>& inParams, begin_cb _hidl_cb) {
-
-    // result variables for the wire
-    hidl_vec<KeyParameter> resultParams;
-    uint64_t resultOpHandle = 0;
-
-    // result variables the backend understands
-    keymaster_key_param_set_t out_params{nullptr, 0};
-    keymaster_operation_handle_t& operation_handle = resultOpHandle;
-
-    auto kmKey = hidlVec2KmKeyBlob(key);
-    auto kmInParams = hidlParams2KmParamSet(inParams);
-
-    auto rc = keymaster_device_->begin(keymaster_device_, legacy_enum_conversion(purpose), &kmKey,
-                                       &kmInParams, &out_params, &operation_handle);
-
-    if (rc == KM_ERROR_OK) resultParams = kmParamSet2Hidl(out_params);
-
-    _hidl_cb(legacy_enum_conversion(rc), resultParams, resultOpHandle);
-
-    keymaster_free_param_set(&out_params);
-
-    return Void();
-}
-
-Return<void> KeymasterDevice::update(uint64_t operationHandle,
-                                     const hidl_vec<KeyParameter>& inParams,
-                                     const hidl_vec<uint8_t>& input, update_cb _hidl_cb) {
-    // result variables for the wire
-    uint32_t resultConsumed = 0;
-    hidl_vec<KeyParameter> resultParams;
-    hidl_vec<uint8_t> resultBlob;
-
-    // result variables the backend understands
-    size_t consumed = 0;
-    keymaster_key_param_set_t out_params{nullptr, 0};
-    keymaster_blob_t out_blob{nullptr, 0};
-
-    auto kmInParams = hidlParams2KmParamSet(inParams);
-    auto kmInput = hidlVec2KmBlob(input);
-
-    auto rc = keymaster_device_->update(keymaster_device_, operationHandle, &kmInParams, &kmInput,
-                                        &consumed, &out_params, &out_blob);
-
-    if (rc == KM_ERROR_OK) {
-        resultConsumed = consumed;
-        resultParams = kmParamSet2Hidl(out_params);
-        resultBlob = kmBlob2hidlVec(out_blob);
-    }
-
-    _hidl_cb(legacy_enum_conversion(rc), resultConsumed, resultParams, resultBlob);
-
-    keymaster_free_param_set(&out_params);
-    if (out_blob.data) free(const_cast<uint8_t*>(out_blob.data));
-
-    return Void();
-}
-
-Return<void> KeymasterDevice::finish(uint64_t operationHandle,
-                                     const hidl_vec<KeyParameter>& inParams,
-                                     const hidl_vec<uint8_t>& input,
-                                     const hidl_vec<uint8_t>& signature, finish_cb _hidl_cb) {
-    // result variables for the wire
-    hidl_vec<KeyParameter> resultParams;
-    hidl_vec<uint8_t> resultBlob;
-
-    // result variables the backend understands
-    keymaster_key_param_set_t out_params{nullptr, 0};
-    keymaster_blob_t out_blob{nullptr, 0};
-
-    auto kmInParams = hidlParams2KmParamSet(inParams);
-    auto kmInput = hidlVec2KmBlob(input);
-    auto kmSignature = hidlVec2KmBlob(signature);
-
-    auto rc = keymaster_device_->finish(keymaster_device_, operationHandle, &kmInParams, &kmInput,
-                                        &kmSignature, &out_params, &out_blob);
-
-    if (rc == KM_ERROR_OK) {
-        resultParams = kmParamSet2Hidl(out_params);
-        resultBlob = kmBlob2hidlVec(out_blob);
-    }
-
-    _hidl_cb(legacy_enum_conversion(rc), resultParams, resultBlob);
-
-    keymaster_free_param_set(&out_params);
-    if (out_blob.data) free(const_cast<uint8_t*>(out_blob.data));
-
-    return Void();
-}
-
-Return<ErrorCode> KeymasterDevice::abort(uint64_t operationHandle) {
-    return legacy_enum_conversion(keymaster_device_->abort(keymaster_device_, operationHandle));
 }
 
 IKeymasterDevice* HIDL_FETCH_IKeymasterDevice(const char* name) {
-    keymaster2_device_t* dev = nullptr;
-
     ALOGI("Fetching keymaster device name %s", name);
 
-    uint32_t version = -1;
-    bool supports_ec = false;
-    bool supports_all_digests = false;
-
     if (name && strcmp(name, "softwareonly") == 0) {
-        dev = (new SoftKeymasterDevice(new SoftwareOnlyHidlKeymasterContext))->keymaster2_device();
+        return ::keymaster::ng::CreateKeymasterDevice();
     } else if (name && strcmp(name, "default") == 0) {
-        auto rc = keymaster_device_initialize(&dev, &version, &supports_ec, &supports_all_digests);
-        if (rc) return nullptr;
+        return createKeymaster3Device();
     }
-
-    auto kmrc = ::keymaster::ConfigureDevice(dev);
-    if (kmrc != KM_ERROR_OK) {
-        dev->common.close(&dev->common);
-        return nullptr;
-    }
-
-    return new KeymasterDevice(dev, version, supports_ec, supports_all_digests);
+    return nullptr;
 }
 
 }  // namespace implementation
diff --git a/keymaster/3.0/default/KeymasterDevice.h b/keymaster/3.0/default/KeymasterDevice.h
index e048d5b..267bf85 100644
--- a/keymaster/3.0/default/KeymasterDevice.h
+++ b/keymaster/3.0/default/KeymasterDevice.h
@@ -18,78 +18,14 @@
 #ifndef HIDL_GENERATED_android_hardware_keymaster_V3_0_KeymasterDevice_H_
 #define HIDL_GENERATED_android_hardware_keymaster_V3_0_KeymasterDevice_H_
 
-#include <hardware/keymaster2.h>
-
 #include <android/hardware/keymaster/3.0/IKeymasterDevice.h>
-#include <hidl/Status.h>
 
-#include <hidl/MQDescriptor.h>
 namespace android {
 namespace hardware {
 namespace keymaster {
 namespace V3_0 {
 namespace implementation {
 
-using ::android::hardware::keymaster::V3_0::ErrorCode;
-using ::android::hardware::keymaster::V3_0::IKeymasterDevice;
-using ::android::hardware::keymaster::V3_0::KeyCharacteristics;
-using ::android::hardware::keymaster::V3_0::KeyFormat;
-using ::android::hardware::keymaster::V3_0::KeyParameter;
-using ::android::hardware::keymaster::V3_0::KeyPurpose;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::hidl_string;
-using ::android::sp;
-
-class KeymasterDevice : public IKeymasterDevice {
-  public:
-    KeymasterDevice(keymaster2_device_t* dev, uint32_t hardware_version, bool hardware_supports_ec,
-                    bool hardware_supports_all_digests)
-        : keymaster_device_(dev), hardware_version_(hardware_version),
-          hardware_supports_ec_(hardware_supports_ec),
-          hardware_supports_all_digests_(hardware_supports_all_digests) {}
-    virtual ~KeymasterDevice();
-
-    // Methods from ::android::hardware::keymaster::V3_0::IKeymasterDevice follow.
-    Return<void> getHardwareFeatures(getHardwareFeatures_cb _hidl_cb);
-    Return<ErrorCode> addRngEntropy(const hidl_vec<uint8_t>& data) override;
-    Return<void> generateKey(const hidl_vec<KeyParameter>& keyParams,
-                             generateKey_cb _hidl_cb) override;
-    Return<void> getKeyCharacteristics(const hidl_vec<uint8_t>& keyBlob,
-                                       const hidl_vec<uint8_t>& clientId,
-                                       const hidl_vec<uint8_t>& appData,
-                                       getKeyCharacteristics_cb _hidl_cb) override;
-    Return<void> importKey(const hidl_vec<KeyParameter>& params, KeyFormat keyFormat,
-                           const hidl_vec<uint8_t>& keyData, importKey_cb _hidl_cb) override;
-    Return<void> exportKey(KeyFormat exportFormat, const hidl_vec<uint8_t>& keyBlob,
-                           const hidl_vec<uint8_t>& clientId, const hidl_vec<uint8_t>& appData,
-                           exportKey_cb _hidl_cb) override;
-    Return<void> attestKey(const hidl_vec<uint8_t>& keyToAttest,
-                           const hidl_vec<KeyParameter>& attestParams,
-                           attestKey_cb _hidl_cb) override;
-    Return<void> upgradeKey(const hidl_vec<uint8_t>& keyBlobToUpgrade,
-                            const hidl_vec<KeyParameter>& upgradeParams,
-                            upgradeKey_cb _hidl_cb) override;
-    Return<ErrorCode> deleteKey(const hidl_vec<uint8_t>& keyBlob) override;
-    Return<ErrorCode> deleteAllKeys() override;
-    Return<ErrorCode> destroyAttestationIds() override;
-    Return<void> begin(KeyPurpose purpose, const hidl_vec<uint8_t>& key,
-                       const hidl_vec<KeyParameter>& inParams, begin_cb _hidl_cb) override;
-    Return<void> update(uint64_t operationHandle, const hidl_vec<KeyParameter>& inParams,
-                        const hidl_vec<uint8_t>& input, update_cb _hidl_cb) override;
-    Return<void> finish(uint64_t operationHandle, const hidl_vec<KeyParameter>& inParams,
-                        const hidl_vec<uint8_t>& input, const hidl_vec<uint8_t>& signature,
-                        finish_cb _hidl_cb) override;
-    Return<ErrorCode> abort(uint64_t operationHandle) override;
-
-  private:
-    keymaster2_device_t* keymaster_device_;
-    uint32_t hardware_version_;
-    bool hardware_supports_ec_;
-    bool hardware_supports_all_digests_;
-};
-
 extern "C" IKeymasterDevice* HIDL_FETCH_IKeymasterDevice(const char* name);
 
 }  // namespace implementation
diff --git a/keymaster/3.0/default/android.hardware.keymaster@3.0-service.rc b/keymaster/3.0/default/android.hardware.keymaster@3.0-service.rc
index 849d270..086ba2f 100644
--- a/keymaster/3.0/default/android.hardware.keymaster@3.0-service.rc
+++ b/keymaster/3.0/default/android.hardware.keymaster@3.0-service.rc
@@ -1,4 +1,4 @@
-service keymaster-3-0 /vendor/bin/hw/android.hardware.keymaster@3.0-service
+service vendor.keymaster-3-0 /vendor/bin/hw/android.hardware.keymaster@3.0-service
     class early_hal
     user system
     group system drmrpc
diff --git a/keymaster/3.0/vts/functional/keymaster_hidl_hal_test.cpp b/keymaster/3.0/vts/functional/keymaster_hidl_hal_test.cpp
index e7b222a..6abd9bf 100644
--- a/keymaster/3.0/vts/functional/keymaster_hidl_hal_test.cpp
+++ b/keymaster/3.0/vts/functional/keymaster_hidl_hal_test.cpp
@@ -898,13 +898,20 @@
         }
     }
 
-    void CheckOrigin() {
+    void CheckOrigin(bool asymmetric = false) {
         SCOPED_TRACE("CheckOrigin");
         if (is_secure_ && supports_symmetric_) {
             EXPECT_TRUE(
                 contains(key_characteristics_.teeEnforced, TAG_ORIGIN, KeyOrigin::IMPORTED));
         } else if (is_secure_) {
-            EXPECT_TRUE(contains(key_characteristics_.teeEnforced, TAG_ORIGIN, KeyOrigin::UNKNOWN));
+            // wrapped KM0
+            if (asymmetric) {
+                EXPECT_TRUE(
+                    contains(key_characteristics_.teeEnforced, TAG_ORIGIN, KeyOrigin::UNKNOWN));
+            } else {
+                EXPECT_TRUE(contains(key_characteristics_.softwareEnforced, TAG_ORIGIN,
+                                     KeyOrigin::IMPORTED));
+            }
         } else {
             EXPECT_TRUE(
                 contains(key_characteristics_.softwareEnforced, TAG_ORIGIN, KeyOrigin::IMPORTED));
@@ -993,8 +1000,8 @@
                                    HidlBuf(app_id));
 
     if (!KeymasterHidlTest::IsSecure()) {
-        // SW is KM2
-        EXPECT_EQ(att_keymaster_version, 2U);
+        // SW is KM3
+        EXPECT_EQ(att_keymaster_version, 3U);
     }
 
     if (KeymasterHidlTest::SupportsSymmetric()) {
@@ -1059,13 +1066,17 @@
 
 class NewKeyGenerationTest : public KeymasterHidlTest {
   protected:
-    void CheckBaseParams(const KeyCharacteristics& keyCharacteristics) {
+    void CheckBaseParams(const KeyCharacteristics& keyCharacteristics, bool asymmetric = false) {
         // TODO(swillden): Distinguish which params should be in which auth list.
 
         AuthorizationSet auths(keyCharacteristics.teeEnforced);
         auths.push_back(AuthorizationSet(keyCharacteristics.softwareEnforced));
 
-        EXPECT_TRUE(auths.Contains(TAG_ORIGIN, KeyOrigin::GENERATED));
+        if (!SupportsSymmetric() && asymmetric) {
+            EXPECT_TRUE(auths.Contains(TAG_ORIGIN, KeyOrigin::UNKNOWN));
+        } else {
+            EXPECT_TRUE(auths.Contains(TAG_ORIGIN, KeyOrigin::GENERATED));
+        }
 
         EXPECT_TRUE(auths.Contains(TAG_PURPOSE, KeyPurpose::SIGN));
         EXPECT_TRUE(auths.Contains(TAG_PURPOSE, KeyPurpose::VERIFY));
@@ -1114,7 +1125,7 @@
                                              &key_blob, &key_characteristics));
 
         ASSERT_GT(key_blob.size(), 0U);
-        CheckBaseParams(key_characteristics);
+        CheckBaseParams(key_characteristics, true /* asymmetric */);
 
         AuthorizationSet crypto_params;
         if (IsSecure()) {
@@ -1160,7 +1171,7 @@
                                                  .Authorizations(UserAuths()),
                                              &key_blob, &key_characteristics));
         ASSERT_GT(key_blob.size(), 0U);
-        CheckBaseParams(key_characteristics);
+        CheckBaseParams(key_characteristics, true /* asymmetric */);
 
         AuthorizationSet crypto_params;
         if (IsSecure()) {
@@ -1565,7 +1576,9 @@
                                           .Digest(Digest::NONE)
                                           .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)));
     string result;
-    EXPECT_EQ(ErrorCode::INVALID_INPUT_LENGTH, Finish(message, &result));
+    ErrorCode finish_error_code = Finish(message, &result);
+    EXPECT_TRUE(finish_error_code == ErrorCode::INVALID_INPUT_LENGTH ||
+                finish_error_code == ErrorCode::INVALID_ARGUMENT);
 
     // Very large message that should exceed the transfer buffer size of any reasonable TEE.
     message = string(128 * 1024, 'a');
@@ -1573,7 +1586,9 @@
               Begin(KeyPurpose::SIGN, AuthorizationSetBuilder()
                                           .Digest(Digest::NONE)
                                           .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)));
-    EXPECT_EQ(ErrorCode::INVALID_INPUT_LENGTH, Finish(message, &result));
+    finish_error_code = Finish(message, &result);
+    EXPECT_TRUE(finish_error_code == ErrorCode::INVALID_INPUT_LENGTH ||
+                finish_error_code == ErrorCode::INVALID_ARGUMENT);
 }
 
 /*
@@ -2279,8 +2294,7 @@
  * Verifies that attempting to export RSA keys from corrupted key blobs fails.  This is essentially
  * a poor-man's key blob fuzzer.
  */
-// Disabled due to b/33385206
-TEST_F(ExportKeyTest, DISABLED_RsaCorruptedKeyBlob) {
+TEST_F(ExportKeyTest, RsaCorruptedKeyBlob) {
     ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
                                              .Authorization(TAG_NO_AUTH_REQUIRED)
                                              .RsaSigningKey(1024, 3)
@@ -2303,8 +2317,7 @@
  * Verifies that attempting to export ECDSA keys from corrupted key blobs fails.  This is
  * essentially a poor-man's key blob fuzzer.
  */
-// Disabled due to b/33385206
-TEST_F(ExportKeyTest, DISABLED_EcCorruptedKeyBlob) {
+TEST_F(ExportKeyTest, EcCorruptedKeyBlob) {
     ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
                                              .Authorization(TAG_NO_AUTH_REQUIRED)
                                              .EcdsaSigningKey(EcCurve::P_256)
@@ -2357,7 +2370,7 @@
     CheckKm0CryptoParam(TAG_RSA_PUBLIC_EXPONENT, 65537U);
     CheckKm1CryptoParam(TAG_DIGEST, Digest::SHA_2_256);
     CheckKm1CryptoParam(TAG_PADDING, PaddingMode::RSA_PSS);
-    CheckOrigin();
+    CheckOrigin(true /* asymmetric */);
 
     string message(1024 / 8, 'a');
     auto params = AuthorizationSetBuilder().Digest(Digest::SHA_2_256).Padding(PaddingMode::RSA_PSS);
@@ -2413,7 +2426,7 @@
     CheckKm1CryptoParam(TAG_DIGEST, Digest::SHA_2_256);
     CheckKm2CryptoParam(TAG_EC_CURVE, EcCurve::P_256);
 
-    CheckOrigin();
+    CheckOrigin(true /* asymmetric */);
 
     string message(32, 'a');
     auto params = AuthorizationSetBuilder().Digest(Digest::SHA_2_256);
@@ -2439,7 +2452,7 @@
     CheckKm1CryptoParam(TAG_DIGEST, Digest::SHA_2_256);
     CheckKm2CryptoParam(TAG_EC_CURVE, EcCurve::P_521);
 
-    CheckOrigin();
+    CheckOrigin(true /* asymmetric */);
 
     string message(32, 'a');
     auto params = AuthorizationSetBuilder().Digest(Digest::SHA_2_256);
diff --git a/keymaster/4.0/Android.bp b/keymaster/4.0/Android.bp
new file mode 100644
index 0000000..378204a
--- /dev/null
+++ b/keymaster/4.0/Android.bp
@@ -0,0 +1,26 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.keymaster@4.0",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "types.hal",
+        "IKeymasterDevice.hal",
+    ],
+    interfaces: [
+        "android.hardware.keymaster@3.0",
+        "android.hidl.base@1.0",
+    ],
+    types: [
+        "HardwareAuthToken",
+        "KeyCharacteristics",
+        "KeyParameter",
+        "KeyPurpose",
+        "Tag",
+    ],
+    gen_java: false,
+}
+
diff --git a/keymaster/4.0/IKeymasterDevice.hal b/keymaster/4.0/IKeymasterDevice.hal
new file mode 100644
index 0000000..84354bf
--- /dev/null
+++ b/keymaster/4.0/IKeymasterDevice.hal
@@ -0,0 +1,543 @@
+/*
+ * 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.keymaster@4.0;
+
+import android.hardware.keymaster@3.0::ErrorCode;
+import android.hardware.keymaster@3.0::KeyFormat;
+
+/**
+ * Keymaster device definition.  For thorough documentation see the implementer's reference, at
+ * https://source.android.com/security/keystore/implementer-ref.html
+ */
+interface IKeymasterDevice {
+
+    /**
+     * Returns information about the underlying Keymaster hardware.
+     *
+     * @return security level of the Keymaster implementation accessed through this HAL.
+     *
+     * @return keymasterName is the name of the Keymaster implementation.
+     *
+     * @return keymasterAuthorName is the name of the author of the Keymaster implementation
+     *         (organization name, not individual).
+     */
+    getHardwareInfo()
+        generates (SecurityLevel securityLevel, string keymasterName, string keymasterAuthorName);
+
+    /**
+     * Start the creation of an HMAC key, shared with another Keymaster implementation.  Any device
+     * with a StrongBox Keymaster has two Keymaster instances, because there must be a TEE Keymaster
+     * as well.  The HMAC key used to MAC and verify authentication tokens must be shared between
+     * TEE and StrongBox so they can each validate tokens produced by the other.  This method is the
+     * first step in the process for for agreeing on a shared key.  It is called by Keystore during
+     * startup if and only if Keystore loads multiple Keymaster HALs.  Keystore calls it on each of
+     * the HAL instances and collects the results in preparation for the second step.
+     */
+    getHmacSharingParameters() generates (ErrorCode error, HmacSharingParameters params);
+
+    /**
+     * Complete the creation of an HMAC key, shared with another Keymaster implementation.  Any
+     * device with a StrongBox Keymaster has two Keymasters instances, because there must be a TEE
+     * Keymaster as well.  The HMAC key used to MAC and verify authentication tokens must be shared
+     * between TEE and StrongBox so they can each validate tokens produced by the other.  This
+     * method is the second and final step in the process for for agreeing on a shared key.  It is
+     * called by Keystore during startup if and only if Keystore loads multiple Keymaster HALs.
+     * Keystore calls it on each of the HAL instances, and sends to it all of the
+     * HmacSharingParameters returned by all HALs.
+     *
+     * This method computes the shared 32-byte HMAC ``H'' as follows (all Keymaster instances
+     * perform the same computation to arrive at the same result):
+     *
+     *     H = CKDF(key = K,
+     *              context = P1 || P2 || ... || Pn,
+     *              label = "KeymasterSharedMac")
+     *
+     * where:
+     *
+     *     ``CKDF'' is the standard AES-CMAC KDF from NIST SP 800-108 in counter mode (see Section
+     *           5.1 of the referenced publication).  ``key'', ``context'', and ``label'' are
+     *           defined in the standard.  The counter is prefixed, as shown in the construction on
+     *           page 12 of the standard.  The label string is UTF-8 encoded.
+     *
+     *     ``K'' is a pre-established shared secret, set up during factory reset.  The mechanism for
+     *           establishing this shared secret is implementation-defined, but see below for a
+     *           recommended approach, which assumes that the TEE Keymaster does not have storage
+     *           available to it, but the StrongBox Keymaster does.
+     *
+     *           <b>CRITICAL SECURITY REQUIREMENT</b>: All keys created by a Keymaster instance must
+     *           be cryptographically bound to the value of K, such that establishing a new K
+     *           permanently destroys them.
+     *
+     *     ``||'' represents concatenation.
+     *
+     *     ``Pi'' is the i'th HmacSharingParameters value in the params vector.  Note that at
+     *           present only two Keymaster implementations are supported, but this mechanism
+     *           extends without modification to any number of implementations.  Encoding of an
+     *           HmacSharingParameters is the concatenation of its two fields, i.e. seed || nonce.
+     *
+     * Process for establishing K:
+     *
+     *     Any method of securely establishing K that ensures that an attacker cannot obtain or
+     *     derive its value is acceptable.  What follows is a recommended approach, to be executed
+     *     during each factory reset.  It relies on use of the factory-installed attestation keys to
+     *     mitigate man-in-the-middle attacks.  This protocol requires that one of the instancess
+     *     have secure persistent storage.  This model was chosen because StrongBox has secure
+     *     persistent storage (by definition), but the TEE may not.  The instance without storage is
+     *     assumed to be able to derive a unique hardware-bound key (HBK) which is used only for
+     *     this purpose, and is not derivable outside of the secure environment..
+     *
+     *     In what follows, T is the Keymaster instance without storage, S is the Keymaster instance
+     *     with storage:
+     *
+     *     1. T generates an ephemeral EC P-256 key pair K1
+     *     2. T sends K1_pub to S, signed with T's attestation key.
+     *     3. S validates the signature on K1_pub.
+     *     4. S generates an ephemeral EC P-256 key pair K2.
+     *     5. S sends {K1_pub, K2_pub}, to T, signed with S's attestation key.
+     *     6. T validates the signature on {K1_pub, K2_pub}
+     *     7. T uses {K1_priv, K2_pub} with ECDH to compute session secret Q.
+     *     8. T generates a random seed S
+     *     9. T computes K = KDF(HBK, S), where KDF is some secure key derivation function.
+     *     10. T sends M = AES-GCM-ENCRYPT(Q, {S || K}) to S.
+     *     10. S uses {K2_priv, K1_pub} with ECDH to compute session secret Q.
+     *     11. S computes S || K = AES-GCM-DECRYPT(Q, M) and stores S and K.
+     *
+     *     When S receives the getHmacSharingParameters call, it returns the stored S as the seed
+     *     and a nonce.  When T receives the same call, it returns an empty seed and a nonce.  When
+     *     T receives the computeSharedHmac call, it uses the seed provided by S to compute K.  S,
+     *     of course, has K stored.
+     *
+     * @param params The HmacSharingParameters data returned by all Keymaster instances when
+     *        getHmacSharingParameters was called.
+     *
+     * @return sharingCheck A 32-byte value used to verify that all Keymaster instances have
+     *         computed the same shared HMAC key.  The sharingCheck value is computed as follows:
+     *
+     *             sharingCheck = HMAC(H, "Keymaster HMAC Verification")
+     *
+     *         The string is UTF-8 encoded.  If the returned values of all Keymaster instances don't
+     *         match, Keystore will assume that HMAC agreement failed.
+     */
+    computeSharedHmac(vec<HmacSharingParameters> params)
+        generates (ErrorCode error, vec<uint8_t> sharingCheck);
+
+    /**
+     * Verify authorizations for another Keymaster instance.
+     *
+     * On systems with both a StrongBox and a TEE Keymaster instance it is sometimes useful to ask
+     * the TEE Keymaster to verify authorizations for a key hosted in StrongBox.
+     *
+     * For every StrongBox operation, Keystore is required to call this method on the TEE Keymaster,
+     * passing in the StrongBox key's hardwareEnforced authorization list and the operation handle
+     * returned by StrongBox begin().  The TEE Keymaster must validate all of the authorizations it
+     * can and return those it validated in the VerificationToken.  If it cannot verify any, the
+     * parametersVerified field of the VerificationToken must be empty.  Keystore must then pass the
+     * VerificationToken to the subsequent invocations of StrongBox update() and finish().
+     *
+     * StrongBox implementations must return ErrorCode::UNIMPLEMENTED.
+     *
+     * @param operationHandle the operation handle returned by StrongBox Keymaster's begin().
+     *
+     * @param parametersToVerify Set of authorizations to verify.
+     *
+     * @param authToken A HardwareAuthToken if needed to authorize key usage.
+     */
+    verifyAuthorization(uint64_t operationHandle, vec<KeyParameter> parametersToVerify,
+                        HardwareAuthToken authToken)
+        generates (ErrorCode error, VerificationToken token);
+
+
+    /**
+     * Adds entropy to the RNG used by Keymaster.  Entropy added through this method is guaranteed
+     * not to be the only source of entropy used, and the mixing function is required to be secure,
+     * in the sense that if the RNG is seeded (from any source) with any data the attacker cannot
+     * predict (or control), then the RNG output is indistinguishable from random.  Thus, if the
+     * entropy from any source is good, the output must be good.
+     *
+     * @param data Bytes to be mixed into the RNG.
+     *
+     * @return error See the ErrorCode enum in types.hal.
+     */
+    addRngEntropy(vec<uint8_t> data) generates (ErrorCode error);
+
+    /**
+     * Generates a key, or key pair, returning a key blob and a description of the key.
+     *
+     * @param keyParams Key generation parameters are defined as Keymaster tag/value pairs, provided
+     *        in params.  See Tag in types.hal for the full list.
+     *
+     * @return error See the ErrorCode enum in types.hal.
+     *
+     * @return keyBlob Opaque, encrypted descriptor of the generated key.  A recommended
+     *        implementation strategy is to include an encrypted copy of the key material, wrapped
+     *        in a key unavailable outside secure hardware.
+     *
+     * @return keyCharacteristics Description of the generated key.  See KeyCharacteristis in
+     *         types.hal.
+     */
+    generateKey(vec<KeyParameter> keyParams)
+        generates (ErrorCode error, vec<uint8_t> keyBlob, KeyCharacteristics keyCharacteristics);
+
+    /**
+     * Imports a key, or key pair, returning a key blob and/or a description of the key.
+     *
+     * @param keyParams Key generation parameters are defined as Keymaster tag/value pairs, provided
+     *        in params.  See Tag for the full list.
+     *
+     * @param keyFormat The format of the key material to import.
+     *
+     * @pram keyData The key material to import, in the format specifed in keyFormat.
+     *
+     * @return error See the ErrorCode enum.
+     *
+     * @return keyBlob Opaque, encrypted descriptor of the generated key, which will generally
+     *         contain a copy of the key material, wrapped in a key unavailable outside secure
+     *         hardware.
+     *
+     * @return keyCharacteristics Decription of the generated key.
+     */
+    importKey(vec<KeyParameter> keyParams, KeyFormat keyFormat, vec<uint8_t> keyData)
+        generates (ErrorCode error, vec<uint8_t> keyBlob, KeyCharacteristics keyCharacteristics);
+
+    /**
+     * Securely imports a key, or key pair, returning a key blob and a description of the imported
+     * key.
+     *
+     * @param wrappedKeyData The wrapped key material to import.  The wrapped key is in DER-encoded
+     * ASN.1 format, specified by the following schema:
+     *
+     *     KeyDescription ::= SEQUENCE(
+     *         keyFormat INTEGER,                   # Values from KeyFormat enum.
+     *         keyParams AuthorizationList,
+     *     )
+     *
+     *     SecureKeyWrapper ::= SEQUENCE(
+     *         version INTEGER,                     # Contains value 0
+     *         encryptedTransportKey OCTET_STRING,
+     *         initializationVector OCTET_STRING,
+     *         keyDescription KeyDescription,
+     *         encryptedKey OCTET_STRING,
+     *         tag OCTET_STRING
+     *     )
+     *
+     *     Where:
+     *
+     *     o keyFormat is an integer from the KeyFormat enum, defining the format of the plaintext
+     *       key material.
+     *     o keyParams is the characteristics of the key to be imported (as with generateKey or
+     *       importKey).  If the secure import is successful, these characteristics must be
+     *       associated with the key exactly as if the key material had been insecurely imported
+     *       with the @3.0::IKeymasterDevice::importKey.
+     *     o encryptedTransportKey is a 256-bit AES key, XORed with a masking key and then encrypted
+     *       in RSA-OAEP mode (SHA-256 digest, SHA-1 MGF1 digest) with the wrapping key specified by
+     *       wrappingKeyBlob.
+     *     o keyDescription is a KeyDescription, above.
+     *     o encryptedKey is the key material of the key to be imported, in format keyFormat, and
+     *       encrypted with encryptedEphemeralKey in AES-GCM mode, with the DER-encoded
+     *       representation of keyDescription provided as additional authenticated data.
+     *     o tag is the tag produced by the AES-GCM encryption of encryptedKey.
+     *
+     * So, importWrappedKey does the following:
+     *
+     *     1. Get the private key material for wrappingKeyBlob, verifying that the wrapping key has
+     *        purpose KEY_WRAP, padding mode RSA_OAEP, and digest SHA_2_256, returning the
+     *        appropriate error if any of those requirements fail.
+     *     2. Extract the encryptedTransportKey field from the SecureKeyWrapper, and decrypt
+     *        it with the wrapping key.
+     *     3. XOR the result of step 2 with maskingKey.
+     *     4. Use the result of step 3 as an AES-GCM key to decrypt encryptedKey, using the encoded
+     *        value of keyDescription as the additional authenticated data.  Call the result
+     *        "keyData" for the next step.
+     *     5. Perform the equivalent of calling importKey(keyParams, keyFormat, keyData), except
+     *        that the origin tag should be set to SECURELY_IMPORTED.
+     *
+     * @param wrappingKeyBlob The opaque key descriptor returned by generateKey() or importKey().
+     *        This key must have been created with Purpose::WRAP_KEY, and must be a key algorithm
+     *        that supports encryption and must be at least as strong (in key size) as the key to be
+     *        imported (per NIST key length recommendations: 112 bits symmetric is equivalent to
+     *        2048-bit RSA or 224-bit EC, 128 bits symmetric ~ 3072-bit RSA or 256-bit EC, etc.).
+     *
+     * @param maskingKey The 32-byte value XOR'd with the transport key in the SecureWrappedKey
+     *        structure.
+     *
+     * @return error See the ErrorCode enum.
+     *
+     * @return keyBlob Opaque descriptor of the imported key.  It is recommended that the keyBlob
+     *         contain a copy of the key material, wrapped in a key unavailable outside secure
+     *         hardware.
+     */
+    importWrappedKey(vec<uint8_t> wrappedKeyData, vec<uint8_t> wrappingKeyBlob,
+                     vec<uint8_t> maskingKey)
+        generates (ErrorCode error, vec<uint8_t> keyBlob, KeyCharacteristics keyCharacteristics);
+
+    /**
+     * Returns the characteristics of the specified key, if the keyBlob is valid (implementations
+     * must fully validate the integrity of the key).
+     *
+     * @param keyBlob The opaque descriptor returned by generateKey() or importKey();
+     *
+     * @param clientId An opaque byte string identifying the client.  This value must match the
+     *        Tag::APPLICATION_ID data provided during key generation/import.  Without the correct
+     *        value, it must be computationally infeasible for the secure hardware to obtain the key
+     *        material.
+     *
+     * @param appData An opaque byte string provided by the application.  This value must match the
+     *        Tag::APPLICATION_DATA data provided during key generation/import.  Without the correct
+     *        value, it must be computationally infeasible for the secure hardware to obtain the key
+     *        material.
+     *
+     * @return error See the ErrorCode enum in types.hal.
+     *
+     * @return keyCharacteristics Decription of the generated key.  See KeyCharacteristis in
+     *         types.hal.
+     */
+    getKeyCharacteristics(vec<uint8_t> keyBlob, vec<uint8_t> clientId, vec<uint8_t> appData)
+        generates (ErrorCode error, KeyCharacteristics keyCharacteristics);
+
+    /**
+     * Exports a public key, returning the key in the specified format.
+     *
+     * @parm keyFormat The format used for export.  See KeyFormat in types.hal.
+     *
+     * @param keyBlob The opaque descriptor returned by generateKey() or importKey().  The
+     *        referenced key must be asymmetric.
+     *
+     * @param clientId An opaque byte string identifying the client.  This value must match the
+     *        Tag::APPLICATION_ID data provided during key generation/import.  Without the correct
+     *        value, it must be computationally infeasible for the secure hardware to obtain the key
+     *        material.
+     *
+     * @param appData An opaque byte string provided by the application.  This value must match the
+     *        Tag::APPLICATION_DATA data provided during key generation/import.  Without the correct
+     *        value, it must be computationally infeasible for the secure hardware to obtain the key
+     *        material.
+     *
+     * @return error See the ErrorCode enum in types.hal.
+     *
+     * @return keyMaterial The public key material in PKCS#8 format.
+     */
+    exportKey(KeyFormat keyFormat, vec<uint8_t> keyBlob, vec<uint8_t> clientId,
+              vec<uint8_t> appData) generates (ErrorCode error, vec<uint8_t> keyMaterial);
+
+    /**
+     * Generates a signed X.509 certificate chain attesting to the presence of keyToAttest in
+     * Keymaster.  The certificate must contain an extension with OID 1.3.6.1.4.1.11129.2.1.17 and
+     * value defined in:
+     *
+     *     https://developer.android.com/training/articles/security-key-attestation.html.
+     *
+     * @param keyToAttest The opaque descriptor returned by generateKey() or importKey().  The
+     *        referenced key must be asymmetric.
+     *
+     * @param attestParams Parameters for the attestation, notably Tag::ATTESTATION_CHALLENGE.
+     *
+     * @return error See the ErrorCode enum in types.hal.
+     *
+     * @return certChain The attestation certificate, and additional certificates back to the root
+     *         attestation certificate, which clients will need to check against a known-good value.
+     */
+    attestKey(vec<uint8_t> keyToAttest, vec<KeyParameter> attestParams)
+        generates (ErrorCode error, vec<vec<uint8_t>> certChain);
+
+    /**
+     * Upgrades an old key blob.  Keys can become "old" in two ways: Keymaster can be upgraded to a
+     * new version with an incompatible key blob format, or the system can be updated to invalidate
+     * the OS version and/or patch level.  In either case, attempts to use an old key blob with
+     * getKeyCharacteristics(), exportKey(), attestKey() or begin() must result in Keymaster
+     * returning ErrorCode::KEY_REQUIRES_UPGRADE.  The caller must use this method to upgrade the
+     * key blob.
+     *
+     * @param keyBlobToUpgrade The opaque descriptor returned by generateKey() or importKey();
+     *
+     * @param upgradeParams A parameter list containing any parameters needed to complete the
+     *        upgrade, including Tag::APPLICATION_ID and Tag::APPLICATION_DATA.
+     *
+     * @return error See the ErrorCode enum.
+     *
+     * @return upgradedKeyBlob A new key blob that references the same key as keyBlobToUpgrade, but
+     *         is in the new format, or has the new version data.
+     */
+    upgradeKey(vec<uint8_t> keyBlobToUpgrade, vec<KeyParameter> upgradeParams)
+        generates (ErrorCode error, vec<uint8_t> upgradedKeyBlob);
+
+    /**
+     * Deletes the key, or key pair, associated with the key blob.  Calling this function on a key
+     * with Tag::ROLLBACK_RESISTANCE in its hardware-enforced authorization list must render the key
+     * permanently unusable.  Keys without Tag::ROLLBACK_RESISTANCE may or may not be rendered
+     * unusable.
+     *
+     * @param keyBlob The opaque descriptor returned by generateKey() or importKey();
+     *
+     * @return error See the ErrorCode enum.
+     */
+    deleteKey(vec<uint8_t> keyBlob) generates (ErrorCode error);
+
+    /**
+     * Deletes all keys in the hardware keystore.  Used when keystore is reset completely.  After
+     * this function is called all keys with Tag::ROLLBACK_RESISTANCE in their hardware-enforced
+     * authorization lists must be rendered permanently unusable.  Keys without
+     * Tag::ROLLBACK_RESISTANCE may or may not be rendered unusable.
+     *
+     * @return error See the ErrorCode enum.
+     */
+    deleteAllKeys() generates (ErrorCode error);
+
+    /**
+     * Destroys knowledge of the device's ids.  This prevents all device id attestation in the
+     * future.  The destruction must be permanent so that not even a factory reset will restore the
+     * device ids.
+     *
+     * Device id attestation may be provided only if this method is fully implemented, allowing the
+     * user to permanently disable device id attestation.  If this cannot be guaranteed, the device
+     * must never attest any device ids.
+     *
+     * This is a NOP if device id attestation is not supported.
+     *
+     * @return error See the ErrorCode enum.
+     */
+    destroyAttestationIds() generates (ErrorCode error);
+
+    /**
+     * Begins a cryptographic operation using the specified key.  If all is well, begin() must
+     * return ErrorCode::OK and create an operation handle which must be passed to subsequent calls
+     * to update(), finish() or abort().
+     *
+     * It is critical that each call to begin() be paired with a subsequent call to finish() or
+     * abort(), to allow the Keymaster implementation to clean up any internal operation state.  The
+     * caller's failure to do this may leak internal state space or other internal resources and may
+     * eventually cause begin() to return ErrorCode::TOO_MANY_OPERATIONS when it runs out of space
+     * for operations.  Any result other than ErrorCode::OK from begin(), update() or finish()
+     * implicitly aborts the operation, in which case abort() need not be called (and must return
+     * ErrorCode::INVALID_OPERATION_HANDLE if called).
+     *
+     * @param purpose The purpose of the operation, one of KeyPurpose::ENCRYPT, KeyPurpose::DECRYPT,
+     *        KeyPurpose::SIGN or KeyPurpose::VERIFY.  Note that for AEAD modes, encryption and
+     *        decryption imply signing and verification, respectively, but must be specified as
+     *        KeyPurpose::ENCRYPT and KeyPurpose::DECRYPT.
+     *
+     * @param keyBlob The opaque key descriptor returned by generateKey() or importKey().  The key
+     *        must have a purpose compatible with purpose and all of its usage requirements must be
+     *        satisfied, or begin() must return an appropriate error code.
+     *
+     * @param inParams Additional parameters for the operation.  If Tag::APPLICATION_ID or
+     *        Tag::APPLICATION_DATA were provided during generation, they must be provided here, or
+     *        the operation must fail with ErrorCode::INVALID_KEY_BLOB.  For operations that require
+     *        a nonce or IV, on keys that were generated with Tag::CALLER_NONCE, inParams may
+     *        contain a tag Tag::NONCE.  If Tag::NONCE is provided for a key without
+     *        Tag:CALLER_NONCE, ErrorCode::CALLER_NONCE_PROHIBITED must be returned.
+     *
+     * @param authToken Authentication token.  Callers that provide no token must set all numeric
+     *        fields to zero and the MAC must be an empty vector.
+     *
+     * @return error See the ErrorCode enum in types.hal.
+     *
+     * @return outParams Output parameters.  Used to return additional data from the operation
+     *         initialization, notably to return the IV or nonce from operations that generate an IV
+     *         or nonce.
+     *
+     * @return operationHandle The newly-created operation handle which must be passed to update(),
+     *         finish() or abort().
+     */
+    begin(KeyPurpose purpose, vec<uint8_t> keyBlob, vec<KeyParameter> inParams,
+          HardwareAuthToken authToken)
+        generates (ErrorCode error, vec<KeyParameter> outParams, OperationHandle operationHandle);
+
+    /**
+     * Provides data to, and possibly receives output from, an ongoing cryptographic operation begun
+     * with begin().
+     *
+     * If operationHandle is invalid, update() must return ErrorCode::INVALID_OPERATION_HANDLE.
+     *
+     * update() may not consume all of the data provided in the data buffer.  update() must return
+     * the amount consumed in inputConsumed.  The caller may provide the unconsumed data in a
+     * subsequent call.
+     *
+     * @param operationHandle The operation handle returned by begin().
+     *
+     * @param inParams Additional parameters for the operation.  For AEAD modes, this is used to
+     *        specify Tag::ADDITIONAL_DATA.  Note that additional data may be provided in multiple
+     *        calls to update(), but only until input data has been provided.
+     *
+     * @param input Data to be processed.  Note that update() may or may not consume all of the data
+     *        provided.  See inputConsumed.
+     *
+     * @param authToken Authentication token.  Callers that provide no token must set all numeric
+     *        fields to zero and the MAC must be an empty vector.
+     *
+     * @param verificationToken Verification token, used to prove that another Keymaster HAL has
+     *        verified some parameters, and to deliver the other HAL's current timestamp, if needed.
+     *        If not provided, all fields must be initialized to zero and vectors empty.
+     *
+     * @return error See the ErrorCode enum in types.hal.
+     *
+     * @return inputConsumed Amount of data that was consumed by update().  If this is less than the
+     *         amount provided, the caller may provide the remainder in a subsequent call to
+     *         update() or finish().  Every call to update must consume at least one byte, and
+     *         implementations should consume as much data as reasonably possible for each call.
+     *
+     * @return outParams Output parameters, used to return additional data from the operation.
+     *
+     * @return output The output data, if any.
+     */
+    update(OperationHandle operationHandle, vec<KeyParameter> inParams, vec<uint8_t> input,
+           HardwareAuthToken authToken, VerificationToken verificationToken)
+        generates (ErrorCode error, uint32_t inputConsumed, vec<KeyParameter> outParams,
+                   vec<uint8_t> output);
+
+    /**
+     * Finalizes a cryptographic operation begun with begin() and invalidates operationHandle.
+     *
+     * @param operationHandle The operation handle returned by begin().  This handle must be invalid
+     *        when finish() returns.
+     *
+     * @param inParams Additional parameters for the operation.  For AEAD modes, this is used to
+     *        specify Tag::ADDITIONAL_DATA, but only if no input data was provided to update().
+     *
+     * @param input Data to be processed, per the parameters established in the call to begin().
+     *        finish() must consume all provided data or return ErrorCode::INVALID_INPUT_LENGTH.
+     *
+     * @param signature The signature to be verified if the purpose specified in the begin() call
+     *        was KeyPurpose::VERIFY.
+     *
+     * @param authToken Authentication token.  Callers that provide no token must set all numeric
+     *        fields to zero and the MAC must be an empty vector.
+     *
+     * @param verificationToken Verification token, used to prove that another Keymaster HAL has
+     *        verified some parameters, and to deliver the other HAL's current timestamp, if needed.
+     *        If not provided, all fields must be initialized to zero and vectors empty.
+     *
+     * @return error See the ErrorCode enum in types.hal.
+     *
+     * @return outParams Any output parameters generated by finish().
+     *
+     * @return output The output data, if any.
+     */
+    finish(OperationHandle operationHandle, vec<KeyParameter> inParams, vec<uint8_t> input,
+           vec<uint8_t> signature, HardwareAuthToken authToken, VerificationToken verificationToken)
+        generates (ErrorCode error, vec<KeyParameter> outParams, vec<uint8_t> output);
+
+    /**
+     * Aborts a cryptographic operation begun with begin(), freeing all internal resources and
+     * invalidating operationHandle.
+     *
+     * @param operationHandle The operation handle returned by begin().  This handle must be
+     *        invalid when abort() returns.
+     *
+     * @return error See the ErrorCode enum in types.hal.
+     */
+    abort(OperationHandle operationHandle) generates (ErrorCode error);
+};
diff --git a/broadcastradio/1.1/utils/Android.bp b/keymaster/4.0/default/Android.bp
similarity index 61%
copy from broadcastradio/1.1/utils/Android.bp
copy to keymaster/4.0/default/Android.bp
index e80d133..0cede50 100644
--- a/broadcastradio/1.1/utils/Android.bp
+++ b/keymaster/4.0/default/Android.bp
@@ -14,21 +14,24 @@
 // limitations under the License.
 //
 
-cc_library_static {
-    name: "android.hardware.broadcastradio@1.1-utils-lib",
-    vendor_available: true,
+cc_binary {
+    name: "android.hardware.keymaster@4.0-service",
+    defaults: ["hidl_defaults"],
     relative_install_path: "hw",
-    cflags: [
-        "-Wall",
-        "-Wextra",
-        "-Werror",
-    ],
-    srcs: [
-        "Utils.cpp",
-        "WorkerThread.cpp",
-    ],
-    export_include_dirs: ["include"],
+    vendor: true,
+    init_rc: ["android.hardware.keymaster@4.0-service.rc"],
+    srcs: ["service.cpp"],
+
     shared_libs: [
-        "android.hardware.broadcastradio@1.1",
+        "android.hardware.keymaster@4.0",
+        "libbase",
+        "libcutils",
+        "libhardware",
+        "libhidlbase",
+        "libhidltransport",
+        "libkeymaster4",
+        "liblog",
+        "libutils",
     ],
+
 }
diff --git a/keymaster/4.0/default/OWNERS b/keymaster/4.0/default/OWNERS
new file mode 100644
index 0000000..335660d
--- /dev/null
+++ b/keymaster/4.0/default/OWNERS
@@ -0,0 +1,2 @@
+jdanis@google.com
+swillden@google.com
diff --git a/keymaster/4.0/default/android.hardware.keymaster@4.0-service.rc b/keymaster/4.0/default/android.hardware.keymaster@4.0-service.rc
new file mode 100644
index 0000000..2ce439e
--- /dev/null
+++ b/keymaster/4.0/default/android.hardware.keymaster@4.0-service.rc
@@ -0,0 +1,4 @@
+service vendor.keymaster-4-0 /vendor/bin/hw/android.hardware.keymaster@4.0-service
+    class early_hal
+    user system
+    group system drmrpc
diff --git a/keymaster/4.0/default/service.cpp b/keymaster/4.0/default/service.cpp
new file mode 100644
index 0000000..f4b5fd3
--- /dev/null
+++ b/keymaster/4.0/default/service.cpp
@@ -0,0 +1,33 @@
+/*
+**
+** 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.
+*/
+
+#include <android-base/logging.h>
+#include <android/hardware/keymaster/4.0/IKeymasterDevice.h>
+#include <hidl/HidlTransportSupport.h>
+
+#include <AndroidKeymaster4Device.h>
+
+int main() {
+    auto keymaster = ::keymaster::V4_0::ng::CreateKeymasterDevice();
+    auto status = keymaster->registerAsService();
+    if (status != android::OK) {
+        LOG(FATAL) << "Could not register service for Keymaster 4.0 (" << status << ")";
+    }
+
+    android::hardware::joinRpcThreadpool();
+    return -1;  // Should never get here.
+}
diff --git a/broadcastradio/1.1/utils/Android.bp b/keymaster/4.0/support/Android.bp
similarity index 73%
copy from broadcastradio/1.1/utils/Android.bp
copy to keymaster/4.0/support/Android.bp
index e80d133..31acfca 100644
--- a/broadcastradio/1.1/utils/Android.bp
+++ b/keymaster/4.0/support/Android.bp
@@ -14,21 +14,24 @@
 // limitations under the License.
 //
 
-cc_library_static {
-    name: "android.hardware.broadcastradio@1.1-utils-lib",
+cc_library {
+    name: "libkeymaster4support",
     vendor_available: true,
-    relative_install_path: "hw",
     cflags: [
         "-Wall",
         "-Wextra",
         "-Werror",
     ],
     srcs: [
-        "Utils.cpp",
-        "WorkerThread.cpp",
+        "attestation_record.cpp",
+        "authorization_set.cpp",
+        "key_param_output.cpp",
     ],
     export_include_dirs: ["include"],
     shared_libs: [
-        "android.hardware.broadcastradio@1.1",
-    ],
+        "android.hardware.keymaster@3.0",
+        "android.hardware.keymaster@4.0",
+        "libcrypto",
+        "libhidlbase",
+    ]
 }
diff --git a/keymaster/4.0/support/OWNERS b/keymaster/4.0/support/OWNERS
new file mode 100644
index 0000000..335660d
--- /dev/null
+++ b/keymaster/4.0/support/OWNERS
@@ -0,0 +1,2 @@
+jdanis@google.com
+swillden@google.com
diff --git a/keymaster/4.0/support/attestation_record.cpp b/keymaster/4.0/support/attestation_record.cpp
new file mode 100644
index 0000000..8f37d9c
--- /dev/null
+++ b/keymaster/4.0/support/attestation_record.cpp
@@ -0,0 +1,289 @@
+/*
+ * 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.
+ */
+
+#include <keymasterV4_0/attestation_record.h>
+
+#include <assert.h>
+
+#include <openssl/asn1t.h>
+#include <openssl/bn.h>
+#include <openssl/evp.h>
+#include <openssl/x509.h>
+
+#include <keymasterV4_0/authorization_set.h>
+#include <keymasterV4_0/openssl_utils.h>
+
+namespace android {
+namespace hardware {
+namespace keymaster {
+namespace V4_0 {
+
+struct stack_st_ASN1_TYPE_Delete {
+    void operator()(stack_st_ASN1_TYPE* p) { sk_ASN1_TYPE_free(p); }
+};
+
+struct ASN1_STRING_Delete {
+    void operator()(ASN1_STRING* p) { ASN1_STRING_free(p); }
+};
+
+struct ASN1_TYPE_Delete {
+    void operator()(ASN1_TYPE* p) { ASN1_TYPE_free(p); }
+};
+
+#define ASN1_INTEGER_SET STACK_OF(ASN1_INTEGER)
+
+typedef struct km_root_of_trust {
+    ASN1_OCTET_STRING* verified_boot_key;
+    ASN1_BOOLEAN* device_locked;
+    ASN1_ENUMERATED* verified_boot_state;
+} KM_ROOT_OF_TRUST;
+
+ASN1_SEQUENCE(KM_ROOT_OF_TRUST) = {
+    ASN1_SIMPLE(KM_ROOT_OF_TRUST, verified_boot_key, ASN1_OCTET_STRING),
+    ASN1_SIMPLE(KM_ROOT_OF_TRUST, device_locked, ASN1_BOOLEAN),
+    ASN1_SIMPLE(KM_ROOT_OF_TRUST, verified_boot_state, ASN1_ENUMERATED),
+} ASN1_SEQUENCE_END(KM_ROOT_OF_TRUST);
+IMPLEMENT_ASN1_FUNCTIONS(KM_ROOT_OF_TRUST);
+
+typedef struct km_auth_list {
+    ASN1_INTEGER_SET* purpose;
+    ASN1_INTEGER* algorithm;
+    ASN1_INTEGER* key_size;
+    ASN1_INTEGER_SET* digest;
+    ASN1_INTEGER_SET* padding;
+    ASN1_INTEGER* ec_curve;
+    ASN1_INTEGER* rsa_public_exponent;
+    ASN1_INTEGER* active_date_time;
+    ASN1_INTEGER* origination_expire_date_time;
+    ASN1_INTEGER* usage_expire_date_time;
+    ASN1_NULL* no_auth_required;
+    ASN1_INTEGER* user_auth_type;
+    ASN1_INTEGER* auth_timeout;
+    ASN1_NULL* allow_while_on_body;
+    ASN1_NULL* all_applications;
+    ASN1_OCTET_STRING* application_id;
+    ASN1_INTEGER* creation_date_time;
+    ASN1_INTEGER* origin;
+    ASN1_NULL* rollback_resistant;
+    KM_ROOT_OF_TRUST* root_of_trust;
+    ASN1_INTEGER* os_version;
+    ASN1_INTEGER* os_patchlevel;
+    ASN1_OCTET_STRING* attestation_application_id;
+} KM_AUTH_LIST;
+
+ASN1_SEQUENCE(KM_AUTH_LIST) = {
+    ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, purpose, ASN1_INTEGER, TAG_PURPOSE.maskedTag()),
+    ASN1_EXP_OPT(KM_AUTH_LIST, algorithm, ASN1_INTEGER, TAG_ALGORITHM.maskedTag()),
+    ASN1_EXP_OPT(KM_AUTH_LIST, key_size, ASN1_INTEGER, TAG_KEY_SIZE.maskedTag()),
+    ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, digest, ASN1_INTEGER, TAG_DIGEST.maskedTag()),
+    ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, padding, ASN1_INTEGER, TAG_PADDING.maskedTag()),
+    ASN1_EXP_OPT(KM_AUTH_LIST, ec_curve, ASN1_INTEGER, TAG_EC_CURVE.maskedTag()),
+    ASN1_EXP_OPT(KM_AUTH_LIST, rsa_public_exponent, ASN1_INTEGER,
+                 TAG_RSA_PUBLIC_EXPONENT.maskedTag()),
+    ASN1_EXP_OPT(KM_AUTH_LIST, active_date_time, ASN1_INTEGER, TAG_ACTIVE_DATETIME.maskedTag()),
+    ASN1_EXP_OPT(KM_AUTH_LIST, origination_expire_date_time, ASN1_INTEGER,
+                 TAG_ORIGINATION_EXPIRE_DATETIME.maskedTag()),
+    ASN1_EXP_OPT(KM_AUTH_LIST, usage_expire_date_time, ASN1_INTEGER,
+                 TAG_USAGE_EXPIRE_DATETIME.maskedTag()),
+    ASN1_EXP_OPT(KM_AUTH_LIST, no_auth_required, ASN1_NULL, TAG_NO_AUTH_REQUIRED.maskedTag()),
+    ASN1_EXP_OPT(KM_AUTH_LIST, user_auth_type, ASN1_INTEGER, TAG_USER_AUTH_TYPE.maskedTag()),
+    ASN1_EXP_OPT(KM_AUTH_LIST, auth_timeout, ASN1_INTEGER, TAG_AUTH_TIMEOUT.maskedTag()),
+    ASN1_EXP_OPT(KM_AUTH_LIST, allow_while_on_body, ASN1_NULL, TAG_ALLOW_WHILE_ON_BODY.maskedTag()),
+    ASN1_EXP_OPT(KM_AUTH_LIST, application_id, ASN1_OCTET_STRING, TAG_APPLICATION_ID.maskedTag()),
+    ASN1_EXP_OPT(KM_AUTH_LIST, creation_date_time, ASN1_INTEGER, TAG_CREATION_DATETIME.maskedTag()),
+    ASN1_EXP_OPT(KM_AUTH_LIST, origin, ASN1_INTEGER, TAG_ORIGIN.maskedTag()),
+    ASN1_EXP_OPT(KM_AUTH_LIST, rollback_resistant, ASN1_NULL, TAG_ROLLBACK_RESISTANCE.maskedTag()),
+    ASN1_EXP_OPT(KM_AUTH_LIST, root_of_trust, KM_ROOT_OF_TRUST, TAG_ROOT_OF_TRUST.maskedTag()),
+    ASN1_EXP_OPT(KM_AUTH_LIST, os_version, ASN1_INTEGER, TAG_OS_VERSION.maskedTag()),
+    ASN1_EXP_OPT(KM_AUTH_LIST, os_patchlevel, ASN1_INTEGER, TAG_OS_PATCHLEVEL.maskedTag()),
+    ASN1_EXP_OPT(KM_AUTH_LIST, attestation_application_id, ASN1_OCTET_STRING,
+                 TAG_ATTESTATION_APPLICATION_ID.maskedTag()),
+} ASN1_SEQUENCE_END(KM_AUTH_LIST);
+IMPLEMENT_ASN1_FUNCTIONS(KM_AUTH_LIST);
+
+typedef struct km_key_description {
+    ASN1_INTEGER* attestation_version;
+    ASN1_ENUMERATED* attestation_security_level;
+    ASN1_INTEGER* keymaster_version;
+    ASN1_ENUMERATED* keymaster_security_level;
+    ASN1_OCTET_STRING* attestation_challenge;
+    KM_AUTH_LIST* software_enforced;
+    KM_AUTH_LIST* tee_enforced;
+    ASN1_INTEGER* unique_id;
+} KM_KEY_DESCRIPTION;
+
+ASN1_SEQUENCE(KM_KEY_DESCRIPTION) = {
+    ASN1_SIMPLE(KM_KEY_DESCRIPTION, attestation_version, ASN1_INTEGER),
+    ASN1_SIMPLE(KM_KEY_DESCRIPTION, attestation_security_level, ASN1_ENUMERATED),
+    ASN1_SIMPLE(KM_KEY_DESCRIPTION, keymaster_version, ASN1_INTEGER),
+    ASN1_SIMPLE(KM_KEY_DESCRIPTION, keymaster_security_level, ASN1_ENUMERATED),
+    ASN1_SIMPLE(KM_KEY_DESCRIPTION, attestation_challenge, ASN1_OCTET_STRING),
+    ASN1_SIMPLE(KM_KEY_DESCRIPTION, unique_id, ASN1_OCTET_STRING),
+    ASN1_SIMPLE(KM_KEY_DESCRIPTION, software_enforced, KM_AUTH_LIST),
+    ASN1_SIMPLE(KM_KEY_DESCRIPTION, tee_enforced, KM_AUTH_LIST),
+} ASN1_SEQUENCE_END(KM_KEY_DESCRIPTION);
+IMPLEMENT_ASN1_FUNCTIONS(KM_KEY_DESCRIPTION);
+
+template <Tag tag>
+void copyAuthTag(const stack_st_ASN1_INTEGER* stack, TypedTag<TagType::ENUM_REP, tag> ttag,
+                 AuthorizationSet* auth_list) {
+    typedef typename TypedTag2ValueType<decltype(ttag)>::type ValueT;
+    for (size_t i = 0; i < sk_ASN1_INTEGER_num(stack); ++i) {
+        auth_list->push_back(
+            ttag, static_cast<ValueT>(ASN1_INTEGER_get(sk_ASN1_INTEGER_value(stack, i))));
+    }
+}
+
+template <Tag tag>
+void copyAuthTag(const ASN1_INTEGER* asn1_int, TypedTag<TagType::ENUM, tag> ttag,
+                 AuthorizationSet* auth_list) {
+    typedef typename TypedTag2ValueType<decltype(ttag)>::type ValueT;
+    if (!asn1_int) return;
+    auth_list->push_back(ttag, static_cast<ValueT>(ASN1_INTEGER_get(asn1_int)));
+}
+
+template <Tag tag>
+void copyAuthTag(const ASN1_INTEGER* asn1_int, TypedTag<TagType::UINT, tag> ttag,
+                 AuthorizationSet* auth_list) {
+    if (!asn1_int) return;
+    auth_list->push_back(ttag, ASN1_INTEGER_get(asn1_int));
+}
+
+BIGNUM* construct_uint_max() {
+    BIGNUM* value = BN_new();
+    BIGNUM_Ptr one(BN_new());
+    BN_one(one.get());
+    BN_lshift(value, one.get(), 32);
+    return value;
+}
+
+uint64_t BignumToUint64(BIGNUM* num) {
+    static_assert((sizeof(BN_ULONG) == sizeof(uint32_t)) || (sizeof(BN_ULONG) == sizeof(uint64_t)),
+                  "This implementation only supports 32 and 64-bit BN_ULONG");
+    if (sizeof(BN_ULONG) == sizeof(uint32_t)) {
+        BIGNUM_Ptr uint_max(construct_uint_max());
+        BIGNUM_Ptr hi(BN_new()), lo(BN_new());
+        BN_CTX_Ptr ctx(BN_CTX_new());
+        BN_div(hi.get(), lo.get(), num, uint_max.get(), ctx.get());
+        return static_cast<uint64_t>(BN_get_word(hi.get())) << 32 | BN_get_word(lo.get());
+    } else if (sizeof(BN_ULONG) == sizeof(uint64_t)) {
+        return BN_get_word(num);
+    } else {
+        return 0;
+    }
+}
+
+template <Tag tag>
+void copyAuthTag(const ASN1_INTEGER* asn1_int, TypedTag<TagType::ULONG, tag> ttag,
+                 AuthorizationSet* auth_list) {
+    if (!asn1_int) return;
+    BIGNUM_Ptr num(ASN1_INTEGER_to_BN(asn1_int, nullptr));
+    auth_list->push_back(ttag, BignumToUint64(num.get()));
+}
+
+template <Tag tag>
+void copyAuthTag(const ASN1_INTEGER* asn1_int, TypedTag<TagType::DATE, tag> ttag,
+                 AuthorizationSet* auth_list) {
+    if (!asn1_int) return;
+    BIGNUM_Ptr num(ASN1_INTEGER_to_BN(asn1_int, nullptr));
+    auth_list->push_back(ttag, BignumToUint64(num.get()));
+}
+
+template <Tag tag>
+void copyAuthTag(const ASN1_NULL* asn1_null, TypedTag<TagType::BOOL, tag> ttag,
+                 AuthorizationSet* auth_list) {
+    if (!asn1_null) return;
+    auth_list->push_back(ttag);
+}
+
+template <Tag tag>
+void copyAuthTag(const ASN1_OCTET_STRING* asn1_string, TypedTag<TagType::BYTES, tag> ttag,
+                 AuthorizationSet* auth_list) {
+    if (!asn1_string) return;
+    hidl_vec<uint8_t> buf;
+    buf.setToExternal(asn1_string->data, asn1_string->length);
+    auth_list->push_back(ttag, buf);
+}
+
+// Extract the values from the specified ASN.1 record and place them in auth_list.
+static ErrorCode extract_auth_list(const KM_AUTH_LIST* record, AuthorizationSet* auth_list) {
+    if (!record) return ErrorCode::OK;
+
+    copyAuthTag(record->active_date_time, TAG_ACTIVE_DATETIME, auth_list);
+    copyAuthTag(record->algorithm, TAG_ALGORITHM, auth_list);
+    copyAuthTag(record->application_id, TAG_APPLICATION_ID, auth_list);
+    copyAuthTag(record->auth_timeout, TAG_AUTH_TIMEOUT, auth_list);
+    copyAuthTag(record->creation_date_time, TAG_CREATION_DATETIME, auth_list);
+    copyAuthTag(record->digest, TAG_DIGEST, auth_list);
+    copyAuthTag(record->ec_curve, TAG_EC_CURVE, auth_list);
+    copyAuthTag(record->key_size, TAG_KEY_SIZE, auth_list);
+    copyAuthTag(record->no_auth_required, TAG_NO_AUTH_REQUIRED, auth_list);
+    copyAuthTag(record->origin, TAG_ORIGIN, auth_list);
+    copyAuthTag(record->origination_expire_date_time, TAG_ORIGINATION_EXPIRE_DATETIME, auth_list);
+    copyAuthTag(record->os_patchlevel, TAG_OS_PATCHLEVEL, auth_list);
+    copyAuthTag(record->os_version, TAG_OS_VERSION, auth_list);
+    copyAuthTag(record->padding, TAG_PADDING, auth_list);
+    copyAuthTag(record->purpose, TAG_PURPOSE, auth_list);
+    copyAuthTag(record->rollback_resistant, TAG_ROLLBACK_RESISTANCE, auth_list);
+    copyAuthTag(record->rsa_public_exponent, TAG_RSA_PUBLIC_EXPONENT, auth_list);
+    copyAuthTag(record->usage_expire_date_time, TAG_USAGE_EXPIRE_DATETIME, auth_list);
+    copyAuthTag(record->user_auth_type, TAG_USER_AUTH_TYPE, auth_list);
+    copyAuthTag(record->attestation_application_id, TAG_ATTESTATION_APPLICATION_ID, auth_list);
+
+    return ErrorCode::OK;
+}
+
+MAKE_OPENSSL_PTR_TYPE(KM_KEY_DESCRIPTION)
+
+// Parse the DER-encoded attestation record, placing the results in keymaster_version,
+// attestation_challenge, software_enforced, tee_enforced and unique_id.
+ErrorCode parse_attestation_record(const uint8_t* asn1_key_desc, size_t asn1_key_desc_len,
+                                   uint32_t* attestation_version,  //
+                                   SecurityLevel* attestation_security_level,
+                                   uint32_t* keymaster_version,
+                                   SecurityLevel* keymaster_security_level,
+                                   hidl_vec<uint8_t>* attestation_challenge,
+                                   AuthorizationSet* software_enforced,
+                                   AuthorizationSet* tee_enforced,  //
+                                   hidl_vec<uint8_t>* unique_id) {
+    const uint8_t* p = asn1_key_desc;
+    KM_KEY_DESCRIPTION_Ptr record(d2i_KM_KEY_DESCRIPTION(nullptr, &p, asn1_key_desc_len));
+    if (!record.get()) return ErrorCode::UNKNOWN_ERROR;
+
+    *attestation_version = ASN1_INTEGER_get(record->attestation_version);
+    *attestation_security_level =
+        static_cast<SecurityLevel>(ASN1_ENUMERATED_get(record->attestation_security_level));
+    *keymaster_version = ASN1_INTEGER_get(record->keymaster_version);
+    *keymaster_security_level =
+        static_cast<SecurityLevel>(ASN1_ENUMERATED_get(record->keymaster_security_level));
+
+    auto& chall = record->attestation_challenge;
+    attestation_challenge->resize(chall->length);
+    memcpy(attestation_challenge->data(), chall->data, chall->length);
+    auto& uid = record->unique_id;
+    unique_id->resize(uid->length);
+    memcpy(unique_id->data(), uid->data, uid->length);
+
+    ErrorCode error = extract_auth_list(record->software_enforced, software_enforced);
+    if (error != ErrorCode::OK) return error;
+
+    return extract_auth_list(record->tee_enforced, tee_enforced);
+}
+
+}  // namespace V4_0
+}  // namespace keymaster
+}  // namespace hardware
+}  // namespace android
diff --git a/keymaster/4.0/support/authorization_set.cpp b/keymaster/4.0/support/authorization_set.cpp
new file mode 100644
index 0000000..de3e270
--- /dev/null
+++ b/keymaster/4.0/support/authorization_set.cpp
@@ -0,0 +1,515 @@
+/*
+ * 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.
+ */
+
+#include <keymasterV4_0/authorization_set.h>
+
+#include <assert.h>
+
+namespace android {
+namespace hardware {
+namespace keymaster {
+namespace V4_0 {
+
+inline bool keyParamLess(const KeyParameter& a, const KeyParameter& b) {
+    if (a.tag != b.tag) return a.tag < b.tag;
+    int retval;
+    switch (typeFromTag(a.tag)) {
+        case TagType::INVALID:
+        case TagType::BOOL:
+            return false;
+        case TagType::ENUM:
+        case TagType::ENUM_REP:
+        case TagType::UINT:
+        case TagType::UINT_REP:
+            return a.f.integer < b.f.integer;
+        case TagType::ULONG:
+        case TagType::ULONG_REP:
+            return a.f.longInteger < b.f.longInteger;
+        case TagType::DATE:
+            return a.f.dateTime < b.f.dateTime;
+        case TagType::BIGNUM:
+        case TagType::BYTES:
+            // Handle the empty cases.
+            if (a.blob.size() == 0) return b.blob.size() != 0;
+            if (b.blob.size() == 0) return false;
+
+            retval = memcmp(&a.blob[0], &b.blob[0], std::min(a.blob.size(), b.blob.size()));
+            // if one is the prefix of the other the longer wins
+            if (retval == 0) return a.blob.size() < b.blob.size();
+            // Otherwise a is less if a is less.
+            else
+                return retval < 0;
+    }
+    return false;
+}
+
+inline bool keyParamEqual(const KeyParameter& a, const KeyParameter& b) {
+    if (a.tag != b.tag) return false;
+
+    switch (typeFromTag(a.tag)) {
+        case TagType::INVALID:
+        case TagType::BOOL:
+            return true;
+        case TagType::ENUM:
+        case TagType::ENUM_REP:
+        case TagType::UINT:
+        case TagType::UINT_REP:
+            return a.f.integer == b.f.integer;
+        case TagType::ULONG:
+        case TagType::ULONG_REP:
+            return a.f.longInteger == b.f.longInteger;
+        case TagType::DATE:
+            return a.f.dateTime == b.f.dateTime;
+        case TagType::BIGNUM:
+        case TagType::BYTES:
+            if (a.blob.size() != b.blob.size()) return false;
+            return a.blob.size() == 0 || memcmp(&a.blob[0], &b.blob[0], a.blob.size()) == 0;
+    }
+    return false;
+}
+
+void AuthorizationSet::Sort() {
+    std::sort(data_.begin(), data_.end(), keyParamLess);
+}
+
+void AuthorizationSet::Deduplicate() {
+    if (data_.empty()) return;
+
+    Sort();
+    std::vector<KeyParameter> result;
+
+    auto curr = data_.begin();
+    auto prev = curr++;
+    for (; curr != data_.end(); ++prev, ++curr) {
+        if (prev->tag == Tag::INVALID) continue;
+
+        if (!keyParamEqual(*prev, *curr)) {
+            result.emplace_back(std::move(*prev));
+        }
+    }
+    result.emplace_back(std::move(*prev));
+
+    std::swap(data_, result);
+}
+
+void AuthorizationSet::Union(const AuthorizationSet& other) {
+    data_.insert(data_.end(), other.data_.begin(), other.data_.end());
+    Deduplicate();
+}
+
+void AuthorizationSet::Subtract(const AuthorizationSet& other) {
+    Deduplicate();
+
+    auto i = other.begin();
+    while (i != other.end()) {
+        int pos = -1;
+        do {
+            pos = find(i->tag, pos);
+            if (pos != -1 && keyParamEqual(*i, data_[pos])) {
+                data_.erase(data_.begin() + pos);
+                break;
+            }
+        } while (pos != -1);
+        ++i;
+    }
+}
+
+KeyParameter& AuthorizationSet::operator[](int at) {
+    return data_[at];
+}
+
+const KeyParameter& AuthorizationSet::operator[](int at) const {
+    return data_[at];
+}
+
+void AuthorizationSet::Clear() {
+    data_.clear();
+}
+
+size_t AuthorizationSet::GetTagCount(Tag tag) const {
+    size_t count = 0;
+    for (int pos = -1; (pos = find(tag, pos)) != -1;) ++count;
+    return count;
+}
+
+int AuthorizationSet::find(Tag tag, int begin) const {
+    auto iter = data_.begin() + (1 + begin);
+
+    while (iter != data_.end() && iter->tag != tag) ++iter;
+
+    if (iter != data_.end()) return iter - data_.begin();
+    return -1;
+}
+
+bool AuthorizationSet::erase(int index) {
+    auto pos = data_.begin() + index;
+    if (pos != data_.end()) {
+        data_.erase(pos);
+        return true;
+    }
+    return false;
+}
+
+NullOr<const KeyParameter&> AuthorizationSet::GetEntry(Tag tag) const {
+    int pos = find(tag);
+    if (pos == -1) return {};
+    return data_[pos];
+}
+
+/**
+ * Persistent format is:
+ * | 32 bit indirect_size         |
+ * --------------------------------
+ * | indirect_size bytes of data  | this is where the blob data is stored
+ * --------------------------------
+ * | 32 bit element_count         | number of entries
+ * | 32 bit elements_size         | total bytes used by entries (entries have variable length)
+ * --------------------------------
+ * | elementes_size bytes of data | where the elements are stored
+ */
+
+/**
+ * Persistent format of blobs and bignums:
+ * | 32 bit tag             |
+ * | 32 bit blob_length     |
+ * | 32 bit indirect_offset |
+ */
+
+struct OutStreams {
+    std::ostream& indirect;
+    std::ostream& elements;
+};
+
+OutStreams& serializeParamValue(OutStreams& out, const hidl_vec<uint8_t>& blob) {
+    uint32_t buffer;
+
+    // write blob_length
+    auto blob_length = blob.size();
+    if (blob_length > std::numeric_limits<uint32_t>::max()) {
+        out.elements.setstate(std::ios_base::badbit);
+        return out;
+    }
+    buffer = blob_length;
+    out.elements.write(reinterpret_cast<const char*>(&buffer), sizeof(uint32_t));
+
+    // write indirect_offset
+    auto offset = out.indirect.tellp();
+    if (offset < 0 || offset > std::numeric_limits<uint32_t>::max() ||
+        uint32_t(offset) + uint32_t(blob_length) < uint32_t(offset)) {  // overflow check
+        out.elements.setstate(std::ios_base::badbit);
+        return out;
+    }
+    buffer = offset;
+    out.elements.write(reinterpret_cast<const char*>(&buffer), sizeof(uint32_t));
+
+    // write blob to indirect stream
+    if (blob_length) out.indirect.write(reinterpret_cast<const char*>(&blob[0]), blob_length);
+
+    return out;
+}
+
+template <typename T>
+OutStreams& serializeParamValue(OutStreams& out, const T& value) {
+    out.elements.write(reinterpret_cast<const char*>(&value), sizeof(T));
+    return out;
+}
+
+OutStreams& serialize(TAG_INVALID_t&&, OutStreams& out, const KeyParameter&) {
+    // skip invalid entries.
+    return out;
+}
+template <typename T>
+OutStreams& serialize(T ttag, OutStreams& out, const KeyParameter& param) {
+    out.elements.write(reinterpret_cast<const char*>(&param.tag), sizeof(int32_t));
+    return serializeParamValue(out, accessTagValue(ttag, param));
+}
+
+template <typename... T>
+struct choose_serializer;
+template <typename... Tags>
+struct choose_serializer<MetaList<Tags...>> {
+    static OutStreams& serialize(OutStreams& out, const KeyParameter& param) {
+        return choose_serializer<Tags...>::serialize(out, param);
+    }
+};
+
+template <>
+struct choose_serializer<> {
+    static OutStreams& serialize(OutStreams& out, const KeyParameter&) { return out; }
+};
+
+template <TagType tag_type, Tag tag, typename... Tail>
+struct choose_serializer<TypedTag<tag_type, tag>, Tail...> {
+    static OutStreams& serialize(OutStreams& out, const KeyParameter& param) {
+        if (param.tag == tag) {
+            return V4_0::serialize(TypedTag<tag_type, tag>(), out, param);
+        } else {
+            return choose_serializer<Tail...>::serialize(out, param);
+        }
+    }
+};
+
+OutStreams& serialize(OutStreams& out, const KeyParameter& param) {
+    return choose_serializer<all_tags_t>::serialize(out, param);
+}
+
+std::ostream& serialize(std::ostream& out, const std::vector<KeyParameter>& params) {
+    std::stringstream indirect;
+    std::stringstream elements;
+    OutStreams streams = {indirect, elements};
+    for (const auto& param : params) {
+        serialize(streams, param);
+    }
+    if (indirect.bad() || elements.bad()) {
+        out.setstate(std::ios_base::badbit);
+        return out;
+    }
+    auto pos = indirect.tellp();
+    if (pos < 0 || pos > std::numeric_limits<uint32_t>::max()) {
+        out.setstate(std::ios_base::badbit);
+        return out;
+    }
+    uint32_t indirect_size = pos;
+    pos = elements.tellp();
+    if (pos < 0 || pos > std::numeric_limits<uint32_t>::max()) {
+        out.setstate(std::ios_base::badbit);
+        return out;
+    }
+    uint32_t elements_size = pos;
+    uint32_t element_count = params.size();
+
+    out.write(reinterpret_cast<const char*>(&indirect_size), sizeof(uint32_t));
+
+    pos = out.tellp();
+    if (indirect_size) out << indirect.rdbuf();
+    assert(out.tellp() - pos == indirect_size);
+
+    out.write(reinterpret_cast<const char*>(&element_count), sizeof(uint32_t));
+    out.write(reinterpret_cast<const char*>(&elements_size), sizeof(uint32_t));
+
+    pos = out.tellp();
+    if (elements_size) out << elements.rdbuf();
+    assert(out.tellp() - pos == elements_size);
+
+    return out;
+}
+
+struct InStreams {
+    std::istream& indirect;
+    std::istream& elements;
+};
+
+InStreams& deserializeParamValue(InStreams& in, hidl_vec<uint8_t>* blob) {
+    uint32_t blob_length = 0;
+    uint32_t offset = 0;
+    in.elements.read(reinterpret_cast<char*>(&blob_length), sizeof(uint32_t));
+    blob->resize(blob_length);
+    in.elements.read(reinterpret_cast<char*>(&offset), sizeof(uint32_t));
+    in.indirect.seekg(offset);
+    in.indirect.read(reinterpret_cast<char*>(&(*blob)[0]), blob->size());
+    return in;
+}
+
+template <typename T>
+InStreams& deserializeParamValue(InStreams& in, T* value) {
+    in.elements.read(reinterpret_cast<char*>(value), sizeof(T));
+    return in;
+}
+
+InStreams& deserialize(TAG_INVALID_t&&, InStreams& in, KeyParameter*) {
+    // there should be no invalid KeyParamaters but if handle them as zero sized.
+    return in;
+}
+
+template <typename T>
+InStreams& deserialize(T&& ttag, InStreams& in, KeyParameter* param) {
+    return deserializeParamValue(in, &accessTagValue(ttag, *param));
+}
+
+template <typename... T>
+struct choose_deserializer;
+template <typename... Tags>
+struct choose_deserializer<MetaList<Tags...>> {
+    static InStreams& deserialize(InStreams& in, KeyParameter* param) {
+        return choose_deserializer<Tags...>::deserialize(in, param);
+    }
+};
+template <>
+struct choose_deserializer<> {
+    static InStreams& deserialize(InStreams& in, KeyParameter*) {
+        // encountered an unknown tag -> fail parsing
+        in.elements.setstate(std::ios_base::badbit);
+        return in;
+    }
+};
+template <TagType tag_type, Tag tag, typename... Tail>
+struct choose_deserializer<TypedTag<tag_type, tag>, Tail...> {
+    static InStreams& deserialize(InStreams& in, KeyParameter* param) {
+        if (param->tag == tag) {
+            return V4_0::deserialize(TypedTag<tag_type, tag>(), in, param);
+        } else {
+            return choose_deserializer<Tail...>::deserialize(in, param);
+        }
+    }
+};
+
+InStreams& deserialize(InStreams& in, KeyParameter* param) {
+    in.elements.read(reinterpret_cast<char*>(&param->tag), sizeof(Tag));
+    return choose_deserializer<all_tags_t>::deserialize(in, param);
+}
+
+std::istream& deserialize(std::istream& in, std::vector<KeyParameter>* params) {
+    uint32_t indirect_size = 0;
+    in.read(reinterpret_cast<char*>(&indirect_size), sizeof(uint32_t));
+    std::string indirect_buffer(indirect_size, '\0');
+    if (indirect_buffer.size() != indirect_size) {
+        in.setstate(std::ios_base::badbit);
+        return in;
+    }
+    in.read(&indirect_buffer[0], indirect_buffer.size());
+
+    uint32_t element_count = 0;
+    in.read(reinterpret_cast<char*>(&element_count), sizeof(uint32_t));
+    uint32_t elements_size = 0;
+    in.read(reinterpret_cast<char*>(&elements_size), sizeof(uint32_t));
+
+    std::string elements_buffer(elements_size, '\0');
+    if (elements_buffer.size() != elements_size) {
+        in.setstate(std::ios_base::badbit);
+        return in;
+    }
+    in.read(&elements_buffer[0], elements_buffer.size());
+
+    if (in.bad()) return in;
+
+    // TODO write one-shot stream buffer to avoid copying here
+    std::stringstream indirect(indirect_buffer);
+    std::stringstream elements(elements_buffer);
+    InStreams streams = {indirect, elements};
+
+    params->resize(element_count);
+
+    for (uint32_t i = 0; i < element_count; ++i) {
+        deserialize(streams, &(*params)[i]);
+    }
+    return in;
+}
+
+void AuthorizationSet::Serialize(std::ostream* out) const {
+    serialize(*out, data_);
+}
+
+void AuthorizationSet::Deserialize(std::istream* in) {
+    deserialize(*in, &data_);
+}
+
+AuthorizationSetBuilder& AuthorizationSetBuilder::RsaKey(uint32_t key_size,
+                                                         uint64_t public_exponent) {
+    Authorization(TAG_ALGORITHM, Algorithm::RSA);
+    Authorization(TAG_KEY_SIZE, key_size);
+    Authorization(TAG_RSA_PUBLIC_EXPONENT, public_exponent);
+    return *this;
+}
+
+AuthorizationSetBuilder& AuthorizationSetBuilder::EcdsaKey(uint32_t key_size) {
+    Authorization(TAG_ALGORITHM, Algorithm::EC);
+    Authorization(TAG_KEY_SIZE, key_size);
+    return *this;
+}
+
+AuthorizationSetBuilder& AuthorizationSetBuilder::EcdsaKey(EcCurve curve) {
+    Authorization(TAG_ALGORITHM, Algorithm::EC);
+    Authorization(TAG_EC_CURVE, curve);
+    return *this;
+}
+
+AuthorizationSetBuilder& AuthorizationSetBuilder::AesKey(uint32_t key_size) {
+    Authorization(TAG_ALGORITHM, Algorithm::AES);
+    return Authorization(TAG_KEY_SIZE, key_size);
+}
+
+AuthorizationSetBuilder& AuthorizationSetBuilder::HmacKey(uint32_t key_size) {
+    Authorization(TAG_ALGORITHM, Algorithm::HMAC);
+    Authorization(TAG_KEY_SIZE, key_size);
+    return SigningKey();
+}
+
+AuthorizationSetBuilder& AuthorizationSetBuilder::RsaSigningKey(uint32_t key_size,
+                                                                uint64_t public_exponent) {
+    RsaKey(key_size, public_exponent);
+    return SigningKey();
+}
+
+AuthorizationSetBuilder& AuthorizationSetBuilder::RsaEncryptionKey(uint32_t key_size,
+                                                                   uint64_t public_exponent) {
+    RsaKey(key_size, public_exponent);
+    return EncryptionKey();
+}
+
+AuthorizationSetBuilder& AuthorizationSetBuilder::EcdsaSigningKey(uint32_t key_size) {
+    EcdsaKey(key_size);
+    return SigningKey();
+}
+
+AuthorizationSetBuilder& AuthorizationSetBuilder::EcdsaSigningKey(EcCurve curve) {
+    EcdsaKey(curve);
+    return SigningKey();
+}
+
+AuthorizationSetBuilder& AuthorizationSetBuilder::AesEncryptionKey(uint32_t key_size) {
+    AesKey(key_size);
+    return EncryptionKey();
+}
+
+AuthorizationSetBuilder& AuthorizationSetBuilder::SigningKey() {
+    Authorization(TAG_PURPOSE, KeyPurpose::SIGN);
+    return Authorization(TAG_PURPOSE, KeyPurpose::VERIFY);
+}
+
+AuthorizationSetBuilder& AuthorizationSetBuilder::EncryptionKey() {
+    Authorization(TAG_PURPOSE, KeyPurpose::ENCRYPT);
+    return Authorization(TAG_PURPOSE, KeyPurpose::DECRYPT);
+}
+
+AuthorizationSetBuilder& AuthorizationSetBuilder::NoDigestOrPadding() {
+    Authorization(TAG_DIGEST, Digest::NONE);
+    return Authorization(TAG_PADDING, PaddingMode::NONE);
+}
+
+AuthorizationSetBuilder& AuthorizationSetBuilder::EcbMode() {
+    return Authorization(TAG_BLOCK_MODE, BlockMode::ECB);
+}
+
+AuthorizationSetBuilder& AuthorizationSetBuilder::BlockMode(
+    std::initializer_list<V4_0::BlockMode> blockModes) {
+    for (auto mode : blockModes) {
+        push_back(TAG_BLOCK_MODE, mode);
+    }
+    return *this;
+}
+
+AuthorizationSetBuilder& AuthorizationSetBuilder::Digest(
+    std::initializer_list<V4_0::Digest> digests) {
+    for (auto digest : digests) {
+        push_back(TAG_DIGEST, digest);
+    }
+    return *this;
+}
+
+}  // namespace V4_0
+}  // namespace keymaster
+}  // namespace hardware
+}  // namespace android
diff --git a/keymaster/4.0/support/include/keymasterV4_0/attestation_record.h b/keymaster/4.0/support/include/keymasterV4_0/attestation_record.h
new file mode 100644
index 0000000..fae403a
--- /dev/null
+++ b/keymaster/4.0/support/include/keymasterV4_0/attestation_record.h
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+
+#ifndef HARDWARE_INTERFACES_KEYMASTER_40_VTS_FUNCTIONAL_ATTESTATION_RECORD_H_
+#define HARDWARE_INTERFACES_KEYMASTER_40_VTS_FUNCTIONAL_ATTESTATION_RECORD_H_
+
+#include <android/hardware/keymaster/4.0/IKeymasterDevice.h>
+
+namespace android {
+namespace hardware {
+namespace keymaster {
+namespace V4_0 {
+
+class AuthorizationSet;
+
+/**
+ * The OID for Android attestation records.  For the curious, it breaks down as follows:
+ *
+ * 1 = ISO
+ * 3 = org
+ * 6 = DoD (Huh? OIDs are weird.)
+ * 1 = IANA
+ * 4 = Private
+ * 1 = Enterprises
+ * 11129 = Google
+ * 2 = Google security
+ * 1 = certificate extension
+ * 17 = Android attestation extension.
+ */
+static const char kAttestionRecordOid[] = "1.3.6.1.4.1.11129.2.1.17";
+
+ErrorCode parse_attestation_record(const uint8_t* asn1_key_desc, size_t asn1_key_desc_len,
+                                   uint32_t* attestation_version,  //
+                                   SecurityLevel* attestation_security_level,
+                                   uint32_t* keymaster_version,
+                                   SecurityLevel* keymaster_security_level,
+                                   hidl_vec<uint8_t>* attestation_challenge,
+                                   AuthorizationSet* software_enforced,
+                                   AuthorizationSet* tee_enforced,  //
+                                   hidl_vec<uint8_t>* unique_id);
+}  // namespace V4_0
+}  // namespace keymaster
+}  // namespace hardware
+}  // namespace android
+
+#endif  // HARDWARE_INTERFACES_KEYMASTER_40_VTS_FUNCTIONAL_ATTESTATION_RECORD_H_
diff --git a/keymaster/4.0/support/include/keymasterV4_0/authorization_set.h b/keymaster/4.0/support/include/keymasterV4_0/authorization_set.h
new file mode 100644
index 0000000..f67f192
--- /dev/null
+++ b/keymaster/4.0/support/include/keymasterV4_0/authorization_set.h
@@ -0,0 +1,300 @@
+/*
+ * 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.
+ */
+
+#ifndef SYSTEM_SECURITY_KEYSTORE_KM4_AUTHORIZATION_SET_H_
+#define SYSTEM_SECURITY_KEYSTORE_KM4_AUTHORIZATION_SET_H_
+
+#include <vector>
+
+#include <keymasterV4_0/keymaster_tags.h>
+
+namespace android {
+namespace hardware {
+namespace keymaster {
+namespace V4_0 {
+
+class AuthorizationSetBuilder;
+
+/**
+ * An ordered collection of KeyParameters. It provides memory ownership and some convenient
+ * functionality for sorting, deduplicating, joining, and subtracting sets of KeyParameters.
+ * For serialization, wrap the backing store of this structure in a hidl_vec<KeyParameter>.
+ */
+class AuthorizationSet {
+   public:
+    typedef KeyParameter value_type;
+
+    /**
+     * Construct an empty, dynamically-allocated, growable AuthorizationSet.
+     */
+    AuthorizationSet(){};
+
+    // Copy constructor.
+    AuthorizationSet(const AuthorizationSet& other) : data_(other.data_) {}
+
+    // Move constructor.
+    AuthorizationSet(AuthorizationSet&& other) : data_(std::move(other.data_)) {}
+
+    // Constructor from hidl_vec<KeyParameter>
+    AuthorizationSet(const hidl_vec<KeyParameter>& other) { *this = other; }
+
+    // Copy assignment.
+    AuthorizationSet& operator=(const AuthorizationSet& other) {
+        data_ = other.data_;
+        return *this;
+    }
+
+    // Move assignment.
+    AuthorizationSet& operator=(AuthorizationSet&& other) {
+        data_ = std::move(other.data_);
+        return *this;
+    }
+
+    AuthorizationSet& operator=(const hidl_vec<KeyParameter>& other) {
+        if (other.size() > 0) {
+            data_.resize(other.size());
+            for (size_t i = 0; i < data_.size(); ++i) {
+                /* This makes a deep copy even of embedded blobs.
+                 * See assignment operator/copy constructor of hidl_vec.*/
+                data_[i] = other[i];
+            }
+        }
+        return *this;
+    }
+
+    /**
+     * Clear existing authorization set data
+     */
+    void Clear();
+
+    ~AuthorizationSet() = default;
+
+    /**
+     * Returns the size of the set.
+     */
+    size_t size() const { return data_.size(); }
+
+    /**
+     * Returns true if the set is empty.
+     */
+    bool empty() const { return size() == 0; }
+
+    /**
+     * Returns the data in the set, directly. Be careful with this.
+     */
+    const KeyParameter* data() const { return data_.data(); }
+
+    /**
+     * Sorts the set
+     */
+    void Sort();
+
+    /**
+     * Sorts the set and removes duplicates (inadvertently duplicating tags is easy to do with the
+     * AuthorizationSetBuilder).
+     */
+    void Deduplicate();
+
+    /**
+     * Adds all elements from \p set that are not already present in this AuthorizationSet.  As a
+     * side-effect, if \p set is not null this AuthorizationSet will end up sorted.
+     */
+    void Union(const AuthorizationSet& set);
+
+    /**
+     * Removes all elements in \p set from this AuthorizationSet.
+     */
+    void Subtract(const AuthorizationSet& set);
+
+    /**
+     * Returns the offset of the next entry that matches \p tag, starting from the element after \p
+     * begin.  If not found, returns -1.
+     */
+    int find(Tag tag, int begin = -1) const;
+
+    /**
+     * Removes the entry at the specified index. Returns true if successful, false if the index was
+     * out of bounds.
+     */
+    bool erase(int index);
+
+    /**
+     * Returns iterator (pointer) to beginning of elems array, to enable STL-style iteration
+     */
+    std::vector<KeyParameter>::const_iterator begin() const { return data_.begin(); }
+
+    /**
+     * Returns iterator (pointer) one past end of elems array, to enable STL-style iteration
+     */
+    std::vector<KeyParameter>::const_iterator end() const { return data_.end(); }
+
+    /**
+     * Returns the nth element of the set.
+     * Like for std::vector::operator[] there is no range check performed. Use of out of range
+     * indices is undefined.
+     */
+    KeyParameter& operator[](int n);
+
+    /**
+     * Returns the nth element of the set.
+     * Like for std::vector::operator[] there is no range check performed. Use of out of range
+     * indices is undefined.
+     */
+    const KeyParameter& operator[](int n) const;
+
+    /**
+     * Returns true if the set contains at least one instance of \p tag
+     */
+    bool Contains(Tag tag) const { return find(tag) != -1; }
+
+    template <TagType tag_type, Tag tag, typename ValueT>
+    bool Contains(TypedTag<tag_type, tag> ttag, const ValueT& value) const {
+        for (const auto& param : data_) {
+            auto entry = authorizationValue(ttag, param);
+            if (entry.isOk() && static_cast<ValueT>(entry.value()) == value) return true;
+        }
+        return false;
+    }
+    /**
+     * Returns the number of \p tag entries.
+     */
+    size_t GetTagCount(Tag tag) const;
+
+    template <typename T>
+    inline NullOr<const typename TypedTag2ValueType<T>::type&> GetTagValue(T tag) const {
+        auto entry = GetEntry(tag);
+        if (entry.isOk()) return authorizationValue(tag, entry.value());
+        return {};
+    }
+
+    void push_back(const KeyParameter& param) { data_.push_back(param); }
+    void push_back(KeyParameter&& param) { data_.push_back(std::move(param)); }
+    void push_back(const AuthorizationSet& set) {
+        for (auto& entry : set) {
+            push_back(entry);
+        }
+    }
+    void push_back(AuthorizationSet&& set) {
+        std::move(set.begin(), set.end(), std::back_inserter(*this));
+    }
+
+    /**
+     * Append the tag and enumerated value to the set.
+     * "val" may be exactly one parameter unless a boolean parameter is added.
+     * In this case "val" is omitted. This condition is checked at compile time by Authorization()
+     */
+    template <typename TypedTagT, typename... Value>
+    void push_back(TypedTagT tag, Value&&... val) {
+        push_back(Authorization(tag, std::forward<Value>(val)...));
+    }
+
+    template <typename Iterator>
+    void append(Iterator begin, Iterator end) {
+        while (begin != end) {
+            push_back(*begin);
+            ++begin;
+        }
+    }
+
+    hidl_vec<KeyParameter> hidl_data() const {
+        hidl_vec<KeyParameter> result;
+        result.setToExternal(const_cast<KeyParameter*>(data()), size());
+        return result;
+    }
+
+    void Serialize(std::ostream* out) const;
+    void Deserialize(std::istream* in);
+
+   private:
+    NullOr<const KeyParameter&> GetEntry(Tag tag) const;
+
+    std::vector<KeyParameter> data_;
+};
+
+class AuthorizationSetBuilder : public AuthorizationSet {
+   public:
+    template <typename TagType, typename... ValueType>
+    AuthorizationSetBuilder& Authorization(TagType ttag, ValueType&&... value) {
+        push_back(ttag, std::forward<ValueType>(value)...);
+        return *this;
+    }
+
+    template <Tag tag>
+    AuthorizationSetBuilder& Authorization(TypedTag<TagType::BYTES, tag> ttag, const uint8_t* data,
+                                           size_t data_length) {
+        hidl_vec<uint8_t> new_blob;
+        new_blob.setToExternal(const_cast<uint8_t*>(data), data_length);
+        push_back(ttag, std::move(new_blob));
+        return *this;
+    }
+
+    template <Tag tag>
+    AuthorizationSetBuilder& Authorization(TypedTag<TagType::BYTES, tag> ttag, const char* data,
+                                           size_t data_length) {
+        return Authorization(ttag, reinterpret_cast<const uint8_t*>(data), data_length);
+    }
+
+    AuthorizationSetBuilder& Authorizations(const AuthorizationSet& set) {
+        for (const auto& entry : set) {
+            push_back(entry);
+        }
+        return *this;
+    }
+
+    AuthorizationSetBuilder& RsaKey(uint32_t key_size, uint64_t public_exponent);
+    AuthorizationSetBuilder& EcdsaKey(uint32_t key_size);
+    AuthorizationSetBuilder& EcdsaKey(EcCurve curve);
+    AuthorizationSetBuilder& AesKey(uint32_t key_size);
+    AuthorizationSetBuilder& HmacKey(uint32_t key_size);
+
+    AuthorizationSetBuilder& RsaSigningKey(uint32_t key_size, uint64_t public_exponent);
+    AuthorizationSetBuilder& RsaEncryptionKey(uint32_t key_size, uint64_t public_exponent);
+    AuthorizationSetBuilder& EcdsaSigningKey(uint32_t key_size);
+    AuthorizationSetBuilder& EcdsaSigningKey(EcCurve curve);
+    AuthorizationSetBuilder& AesEncryptionKey(uint32_t key_size);
+
+    AuthorizationSetBuilder& SigningKey();
+    AuthorizationSetBuilder& EncryptionKey();
+    AuthorizationSetBuilder& NoDigestOrPadding();
+    AuthorizationSetBuilder& EcbMode();
+
+    AuthorizationSetBuilder& BlockMode(std::initializer_list<BlockMode> blockModes);
+    AuthorizationSetBuilder& Digest(std::initializer_list<Digest> digests);
+
+    template <typename... T>
+    AuthorizationSetBuilder& BlockMode(T&&... a) {
+        return BlockMode({std::forward<T>(a)...});
+    }
+    template <typename... T>
+    AuthorizationSetBuilder& Digest(T&&... a) {
+        return Digest({std::forward<T>(a)...});
+    }
+    template <typename... T>
+    AuthorizationSetBuilder& Padding(T&&... a) {
+        return Padding({std::forward<T>(a)...});
+    }
+
+    AuthorizationSetBuilder& Padding(PaddingMode padding) {
+        return Authorization(TAG_PADDING, padding);
+    }
+};
+
+}  // namespace V4_0
+}  // namespace keymaster
+}  // namespace hardware
+}  // namespace android
+
+#endif  // SYSTEM_SECURITY_KEYSTORE_KM4_AUTHORIZATION_SET_H_
diff --git a/keymaster/4.0/support/include/keymasterV4_0/key_param_output.h b/keymaster/4.0/support/include/keymasterV4_0/key_param_output.h
new file mode 100644
index 0000000..9736da0
--- /dev/null
+++ b/keymaster/4.0/support/include/keymasterV4_0/key_param_output.h
@@ -0,0 +1,90 @@
+/*
+ * 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 <iostream>
+
+#include <android/hardware/keymaster/4.0/types.h>
+
+#include "keymaster_tags.h"
+
+namespace android {
+namespace hardware {
+namespace keymaster {
+
+namespace V3_0 {
+
+inline ::std::ostream& operator<<(::std::ostream& os, Algorithm value) {
+    return os << toString(value);
+}
+
+inline ::std::ostream& operator<<(::std::ostream& os, BlockMode value) {
+    return os << toString(value);
+}
+
+inline ::std::ostream& operator<<(::std::ostream& os, Digest value) {
+    return os << toString(value);
+}
+
+inline ::std::ostream& operator<<(::std::ostream& os, EcCurve value) {
+    return os << toString(value);
+}
+
+inline ::std::ostream& operator<<(::std::ostream& os, ErrorCode value) {
+    return os << toString(value);
+}
+
+inline ::std::ostream& operator<<(::std::ostream& os, PaddingMode value) {
+    return os << toString(value);
+}
+
+}  // namespace V3_0
+
+namespace V4_0 {
+
+inline ::std::ostream& operator<<(::std::ostream& os, KeyOrigin value) {
+    return os << toString(value);
+}
+
+template <typename ValueT>
+::std::ostream& operator<<(::std::ostream& os, const NullOr<ValueT>& value) {
+    if (!value.isOk()) {
+        os << "(value not present)";
+    } else {
+        os << value.value();
+    }
+    return os;
+}
+
+::std::ostream& operator<<(::std::ostream& os, const hidl_vec<KeyParameter>& set);
+::std::ostream& operator<<(::std::ostream& os, const KeyParameter& value);
+
+inline ::std::ostream& operator<<(::std::ostream& os, const KeyCharacteristics& value) {
+    return os << "SW: " << value.softwareEnforced << ::std::endl
+              << "HW: " << value.hardwareEnforced << ::std::endl;
+}
+
+inline ::std::ostream& operator<<(::std::ostream& os, KeyPurpose value) {
+    return os << toString(value);
+}
+
+inline ::std::ostream& operator<<(::std::ostream& os, Tag tag) {
+    return os << toString(tag);
+}
+
+}  // namespace V4_0
+}  // namespace keymaster
+}  // namespace hardware
+}  // namespace android
diff --git a/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h b/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h
new file mode 100644
index 0000000..e5187df
--- /dev/null
+++ b/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h
@@ -0,0 +1,346 @@
+/*
+ * 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.
+ */
+
+#ifndef SYSTEM_SECURITY_KEYSTORE_KEYMASTER_TAGS_H_
+#define SYSTEM_SECURITY_KEYSTORE_KEYMASTER_TAGS_H_
+
+/**
+ * This header contains various definitions that make working with keymaster tags safer and easier.
+ *
+ * It makes use of a fair amount of template metaprogramming. The metaprogramming serves the purpose
+ * of making it impossible to make certain classes of mistakes when operating on keymaster
+ * authorizations.  For example, it's an error to create a KeyParameter with tag == Tag::PURPOSE
+ * and then to assign Algorithm::RSA to algorithm element of its union. But because the user
+ * must choose the union field, there could be a mismatch which the compiler has now way to
+ * diagnose.
+ *
+ * The machinery in this header solves these problems by describing which union field corresponds
+ * to which Tag. Central to this mechanism is the template TypedTag. It has zero size and binds a
+ * numeric Tag to a type that the compiler understands. By means of the macro DECLARE_TYPED_TAG,
+ * we declare types for each of the tags defined in hardware/interfaces/keymaster/4.0/types.hal.
+ *
+ * The macro DECLARE_TYPED_TAG(name) generates a typename TAG_name_t and a zero sized instance
+ * TAG_name. Once these typed tags have been declared we define metafunctions mapping the each tag
+ * to its value c++ type and the correct union element of KeyParameter. This is done by means of
+ * the macros MAKE_TAG_*VALUE_ACCESSOR, which generates TypedTag2ValueType, a metafunction mapping
+ * a typed tag to the corresponding c++ type, and access function, accessTagValue returning a
+ * reference to the correct element of KeyParameter.
+ * E.g.:
+ *      given "KeyParameter param;" then "accessTagValue(TAG_PURPOSE, param)"
+ *      yields a reference to param.f.purpose
+ * If used in an assignment the compiler can now check the compatibility of the assigned value.
+ *
+ * For convenience we also provide the constructor like function Authorization().
+ * Authorization takes a typed tag and a value and checks at compile time whether the value given
+ * is suitable for the given tag. At runtime it creates a new KeyParameter initialized with the
+ * given tag and value and returns it by value.
+ *
+ * The second convenience function, authorizationValue, allows access to the KeyParameter value in
+ * a safe way. It takes a typed tag and a KeyParameter and returns a reference to the value wrapped
+ * by NullOr. NullOr has out-of-band information about whether it is save to access the wrapped
+ * reference.
+ * E.g.:
+ *      auto param = Authorization(TAG_ALGORITM, Algorithm::RSA);
+ *      auto value1 = authorizationValue(TAG_PURPOSE, param);
+ *      auto value2 = authorizationValue(TAG_ALGORITM, param);
+ * value1.isOk() yields false, but value2.isOk() yields true, thus value2.value() is save to access.
+ */
+
+#include <android/hardware/keymaster/4.0/IKeymasterDevice.h>
+
+#include <type_traits>
+
+namespace android {
+namespace hardware {
+namespace keymaster {
+namespace V4_0 {
+
+using ::android::hardware::keymaster::V3_0::Algorithm;
+using ::android::hardware::keymaster::V3_0::BlockMode;
+using ::android::hardware::keymaster::V3_0::Digest;
+using ::android::hardware::keymaster::V3_0::EcCurve;
+using ::android::hardware::keymaster::V3_0::HardwareAuthenticatorType;
+using ::android::hardware::keymaster::V3_0::KeyFormat;
+using ::android::hardware::keymaster::V3_0::PaddingMode;
+using ::android::hardware::keymaster::V3_0::TagType;
+
+// The following create the numeric values that KM_TAG_PADDING and KM_TAG_DIGEST used to have.  We
+// need these old values to be able to support old keys that use them.
+static const int32_t KM_TAG_DIGEST_OLD = static_cast<int32_t>(TagType::ENUM) | 5;
+static const int32_t KM_TAG_PADDING_OLD = static_cast<int32_t>(TagType::ENUM) | 7;
+
+constexpr TagType typeFromTag(Tag tag) {
+    return static_cast<TagType>(static_cast<uint32_t>(tag) & static_cast<uint32_t>(0xf0000000));
+}
+
+/**
+ * TypedTag is a templatized version of Tag, which provides compile-time checking of
+ * keymaster tag types. Instances are convertible to Tag, so they can be used wherever
+ * Tag is expected, and because they encode the tag type it's possible to create
+ * function overloads that only operate on tags with a particular type.
+ */
+template <TagType tag_type, Tag tag>
+struct TypedTag {
+    inline TypedTag() {
+        // Ensure that it's impossible to create a TypedTag instance whose 'tag' doesn't have type
+        // 'tag_type'.  Attempting to instantiate a tag with the wrong type will result in a compile
+        // error (no match for template specialization StaticAssert<false>), with no run-time cost.
+        static_assert(typeFromTag(tag) == tag_type, "mismatch between tag and tag_type");
+    }
+    operator Tag() const { return tag; }
+    int32_t maskedTag() { return tag & 0x0FFFFFFF; }
+};
+
+template <Tag tag>
+struct Tag2TypedTag {
+    typedef TypedTag<typeFromTag(tag), tag> type;
+};
+
+#define DECLARE_TYPED_TAG(name)                                    \
+    typedef typename Tag2TypedTag<Tag::name>::type TAG_##name##_t; \
+    static TAG_##name##_t TAG_##name;
+
+DECLARE_TYPED_TAG(INVALID);
+DECLARE_TYPED_TAG(KEY_SIZE);
+DECLARE_TYPED_TAG(MAC_LENGTH);
+DECLARE_TYPED_TAG(CALLER_NONCE);
+DECLARE_TYPED_TAG(MIN_MAC_LENGTH);
+DECLARE_TYPED_TAG(RSA_PUBLIC_EXPONENT);
+DECLARE_TYPED_TAG(INCLUDE_UNIQUE_ID);
+DECLARE_TYPED_TAG(ACTIVE_DATETIME);
+DECLARE_TYPED_TAG(ORIGINATION_EXPIRE_DATETIME);
+DECLARE_TYPED_TAG(USAGE_EXPIRE_DATETIME);
+DECLARE_TYPED_TAG(MIN_SECONDS_BETWEEN_OPS);
+DECLARE_TYPED_TAG(MAX_USES_PER_BOOT);
+DECLARE_TYPED_TAG(USER_SECURE_ID);
+DECLARE_TYPED_TAG(NO_AUTH_REQUIRED);
+DECLARE_TYPED_TAG(AUTH_TIMEOUT);
+DECLARE_TYPED_TAG(ALLOW_WHILE_ON_BODY);
+DECLARE_TYPED_TAG(APPLICATION_ID);
+DECLARE_TYPED_TAG(APPLICATION_DATA);
+DECLARE_TYPED_TAG(CREATION_DATETIME);
+DECLARE_TYPED_TAG(ROLLBACK_RESISTANCE);
+DECLARE_TYPED_TAG(ROOT_OF_TRUST);
+DECLARE_TYPED_TAG(ASSOCIATED_DATA);
+DECLARE_TYPED_TAG(NONCE);
+DECLARE_TYPED_TAG(BOOTLOADER_ONLY);
+DECLARE_TYPED_TAG(OS_VERSION);
+DECLARE_TYPED_TAG(OS_PATCHLEVEL);
+DECLARE_TYPED_TAG(UNIQUE_ID);
+DECLARE_TYPED_TAG(ATTESTATION_CHALLENGE);
+DECLARE_TYPED_TAG(ATTESTATION_APPLICATION_ID);
+DECLARE_TYPED_TAG(RESET_SINCE_ID_ROTATION);
+
+DECLARE_TYPED_TAG(PURPOSE);
+DECLARE_TYPED_TAG(ALGORITHM);
+DECLARE_TYPED_TAG(BLOCK_MODE);
+DECLARE_TYPED_TAG(DIGEST);
+DECLARE_TYPED_TAG(PADDING);
+DECLARE_TYPED_TAG(BLOB_USAGE_REQUIREMENTS);
+DECLARE_TYPED_TAG(ORIGIN);
+DECLARE_TYPED_TAG(USER_AUTH_TYPE);
+DECLARE_TYPED_TAG(EC_CURVE);
+
+template <typename... Elems>
+struct MetaList {};
+
+using all_tags_t = MetaList<
+    TAG_INVALID_t, TAG_KEY_SIZE_t, TAG_MAC_LENGTH_t, TAG_CALLER_NONCE_t, TAG_MIN_MAC_LENGTH_t,
+    TAG_RSA_PUBLIC_EXPONENT_t, TAG_INCLUDE_UNIQUE_ID_t, TAG_ACTIVE_DATETIME_t,
+    TAG_ORIGINATION_EXPIRE_DATETIME_t, TAG_USAGE_EXPIRE_DATETIME_t, TAG_MIN_SECONDS_BETWEEN_OPS_t,
+    TAG_MAX_USES_PER_BOOT_t, TAG_USER_SECURE_ID_t, TAG_NO_AUTH_REQUIRED_t, TAG_AUTH_TIMEOUT_t,
+    TAG_ALLOW_WHILE_ON_BODY_t, TAG_APPLICATION_ID_t, TAG_APPLICATION_DATA_t,
+    TAG_CREATION_DATETIME_t, TAG_ROLLBACK_RESISTANCE_t, TAG_ROOT_OF_TRUST_t, TAG_ASSOCIATED_DATA_t,
+    TAG_NONCE_t, TAG_BOOTLOADER_ONLY_t, TAG_OS_VERSION_t, TAG_OS_PATCHLEVEL_t, TAG_UNIQUE_ID_t,
+    TAG_ATTESTATION_CHALLENGE_t, TAG_ATTESTATION_APPLICATION_ID_t, TAG_RESET_SINCE_ID_ROTATION_t,
+    TAG_PURPOSE_t, TAG_ALGORITHM_t, TAG_BLOCK_MODE_t, TAG_DIGEST_t, TAG_PADDING_t,
+    TAG_BLOB_USAGE_REQUIREMENTS_t, TAG_ORIGIN_t, TAG_USER_AUTH_TYPE_t, TAG_EC_CURVE_t>;
+
+template <typename TypedTagType>
+struct TypedTag2ValueType;
+
+#define MAKE_TAG_VALUE_ACCESSOR(tag_type, field_name)                              \
+    template <Tag tag>                                                             \
+    struct TypedTag2ValueType<TypedTag<tag_type, tag>> {                           \
+        typedef decltype(static_cast<KeyParameter*>(nullptr)->field_name) type;    \
+    };                                                                             \
+    template <Tag tag>                                                             \
+    inline auto accessTagValue(TypedTag<tag_type, tag>, const KeyParameter& param) \
+        ->const decltype(param.field_name)& {                                      \
+        return param.field_name;                                                   \
+    }                                                                              \
+    template <Tag tag>                                                             \
+    inline auto accessTagValue(TypedTag<tag_type, tag>, KeyParameter& param)       \
+        ->decltype(param.field_name)& {                                            \
+        return param.field_name;                                                   \
+    }
+
+MAKE_TAG_VALUE_ACCESSOR(TagType::ULONG, f.longInteger)
+MAKE_TAG_VALUE_ACCESSOR(TagType::ULONG_REP, f.longInteger)
+MAKE_TAG_VALUE_ACCESSOR(TagType::DATE, f.dateTime)
+MAKE_TAG_VALUE_ACCESSOR(TagType::UINT, f.integer)
+MAKE_TAG_VALUE_ACCESSOR(TagType::UINT_REP, f.integer)
+MAKE_TAG_VALUE_ACCESSOR(TagType::BOOL, f.boolValue)
+MAKE_TAG_VALUE_ACCESSOR(TagType::BYTES, blob)
+MAKE_TAG_VALUE_ACCESSOR(TagType::BIGNUM, blob)
+
+#define MAKE_TAG_ENUM_VALUE_ACCESSOR(typed_tag, field_name)                     \
+    template <>                                                                 \
+    struct TypedTag2ValueType<decltype(typed_tag)> {                            \
+        typedef decltype(static_cast<KeyParameter*>(nullptr)->field_name) type; \
+    };                                                                          \
+    inline auto accessTagValue(decltype(typed_tag), const KeyParameter& param)  \
+        ->const decltype(param.field_name)& {                                   \
+        return param.field_name;                                                \
+    }                                                                           \
+    inline auto accessTagValue(decltype(typed_tag), KeyParameter& param)        \
+        ->decltype(param.field_name)& {                                         \
+        return param.field_name;                                                \
+    }
+
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_ALGORITHM, f.algorithm)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_BLOB_USAGE_REQUIREMENTS, f.keyBlobUsageRequirements)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_BLOCK_MODE, f.blockMode)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_DIGEST, f.digest)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_EC_CURVE, f.ecCurve)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_ORIGIN, f.origin)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_PADDING, f.paddingMode)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_PURPOSE, f.purpose)
+MAKE_TAG_ENUM_VALUE_ACCESSOR(TAG_USER_AUTH_TYPE, f.hardwareAuthenticatorType)
+
+template <TagType tag_type, Tag tag, typename ValueT>
+inline KeyParameter makeKeyParameter(TypedTag<tag_type, tag> ttag, ValueT&& value) {
+    KeyParameter param;
+    param.tag = tag;
+    param.f.longInteger = 0;
+    accessTagValue(ttag, param) = std::forward<ValueT>(value);
+    return param;
+}
+
+// the boolean case
+template <Tag tag>
+inline KeyParameter makeKeyParameter(TypedTag<TagType::BOOL, tag>) {
+    KeyParameter param;
+    param.tag = tag;
+    param.f.boolValue = true;
+    return param;
+}
+
+template <typename... Pack>
+struct FirstOrNoneHelper;
+template <typename First>
+struct FirstOrNoneHelper<First> {
+    typedef First type;
+};
+template <>
+struct FirstOrNoneHelper<> {
+    struct type {};
+};
+
+template <typename... Pack>
+using FirstOrNone = typename FirstOrNoneHelper<Pack...>::type;
+
+template <TagType tag_type, Tag tag, typename... Args>
+inline KeyParameter Authorization(TypedTag<tag_type, tag> ttag, Args&&... args) {
+    static_assert(tag_type != TagType::BOOL || (sizeof...(args) == 0),
+                  "TagType::BOOL Authorizations do not take parameters. Presence is truth.");
+    static_assert(tag_type == TagType::BOOL || (sizeof...(args) == 1),
+                  "Authorization other then TagType::BOOL take exactly one parameter.");
+    static_assert(
+        tag_type == TagType::BOOL ||
+            std::is_convertible<std::remove_cv_t<std::remove_reference_t<FirstOrNone<Args...>>>,
+                                typename TypedTag2ValueType<TypedTag<tag_type, tag>>::type>::value,
+        "Invalid argument type for given tag.");
+
+    return makeKeyParameter(ttag, std::forward<Args>(args)...);
+}
+
+/**
+ * This class wraps a (mostly return) value and stores whether or not the wrapped value is valid out
+ * of band. Note that if the wrapped value is a reference it is unsafe to access the value if
+ * !isOk(). If the wrapped type is a pointer or value and !isOk(), it is still safe to access the
+ * wrapped value. In this case the pointer will be NULL though, and the value will be default
+ * constructed.
+ */
+template <typename ValueT>
+class NullOr {
+    template <typename T>
+    struct reference_initializer {
+        static T&& init() { return *static_cast<std::remove_reference_t<T>*>(nullptr); }
+    };
+    template <typename T>
+    struct pointer_initializer {
+        static T init() { return nullptr; }
+    };
+    template <typename T>
+    struct value_initializer {
+        static T init() { return T(); }
+    };
+    template <typename T>
+    using initializer_t =
+        std::conditional_t<std::is_lvalue_reference<T>::value, reference_initializer<T>,
+                           std::conditional_t<std::is_pointer<T>::value, pointer_initializer<T>,
+                                              value_initializer<T>>>;
+
+   public:
+    NullOr() : value_(initializer_t<ValueT>::init()), null_(true) {}
+    NullOr(ValueT&& value) : value_(std::forward<ValueT>(value)), null_(false) {}
+
+    bool isOk() const { return !null_; }
+
+    const ValueT& value() const & { return value_; }
+    ValueT& value() & { return value_; }
+    ValueT&& value() && { return std::move(value_); }
+
+   private:
+    ValueT value_;
+    bool null_;
+};
+
+template <typename T>
+std::remove_reference_t<T> NullOrOr(T&& v) {
+    if (v.isOk()) return v;
+    return {};
+}
+
+template <typename Head, typename... Tail>
+std::remove_reference_t<Head> NullOrOr(Head&& head, Tail&&... tail) {
+    if (head.isOk()) return head;
+    return NullOrOr(std::forward<Tail>(tail)...);
+}
+
+template <typename Default, typename Wrapped>
+std::remove_reference_t<Wrapped> defaultOr(NullOr<Wrapped>&& optional, Default&& def) {
+    static_assert(std::is_convertible<std::remove_reference_t<Default>,
+                                      std::remove_reference_t<Wrapped>>::value,
+                  "Type of default value must match the type wrapped by NullOr");
+    if (optional.isOk()) return optional.value();
+    return def;
+}
+
+template <TagType tag_type, Tag tag>
+inline NullOr<const typename TypedTag2ValueType<TypedTag<tag_type, tag>>::type&> authorizationValue(
+    TypedTag<tag_type, tag> ttag, const KeyParameter& param) {
+    if (tag != param.tag) return {};
+    return accessTagValue(ttag, param);
+}
+
+}  // namespace V4_0
+}  // namespace keymaster
+}  // namespace hardware
+}  // namespace android
+
+#endif  // SYSTEM_SECURITY_KEYSTORE_KEYMASTER_TAGS_H_
diff --git a/keymaster/4.0/support/include/keymasterV4_0/openssl_utils.h b/keymaster/4.0/support/include/keymasterV4_0/openssl_utils.h
new file mode 100644
index 0000000..2d3bcf1
--- /dev/null
+++ b/keymaster/4.0/support/include/keymasterV4_0/openssl_utils.h
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+
+template <typename T, void (*F)(T*)>
+struct UniquePtrDeleter {
+    void operator()(T* p) const { F(p); }
+};
+
+typedef UniquePtrDeleter<EVP_PKEY, EVP_PKEY_free> EVP_PKEY_Delete;
+
+#define MAKE_OPENSSL_PTR_TYPE(type) \
+    typedef std::unique_ptr<type, UniquePtrDeleter<type, type##_free>> type##_Ptr;
+
+MAKE_OPENSSL_PTR_TYPE(ASN1_OBJECT)
+MAKE_OPENSSL_PTR_TYPE(EVP_PKEY)
+MAKE_OPENSSL_PTR_TYPE(RSA)
+MAKE_OPENSSL_PTR_TYPE(X509)
+MAKE_OPENSSL_PTR_TYPE(BN_CTX)
+
+typedef std::unique_ptr<BIGNUM, UniquePtrDeleter<BIGNUM, BN_free>> BIGNUM_Ptr;
+
+inline const EVP_MD* openssl_digest(android::hardware::keymaster::V4_0::Digest digest) {
+    switch (digest) {
+        case android::hardware::keymaster::V4_0::Digest::NONE:
+            return nullptr;
+        case android::hardware::keymaster::V4_0::Digest::MD5:
+            return EVP_md5();
+        case android::hardware::keymaster::V4_0::Digest::SHA1:
+            return EVP_sha1();
+        case android::hardware::keymaster::V4_0::Digest::SHA_2_224:
+            return EVP_sha224();
+        case android::hardware::keymaster::V4_0::Digest::SHA_2_256:
+            return EVP_sha256();
+        case android::hardware::keymaster::V4_0::Digest::SHA_2_384:
+            return EVP_sha384();
+        case android::hardware::keymaster::V4_0::Digest::SHA_2_512:
+            return EVP_sha512();
+    }
+    return nullptr;
+}
diff --git a/keymaster/4.0/support/key_param_output.cpp b/keymaster/4.0/support/key_param_output.cpp
new file mode 100644
index 0000000..e90e2fe
--- /dev/null
+++ b/keymaster/4.0/support/key_param_output.cpp
@@ -0,0 +1,98 @@
+/*
+ * 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 <keymasterV4_0/key_param_output.h>
+
+#include <keymasterV4_0/keymaster_tags.h>
+
+#include <iomanip>
+
+namespace android {
+namespace hardware {
+namespace keymaster {
+
+using ::std::ostream;
+using ::std::endl;
+
+namespace V4_0 {
+
+ostream& operator<<(ostream& os, const hidl_vec<KeyParameter>& set) {
+    if (set.size() == 0) {
+        os << "(Empty)" << endl;
+    } else {
+        os << "\n";
+        for (const auto& elem : set) os << elem << endl;
+    }
+    return os;
+}
+
+ostream& operator<<(ostream& os, const KeyParameter& param) {
+    os << param.tag << ": ";
+    switch (typeFromTag(param.tag)) {
+        case TagType::INVALID:
+            return os << " Invalid";
+        case TagType::UINT_REP:
+        case TagType::UINT:
+            return os << param.f.integer;
+        case TagType::ENUM_REP:
+        case TagType::ENUM:
+            switch (param.tag) {
+                case Tag::ALGORITHM:
+                    return os << param.f.algorithm;
+                case Tag::BLOCK_MODE:
+                    return os << param.f.blockMode;
+                case Tag::PADDING:
+                    return os << param.f.paddingMode;
+                case Tag::DIGEST:
+                    return os << param.f.digest;
+                case Tag::EC_CURVE:
+                    return os << (int)param.f.ecCurve;
+                case Tag::ORIGIN:
+                    return os << param.f.origin;
+                case Tag::BLOB_USAGE_REQUIREMENTS:
+                    return os << (int)param.f.keyBlobUsageRequirements;
+                case Tag::PURPOSE:
+                    return os << param.f.purpose;
+                default:
+                    return os << " UNKNOWN ENUM " << param.f.integer;
+            }
+        case TagType::ULONG_REP:
+        case TagType::ULONG:
+            return os << param.f.longInteger;
+        case TagType::DATE:
+            return os << param.f.dateTime;
+        case TagType::BOOL:
+            return os << "true";
+        case TagType::BIGNUM:
+            os << " Bignum: ";
+            for (size_t i = 0; i < param.blob.size(); ++i) {
+                os << std::hex << ::std::setw(2) << static_cast<int>(param.blob[i]) << ::std::dec;
+            }
+            return os;
+        case TagType::BYTES:
+            os << " Bytes: ";
+            for (size_t i = 0; i < param.blob.size(); ++i) {
+                os << ::std::hex << ::std::setw(2) << static_cast<int>(param.blob[i]) << ::std::dec;
+            }
+            return os;
+    }
+    return os << "UNKNOWN TAG TYPE!";
+}
+
+}  // namespace V4_0
+}  // namespace keymaster
+}  // namespace hardware
+}  // namespace android
diff --git a/keymaster/4.0/types.hal b/keymaster/4.0/types.hal
new file mode 100644
index 0000000..8ca2274
--- /dev/null
+++ b/keymaster/4.0/types.hal
@@ -0,0 +1,384 @@
+/*
+ * 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.keymaster@4.0;
+
+import android.hardware.keymaster@3.0::Algorithm;
+import android.hardware.keymaster@3.0::BlockMode;
+import android.hardware.keymaster@3.0::Digest;
+import android.hardware.keymaster@3.0::EcCurve;
+import android.hardware.keymaster@3.0::ErrorCode;
+import android.hardware.keymaster@3.0::HardwareAuthenticatorType;
+import android.hardware.keymaster@3.0::KeyBlobUsageRequirements;
+import android.hardware.keymaster@3.0::KeyDerivationFunction;
+import android.hardware.keymaster@3.0::KeyFormat;
+import android.hardware.keymaster@3.0::KeyOrigin;
+import android.hardware.keymaster@3.0::PaddingMode;
+import android.hardware.keymaster@3.0::SecurityLevel;
+import android.hardware.keymaster@3.0::TagType;
+
+/**
+ * Time in milliseconds since some arbitrary point in time.  Time must be monotonically increasing,
+ * and a secure environment's notion of "current time" must not repeat until the Android device
+ * reboots, or until at least 50 million years have elapsed (note that this requirement is satisfied
+ * by setting the clock to zero during each boot, and then counting time accurately).
+ */
+typedef uint64_t Timestamp;
+
+/**
+ * A place to define any needed constants.
+ */
+enum Constants : uint32_t {
+    AUTH_TOKEN_MAC_LENGTH = 32,
+};
+
+enum Tag : uint32_t {
+    INVALID = TagType:INVALID | 0,
+
+    /**
+     * Tags that must be semantically enforced by hardware and software implementations.
+     */
+
+    /** Crypto parameters */
+    PURPOSE = TagType:ENUM_REP | 1,    /* KeyPurpose. */
+    ALGORITHM = TagType:ENUM | 2,      /* Algorithm. */
+    KEY_SIZE = TagType:UINT | 3,       /* Key size in bits. */
+    BLOCK_MODE = TagType:ENUM_REP | 4, /* BlockMode. */
+    DIGEST = TagType:ENUM_REP | 5,     /* Digest. */
+    PADDING = TagType:ENUM_REP | 6,    /* PaddingMode. */
+    CALLER_NONCE = TagType:BOOL | 7,   /* Allow caller to specify nonce or IV. */
+    MIN_MAC_LENGTH = TagType:UINT | 8, /* Minimum length of MAC or AEAD authentication tag in
+                                        * bits. */
+    // 9 reserved
+    EC_CURVE = TagType:ENUM | 10,      /* EcCurve. */
+
+    /** Algorithm-specific. */
+    RSA_PUBLIC_EXPONENT = TagType:ULONG | 200,
+    // 201 reserved for ECIES
+    INCLUDE_UNIQUE_ID = TagType:BOOL | 202, /* If true, attestation certificates for this key must
+                                             * contain an application-scoped and time-bounded
+                                             * device-unique ID.*/
+
+    /** Other hardware-enforced. */
+    BLOB_USAGE_REQUIREMENTS = TagType:ENUM | 301, /* KeyBlobUsageRequirements. */
+    BOOTLOADER_ONLY = TagType:BOOL | 302,         /* Usable only by bootloader. */
+    ROLLBACK_RESISTANCE = TagType:BOOL | 303,     /* Whether key is rollback-resistant.  Specified
+                                                   * in the key description provided to generateKey
+                                                   * or importKey if rollback resistance is desired.
+                                                   * If the implementation cannot provide rollback
+                                                   * resistance, it must return
+                                                   * ROLLBACK_RESISTANCE_UNAVAILABLE. */
+
+    /* HARDWARE_TYPE specifies the type of the secure hardware that is requested for the key
+     * generation / import.  See the SecurityLevel enum.  In the absence of this tag, keystore must
+     * use TRUSTED_ENVIRONMENT.  If this tag is present and the requested hardware type is not
+     * available, Keymaster returns HARDWARE_TYPE_UNAVAILABLE. This tag is not included in
+     * attestations, but hardware type must be reflected in the Keymaster SecurityLevel of the
+     * attestation header. */
+    HARDWARE_TYPE = TagType:ENUM | 304,
+
+    /**
+     * Tags that should be semantically enforced by hardware if possible and will otherwise be
+     * enforced by software (keystore).
+     */
+
+    /** Key validity period */
+    ACTIVE_DATETIME = TagType:DATE | 400,             /* Start of validity. */
+    ORIGINATION_EXPIRE_DATETIME = TagType:DATE | 401, /* Date when new "messages" should no longer
+                                                       * be created. */
+    USAGE_EXPIRE_DATETIME = TagType:DATE | 402,       /* Date when existing "messages" should no
+                                                       * longer be trusted. */
+    MIN_SECONDS_BETWEEN_OPS = TagType:UINT | 403,     /* Minimum elapsed time between
+                                                       * cryptographic operations with the key. */
+    MAX_USES_PER_BOOT = TagType:UINT | 404,           /* Number of times the key can be used per
+                                                       * boot. */
+
+    /** User authentication */
+    // 500-501 reserved
+    USER_SECURE_ID = TagType:ULONG_REP | 502, /* Secure ID of authorized user or authenticator(s).
+                                               * Disallowed if ALL_USERS or NO_AUTH_REQUIRED is
+                                               * present. */
+    NO_AUTH_REQUIRED = TagType:BOOL | 503,    /* If key is usable without authentication. */
+    USER_AUTH_TYPE = TagType:ENUM | 504,      /* Bitmask of authenticator types allowed when
+                                               * USER_SECURE_ID contains a secure user ID, rather
+                                               * than a secure authenticator ID.  Defined in
+                                               * HardwareAuthenticatorType. */
+    AUTH_TIMEOUT = TagType:UINT | 505,        /* Required freshness of user authentication for
+                                               * private/secret key operations, in seconds.  Public
+                                               * key operations require no authentication.  If
+                                               * absent, authentication is required for every use.
+                                               * Authentication state is lost when the device is
+                                               * powered off. */
+    ALLOW_WHILE_ON_BODY =  TagType:BOOL | 506, /* Allow key to be used after authentication timeout
+                                                * if device is still on-body (requires secure
+                                                * on-body sensor. */
+
+    /** Application access control */
+    APPLICATION_ID = TagType:BYTES | 601, /* Byte string identifying the authorized application. */
+
+    /**
+     * Semantically unenforceable tags, either because they have no specific meaning or because
+     * they're informational only.
+     */
+    APPLICATION_DATA = TagType:BYTES | 700, /* Data provided by authorized application. */
+    CREATION_DATETIME = TagType:DATE | 701, /* Key creation time */
+    ORIGIN = TagType:ENUM | 702,            /* keymaster_key_origin_t. */
+    // 703 is unused.
+    ROOT_OF_TRUST = TagType:BYTES | 704,         /* Root of trust ID. */
+    OS_VERSION = TagType:UINT | 705,             /* Version of system (keymaster2) */
+    OS_PATCHLEVEL = TagType:UINT | 706,          /* Patch level of system (keymaster2) */
+    UNIQUE_ID = TagType:BYTES | 707,             /* Used to provide unique ID in attestation */
+    ATTESTATION_CHALLENGE = TagType:BYTES | 708, /* Used to provide challenge in attestation */
+    ATTESTATION_APPLICATION_ID = TagType:BYTES | 709, /* Used to identify the set of possible
+                                                       * applications of which one has initiated a
+                                                       * key attestation */
+    ATTESTATION_ID_BRAND = TagType:BYTES | 710,   /* Used to provide the device's brand name to be
+                                                   * included in attestation */
+    ATTESTATION_ID_DEVICE = TagType:BYTES | 711,  /* Used to provide the device's device name to
+                                                   * be included in attestation */
+    ATTESTATION_ID_PRODUCT = TagType:BYTES | 712, /* Used to provide the device's product name to
+                                                   * be included in attestation */
+    ATTESTATION_ID_SERIAL =
+    TagType:BYTES | 713,                       /* Used to provide the device's serial number to be
+                                                * included in attestation */
+    ATTESTATION_ID_IMEI = TagType:BYTES | 714, /* Used to provide the device's IMEI to be included
+                                                * in attestation */
+    ATTESTATION_ID_MEID = TagType:BYTES | 715, /* Used to provide the device's MEID to be included
+                                                * in attestation */
+    ATTESTATION_ID_MANUFACTURER =
+    TagType:BYTES | 716,                        /* Used to provide the device's manufacturer
+                                                 * name to be included in attestation */
+    ATTESTATION_ID_MODEL = TagType:BYTES | 717, /* Used to provide the device's model name to be
+                                                 * included in attestation */
+
+    /** Tags used only to provide data to or receive data from operations */
+    ASSOCIATED_DATA = TagType:BYTES | 1000, /* Used to provide associated data for AEAD modes. */
+    NONCE = TagType:BYTES | 1001,           /* Nonce or Initialization Vector */
+    MAC_LENGTH = TagType:UINT | 1003,       /* MAC or AEAD authentication tag length in bits. */
+
+    RESET_SINCE_ID_ROTATION = TagType:BOOL | 1004, /* Whether the device has beeen factory reset
+                                                    * since the last unique ID rotation.  Used for
+                                                    * key attestation. */
+};
+
+/**
+ * The origin of a key, i.e. where it was generated.
+ */
+enum KeyOrigin : @3.0::KeyOrigin {
+    /** Securely imported into Keymaster.  Was created elsewhere, and passed securely through
+     *  Android to secure hardware. */
+    SECURELY_IMPORTED = 4,
+};
+
+/**
+ * Possible purposes of a key (or pair).
+ */
+enum KeyPurpose : uint32_t {
+    ENCRYPT = 0,    /* Usable with RSA, EC and AES keys. */
+    DECRYPT = 1,    /* Usable with RSA, EC and AES keys. */
+    SIGN = 2,       /* Usable with RSA, EC and HMAC keys. */
+    VERIFY = 3,     /* Usable with RSA, EC and HMAC keys. */
+    /* 4 is reserved */
+    WRAP_KEY = 5,   /* Usable with wrapping keys. */
+};
+
+/**
+ * Keymaster error codes.
+ */
+enum ErrorCode : @3.0::ErrorCode {
+    ROLLBACK_RESISTANCE_UNAVAILABLE = -67,
+    HARDWARE_TYPE_UNAVAILABLE = -68,
+};
+
+/**
+ * Device security levels.
+ */
+enum SecurityLevel : @3.0::SecurityLevel {
+    /**
+     * STRONGBOX specifies that the secure hardware satisfies the following requirements:
+     *
+     *    a) Has a discrete CPU.  The StrongBox device must not be the same CPU that is used to run
+     *       the Android non-secure world, or any other untrusted code.  The StrongBox CPU must not
+     *       share cache, RAM or any other critical resources with any device that runs untrusted
+     *       code.
+     *
+     *    b) Has integral secure storage.  The StrongBox device must have its own non-volatile
+     *       storage that is not accessible by any other hardware component.
+     *
+     *    c) Has a high-quality True Random Number Generator.  The StrongBox device must have sole
+     *       control of and access to a high-quality TRNG which it uses for generating necessary
+     *       random bits.  It must combine the output of this TRNG with caller-provided entropy in a
+     *       strong CPRNG, as do non-Strongbox Keymaster implementations.
+     *
+     *    d) Is enclosed in tamper-resistant packaging.  The StrongBox device must have
+     *       tamper-resistant packaging which provides obstacles to physical penetration which are
+     *       higher than those provided by normal integrated circuit packages.
+     *
+     *    e) Provides side-channel resistance.  The StrongBox device must implement resistance
+     *       against common side-channel attacks, including power analysis, timing analysis, EM
+     *       snooping, etc.
+     *
+     * Devices with StrongBox Keymasters must also have a non-StrongBox Keymaster, which lives in
+     * the higher-performance TEE.  Keystore must load both StrongBox (if available) and
+     * non-StrongBox HALs and route key generation/import requests appropriately.  Callers that want
+     * StrongBox keys must add Tag::HARDWARE_TYPE with value SecurityLevel::STRONGBOX to the key
+     * description provided to generateKey or importKey.  Keytore must route the request to a
+     * StrongBox HAL (a HAL whose isStrongBox method returns true).  Keymaster implementations that
+     * receive a request for a Tag::HARDWARE_TYPE that is inappropriate must fail with
+     * ErrorCode::HARDWARE_TYPE_UNAVAILABLE.
+     */
+    STRONGBOX = 2,              /* See IKeymaster::isStrongBox */
+};
+
+struct KeyParameter {
+    /**
+     * Discriminates the uinon/blob field used.  The blob cannot be coincided with the union, but
+     * only one of "f" and "blob" is ever used at a time. */
+    Tag tag;
+    union IntegerParams {
+        /** Enum types */
+        Algorithm algorithm;
+        BlockMode blockMode;
+        PaddingMode paddingMode;
+        Digest digest;
+        EcCurve ecCurve;
+        KeyOrigin origin;
+        KeyBlobUsageRequirements keyBlobUsageRequirements;
+        KeyPurpose purpose;
+        KeyDerivationFunction keyDerivationFunction;
+        HardwareAuthenticatorType hardwareAuthenticatorType;
+        SecurityLevel hardwareType;
+
+        /** Other types */
+        bool boolValue;  // Always true, if a boolean tag is present.
+        uint32_t integer;
+        uint64_t longInteger;
+        uint64_t dateTime;
+    };
+    IntegerParams f;  // Hidl does not support anonymous unions, so we have to name it.
+    vec<uint8_t> blob;
+};
+
+struct KeyCharacteristics {
+    vec<KeyParameter> softwareEnforced;
+    vec<KeyParameter> hardwareEnforced;
+};
+
+/**
+ * Data used to prove successful authentication.
+ */
+struct HardwareAuthToken {
+    uint64_t challenge;
+    uint64_t userId;             // Secure User ID, not Android user ID.
+    uint64_t authenticatorId;    // Secure authenticator ID.
+    HardwareAuthenticatorType authenticatorType;
+    Timestamp timestamp;
+    /**
+     * MACs are computed with a backward-compatible method, used by Keymaster 3.0, Gatekeeper 1.0
+     * and Fingerprint 1.0, as well as pre-treble HALs.
+     *
+     * The MAC is Constants::AUTH_TOKEN_MAC_LENGTH bytes in length and is computed as follows:
+     *
+     *     HMAC_SHA256(
+     *         H, 0 || challenge || user_id || authenticator_id || authenticator_type || timestamp)
+     *
+     * where ``||'' represents concatenation, the leading zero is a single byte, and all integers
+     * are represented as unsigned values, the full width of the type.  The challenge, userId and
+     * authenticatorId values are in machine order, but authenticatorType and timestamp are in
+     * network order.  This odd construction is compatible with the hw_auth_token_t structure,
+     *
+     * Note that mac is a vec rather than an array, not because it's actually variable-length but
+     * because it could be empty.  As documented in the IKeymasterDevice::begin,
+     * IKeymasterDevice::update and IKeymasterDevice::finish doc comments, an empty mac indicates
+     * that this auth token is empty.
+     */
+    vec<uint8_t> mac;
+};
+
+typedef uint64_t OperationHandle;
+
+/**
+ * HmacSharingParameters holds the data used in the process of establishing a shared HMAC key
+ * between multiple Keymaster instances.  Sharing parameters are returned in this struct by
+ * getHmacSharingParameters() and send to computeSharedHmac().  See the named methods in IKeymaster
+ * for details of usage.
+ */
+struct HmacSharingParameters {
+    /**
+     * Either empty or contains a persistent value that is associated with the pre-shared HMAC
+     * agreement key (see documentation of computeSharedHmac in @4.0::IKeymaster).  It is either
+     * empty or 32 bytes in length.
+     */
+    vec<uint8_t> seed;
+
+    /**
+     * A 32-byte value which is guaranteed to be different each time
+     * getHmacSharingParameters() is called.  Probabilistic uniqueness (i.e. random) is acceptable,
+     * though a stronger uniqueness guarantee (e.g. counter) is recommended where possible.
+     */
+    uint8_t[32] nonce;
+};
+
+/**
+ * VerificationToken enables one Keymaster instance to validate authorizations for another.  See
+ * verifyAuthorizations() in IKeymaster for details.
+ */
+struct VerificationToken {
+    /**
+     * The operation handle, used to ensure freshness.
+     */
+    uint64_t challenge;
+
+    /**
+     * The current time of the secure environment that generates the VerificationToken.  This can be
+     * checked against auth tokens generated by the same secure environment, which avoids needing to
+     * synchronize clocks.
+     */
+    Timestamp timestamp;
+
+    /**
+     * A list of the parameters verified.  Empty if the only parameters verified are time-related.
+     * In that case the timestamp is the payload.
+     */
+    vec<KeyParameter> parametersVerified;
+
+    /**
+     * SecurityLevel of the secure environment that generated the token.
+     */
+    SecurityLevel securityLevel;
+
+    /**
+     * 32-byte HMAC of the above values, computed as:
+     *
+     *    HMAC(H,
+     *         "Auth Verification" || challenge || timestamp || securityLevel || parametersVerified)
+     *
+     * where:
+     *
+     *   ``HMAC'' is the shared HMAC key (see computeSharedHmac() in IKeymaster).
+     *
+     *   ``||'' represents concatenation
+     *
+     * The representation of challenge and timestamp is as 64-bit unsigned integers in big-endian
+     * order.  securityLevel is represented as a 32-bit unsigned integer in big-endian order.
+     *
+     * If parametersVerified is non-empty, the representation of parametersVerified is an ASN.1 DER
+     * encoded representation of the values.  The ASN.1 schema used is the AuthorizationList schema
+     * from the Keystore attestation documentation.  If parametersVerified is empty, it is simply
+     * omitted from the HMAC computation.
+     */
+    vec<uint8_t> mac;
+};
diff --git a/keymaster/4.0/vts/OWNERS b/keymaster/4.0/vts/OWNERS
new file mode 100644
index 0000000..376c12b
--- /dev/null
+++ b/keymaster/4.0/vts/OWNERS
@@ -0,0 +1,4 @@
+jdanis@google.com
+swillden@google.com
+yim@google.com
+yuexima@google.com
diff --git a/broadcastradio/1.1/tests/Android.bp b/keymaster/4.0/vts/functional/Android.bp
similarity index 70%
copy from broadcastradio/1.1/tests/Android.bp
copy to keymaster/4.0/vts/functional/Android.bp
index fa1fd94..3c3063c 100644
--- a/broadcastradio/1.1/tests/Android.bp
+++ b/keymaster/4.0/vts/functional/Android.bp
@@ -15,15 +15,15 @@
 //
 
 cc_test {
-    name: "android.hardware.broadcastradio@1.1-utils-tests",
-    vendor: true,
-    cflags: [
-        "-Wall",
-        "-Wextra",
-        "-Werror",
-    ],
+    name: "VtsHalKeymasterV4_0TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: [
-        "WorkerThread_test.cpp",
+        "keymaster_hidl_hal_test.cpp",
     ],
-    static_libs: ["android.hardware.broadcastradio@1.1-utils-lib"],
+    static_libs: [
+        "android.hardware.keymaster@4.0",
+        "libcrypto",
+        "libkeymaster4support",
+        "libsoftkeymasterdevice",
+    ],
 }
diff --git a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
new file mode 100644
index 0000000..c8858de
--- /dev/null
+++ b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
@@ -0,0 +1,4100 @@
+/*
+ * 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 "keymaster_hidl_hal_test"
+#include <cutils/log.h>
+
+#include <iostream>
+
+#include <openssl/evp.h>
+#include <openssl/x509.h>
+
+#include <android/hardware/keymaster/4.0/IKeymasterDevice.h>
+#include <android/hardware/keymaster/4.0/types.h>
+#include <cutils/properties.h>
+#include <keymaster/keymaster_configuration.h>
+
+#include <VtsHalHidlTargetTestBase.h>
+
+#include <keymasterV4_0/attestation_record.h>
+#include <keymasterV4_0/authorization_set.h>
+#include <keymasterV4_0/key_param_output.h>
+#include <keymasterV4_0/openssl_utils.h>
+
+using ::android::sp;
+
+using ::std::string;
+
+static bool arm_deleteAllKeys = false;
+static bool dump_Attestations = false;
+
+namespace android {
+namespace hardware {
+
+template <typename T>
+bool operator==(const hidl_vec<T>& a, const hidl_vec<T>& b) {
+    if (a.size() != b.size()) {
+        return false;
+    }
+    for (size_t i = 0; i < a.size(); ++i) {
+        if (a[i] != b[i]) {
+            return false;
+        }
+    }
+    return true;
+}
+
+namespace keymaster {
+namespace V4_0 {
+
+bool operator==(const KeyParameter& a, const KeyParameter& b) {
+    if (a.tag != b.tag) {
+        return false;
+    }
+
+    switch (a.tag) {
+        /* Boolean tags */
+        case Tag::INVALID:
+        case Tag::CALLER_NONCE:
+        case Tag::INCLUDE_UNIQUE_ID:
+        case Tag::BOOTLOADER_ONLY:
+        case Tag::NO_AUTH_REQUIRED:
+        case Tag::ALLOW_WHILE_ON_BODY:
+        case Tag::ROLLBACK_RESISTANCE:
+        case Tag::RESET_SINCE_ID_ROTATION:
+            return true;
+
+        /* Integer tags */
+        case Tag::KEY_SIZE:
+        case Tag::MIN_MAC_LENGTH:
+        case Tag::MIN_SECONDS_BETWEEN_OPS:
+        case Tag::MAX_USES_PER_BOOT:
+        case Tag::OS_VERSION:
+        case Tag::OS_PATCHLEVEL:
+        case Tag::MAC_LENGTH:
+        case Tag::AUTH_TIMEOUT:
+            return a.f.integer == b.f.integer;
+
+        /* Long integer tags */
+        case Tag::RSA_PUBLIC_EXPONENT:
+        case Tag::USER_SECURE_ID:
+            return a.f.longInteger == b.f.longInteger;
+
+        /* Date-time tags */
+        case Tag::ACTIVE_DATETIME:
+        case Tag::ORIGINATION_EXPIRE_DATETIME:
+        case Tag::USAGE_EXPIRE_DATETIME:
+        case Tag::CREATION_DATETIME:
+            return a.f.dateTime == b.f.dateTime;
+
+        /* Bytes tags */
+        case Tag::APPLICATION_ID:
+        case Tag::APPLICATION_DATA:
+        case Tag::ROOT_OF_TRUST:
+        case Tag::UNIQUE_ID:
+        case Tag::ATTESTATION_CHALLENGE:
+        case Tag::ATTESTATION_APPLICATION_ID:
+        case Tag::ATTESTATION_ID_BRAND:
+        case Tag::ATTESTATION_ID_DEVICE:
+        case Tag::ATTESTATION_ID_PRODUCT:
+        case Tag::ATTESTATION_ID_SERIAL:
+        case Tag::ATTESTATION_ID_IMEI:
+        case Tag::ATTESTATION_ID_MEID:
+        case Tag::ATTESTATION_ID_MANUFACTURER:
+        case Tag::ATTESTATION_ID_MODEL:
+        case Tag::ASSOCIATED_DATA:
+        case Tag::NONCE:
+            return a.blob == b.blob;
+
+        /* Enum tags */
+        case Tag::PURPOSE:
+            return a.f.purpose == b.f.purpose;
+        case Tag::ALGORITHM:
+            return a.f.algorithm == b.f.algorithm;
+        case Tag::BLOCK_MODE:
+            return a.f.blockMode == b.f.blockMode;
+        case Tag::DIGEST:
+            return a.f.digest == b.f.digest;
+        case Tag::PADDING:
+            return a.f.paddingMode == b.f.paddingMode;
+        case Tag::EC_CURVE:
+            return a.f.ecCurve == b.f.ecCurve;
+        case Tag::BLOB_USAGE_REQUIREMENTS:
+            return a.f.keyBlobUsageRequirements == b.f.keyBlobUsageRequirements;
+        case Tag::USER_AUTH_TYPE:
+            return a.f.integer == b.f.integer;
+        case Tag::ORIGIN:
+            return a.f.origin == b.f.origin;
+        case Tag::HARDWARE_TYPE:
+            return a.f.hardwareType == b.f.hardwareType;
+    }
+
+    return false;
+}
+
+bool operator==(const AuthorizationSet& a, const AuthorizationSet& b) {
+    return a.size() == b.size() && std::equal(a.begin(), a.end(), b.begin());
+}
+
+bool operator==(const KeyCharacteristics& a, const KeyCharacteristics& b) {
+    // This isn't very efficient. Oh, well.
+    AuthorizationSet a_sw(a.softwareEnforced);
+    AuthorizationSet b_sw(b.softwareEnforced);
+    AuthorizationSet a_tee(b.hardwareEnforced);
+    AuthorizationSet b_tee(b.hardwareEnforced);
+
+    a_sw.Sort();
+    b_sw.Sort();
+    a_tee.Sort();
+    b_tee.Sort();
+
+    return a_sw == b_sw && a_tee == b_tee;
+}
+
+::std::ostream& operator<<(::std::ostream& os, const AuthorizationSet& set) {
+    if (set.size() == 0)
+        os << "(Empty)" << ::std::endl;
+    else {
+        os << "\n";
+        for (size_t i = 0; i < set.size(); ++i) os << set[i] << ::std::endl;
+    }
+    return os;
+}
+
+namespace test {
+namespace {
+
+template <TagType tag_type, Tag tag, typename ValueT>
+bool contains(hidl_vec<KeyParameter>& set, TypedTag<tag_type, tag> ttag, ValueT expected_value) {
+    size_t count = std::count_if(set.begin(), set.end(), [&](const KeyParameter& param) {
+        return param.tag == tag && accessTagValue(ttag, param) == expected_value;
+    });
+    return count == 1;
+}
+
+template <TagType tag_type, Tag tag>
+bool contains(hidl_vec<KeyParameter>& set, TypedTag<tag_type, tag>) {
+    size_t count = std::count_if(set.begin(), set.end(),
+                                 [&](const KeyParameter& param) { return param.tag == tag; });
+    return count > 0;
+}
+
+constexpr char hex_value[256] = {0, 0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,  //
+                                 0, 0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,  //
+                                 0, 0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,  //
+                                 0, 1,  2,  3,  4,  5,  6,  7, 8, 9, 0, 0, 0, 0, 0, 0,  // '0'..'9'
+                                 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0,  // 'A'..'F'
+                                 0, 0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,  //
+                                 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0,  // 'a'..'f'
+                                 0, 0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,  //
+                                 0, 0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,  //
+                                 0, 0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,  //
+                                 0, 0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,  //
+                                 0, 0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,  //
+                                 0, 0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,  //
+                                 0, 0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,  //
+                                 0, 0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0,  //
+                                 0, 0,  0,  0,  0,  0,  0,  0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+string hex2str(string a) {
+    string b;
+    size_t num = a.size() / 2;
+    b.resize(num);
+    for (size_t i = 0; i < num; i++) {
+        b[i] = (hex_value[a[i * 2] & 0xFF] << 4) + (hex_value[a[i * 2 + 1] & 0xFF]);
+    }
+    return b;
+}
+
+char nibble2hex[16] = {'0', '1', '2', '3', '4', '5', '6', '7',
+                       '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
+
+string bin2hex(const hidl_vec<uint8_t>& data) {
+    string retval;
+    retval.reserve(data.size() * 2 + 1);
+    for (uint8_t byte : data) {
+        retval.push_back(nibble2hex[0x0F & (byte >> 4)]);
+        retval.push_back(nibble2hex[0x0F & byte]);
+    }
+    return retval;
+}
+
+string rsa_key = hex2str(
+    "30820275020100300d06092a864886f70d01010105000482025f3082025b"
+    "02010002818100c6095409047d8634812d5a218176e45c41d60a75b13901"
+    "f234226cffe776521c5a77b9e389417b71c0b6a44d13afe4e4a2805d46c9"
+    "da2935adb1ff0c1f24ea06e62b20d776430a4d435157233c6f916783c30e"
+    "310fcbd89b85c2d56771169785ac12bca244abda72bfb19fc44d27c81e1d"
+    "92de284f4061edfd99280745ea6d2502030100010281801be0f04d9cae37"
+    "18691f035338308e91564b55899ffb5084d2460e6630257e05b3ceab0297"
+    "2dfabcd6ce5f6ee2589eb67911ed0fac16e43a444b8c861e544a05933657"
+    "72f8baf6b22fc9e3c5f1024b063ac080a7b2234cf8aee8f6c47bbf4fd3ac"
+    "e7240290bef16c0b3f7f3cdd64ce3ab5912cf6e32f39ab188358afcccd80"
+    "81024100e4b49ef50f765d3b24dde01aceaaf130f2c76670a91a61ae08af"
+    "497b4a82be6dee8fcdd5e3f7ba1cfb1f0c926b88f88c92bfab137fba2285"
+    "227b83c342ff7c55024100ddabb5839c4c7f6bf3d4183231f005b31aa58a"
+    "ffdda5c79e4cce217f6bc930dbe563d480706c24e9ebfcab28a6cdefd324"
+    "b77e1bf7251b709092c24ff501fd91024023d4340eda3445d8cd26c14411"
+    "da6fdca63c1ccd4b80a98ad52b78cc8ad8beb2842c1d280405bc2f6c1bea"
+    "214a1d742ab996b35b63a82a5e470fa88dbf823cdd02401b7b57449ad30d"
+    "1518249a5f56bb98294d4b6ac12ffc86940497a5a5837a6cf946262b4945"
+    "26d328c11e1126380fde04c24f916dec250892db09a6d77cdba351024077"
+    "62cd8f4d050da56bd591adb515d24d7ccd32cca0d05f866d583514bd7324"
+    "d5f33645e8ed8b4a1cb3cc4a1d67987399f2a09f5b3fb68c88d5e5d90ac3"
+    "3492d6");
+
+string ec_256_key = hex2str(
+    "308187020100301306072a8648ce3d020106082a8648ce3d030107046d30"
+    "6b0201010420737c2ecd7b8d1940bf2930aa9b4ed3ff941eed09366bc032"
+    "99986481f3a4d859a14403420004bf85d7720d07c25461683bc648b4778a"
+    "9a14dd8a024e3bdd8c7ddd9ab2b528bbc7aa1b51f14ebbbb0bd0ce21bcc4"
+    "1c6eb00083cf3376d11fd44949e0b2183bfe");
+
+string ec_521_key = hex2str(
+    "3081EE020100301006072A8648CE3D020106052B810400230481D63081D3"
+    "02010104420011458C586DB5DAA92AFAB03F4FE46AA9D9C3CE9A9B7A006A"
+    "8384BEC4C78E8E9D18D7D08B5BCFA0E53C75B064AD51C449BAE0258D54B9"
+    "4B1E885DED08ED4FB25CE9A1818903818600040149EC11C6DF0FA122C6A9"
+    "AFD9754A4FA9513A627CA329E349535A5629875A8ADFBE27DCB932C05198"
+    "6377108D054C28C6F39B6F2C9AF81802F9F326B842FF2E5F3C00AB7635CF"
+    "B36157FC0882D574A10D839C1A0C049DC5E0D775E2EE50671A208431BB45"
+    "E78E70BEFE930DB34818EE4D5C26259F5C6B8E28A652950F9F88D7B4B2C9"
+    "D9");
+
+struct RSA_Delete {
+    void operator()(RSA* p) { RSA_free(p); }
+};
+
+X509* parse_cert_blob(const hidl_vec<uint8_t>& blob) {
+    const uint8_t* p = blob.data();
+    return d2i_X509(nullptr, &p, blob.size());
+}
+
+bool verify_chain(const hidl_vec<hidl_vec<uint8_t>>& chain) {
+    for (size_t i = 0; i < chain.size() - 1; ++i) {
+        X509_Ptr key_cert(parse_cert_blob(chain[i]));
+        X509_Ptr signing_cert;
+        if (i < chain.size() - 1) {
+            signing_cert.reset(parse_cert_blob(chain[i + 1]));
+        } else {
+            signing_cert.reset(parse_cert_blob(chain[i]));
+        }
+        EXPECT_TRUE(!!key_cert.get() && !!signing_cert.get());
+        if (!key_cert.get() || !signing_cert.get()) return false;
+
+        EVP_PKEY_Ptr signing_pubkey(X509_get_pubkey(signing_cert.get()));
+        EXPECT_TRUE(!!signing_pubkey.get());
+        if (!signing_pubkey.get()) return false;
+
+        EXPECT_EQ(1, X509_verify(key_cert.get(), signing_pubkey.get()))
+            << "Verification of certificate " << i << " failed";
+
+        char* cert_issuer =  //
+            X509_NAME_oneline(X509_get_issuer_name(key_cert.get()), nullptr, 0);
+        char* signer_subj =
+            X509_NAME_oneline(X509_get_subject_name(signing_cert.get()), nullptr, 0);
+        EXPECT_STREQ(cert_issuer, signer_subj) << "Cert " << i << " has wrong issuer.";
+        if (i == 0) {
+            char* cert_sub = X509_NAME_oneline(X509_get_subject_name(key_cert.get()), nullptr, 0);
+            EXPECT_STREQ("/CN=Android Keystore Key", cert_sub)
+                << "Cert " << i << " has wrong subject.";
+            free(cert_sub);
+        }
+
+        free(cert_issuer);
+        free(signer_subj);
+
+        if (dump_Attestations) std::cout << bin2hex(chain[i]) << std::endl;
+    }
+
+    return true;
+}
+
+// Extract attestation record from cert. Returned object is still part of cert; don't free it
+// separately.
+ASN1_OCTET_STRING* get_attestation_record(X509* certificate) {
+    ASN1_OBJECT_Ptr oid(OBJ_txt2obj(kAttestionRecordOid, 1 /* dotted string format */));
+    EXPECT_TRUE(!!oid.get());
+    if (!oid.get()) return nullptr;
+
+    int location = X509_get_ext_by_OBJ(certificate, oid.get(), -1 /* search from beginning */);
+    EXPECT_NE(-1, location) << "Attestation extension not found in certificate";
+    if (location == -1) return nullptr;
+
+    X509_EXTENSION* attest_rec_ext = X509_get_ext(certificate, location);
+    EXPECT_TRUE(!!attest_rec_ext)
+        << "Found attestation extension but couldn't retrieve it?  Probably a BoringSSL bug.";
+    if (!attest_rec_ext) return nullptr;
+
+    ASN1_OCTET_STRING* attest_rec = X509_EXTENSION_get_data(attest_rec_ext);
+    EXPECT_TRUE(!!attest_rec) << "Attestation extension contained no data";
+    return attest_rec;
+}
+
+bool tag_in_list(const KeyParameter& entry) {
+    // Attestations don't contain everything in key authorization lists, so we need to filter
+    // the key lists to produce the lists that we expect to match the attestations.
+    auto tag_list = {
+        Tag::INCLUDE_UNIQUE_ID, Tag::BLOB_USAGE_REQUIREMENTS,
+        Tag::EC_CURVE /* Tag::EC_CURVE will be included by KM2 implementations */,
+    };
+    return std::find(tag_list.begin(), tag_list.end(), entry.tag) != tag_list.end();
+}
+
+AuthorizationSet filter_tags(const AuthorizationSet& set) {
+    AuthorizationSet filtered;
+    std::remove_copy_if(set.begin(), set.end(), std::back_inserter(filtered), tag_in_list);
+    return filtered;
+}
+
+std::string make_string(const uint8_t* data, size_t length) {
+    return std::string(reinterpret_cast<const char*>(data), length);
+}
+
+template <size_t N>
+std::string make_string(const uint8_t (&a)[N]) {
+    return make_string(a, N);
+}
+
+class HidlBuf : public hidl_vec<uint8_t> {
+    typedef hidl_vec<uint8_t> super;
+
+   public:
+    HidlBuf() {}
+    HidlBuf(const super& other) : super(other) {}
+    HidlBuf(super&& other) : super(std::move(other)) {}
+    explicit HidlBuf(const std::string& other) : HidlBuf() { *this = other; }
+
+    HidlBuf& operator=(const super& other) {
+        super::operator=(other);
+        return *this;
+    }
+
+    HidlBuf& operator=(super&& other) {
+        super::operator=(std::move(other));
+        return *this;
+    }
+
+    HidlBuf& operator=(const string& other) {
+        resize(other.size());
+        for (size_t i = 0; i < other.size(); ++i) {
+            (*this)[i] = static_cast<uint8_t>(other[i]);
+        }
+        return *this;
+    }
+
+    string to_string() const { return string(reinterpret_cast<const char*>(data()), size()); }
+};
+
+constexpr uint64_t kOpHandleSentinel = 0xFFFFFFFFFFFFFFFF;
+
+}  // namespace
+
+class KeymasterHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
+   public:
+    // get the test environment singleton
+    static KeymasterHidlEnvironment* Instance() {
+        static KeymasterHidlEnvironment* instance = new KeymasterHidlEnvironment;
+        return instance;
+    }
+
+    void registerTestServices() override { registerTestService<IKeymasterDevice>(); }
+
+   private:
+    KeymasterHidlEnvironment(){};
+
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(KeymasterHidlEnvironment);
+};
+
+class KeymasterHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+   public:
+    void TearDown() override {
+        if (key_blob_.size()) {
+            CheckedDeleteKey();
+        }
+        AbortIfNeeded();
+    }
+
+    // SetUpTestCase runs only once per test case, not once per test.
+    static void SetUpTestCase() {
+        string service_name =
+            KeymasterHidlEnvironment::Instance()->getServiceName<IKeymasterDevice>();
+        keymaster_ =
+            ::testing::VtsHalHidlTargetTestBase::getService<IKeymasterDevice>(service_name);
+        ASSERT_NE(keymaster_, nullptr);
+
+        ASSERT_TRUE(keymaster_
+                        ->getHardwareInfo([&](SecurityLevel securityLevel, const hidl_string& name,
+                                              const hidl_string& author) {
+                            securityLevel_ = securityLevel;
+                            name_ = name;
+                            author_ = author;
+                        })
+                        .isOk());
+
+        os_version_ = ::keymaster::GetOsVersion();
+        os_patch_level_ = ::keymaster::GetOsPatchlevel();
+    }
+
+    static void TearDownTestCase() { keymaster_.clear(); }
+
+    static IKeymasterDevice& keymaster() { return *keymaster_; }
+    static uint32_t os_version() { return os_version_; }
+    static uint32_t os_patch_level() { return os_patch_level_; }
+
+    ErrorCode GenerateKey(const AuthorizationSet& key_desc, HidlBuf* key_blob,
+                          KeyCharacteristics* key_characteristics) {
+        EXPECT_NE(key_blob, nullptr) << "Key blob pointer must not be null.  Test bug";
+        EXPECT_EQ(0U, key_blob->size()) << "Key blob not empty before generating key.  Test bug.";
+        EXPECT_NE(key_characteristics, nullptr)
+            << "Previous characteristics not deleted before generating key.  Test bug.";
+
+        ErrorCode error;
+        EXPECT_TRUE(keymaster_
+                        ->generateKey(key_desc.hidl_data(),
+                                      [&](ErrorCode hidl_error, const HidlBuf& hidl_key_blob,
+                                          const KeyCharacteristics& hidl_key_characteristics) {
+                                          error = hidl_error;
+                                          *key_blob = hidl_key_blob;
+                                          *key_characteristics = hidl_key_characteristics;
+                                      })
+                        .isOk());
+        // On error, blob & characteristics should be empty.
+        if (error != ErrorCode::OK) {
+            EXPECT_EQ(0U, key_blob->size());
+            EXPECT_EQ(0U, (key_characteristics->softwareEnforced.size() +
+                           key_characteristics->hardwareEnforced.size()));
+        }
+        return error;
+    }
+
+    ErrorCode GenerateKey(const AuthorizationSet& key_desc) {
+        return GenerateKey(key_desc, &key_blob_, &key_characteristics_);
+    }
+
+    ErrorCode ImportKey(const AuthorizationSet& key_desc, KeyFormat format,
+                        const string& key_material, HidlBuf* key_blob,
+                        KeyCharacteristics* key_characteristics) {
+        ErrorCode error;
+        EXPECT_TRUE(keymaster_
+                        ->importKey(key_desc.hidl_data(), format, HidlBuf(key_material),
+                                    [&](ErrorCode hidl_error, const HidlBuf& hidl_key_blob,
+                                        const KeyCharacteristics& hidl_key_characteristics) {
+                                        error = hidl_error;
+                                        *key_blob = hidl_key_blob;
+                                        *key_characteristics = hidl_key_characteristics;
+                                    })
+                        .isOk());
+        // On error, blob & characteristics should be empty.
+        if (error != ErrorCode::OK) {
+            EXPECT_EQ(0U, key_blob->size());
+            EXPECT_EQ(0U, (key_characteristics->softwareEnforced.size() +
+                           key_characteristics->hardwareEnforced.size()));
+        }
+        return error;
+    }
+
+    ErrorCode ImportKey(const AuthorizationSet& key_desc, KeyFormat format,
+                        const string& key_material) {
+        return ImportKey(key_desc, format, key_material, &key_blob_, &key_characteristics_);
+    }
+
+    ErrorCode ExportKey(KeyFormat format, const HidlBuf& key_blob, const HidlBuf& client_id,
+                        const HidlBuf& app_data, HidlBuf* key_material) {
+        ErrorCode error;
+        EXPECT_TRUE(
+            keymaster_
+                ->exportKey(format, key_blob, client_id, app_data,
+                            [&](ErrorCode hidl_error_code, const HidlBuf& hidl_key_material) {
+                                error = hidl_error_code;
+                                *key_material = hidl_key_material;
+                            })
+                .isOk());
+        // On error, blob should be empty.
+        if (error != ErrorCode::OK) {
+            EXPECT_EQ(0U, key_material->size());
+        }
+        return error;
+    }
+
+    ErrorCode ExportKey(KeyFormat format, HidlBuf* key_material) {
+        HidlBuf client_id, app_data;
+        return ExportKey(format, key_blob_, client_id, app_data, key_material);
+    }
+
+    ErrorCode DeleteKey(HidlBuf* key_blob, bool keep_key_blob = false) {
+        auto rc = keymaster_->deleteKey(*key_blob);
+        if (!keep_key_blob) *key_blob = HidlBuf();
+        if (!rc.isOk()) return ErrorCode::UNKNOWN_ERROR;
+        return rc;
+    }
+
+    ErrorCode DeleteKey(bool keep_key_blob = false) { return DeleteKey(&key_blob_, keep_key_blob); }
+
+    ErrorCode DeleteAllKeys() {
+        ErrorCode error = keymaster_->deleteAllKeys();
+        return error;
+    }
+
+    void CheckedDeleteKey(HidlBuf* key_blob, bool keep_key_blob = false) {
+        auto rc = DeleteKey(key_blob, keep_key_blob);
+        EXPECT_TRUE(rc == ErrorCode::OK || rc == ErrorCode::UNIMPLEMENTED);
+    }
+
+    void CheckedDeleteKey() { CheckedDeleteKey(&key_blob_); }
+
+    ErrorCode GetCharacteristics(const HidlBuf& key_blob, const HidlBuf& client_id,
+                                 const HidlBuf& app_data, KeyCharacteristics* key_characteristics) {
+        ErrorCode error = ErrorCode::UNKNOWN_ERROR;
+        EXPECT_TRUE(
+            keymaster_
+                ->getKeyCharacteristics(
+                    key_blob, client_id, app_data,
+                    [&](ErrorCode hidl_error, const KeyCharacteristics& hidl_key_characteristics) {
+                        error = hidl_error, *key_characteristics = hidl_key_characteristics;
+                    })
+                .isOk());
+        return error;
+    }
+
+    ErrorCode GetCharacteristics(const HidlBuf& key_blob, KeyCharacteristics* key_characteristics) {
+        HidlBuf client_id, app_data;
+        return GetCharacteristics(key_blob, client_id, app_data, key_characteristics);
+    }
+
+    ErrorCode Begin(KeyPurpose purpose, const HidlBuf& key_blob, const AuthorizationSet& in_params,
+                    AuthorizationSet* out_params, OperationHandle* op_handle) {
+        SCOPED_TRACE("Begin");
+        ErrorCode error;
+        OperationHandle saved_handle = *op_handle;
+        EXPECT_TRUE(
+            keymaster_
+                ->begin(purpose, key_blob, in_params.hidl_data(), HardwareAuthToken(),
+                        [&](ErrorCode hidl_error, const hidl_vec<KeyParameter>& hidl_out_params,
+                            uint64_t hidl_op_handle) {
+                            error = hidl_error;
+                            *out_params = hidl_out_params;
+                            *op_handle = hidl_op_handle;
+                        })
+                .isOk());
+        if (error != ErrorCode::OK) {
+            // Some implementations may modify *op_handle on error.
+            *op_handle = saved_handle;
+        }
+        return error;
+    }
+
+    ErrorCode Begin(KeyPurpose purpose, const AuthorizationSet& in_params,
+                    AuthorizationSet* out_params) {
+        SCOPED_TRACE("Begin");
+        EXPECT_EQ(kOpHandleSentinel, op_handle_);
+        return Begin(purpose, key_blob_, in_params, out_params, &op_handle_);
+    }
+
+    ErrorCode Begin(KeyPurpose purpose, const AuthorizationSet& in_params) {
+        SCOPED_TRACE("Begin");
+        AuthorizationSet out_params;
+        ErrorCode error = Begin(purpose, in_params, &out_params);
+        EXPECT_TRUE(out_params.empty());
+        return error;
+    }
+
+    ErrorCode Update(OperationHandle op_handle, const AuthorizationSet& in_params,
+                     const string& input, AuthorizationSet* out_params, string* output,
+                     size_t* input_consumed) {
+        SCOPED_TRACE("Update");
+        ErrorCode error;
+        EXPECT_TRUE(keymaster_
+                        ->update(op_handle, in_params.hidl_data(), HidlBuf(input),
+                                 HardwareAuthToken(), VerificationToken(),
+                                 [&](ErrorCode hidl_error, uint32_t hidl_input_consumed,
+                                     const hidl_vec<KeyParameter>& hidl_out_params,
+                                     const HidlBuf& hidl_output) {
+                                     error = hidl_error;
+                                     out_params->push_back(AuthorizationSet(hidl_out_params));
+                                     output->append(hidl_output.to_string());
+                                     *input_consumed = hidl_input_consumed;
+                                 })
+                        .isOk());
+        return error;
+    }
+
+    ErrorCode Update(const string& input, string* out, size_t* input_consumed) {
+        SCOPED_TRACE("Update");
+        AuthorizationSet out_params;
+        ErrorCode error = Update(op_handle_, AuthorizationSet() /* in_params */, input, &out_params,
+                                 out, input_consumed);
+        EXPECT_TRUE(out_params.empty());
+        return error;
+    }
+
+    ErrorCode Finish(OperationHandle op_handle, const AuthorizationSet& in_params,
+                     const string& input, const string& signature, AuthorizationSet* out_params,
+                     string* output) {
+        SCOPED_TRACE("Finish");
+        ErrorCode error;
+        EXPECT_TRUE(
+            keymaster_
+                ->finish(op_handle, in_params.hidl_data(), HidlBuf(input), HidlBuf(signature),
+                         HardwareAuthToken(), VerificationToken(),
+                         [&](ErrorCode hidl_error, const hidl_vec<KeyParameter>& hidl_out_params,
+                             const HidlBuf& hidl_output) {
+                             error = hidl_error;
+                             *out_params = hidl_out_params;
+                             output->append(hidl_output.to_string());
+                         })
+                .isOk());
+        op_handle_ = kOpHandleSentinel;  // So dtor doesn't Abort().
+        return error;
+    }
+
+    ErrorCode Finish(const string& message, string* output) {
+        SCOPED_TRACE("Finish");
+        AuthorizationSet out_params;
+        string finish_output;
+        ErrorCode error = Finish(op_handle_, AuthorizationSet() /* in_params */, message,
+                                 "" /* signature */, &out_params, output);
+        if (error != ErrorCode::OK) {
+            return error;
+        }
+        EXPECT_EQ(0U, out_params.size());
+        return error;
+    }
+
+    ErrorCode Finish(const string& message, const string& signature, string* output) {
+        SCOPED_TRACE("Finish");
+        AuthorizationSet out_params;
+        ErrorCode error = Finish(op_handle_, AuthorizationSet() /* in_params */, message, signature,
+                                 &out_params, output);
+        op_handle_ = kOpHandleSentinel;  // So dtor doesn't Abort().
+        if (error != ErrorCode::OK) {
+            return error;
+        }
+        EXPECT_EQ(0U, out_params.size());
+        return error;
+    }
+
+    ErrorCode Abort(OperationHandle op_handle) {
+        SCOPED_TRACE("Abort");
+        auto retval = keymaster_->abort(op_handle);
+        EXPECT_TRUE(retval.isOk());
+        return retval;
+    }
+
+    void AbortIfNeeded() {
+        SCOPED_TRACE("AbortIfNeeded");
+        if (op_handle_ != kOpHandleSentinel) {
+            EXPECT_EQ(ErrorCode::OK, Abort(op_handle_));
+            op_handle_ = kOpHandleSentinel;
+        }
+    }
+
+    ErrorCode AttestKey(const HidlBuf& key_blob, const AuthorizationSet& attest_params,
+                        hidl_vec<hidl_vec<uint8_t>>* cert_chain) {
+        SCOPED_TRACE("AttestKey");
+        ErrorCode error;
+        auto rc = keymaster_->attestKey(
+            key_blob, attest_params.hidl_data(),
+            [&](ErrorCode hidl_error, const hidl_vec<hidl_vec<uint8_t>>& hidl_cert_chain) {
+                error = hidl_error;
+                *cert_chain = hidl_cert_chain;
+            });
+
+        EXPECT_TRUE(rc.isOk()) << rc.description();
+        if (!rc.isOk()) return ErrorCode::UNKNOWN_ERROR;
+
+        return error;
+    }
+
+    ErrorCode AttestKey(const AuthorizationSet& attest_params,
+                        hidl_vec<hidl_vec<uint8_t>>* cert_chain) {
+        SCOPED_TRACE("AttestKey");
+        return AttestKey(key_blob_, attest_params, cert_chain);
+    }
+
+    string ProcessMessage(const HidlBuf& key_blob, KeyPurpose operation, const string& message,
+                          const AuthorizationSet& in_params, AuthorizationSet* out_params) {
+        SCOPED_TRACE("ProcessMessage");
+        AuthorizationSet begin_out_params;
+        EXPECT_EQ(ErrorCode::OK,
+                  Begin(operation, key_blob, in_params, &begin_out_params, &op_handle_));
+
+        string unused;
+        AuthorizationSet finish_params;
+        AuthorizationSet finish_out_params;
+        string output;
+        EXPECT_EQ(ErrorCode::OK,
+                  Finish(op_handle_, finish_params, message, unused, &finish_out_params, &output));
+        op_handle_ = kOpHandleSentinel;
+
+        out_params->push_back(begin_out_params);
+        out_params->push_back(finish_out_params);
+        return output;
+    }
+
+    string SignMessage(const HidlBuf& key_blob, const string& message,
+                       const AuthorizationSet& params) {
+        SCOPED_TRACE("SignMessage");
+        AuthorizationSet out_params;
+        string signature = ProcessMessage(key_blob, KeyPurpose::SIGN, message, params, &out_params);
+        EXPECT_TRUE(out_params.empty());
+        return signature;
+    }
+
+    string SignMessage(const string& message, const AuthorizationSet& params) {
+        SCOPED_TRACE("SignMessage");
+        return SignMessage(key_blob_, message, params);
+    }
+
+    string MacMessage(const string& message, Digest digest, size_t mac_length) {
+        SCOPED_TRACE("MacMessage");
+        return SignMessage(
+            key_blob_, message,
+            AuthorizationSetBuilder().Digest(digest).Authorization(TAG_MAC_LENGTH, mac_length));
+    }
+
+    void CheckHmacTestVector(const string& key, const string& message, Digest digest,
+                             const string& expected_mac) {
+        SCOPED_TRACE("CheckHmacTestVector");
+        ASSERT_EQ(ErrorCode::OK,
+                  ImportKey(AuthorizationSetBuilder()
+                                .Authorization(TAG_NO_AUTH_REQUIRED)
+                                .HmacKey(key.size() * 8)
+                                .Authorization(TAG_MIN_MAC_LENGTH, expected_mac.size() * 8)
+                                .Digest(digest),
+                            KeyFormat::RAW, key));
+        string signature = MacMessage(message, digest, expected_mac.size() * 8);
+        EXPECT_EQ(expected_mac, signature)
+            << "Test vector didn't match for key of size " << key.size() << " message of size "
+            << message.size() << " and digest " << digest;
+        CheckedDeleteKey();
+    }
+
+    void CheckAesCtrTestVector(const string& key, const string& nonce, const string& message,
+                               const string& expected_ciphertext) {
+        SCOPED_TRACE("CheckAesCtrTestVector");
+        ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
+                                               .Authorization(TAG_NO_AUTH_REQUIRED)
+                                               .AesEncryptionKey(key.size() * 8)
+                                               .BlockMode(BlockMode::CTR)
+                                               .Authorization(TAG_CALLER_NONCE)
+                                               .Padding(PaddingMode::NONE),
+                                           KeyFormat::RAW, key));
+
+        auto params = AuthorizationSetBuilder()
+                          .Authorization(TAG_NONCE, nonce.data(), nonce.size())
+                          .BlockMode(BlockMode::CTR)
+                          .Padding(PaddingMode::NONE);
+        AuthorizationSet out_params;
+        string ciphertext = EncryptMessage(key_blob_, message, params, &out_params);
+        EXPECT_EQ(expected_ciphertext, ciphertext);
+    }
+
+    void VerifyMessage(const HidlBuf& key_blob, const string& message, const string& signature,
+                       const AuthorizationSet& params) {
+        SCOPED_TRACE("VerifyMessage");
+        AuthorizationSet begin_out_params;
+        ASSERT_EQ(ErrorCode::OK,
+                  Begin(KeyPurpose::VERIFY, key_blob, params, &begin_out_params, &op_handle_));
+
+        string unused;
+        AuthorizationSet finish_params;
+        AuthorizationSet finish_out_params;
+        string output;
+        EXPECT_EQ(ErrorCode::OK, Finish(op_handle_, finish_params, message, signature,
+                                        &finish_out_params, &output));
+        op_handle_ = kOpHandleSentinel;
+        EXPECT_TRUE(output.empty());
+    }
+
+    void VerifyMessage(const string& message, const string& signature,
+                       const AuthorizationSet& params) {
+        SCOPED_TRACE("VerifyMessage");
+        VerifyMessage(key_blob_, message, signature, params);
+    }
+
+    string EncryptMessage(const HidlBuf& key_blob, const string& message,
+                          const AuthorizationSet& in_params, AuthorizationSet* out_params) {
+        SCOPED_TRACE("EncryptMessage");
+        return ProcessMessage(key_blob, KeyPurpose::ENCRYPT, message, in_params, out_params);
+    }
+
+    string EncryptMessage(const string& message, const AuthorizationSet& params,
+                          AuthorizationSet* out_params) {
+        SCOPED_TRACE("EncryptMessage");
+        return EncryptMessage(key_blob_, message, params, out_params);
+    }
+
+    string EncryptMessage(const string& message, const AuthorizationSet& params) {
+        SCOPED_TRACE("EncryptMessage");
+        AuthorizationSet out_params;
+        string ciphertext = EncryptMessage(message, params, &out_params);
+        EXPECT_TRUE(out_params.empty())
+            << "Output params should be empty. Contained: " << out_params;
+        return ciphertext;
+    }
+
+    string DecryptMessage(const HidlBuf& key_blob, const string& ciphertext,
+                          const AuthorizationSet& params) {
+        SCOPED_TRACE("DecryptMessage");
+        AuthorizationSet out_params;
+        string plaintext =
+            ProcessMessage(key_blob, KeyPurpose::DECRYPT, ciphertext, params, &out_params);
+        EXPECT_TRUE(out_params.empty());
+        return plaintext;
+    }
+
+    string DecryptMessage(const string& ciphertext, const AuthorizationSet& params) {
+        SCOPED_TRACE("DecryptMessage");
+        return DecryptMessage(key_blob_, ciphertext, params);
+    }
+
+    std::pair<ErrorCode, HidlBuf> UpgradeKey(const HidlBuf& key_blob) {
+        std::pair<ErrorCode, HidlBuf> retval;
+        keymaster_->upgradeKey(key_blob, hidl_vec<KeyParameter>(),
+                               [&](ErrorCode error, const hidl_vec<uint8_t>& upgraded_blob) {
+                                   retval = std::tie(error, upgraded_blob);
+                               });
+        return retval;
+    }
+
+    static bool IsSecure() { return securityLevel_ != SecurityLevel::SOFTWARE; }
+
+    HidlBuf key_blob_;
+    KeyCharacteristics key_characteristics_;
+    OperationHandle op_handle_ = kOpHandleSentinel;
+
+   private:
+    static sp<IKeymasterDevice> keymaster_;
+    static uint32_t os_version_;
+    static uint32_t os_patch_level_;
+
+    static SecurityLevel securityLevel_;
+    static hidl_string name_;
+    static hidl_string author_;
+};
+
+bool verify_attestation_record(const string& challenge, const string& app_id,
+                               AuthorizationSet expected_sw_enforced,
+                               AuthorizationSet expected_tee_enforced,
+                               const hidl_vec<uint8_t>& attestation_cert) {
+    X509_Ptr cert(parse_cert_blob(attestation_cert));
+    EXPECT_TRUE(!!cert.get());
+    if (!cert.get()) return false;
+
+    ASN1_OCTET_STRING* attest_rec = get_attestation_record(cert.get());
+    EXPECT_TRUE(!!attest_rec);
+    if (!attest_rec) return false;
+
+    AuthorizationSet att_sw_enforced;
+    AuthorizationSet att_tee_enforced;
+    uint32_t att_attestation_version;
+    uint32_t att_keymaster_version;
+    SecurityLevel att_attestation_security_level;
+    SecurityLevel att_keymaster_security_level;
+    HidlBuf att_challenge;
+    HidlBuf att_unique_id;
+    HidlBuf att_app_id;
+    EXPECT_EQ(ErrorCode::OK,
+              parse_attestation_record(attest_rec->data,                 //
+                                       attest_rec->length,               //
+                                       &att_attestation_version,         //
+                                       &att_attestation_security_level,  //
+                                       &att_keymaster_version,           //
+                                       &att_keymaster_security_level,    //
+                                       &att_challenge,                   //
+                                       &att_sw_enforced,                 //
+                                       &att_tee_enforced,                //
+                                       &att_unique_id));
+
+    EXPECT_TRUE(att_attestation_version == 1 || att_attestation_version == 2);
+
+    expected_sw_enforced.push_back(TAG_ATTESTATION_APPLICATION_ID, HidlBuf(app_id));
+
+    EXPECT_GE(att_keymaster_version, 3U);
+    EXPECT_EQ(KeymasterHidlTest::IsSecure() ? SecurityLevel::TRUSTED_ENVIRONMENT
+                                            : SecurityLevel::SOFTWARE,
+              att_keymaster_security_level);
+    EXPECT_EQ(KeymasterHidlTest::IsSecure() ? SecurityLevel::TRUSTED_ENVIRONMENT
+                                            : SecurityLevel::SOFTWARE,
+              att_attestation_security_level);
+
+    EXPECT_EQ(challenge.length(), att_challenge.size());
+    EXPECT_EQ(0, memcmp(challenge.data(), att_challenge.data(), challenge.length()));
+
+    att_sw_enforced.Sort();
+    expected_sw_enforced.Sort();
+    EXPECT_EQ(filter_tags(expected_sw_enforced), filter_tags(att_sw_enforced));
+
+    att_tee_enforced.Sort();
+    expected_tee_enforced.Sort();
+    EXPECT_EQ(filter_tags(expected_tee_enforced), filter_tags(att_tee_enforced));
+
+    return true;
+}
+
+sp<IKeymasterDevice> KeymasterHidlTest::keymaster_;
+uint32_t KeymasterHidlTest::os_version_;
+uint32_t KeymasterHidlTest::os_patch_level_;
+SecurityLevel KeymasterHidlTest::securityLevel_;
+hidl_string KeymasterHidlTest::name_;
+hidl_string KeymasterHidlTest::author_;
+
+class NewKeyGenerationTest : public KeymasterHidlTest {
+   protected:
+    void CheckBaseParams(const KeyCharacteristics& keyCharacteristics) {
+        // TODO(swillden): Distinguish which params should be in which auth list.
+
+        AuthorizationSet auths(keyCharacteristics.hardwareEnforced);
+        auths.push_back(AuthorizationSet(keyCharacteristics.softwareEnforced));
+
+        EXPECT_TRUE(auths.Contains(TAG_ORIGIN, KeyOrigin::GENERATED));
+        EXPECT_TRUE(auths.Contains(TAG_PURPOSE, KeyPurpose::SIGN));
+        EXPECT_TRUE(auths.Contains(TAG_PURPOSE, KeyPurpose::VERIFY));
+
+        // Verify that App ID, App data and ROT are NOT included.
+        EXPECT_FALSE(auths.Contains(TAG_ROOT_OF_TRUST));
+        EXPECT_FALSE(auths.Contains(TAG_APPLICATION_ID));
+        EXPECT_FALSE(auths.Contains(TAG_APPLICATION_DATA));
+
+        // Check that some unexpected tags/values are NOT present.
+        EXPECT_FALSE(auths.Contains(TAG_PURPOSE, KeyPurpose::ENCRYPT));
+        EXPECT_FALSE(auths.Contains(TAG_PURPOSE, KeyPurpose::DECRYPT));
+        EXPECT_FALSE(auths.Contains(TAG_AUTH_TIMEOUT, 301U));
+
+        // Now check that unspecified, defaulted tags are correct.
+        EXPECT_TRUE(auths.Contains(TAG_CREATION_DATETIME));
+
+        EXPECT_TRUE(auths.Contains(TAG_OS_VERSION, os_version()))
+            << "OS version is " << os_version() << " key reported "
+            << auths.GetTagValue(TAG_OS_VERSION);
+        EXPECT_TRUE(auths.Contains(TAG_OS_PATCHLEVEL, os_patch_level()))
+            << "OS patch level is " << os_patch_level() << " key reported "
+            << auths.GetTagValue(TAG_OS_PATCHLEVEL);
+    }
+
+    void CheckCharacteristics(const HidlBuf& key_blob,
+                              const KeyCharacteristics& key_characteristics) {
+        KeyCharacteristics retrieved_chars;
+        ASSERT_EQ(ErrorCode::OK, GetCharacteristics(key_blob, &retrieved_chars));
+        EXPECT_EQ(key_characteristics, retrieved_chars);
+    }
+};
+
+/*
+ * NewKeyGenerationTest.Rsa
+ *
+ * Verifies that keymaster can generate all required RSA key sizes, and that the resulting keys have
+ * correct characteristics.
+ */
+TEST_F(NewKeyGenerationTest, Rsa) {
+    for (uint32_t key_size : {1024, 2048, 3072, 4096}) {
+        HidlBuf key_blob;
+        KeyCharacteristics key_characteristics;
+        ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                                 .RsaSigningKey(key_size, 3)
+                                                 .Digest(Digest::NONE)
+                                                 .Padding(PaddingMode::NONE),
+                                             &key_blob, &key_characteristics));
+
+        ASSERT_GT(key_blob.size(), 0U);
+        CheckBaseParams(key_characteristics);
+        CheckCharacteristics(key_blob, key_characteristics);
+
+        AuthorizationSet crypto_params;
+        if (IsSecure()) {
+            crypto_params = key_characteristics.hardwareEnforced;
+        } else {
+            crypto_params = key_characteristics.softwareEnforced;
+        }
+
+        EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::RSA));
+        EXPECT_TRUE(crypto_params.Contains(TAG_KEY_SIZE, key_size))
+            << "Key size " << key_size << "missing";
+        EXPECT_TRUE(crypto_params.Contains(TAG_RSA_PUBLIC_EXPONENT, 3U));
+
+        CheckedDeleteKey(&key_blob);
+    }
+}
+
+/*
+ * NewKeyGenerationTest.RsaNoDefaultSize
+ *
+ * Verifies that failing to specify a key size for RSA key generation returns UNSUPPORTED_KEY_SIZE.
+ */
+TEST_F(NewKeyGenerationTest, RsaNoDefaultSize) {
+    ASSERT_EQ(ErrorCode::UNSUPPORTED_KEY_SIZE,
+              GenerateKey(AuthorizationSetBuilder()
+                              .Authorization(TAG_ALGORITHM, Algorithm::RSA)
+                              .Authorization(TAG_RSA_PUBLIC_EXPONENT, 3U)
+                              .SigningKey()));
+}
+
+/*
+ * NewKeyGenerationTest.Ecdsa
+ *
+ * Verifies that keymaster can generate all required EC key sizes, and that the resulting keys have
+ * correct characteristics.
+ */
+TEST_F(NewKeyGenerationTest, Ecdsa) {
+    for (uint32_t key_size : {224, 256, 384, 521}) {
+        HidlBuf key_blob;
+        KeyCharacteristics key_characteristics;
+        ASSERT_EQ(
+            ErrorCode::OK,
+            GenerateKey(AuthorizationSetBuilder().EcdsaSigningKey(key_size).Digest(Digest::NONE),
+                        &key_blob, &key_characteristics));
+        ASSERT_GT(key_blob.size(), 0U);
+        CheckBaseParams(key_characteristics);
+        CheckCharacteristics(key_blob, key_characteristics);
+
+        AuthorizationSet crypto_params;
+        if (IsSecure()) {
+            crypto_params = key_characteristics.hardwareEnforced;
+        } else {
+            crypto_params = key_characteristics.softwareEnforced;
+        }
+
+        EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::EC));
+        EXPECT_TRUE(crypto_params.Contains(TAG_KEY_SIZE, key_size))
+            << "Key size " << key_size << "missing";
+
+        CheckedDeleteKey(&key_blob);
+    }
+}
+
+/*
+ * NewKeyGenerationTest.EcdsaDefaultSize
+ *
+ * Verifies that failing to specify a key size for EC key generation returns UNSUPPORTED_KEY_SIZE.
+ */
+TEST_F(NewKeyGenerationTest, EcdsaDefaultSize) {
+    ASSERT_EQ(ErrorCode::UNSUPPORTED_KEY_SIZE,
+              GenerateKey(AuthorizationSetBuilder()
+                              .Authorization(TAG_ALGORITHM, Algorithm::EC)
+                              .SigningKey()
+                              .Digest(Digest::NONE)));
+}
+
+/*
+ * NewKeyGenerationTest.EcdsaInvalidSize
+ *
+ * Verifies that failing to specify an invalid key size for EC key generation returns
+ * UNSUPPORTED_KEY_SIZE.
+ */
+TEST_F(NewKeyGenerationTest, EcdsaInvalidSize) {
+    ASSERT_EQ(ErrorCode::UNSUPPORTED_KEY_SIZE,
+              GenerateKey(AuthorizationSetBuilder().EcdsaSigningKey(190).Digest(Digest::NONE)));
+}
+
+/*
+ * NewKeyGenerationTest.EcdsaMismatchKeySize
+ *
+ * Verifies that specifying mismatched key size and curve for EC key generation returns
+ * INVALID_ARGUMENT.
+ */
+TEST_F(NewKeyGenerationTest, EcdsaMismatchKeySize) {
+    ASSERT_EQ(ErrorCode::INVALID_ARGUMENT,
+              GenerateKey(AuthorizationSetBuilder()
+                              .EcdsaSigningKey(224)
+                              .Authorization(TAG_EC_CURVE, EcCurve::P_256)
+                              .Digest(Digest::NONE)));
+}
+
+/*
+ * NewKeyGenerationTest.EcdsaAllValidSizes
+ *
+ * Verifies that keymaster supports all required EC key sizes.
+ */
+TEST_F(NewKeyGenerationTest, EcdsaAllValidSizes) {
+    size_t valid_sizes[] = {224, 256, 384, 521};
+    for (size_t size : valid_sizes) {
+        EXPECT_EQ(ErrorCode::OK,
+                  GenerateKey(AuthorizationSetBuilder().EcdsaSigningKey(size).Digest(Digest::NONE)))
+            << "Failed to generate size: " << size;
+        CheckCharacteristics(key_blob_, key_characteristics_);
+        CheckedDeleteKey();
+    }
+}
+
+/*
+ * NewKeyGenerationTest.EcdsaAllValidCurves
+ *
+ * Verifies that keymaster supports all required EC curves.
+ */
+TEST_F(NewKeyGenerationTest, EcdsaAllValidCurves) {
+    V4_0::EcCurve curves[] = {EcCurve::P_224, EcCurve::P_256, EcCurve::P_384, EcCurve::P_521};
+    for (V4_0::EcCurve curve : curves) {
+        EXPECT_EQ(
+            ErrorCode::OK,
+            GenerateKey(AuthorizationSetBuilder().EcdsaSigningKey(curve).Digest(Digest::SHA_2_512)))
+            << "Failed to generate key on curve: " << curve;
+        CheckCharacteristics(key_blob_, key_characteristics_);
+        CheckedDeleteKey();
+    }
+}
+
+/*
+ * NewKeyGenerationTest.Hmac
+ *
+ * Verifies that keymaster supports all required digests, and that the resulting keys have correct
+ * characteristics.
+ */
+TEST_F(NewKeyGenerationTest, Hmac) {
+    for (auto digest : {Digest::MD5, Digest::SHA1, Digest::SHA_2_224, Digest::SHA_2_256,
+                        Digest::SHA_2_384, Digest::SHA_2_512}) {
+        HidlBuf key_blob;
+        KeyCharacteristics key_characteristics;
+        constexpr size_t key_size = 128;
+        ASSERT_EQ(
+            ErrorCode::OK,
+            GenerateKey(AuthorizationSetBuilder().HmacKey(key_size).Digest(digest).Authorization(
+                            TAG_MIN_MAC_LENGTH, 128),
+                        &key_blob, &key_characteristics));
+
+        ASSERT_GT(key_blob.size(), 0U);
+        CheckBaseParams(key_characteristics);
+        CheckCharacteristics(key_blob, key_characteristics);
+
+        AuthorizationSet hardwareEnforced = key_characteristics.hardwareEnforced;
+        AuthorizationSet softwareEnforced = key_characteristics.softwareEnforced;
+        if (IsSecure()) {
+            EXPECT_TRUE(hardwareEnforced.Contains(TAG_ALGORITHM, Algorithm::HMAC));
+            EXPECT_TRUE(hardwareEnforced.Contains(TAG_KEY_SIZE, key_size))
+                << "Key size " << key_size << "missing";
+        } else {
+            EXPECT_TRUE(softwareEnforced.Contains(TAG_ALGORITHM, Algorithm::HMAC));
+            EXPECT_TRUE(softwareEnforced.Contains(TAG_KEY_SIZE, key_size))
+                << "Key size " << key_size << "missing";
+        }
+
+        CheckedDeleteKey(&key_blob);
+    }
+}
+
+/*
+ * NewKeyGenerationTest.HmacCheckKeySizes
+ *
+ * Verifies that keymaster supports all key sizes, and rejects all invalid key sizes.
+ */
+TEST_F(NewKeyGenerationTest, HmacCheckKeySizes) {
+    for (size_t key_size = 0; key_size <= 512; ++key_size) {
+        if (key_size < 64 || key_size % 8 != 0) {
+            // To keep this test from being very slow, we only test a random fraction of non-byte
+            // key sizes.  We test only ~10% of such cases. Since there are 392 of them, we expect
+            // to run ~40 of them in each run.
+            if (key_size % 8 == 0 || random() % 10 == 0) {
+                EXPECT_EQ(ErrorCode::UNSUPPORTED_KEY_SIZE,
+                          GenerateKey(AuthorizationSetBuilder()
+                                          .HmacKey(key_size)
+                                          .Digest(Digest::SHA_2_256)
+                                          .Authorization(TAG_MIN_MAC_LENGTH, 256)))
+                    << "HMAC key size " << key_size << " invalid";
+            }
+        } else {
+            EXPECT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                                     .HmacKey(key_size)
+                                                     .Digest(Digest::SHA_2_256)
+                                                     .Authorization(TAG_MIN_MAC_LENGTH, 256)))
+                << "Failed to generate HMAC key of size " << key_size;
+            CheckCharacteristics(key_blob_, key_characteristics_);
+            CheckedDeleteKey();
+        }
+    }
+}
+
+/*
+ * NewKeyGenerationTest.HmacCheckMinMacLengths
+ *
+ * Verifies that keymaster supports all required MAC lengths and rejects all invalid lengths.  This
+ * test is probabilistic in order to keep the runtime down, but any failure prints out the specific
+ * MAC length that failed, so reproducing a failed run will be easy.
+ */
+TEST_F(NewKeyGenerationTest, HmacCheckMinMacLengths) {
+    for (size_t min_mac_length = 0; min_mac_length <= 256; ++min_mac_length) {
+        if (min_mac_length < 64 || min_mac_length % 8 != 0) {
+            // To keep this test from being very long, we only test a random fraction of non-byte
+            // lengths.  We test only ~10% of such cases. Since there are 172 of them, we expect to
+            // run ~17 of them in each run.
+            if (min_mac_length % 8 == 0 || random() % 10 == 0) {
+                EXPECT_EQ(ErrorCode::UNSUPPORTED_MIN_MAC_LENGTH,
+                          GenerateKey(AuthorizationSetBuilder()
+                                          .HmacKey(128)
+                                          .Digest(Digest::SHA_2_256)
+                                          .Authorization(TAG_MIN_MAC_LENGTH, min_mac_length)))
+                    << "HMAC min mac length " << min_mac_length << " invalid.";
+            }
+        } else {
+            EXPECT_EQ(ErrorCode::OK,
+                      GenerateKey(AuthorizationSetBuilder()
+                                      .HmacKey(128)
+                                      .Digest(Digest::SHA_2_256)
+                                      .Authorization(TAG_MIN_MAC_LENGTH, min_mac_length)))
+                << "Failed to generate HMAC key with min MAC length " << min_mac_length;
+            CheckCharacteristics(key_blob_, key_characteristics_);
+            CheckedDeleteKey();
+        }
+    }
+}
+
+/*
+ * NewKeyGenerationTest.HmacMultipleDigests
+ *
+ * Verifies that keymaster rejects HMAC key generation with multiple specified digest algorithms.
+ */
+TEST_F(NewKeyGenerationTest, HmacMultipleDigests) {
+    ASSERT_EQ(ErrorCode::UNSUPPORTED_DIGEST,
+              GenerateKey(AuthorizationSetBuilder()
+                              .HmacKey(128)
+                              .Digest(Digest::SHA1)
+                              .Digest(Digest::SHA_2_256)
+                              .Authorization(TAG_MIN_MAC_LENGTH, 128)));
+}
+
+/*
+ * NewKeyGenerationTest.HmacDigestNone
+ *
+ * Verifies that keymaster rejects HMAC key generation with no digest or Digest::NONE
+ */
+TEST_F(NewKeyGenerationTest, HmacDigestNone) {
+    ASSERT_EQ(
+        ErrorCode::UNSUPPORTED_DIGEST,
+        GenerateKey(AuthorizationSetBuilder().HmacKey(128).Authorization(TAG_MIN_MAC_LENGTH, 128)));
+
+    ASSERT_EQ(ErrorCode::UNSUPPORTED_DIGEST,
+              GenerateKey(AuthorizationSetBuilder()
+                              .HmacKey(128)
+                              .Digest(Digest::NONE)
+                              .Authorization(TAG_MIN_MAC_LENGTH, 128)));
+}
+
+typedef KeymasterHidlTest SigningOperationsTest;
+
+/*
+ * SigningOperationsTest.RsaSuccess
+ *
+ * Verifies that raw RSA signature operations succeed.
+ */
+TEST_F(SigningOperationsTest, RsaSuccess) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .RsaSigningKey(1024, 3)
+                                             .Digest(Digest::NONE)
+                                             .Padding(PaddingMode::NONE)
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)));
+    string message = "12345678901234567890123456789012";
+    string signature = SignMessage(
+        message, AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::NONE));
+}
+
+/*
+ * SigningOperationsTest.RsaPssSha256Success
+ *
+ * Verifies that RSA-PSS signature operations succeed.
+ */
+TEST_F(SigningOperationsTest, RsaPssSha256Success) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .RsaSigningKey(1024, 3)
+                                             .Digest(Digest::SHA_2_256)
+                                             .Padding(PaddingMode::RSA_PSS)
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)));
+    // Use large message, which won't work without digesting.
+    string message(1024, 'a');
+    string signature = SignMessage(
+        message, AuthorizationSetBuilder().Digest(Digest::SHA_2_256).Padding(PaddingMode::RSA_PSS));
+}
+
+/*
+ * SigningOperationsTest.RsaPaddingNoneDoesNotAllowOther
+ *
+ * Verifies that keymaster rejects signature operations that specify a padding mode when the key
+ * supports only unpadded operations.
+ */
+TEST_F(SigningOperationsTest, RsaPaddingNoneDoesNotAllowOther) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .RsaSigningKey(1024, 3)
+                                             .Digest(Digest::NONE)
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .Padding(PaddingMode::NONE)));
+    string message = "12345678901234567890123456789012";
+    string signature;
+
+    EXPECT_EQ(ErrorCode::INCOMPATIBLE_PADDING_MODE,
+              Begin(KeyPurpose::SIGN, AuthorizationSetBuilder()
+                                          .Digest(Digest::NONE)
+                                          .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)));
+}
+
+/*
+ * SigningOperationsTest.RsaPkcs1Sha256Success
+ *
+ * Verifies that digested RSA-PKCS1 signature operations succeed.
+ */
+TEST_F(SigningOperationsTest, RsaPkcs1Sha256Success) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .RsaSigningKey(1024, 3)
+                                             .Digest(Digest::SHA_2_256)
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)));
+    string message(1024, 'a');
+    string signature = SignMessage(message, AuthorizationSetBuilder()
+                                                .Digest(Digest::SHA_2_256)
+                                                .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN));
+}
+
+/*
+ * SigningOperationsTest.RsaPkcs1NoDigestSuccess
+ *
+ * Verifies that undigested RSA-PKCS1 signature operations succeed.
+ */
+TEST_F(SigningOperationsTest, RsaPkcs1NoDigestSuccess) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .RsaSigningKey(1024, 3)
+                                             .Digest(Digest::NONE)
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)));
+    string message(53, 'a');
+    string signature = SignMessage(
+        message,
+        AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::RSA_PKCS1_1_5_SIGN));
+}
+
+/*
+ * SigningOperationsTest.RsaPkcs1NoDigestTooLarge
+ *
+ * Verifies that undigested RSA-PKCS1 signature operations fail with the correct error code when
+ * given a too-long message.
+ */
+TEST_F(SigningOperationsTest, RsaPkcs1NoDigestTooLong) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .RsaSigningKey(1024, 3)
+                                             .Digest(Digest::NONE)
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)));
+    string message(129, 'a');
+
+    EXPECT_EQ(ErrorCode::OK,
+              Begin(KeyPurpose::SIGN, AuthorizationSetBuilder()
+                                          .Digest(Digest::NONE)
+                                          .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)));
+    string signature;
+    EXPECT_EQ(ErrorCode::INVALID_INPUT_LENGTH, Finish(message, &signature));
+}
+
+/*
+ * SigningOperationsTest.RsaPssSha512TooSmallKey
+ *
+ * Verifies that undigested RSA-PSS signature operations fail with the correct error code when
+ * used with a key that is too small for the message.
+ *
+ * A PSS-padded message is of length salt_size + digest_size + 16 (sizes in bits), and the keymaster
+ * specification requires that salt_size == digest_size, so the message will be digest_size * 2 +
+ * 16. Such a message can only be signed by a given key if the key is at least that size. This test
+ * uses SHA512, which has a digest_size == 512, so the message size is 1040 bits, too large for a
+ * 1024-bit key.
+ */
+TEST_F(SigningOperationsTest, RsaPssSha512TooSmallKey) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .RsaSigningKey(1024, 3)
+                                             .Digest(Digest::SHA_2_512)
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .Padding(PaddingMode::RSA_PSS)));
+    EXPECT_EQ(
+        ErrorCode::INCOMPATIBLE_DIGEST,
+        Begin(KeyPurpose::SIGN,
+              AuthorizationSetBuilder().Digest(Digest::SHA_2_512).Padding(PaddingMode::RSA_PSS)));
+}
+
+/*
+ * SigningOperationsTest.RsaNoPaddingTooLong
+ *
+ * Verifies that raw RSA signature operations fail with the correct error code when
+ * given a too-long message.
+ */
+TEST_F(SigningOperationsTest, RsaNoPaddingTooLong) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .RsaSigningKey(1024, 3)
+                                             .Digest(Digest::NONE)
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)));
+    // One byte too long
+    string message(1024 / 8 + 1, 'a');
+    ASSERT_EQ(ErrorCode::OK,
+              Begin(KeyPurpose::SIGN, AuthorizationSetBuilder()
+                                          .Digest(Digest::NONE)
+                                          .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)));
+    string result;
+    ErrorCode finish_error_code = Finish(message, &result);
+    EXPECT_TRUE(finish_error_code == ErrorCode::INVALID_INPUT_LENGTH ||
+                finish_error_code == ErrorCode::INVALID_ARGUMENT);
+
+    // Very large message that should exceed the transfer buffer size of any reasonable TEE.
+    message = string(128 * 1024, 'a');
+    ASSERT_EQ(ErrorCode::OK,
+              Begin(KeyPurpose::SIGN, AuthorizationSetBuilder()
+                                          .Digest(Digest::NONE)
+                                          .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)));
+    finish_error_code = Finish(message, &result);
+    EXPECT_TRUE(finish_error_code == ErrorCode::INVALID_INPUT_LENGTH ||
+                finish_error_code == ErrorCode::INVALID_ARGUMENT);
+}
+
+/*
+ * SigningOperationsTest.RsaAbort
+ *
+ * Verifies that operations can be aborted correctly.  Uses an RSA signing operation for the test,
+ * but the behavior should be algorithm and purpose-independent.
+ */
+TEST_F(SigningOperationsTest, RsaAbort) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .RsaSigningKey(1024, 3)
+                                             .Digest(Digest::NONE)
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .Padding(PaddingMode::NONE)));
+
+    ASSERT_EQ(ErrorCode::OK,
+              Begin(KeyPurpose::SIGN,
+                    AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::NONE)));
+    EXPECT_EQ(ErrorCode::OK, Abort(op_handle_));
+
+    // Another abort should fail
+    EXPECT_EQ(ErrorCode::INVALID_OPERATION_HANDLE, Abort(op_handle_));
+
+    // Set to sentinel, so TearDown() doesn't try to abort again.
+    op_handle_ = kOpHandleSentinel;
+}
+
+/*
+ * SigningOperationsTest.RsaUnsupportedPadding
+ *
+ * Verifies that RSA operations fail with the correct error (but key gen succeeds) when used with a
+ * padding mode inappropriate for RSA.
+ */
+TEST_F(SigningOperationsTest, RsaUnsupportedPadding) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .RsaSigningKey(1024, 3)
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .Digest(Digest::SHA_2_256 /* supported digest */)
+                                             .Padding(PaddingMode::PKCS7)));
+    ASSERT_EQ(
+        ErrorCode::UNSUPPORTED_PADDING_MODE,
+        Begin(KeyPurpose::SIGN,
+              AuthorizationSetBuilder().Digest(Digest::SHA_2_256).Padding(PaddingMode::PKCS7)));
+}
+
+/*
+ * SigningOperationsTest.RsaPssNoDigest
+ *
+ * Verifies that RSA PSS operations fail when no digest is used.  PSS requires a digest.
+ */
+TEST_F(SigningOperationsTest, RsaNoDigest) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .RsaSigningKey(1024, 3)
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .Digest(Digest::NONE)
+                                             .Padding(PaddingMode::RSA_PSS)));
+    ASSERT_EQ(ErrorCode::INCOMPATIBLE_DIGEST,
+              Begin(KeyPurpose::SIGN,
+                    AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::RSA_PSS)));
+
+    ASSERT_EQ(ErrorCode::UNSUPPORTED_DIGEST,
+              Begin(KeyPurpose::SIGN, AuthorizationSetBuilder().Padding(PaddingMode::RSA_PSS)));
+}
+
+/*
+ * SigningOperationsTest.RsaPssNoDigest
+ *
+ * Verifies that RSA operations fail when no padding mode is specified.  PaddingMode::NONE is
+ * supported in some cases (as validated in other tests), but a mode must be specified.
+ */
+TEST_F(SigningOperationsTest, RsaNoPadding) {
+    // Padding must be specified
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .RsaKey(1024, 3)
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .SigningKey()
+                                             .Digest(Digest::NONE)));
+    ASSERT_EQ(ErrorCode::UNSUPPORTED_PADDING_MODE,
+              Begin(KeyPurpose::SIGN, AuthorizationSetBuilder().Digest(Digest::NONE)));
+}
+
+/*
+ * SigningOperationsTest.RsaShortMessage
+ *
+ * Verifies that raw RSA signatures succeed with a message shorter than the key size.
+ */
+TEST_F(SigningOperationsTest, RsaTooShortMessage) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .RsaSigningKey(1024, 3)
+                                             .Digest(Digest::NONE)
+                                             .Padding(PaddingMode::NONE)));
+
+    // Barely shorter
+    string message(1024 / 8 - 1, 'a');
+    SignMessage(message, AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::NONE));
+
+    // Much shorter
+    message = "a";
+    SignMessage(message, AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::NONE));
+}
+
+/*
+ * SigningOperationsTest.RsaSignWithEncryptionKey
+ *
+ * Verifies that RSA encryption keys cannot be used to sign.
+ */
+TEST_F(SigningOperationsTest, RsaSignWithEncryptionKey) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .RsaEncryptionKey(1024, 3)
+                                             .Digest(Digest::NONE)
+                                             .Padding(PaddingMode::NONE)));
+    ASSERT_EQ(ErrorCode::INCOMPATIBLE_PURPOSE,
+              Begin(KeyPurpose::SIGN,
+                    AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::NONE)));
+}
+
+/*
+ * SigningOperationsTest.RsaSignTooLargeMessage
+ *
+ * Verifies that attempting a raw signature of a message which is the same length as the key, but
+ * numerically larger than the public modulus, fails with the correct error.
+ */
+TEST_F(SigningOperationsTest, RsaSignTooLargeMessage) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .RsaSigningKey(1024, 3)
+                                             .Digest(Digest::NONE)
+                                             .Padding(PaddingMode::NONE)));
+
+    // Largest possible message will always be larger than the public modulus.
+    string message(1024 / 8, static_cast<char>(0xff));
+    ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::SIGN, AuthorizationSetBuilder()
+                                                         .Authorization(TAG_NO_AUTH_REQUIRED)
+                                                         .Digest(Digest::NONE)
+                                                         .Padding(PaddingMode::NONE)));
+    string signature;
+    ASSERT_EQ(ErrorCode::INVALID_ARGUMENT, Finish(message, &signature));
+}
+
+/*
+ * SigningOperationsTest.EcdsaAllSizesAndHashes
+ *
+ * Verifies that ECDSA operations succeed with all possible key sizes and hashes.
+ */
+TEST_F(SigningOperationsTest, EcdsaAllSizesAndHashes) {
+    for (auto key_size : {224, 256, 384, 521}) {
+        for (auto digest : {
+                 Digest::SHA1, Digest::SHA_2_224, Digest::SHA_2_256, Digest::SHA_2_384,
+                 Digest::SHA_2_512,
+             }) {
+            ErrorCode error = GenerateKey(AuthorizationSetBuilder()
+                                              .Authorization(TAG_NO_AUTH_REQUIRED)
+                                              .EcdsaSigningKey(key_size)
+                                              .Digest(digest));
+            EXPECT_EQ(ErrorCode::OK, error) << "Failed to generate ECDSA key with size " << key_size
+                                            << " and digest " << digest;
+            if (error != ErrorCode::OK) continue;
+
+            string message(1024, 'a');
+            if (digest == Digest::NONE) message.resize(key_size / 8);
+            SignMessage(message, AuthorizationSetBuilder().Digest(digest));
+            CheckedDeleteKey();
+        }
+    }
+}
+
+/*
+ * SigningOperationsTest.EcdsaAllCurves
+ *
+ * Verifies that ECDSA operations succeed with all possible curves.
+ */
+TEST_F(SigningOperationsTest, EcdsaAllCurves) {
+    for (auto curve : {EcCurve::P_224, EcCurve::P_256, EcCurve::P_384, EcCurve::P_521}) {
+        ErrorCode error = GenerateKey(AuthorizationSetBuilder()
+                                          .Authorization(TAG_NO_AUTH_REQUIRED)
+                                          .EcdsaSigningKey(curve)
+                                          .Digest(Digest::SHA_2_256));
+        EXPECT_EQ(ErrorCode::OK, error) << "Failed to generate ECDSA key with curve " << curve;
+        if (error != ErrorCode::OK) continue;
+
+        string message(1024, 'a');
+        SignMessage(message, AuthorizationSetBuilder().Digest(Digest::SHA_2_256));
+        CheckedDeleteKey();
+    }
+}
+
+/*
+ * SigningOperationsTest.EcdsaNoDigestHugeData
+ *
+ * Verifies that ECDSA operations support very large messages, even without digesting.  This should
+ * work because ECDSA actually only signs the leftmost L_n bits of the message, however large it may
+ * be.  Not using digesting is a bad idea, but in some cases digesting is done by the framework.
+ */
+TEST_F(SigningOperationsTest, EcdsaNoDigestHugeData) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .EcdsaSigningKey(224)
+                                             .Digest(Digest::NONE)));
+    string message(2 * 1024, 'a');
+    SignMessage(message, AuthorizationSetBuilder().Digest(Digest::NONE));
+}
+
+/*
+ * SigningOperationsTest.AesEcbSign
+ *
+ * Verifies that attempts to use AES keys to sign fail in the correct way.
+ */
+TEST_F(SigningOperationsTest, AesEcbSign) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .SigningKey()
+                                             .AesEncryptionKey(128)
+                                             .Authorization(TAG_BLOCK_MODE, BlockMode::ECB)));
+
+    AuthorizationSet out_params;
+    EXPECT_EQ(ErrorCode::UNSUPPORTED_PURPOSE,
+              Begin(KeyPurpose::SIGN, AuthorizationSet() /* in_params */, &out_params));
+    EXPECT_EQ(ErrorCode::UNSUPPORTED_PURPOSE,
+              Begin(KeyPurpose::VERIFY, AuthorizationSet() /* in_params */, &out_params));
+}
+
+/*
+ * SigningOperationsTest.HmacAllDigests
+ *
+ * Verifies that HMAC works with all digests.
+ */
+TEST_F(SigningOperationsTest, HmacAllDigests) {
+    for (auto digest : {Digest::SHA1, Digest::SHA_2_224, Digest::SHA_2_256, Digest::SHA_2_384,
+                        Digest::SHA_2_512}) {
+        ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                                 .Authorization(TAG_NO_AUTH_REQUIRED)
+                                                 .HmacKey(128)
+                                                 .Digest(digest)
+                                                 .Authorization(TAG_MIN_MAC_LENGTH, 160)))
+            << "Failed to create HMAC key with digest " << digest;
+        string message = "12345678901234567890123456789012";
+        string signature = MacMessage(message, digest, 160);
+        EXPECT_EQ(160U / 8U, signature.size())
+            << "Failed to sign with HMAC key with digest " << digest;
+        CheckedDeleteKey();
+    }
+}
+
+/*
+ * SigningOperationsTest.HmacSha256TooLargeMacLength
+ *
+ * Verifies that HMAC fails in the correct way when asked to generate a MAC larger than the digest
+ * size.
+ */
+TEST_F(SigningOperationsTest, HmacSha256TooLargeMacLength) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .HmacKey(128)
+                                             .Digest(Digest::SHA_2_256)
+                                             .Authorization(TAG_MIN_MAC_LENGTH, 256)));
+    AuthorizationSet output_params;
+    EXPECT_EQ(
+        ErrorCode::UNSUPPORTED_MAC_LENGTH,
+        Begin(
+            KeyPurpose::SIGN, key_blob_,
+            AuthorizationSetBuilder().Digest(Digest::SHA_2_256).Authorization(TAG_MAC_LENGTH, 264),
+            &output_params, &op_handle_));
+}
+
+/*
+ * SigningOperationsTest.HmacSha256TooSmallMacLength
+ *
+ * Verifies that HMAC fails in the correct way when asked to generate a MAC smaller than the
+ * specified minimum MAC length.
+ */
+TEST_F(SigningOperationsTest, HmacSha256TooSmallMacLength) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .HmacKey(128)
+                                             .Digest(Digest::SHA_2_256)
+                                             .Authorization(TAG_MIN_MAC_LENGTH, 128)));
+    AuthorizationSet output_params;
+    EXPECT_EQ(
+        ErrorCode::INVALID_MAC_LENGTH,
+        Begin(
+            KeyPurpose::SIGN, key_blob_,
+            AuthorizationSetBuilder().Digest(Digest::SHA_2_256).Authorization(TAG_MAC_LENGTH, 120),
+            &output_params, &op_handle_));
+}
+
+/*
+ * SigningOperationsTest.HmacRfc4231TestCase3
+ *
+ * Validates against the test vectors from RFC 4231 test case 3.
+ */
+TEST_F(SigningOperationsTest, HmacRfc4231TestCase3) {
+    string key(20, 0xaa);
+    string message(50, 0xdd);
+    uint8_t sha_224_expected[] = {
+        0x7f, 0xb3, 0xcb, 0x35, 0x88, 0xc6, 0xc1, 0xf6, 0xff, 0xa9, 0x69, 0x4d, 0x7d, 0x6a,
+        0xd2, 0x64, 0x93, 0x65, 0xb0, 0xc1, 0xf6, 0x5d, 0x69, 0xd1, 0xec, 0x83, 0x33, 0xea,
+    };
+    uint8_t sha_256_expected[] = {
+        0x77, 0x3e, 0xa9, 0x1e, 0x36, 0x80, 0x0e, 0x46, 0x85, 0x4d, 0xb8,
+        0xeb, 0xd0, 0x91, 0x81, 0xa7, 0x29, 0x59, 0x09, 0x8b, 0x3e, 0xf8,
+        0xc1, 0x22, 0xd9, 0x63, 0x55, 0x14, 0xce, 0xd5, 0x65, 0xfe,
+    };
+    uint8_t sha_384_expected[] = {
+        0x88, 0x06, 0x26, 0x08, 0xd3, 0xe6, 0xad, 0x8a, 0x0a, 0xa2, 0xac, 0xe0,
+        0x14, 0xc8, 0xa8, 0x6f, 0x0a, 0xa6, 0x35, 0xd9, 0x47, 0xac, 0x9f, 0xeb,
+        0xe8, 0x3e, 0xf4, 0xe5, 0x59, 0x66, 0x14, 0x4b, 0x2a, 0x5a, 0xb3, 0x9d,
+        0xc1, 0x38, 0x14, 0xb9, 0x4e, 0x3a, 0xb6, 0xe1, 0x01, 0xa3, 0x4f, 0x27,
+    };
+    uint8_t sha_512_expected[] = {
+        0xfa, 0x73, 0xb0, 0x08, 0x9d, 0x56, 0xa2, 0x84, 0xef, 0xb0, 0xf0, 0x75, 0x6c,
+        0x89, 0x0b, 0xe9, 0xb1, 0xb5, 0xdb, 0xdd, 0x8e, 0xe8, 0x1a, 0x36, 0x55, 0xf8,
+        0x3e, 0x33, 0xb2, 0x27, 0x9d, 0x39, 0xbf, 0x3e, 0x84, 0x82, 0x79, 0xa7, 0x22,
+        0xc8, 0x06, 0xb4, 0x85, 0xa4, 0x7e, 0x67, 0xc8, 0x07, 0xb9, 0x46, 0xa3, 0x37,
+        0xbe, 0xe8, 0x94, 0x26, 0x74, 0x27, 0x88, 0x59, 0xe1, 0x32, 0x92, 0xfb,
+    };
+
+    CheckHmacTestVector(key, message, Digest::SHA_2_224, make_string(sha_224_expected));
+    CheckHmacTestVector(key, message, Digest::SHA_2_256, make_string(sha_256_expected));
+    CheckHmacTestVector(key, message, Digest::SHA_2_384, make_string(sha_384_expected));
+    CheckHmacTestVector(key, message, Digest::SHA_2_512, make_string(sha_512_expected));
+}
+
+/*
+ * SigningOperationsTest.HmacRfc4231TestCase5
+ *
+ * Validates against the test vectors from RFC 4231 test case 5.
+ */
+TEST_F(SigningOperationsTest, HmacRfc4231TestCase5) {
+    string key(20, 0x0c);
+    string message = "Test With Truncation";
+
+    uint8_t sha_224_expected[] = {
+        0x0e, 0x2a, 0xea, 0x68, 0xa9, 0x0c, 0x8d, 0x37,
+        0xc9, 0x88, 0xbc, 0xdb, 0x9f, 0xca, 0x6f, 0xa8,
+    };
+    uint8_t sha_256_expected[] = {
+        0xa3, 0xb6, 0x16, 0x74, 0x73, 0x10, 0x0e, 0xe0,
+        0x6e, 0x0c, 0x79, 0x6c, 0x29, 0x55, 0x55, 0x2b,
+    };
+    uint8_t sha_384_expected[] = {
+        0x3a, 0xbf, 0x34, 0xc3, 0x50, 0x3b, 0x2a, 0x23,
+        0xa4, 0x6e, 0xfc, 0x61, 0x9b, 0xae, 0xf8, 0x97,
+    };
+    uint8_t sha_512_expected[] = {
+        0x41, 0x5f, 0xad, 0x62, 0x71, 0x58, 0x0a, 0x53,
+        0x1d, 0x41, 0x79, 0xbc, 0x89, 0x1d, 0x87, 0xa6,
+    };
+
+    CheckHmacTestVector(key, message, Digest::SHA_2_224, make_string(sha_224_expected));
+    CheckHmacTestVector(key, message, Digest::SHA_2_256, make_string(sha_256_expected));
+    CheckHmacTestVector(key, message, Digest::SHA_2_384, make_string(sha_384_expected));
+    CheckHmacTestVector(key, message, Digest::SHA_2_512, make_string(sha_512_expected));
+}
+
+/*
+ * SigningOperationsTest.HmacRfc4231TestCase6
+ *
+ * Validates against the test vectors from RFC 4231 test case 6.
+ */
+TEST_F(SigningOperationsTest, HmacRfc4231TestCase6) {
+    string key(131, 0xaa);
+    string message = "Test Using Larger Than Block-Size Key - Hash Key First";
+
+    uint8_t sha_224_expected[] = {
+        0x95, 0xe9, 0xa0, 0xdb, 0x96, 0x20, 0x95, 0xad, 0xae, 0xbe, 0x9b, 0x2d, 0x6f, 0x0d,
+        0xbc, 0xe2, 0xd4, 0x99, 0xf1, 0x12, 0xf2, 0xd2, 0xb7, 0x27, 0x3f, 0xa6, 0x87, 0x0e,
+    };
+    uint8_t sha_256_expected[] = {
+        0x60, 0xe4, 0x31, 0x59, 0x1e, 0xe0, 0xb6, 0x7f, 0x0d, 0x8a, 0x26,
+        0xaa, 0xcb, 0xf5, 0xb7, 0x7f, 0x8e, 0x0b, 0xc6, 0x21, 0x37, 0x28,
+        0xc5, 0x14, 0x05, 0x46, 0x04, 0x0f, 0x0e, 0xe3, 0x7f, 0x54,
+    };
+    uint8_t sha_384_expected[] = {
+        0x4e, 0xce, 0x08, 0x44, 0x85, 0x81, 0x3e, 0x90, 0x88, 0xd2, 0xc6, 0x3a,
+        0x04, 0x1b, 0xc5, 0xb4, 0x4f, 0x9e, 0xf1, 0x01, 0x2a, 0x2b, 0x58, 0x8f,
+        0x3c, 0xd1, 0x1f, 0x05, 0x03, 0x3a, 0xc4, 0xc6, 0x0c, 0x2e, 0xf6, 0xab,
+        0x40, 0x30, 0xfe, 0x82, 0x96, 0x24, 0x8d, 0xf1, 0x63, 0xf4, 0x49, 0x52,
+    };
+    uint8_t sha_512_expected[] = {
+        0x80, 0xb2, 0x42, 0x63, 0xc7, 0xc1, 0xa3, 0xeb, 0xb7, 0x14, 0x93, 0xc1, 0xdd,
+        0x7b, 0xe8, 0xb4, 0x9b, 0x46, 0xd1, 0xf4, 0x1b, 0x4a, 0xee, 0xc1, 0x12, 0x1b,
+        0x01, 0x37, 0x83, 0xf8, 0xf3, 0x52, 0x6b, 0x56, 0xd0, 0x37, 0xe0, 0x5f, 0x25,
+        0x98, 0xbd, 0x0f, 0xd2, 0x21, 0x5d, 0x6a, 0x1e, 0x52, 0x95, 0xe6, 0x4f, 0x73,
+        0xf6, 0x3f, 0x0a, 0xec, 0x8b, 0x91, 0x5a, 0x98, 0x5d, 0x78, 0x65, 0x98,
+    };
+
+    CheckHmacTestVector(key, message, Digest::SHA_2_224, make_string(sha_224_expected));
+    CheckHmacTestVector(key, message, Digest::SHA_2_256, make_string(sha_256_expected));
+    CheckHmacTestVector(key, message, Digest::SHA_2_384, make_string(sha_384_expected));
+    CheckHmacTestVector(key, message, Digest::SHA_2_512, make_string(sha_512_expected));
+}
+
+/*
+ * SigningOperationsTest.HmacRfc4231TestCase7
+ *
+ * Validates against the test vectors from RFC 4231 test case 7.
+ */
+TEST_F(SigningOperationsTest, HmacRfc4231TestCase7) {
+    string key(131, 0xaa);
+    string message =
+        "This is a test using a larger than block-size key and a larger than "
+        "block-size data. The key needs to be hashed before being used by the HMAC "
+        "algorithm.";
+
+    uint8_t sha_224_expected[] = {
+        0x3a, 0x85, 0x41, 0x66, 0xac, 0x5d, 0x9f, 0x02, 0x3f, 0x54, 0xd5, 0x17, 0xd0, 0xb3,
+        0x9d, 0xbd, 0x94, 0x67, 0x70, 0xdb, 0x9c, 0x2b, 0x95, 0xc9, 0xf6, 0xf5, 0x65, 0xd1,
+    };
+    uint8_t sha_256_expected[] = {
+        0x9b, 0x09, 0xff, 0xa7, 0x1b, 0x94, 0x2f, 0xcb, 0x27, 0x63, 0x5f,
+        0xbc, 0xd5, 0xb0, 0xe9, 0x44, 0xbf, 0xdc, 0x63, 0x64, 0x4f, 0x07,
+        0x13, 0x93, 0x8a, 0x7f, 0x51, 0x53, 0x5c, 0x3a, 0x35, 0xe2,
+    };
+    uint8_t sha_384_expected[] = {
+        0x66, 0x17, 0x17, 0x8e, 0x94, 0x1f, 0x02, 0x0d, 0x35, 0x1e, 0x2f, 0x25,
+        0x4e, 0x8f, 0xd3, 0x2c, 0x60, 0x24, 0x20, 0xfe, 0xb0, 0xb8, 0xfb, 0x9a,
+        0xdc, 0xce, 0xbb, 0x82, 0x46, 0x1e, 0x99, 0xc5, 0xa6, 0x78, 0xcc, 0x31,
+        0xe7, 0x99, 0x17, 0x6d, 0x38, 0x60, 0xe6, 0x11, 0x0c, 0x46, 0x52, 0x3e,
+    };
+    uint8_t sha_512_expected[] = {
+        0xe3, 0x7b, 0x6a, 0x77, 0x5d, 0xc8, 0x7d, 0xba, 0xa4, 0xdf, 0xa9, 0xf9, 0x6e,
+        0x5e, 0x3f, 0xfd, 0xde, 0xbd, 0x71, 0xf8, 0x86, 0x72, 0x89, 0x86, 0x5d, 0xf5,
+        0xa3, 0x2d, 0x20, 0xcd, 0xc9, 0x44, 0xb6, 0x02, 0x2c, 0xac, 0x3c, 0x49, 0x82,
+        0xb1, 0x0d, 0x5e, 0xeb, 0x55, 0xc3, 0xe4, 0xde, 0x15, 0x13, 0x46, 0x76, 0xfb,
+        0x6d, 0xe0, 0x44, 0x60, 0x65, 0xc9, 0x74, 0x40, 0xfa, 0x8c, 0x6a, 0x58,
+    };
+
+    CheckHmacTestVector(key, message, Digest::SHA_2_224, make_string(sha_224_expected));
+    CheckHmacTestVector(key, message, Digest::SHA_2_256, make_string(sha_256_expected));
+    CheckHmacTestVector(key, message, Digest::SHA_2_384, make_string(sha_384_expected));
+    CheckHmacTestVector(key, message, Digest::SHA_2_512, make_string(sha_512_expected));
+}
+
+typedef KeymasterHidlTest VerificationOperationsTest;
+
+/*
+ * VerificationOperationsTest.RsaSuccess
+ *
+ * Verifies that a simple RSA signature/verification sequence succeeds.
+ */
+TEST_F(VerificationOperationsTest, RsaSuccess) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .RsaSigningKey(1024, 3)
+                                             .Digest(Digest::NONE)
+                                             .Padding(PaddingMode::NONE)));
+    string message = "12345678901234567890123456789012";
+    string signature = SignMessage(
+        message, AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::NONE));
+    VerifyMessage(message, signature,
+                  AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::NONE));
+}
+
+/*
+ * VerificationOperationsTest.RsaSuccess
+ *
+ * Verifies RSA signature/verification for all padding modes and digests.
+ */
+TEST_F(VerificationOperationsTest, RsaAllPaddingsAndDigests) {
+    ASSERT_EQ(ErrorCode::OK,
+              GenerateKey(AuthorizationSetBuilder()
+                              .Authorization(TAG_NO_AUTH_REQUIRED)
+                              .RsaSigningKey(2048, 3)
+                              .Digest(Digest::NONE, Digest::MD5, Digest::SHA1, Digest::SHA_2_224,
+                                      Digest::SHA_2_256, Digest::SHA_2_384, Digest::SHA_2_512)
+                              .Padding(PaddingMode::NONE)
+                              .Padding(PaddingMode::RSA_PSS)
+                              .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)));
+
+    string message(128, 'a');
+    string corrupt_message(message);
+    ++corrupt_message[corrupt_message.size() / 2];
+
+    for (auto padding :
+         {PaddingMode::NONE, PaddingMode::RSA_PSS, PaddingMode::RSA_PKCS1_1_5_SIGN}) {
+        for (auto digest : {Digest::NONE, Digest::MD5, Digest::SHA1, Digest::SHA_2_224,
+                            Digest::SHA_2_256, Digest::SHA_2_384, Digest::SHA_2_512}) {
+            if (padding == PaddingMode::NONE && digest != Digest::NONE) {
+                // Digesting only makes sense with padding.
+                continue;
+            }
+
+            if (padding == PaddingMode::RSA_PSS && digest == Digest::NONE) {
+                // PSS requires digesting.
+                continue;
+            }
+
+            string signature =
+                SignMessage(message, AuthorizationSetBuilder().Digest(digest).Padding(padding));
+            VerifyMessage(message, signature,
+                          AuthorizationSetBuilder().Digest(digest).Padding(padding));
+
+            if (digest != Digest::NONE) {
+                // Verify with OpenSSL.
+                HidlBuf pubkey;
+                ASSERT_EQ(ErrorCode::OK, ExportKey(KeyFormat::X509, &pubkey));
+
+                const uint8_t* p = pubkey.data();
+                EVP_PKEY_Ptr pkey(d2i_PUBKEY(nullptr /* alloc new */, &p, pubkey.size()));
+                ASSERT_TRUE(pkey.get());
+
+                EVP_MD_CTX digest_ctx;
+                EVP_MD_CTX_init(&digest_ctx);
+                EVP_PKEY_CTX* pkey_ctx;
+                const EVP_MD* md = openssl_digest(digest);
+                ASSERT_NE(md, nullptr);
+                EXPECT_EQ(1, EVP_DigestVerifyInit(&digest_ctx, &pkey_ctx, md, nullptr /* engine */,
+                                                  pkey.get()));
+
+                switch (padding) {
+                    case PaddingMode::RSA_PSS:
+                        EXPECT_GT(EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_PSS_PADDING), 0);
+                        EXPECT_GT(EVP_PKEY_CTX_set_rsa_pss_saltlen(pkey_ctx, EVP_MD_size(md)), 0);
+                        break;
+                    case PaddingMode::RSA_PKCS1_1_5_SIGN:
+                        // PKCS1 is the default; don't need to set anything.
+                        break;
+                    default:
+                        FAIL();
+                        break;
+                }
+
+                EXPECT_EQ(1, EVP_DigestVerifyUpdate(&digest_ctx, message.data(), message.size()));
+                EXPECT_EQ(1, EVP_DigestVerifyFinal(
+                                 &digest_ctx, reinterpret_cast<const uint8_t*>(signature.data()),
+                                 signature.size()));
+                EVP_MD_CTX_cleanup(&digest_ctx);
+            }
+
+            // Corrupt signature shouldn't verify.
+            string corrupt_signature(signature);
+            ++corrupt_signature[corrupt_signature.size() / 2];
+
+            EXPECT_EQ(ErrorCode::OK,
+                      Begin(KeyPurpose::VERIFY,
+                            AuthorizationSetBuilder().Digest(digest).Padding(padding)));
+            string result;
+            EXPECT_EQ(ErrorCode::VERIFICATION_FAILED, Finish(message, corrupt_signature, &result));
+
+            // Corrupt message shouldn't verify
+            EXPECT_EQ(ErrorCode::OK,
+                      Begin(KeyPurpose::VERIFY,
+                            AuthorizationSetBuilder().Digest(digest).Padding(padding)));
+            EXPECT_EQ(ErrorCode::VERIFICATION_FAILED, Finish(corrupt_message, signature, &result));
+        }
+    }
+}
+
+/*
+ * VerificationOperationsTest.RsaSuccess
+ *
+ * Verifies ECDSA signature/verification for all digests and curves.
+ */
+TEST_F(VerificationOperationsTest, EcdsaAllDigestsAndCurves) {
+    auto digests = {
+        Digest::NONE,      Digest::SHA1,      Digest::SHA_2_224,
+        Digest::SHA_2_256, Digest::SHA_2_384, Digest::SHA_2_512,
+    };
+
+    string message = "1234567890";
+    string corrupt_message = "2234567890";
+    for (auto curve : {EcCurve::P_224, EcCurve::P_256, EcCurve::P_384, EcCurve::P_521}) {
+        ErrorCode error = GenerateKey(AuthorizationSetBuilder()
+                                          .Authorization(TAG_NO_AUTH_REQUIRED)
+                                          .EcdsaSigningKey(curve)
+                                          .Digest(digests));
+        EXPECT_EQ(ErrorCode::OK, error) << "Failed to generate key for EC curve " << curve;
+        if (error != ErrorCode::OK) {
+            continue;
+        }
+
+        for (auto digest : digests) {
+            string signature = SignMessage(message, AuthorizationSetBuilder().Digest(digest));
+            VerifyMessage(message, signature, AuthorizationSetBuilder().Digest(digest));
+
+            // Verify with OpenSSL
+            if (digest != Digest::NONE) {
+                HidlBuf pubkey;
+                ASSERT_EQ(ErrorCode::OK, ExportKey(KeyFormat::X509, &pubkey))
+                    << curve << ' ' << digest;
+
+                const uint8_t* p = pubkey.data();
+                EVP_PKEY_Ptr pkey(d2i_PUBKEY(nullptr /* alloc new */, &p, pubkey.size()));
+                ASSERT_TRUE(pkey.get());
+
+                EVP_MD_CTX digest_ctx;
+                EVP_MD_CTX_init(&digest_ctx);
+                EVP_PKEY_CTX* pkey_ctx;
+                const EVP_MD* md = openssl_digest(digest);
+
+                EXPECT_EQ(1, EVP_DigestVerifyInit(&digest_ctx, &pkey_ctx, md, nullptr /* engine */,
+                                                  pkey.get()))
+                    << curve << ' ' << digest;
+
+                EXPECT_EQ(1, EVP_DigestVerifyUpdate(&digest_ctx, message.data(), message.size()))
+                    << curve << ' ' << digest;
+
+                EXPECT_EQ(1, EVP_DigestVerifyFinal(
+                                 &digest_ctx, reinterpret_cast<const uint8_t*>(signature.data()),
+                                 signature.size()))
+                    << curve << ' ' << digest;
+
+                EVP_MD_CTX_cleanup(&digest_ctx);
+            }
+
+            // Corrupt signature shouldn't verify.
+            string corrupt_signature(signature);
+            ++corrupt_signature[corrupt_signature.size() / 2];
+
+            EXPECT_EQ(ErrorCode::OK,
+                      Begin(KeyPurpose::VERIFY, AuthorizationSetBuilder().Digest(digest)))
+                << curve << ' ' << digest;
+
+            string result;
+            EXPECT_EQ(ErrorCode::VERIFICATION_FAILED, Finish(message, corrupt_signature, &result))
+                << curve << ' ' << digest;
+
+            // Corrupt message shouldn't verify
+            EXPECT_EQ(ErrorCode::OK,
+                      Begin(KeyPurpose::VERIFY, AuthorizationSetBuilder().Digest(digest)))
+                << curve << ' ' << digest;
+
+            EXPECT_EQ(ErrorCode::VERIFICATION_FAILED, Finish(corrupt_message, signature, &result))
+                << curve << ' ' << digest;
+        }
+
+        auto rc = DeleteKey();
+        ASSERT_TRUE(rc == ErrorCode::OK || rc == ErrorCode::UNIMPLEMENTED);
+    }
+}
+
+/*
+ * VerificationOperationsTest.HmacSigningKeyCannotVerify
+ *
+ * Verifies HMAC signing and verification, but that a signing key cannot be used to verify.
+ */
+TEST_F(VerificationOperationsTest, HmacSigningKeyCannotVerify) {
+    string key_material = "HelloThisIsAKey";
+
+    HidlBuf signing_key, verification_key;
+    KeyCharacteristics signing_key_chars, verification_key_chars;
+    EXPECT_EQ(ErrorCode::OK,
+              ImportKey(AuthorizationSetBuilder()
+                            .Authorization(TAG_NO_AUTH_REQUIRED)
+                            .Authorization(TAG_ALGORITHM, Algorithm::HMAC)
+                            .Authorization(TAG_PURPOSE, KeyPurpose::SIGN)
+                            .Digest(Digest::SHA1)
+                            .Authorization(TAG_MIN_MAC_LENGTH, 160),
+                        KeyFormat::RAW, key_material, &signing_key, &signing_key_chars));
+    EXPECT_EQ(ErrorCode::OK,
+              ImportKey(AuthorizationSetBuilder()
+                            .Authorization(TAG_NO_AUTH_REQUIRED)
+                            .Authorization(TAG_ALGORITHM, Algorithm::HMAC)
+                            .Authorization(TAG_PURPOSE, KeyPurpose::VERIFY)
+                            .Digest(Digest::SHA1)
+                            .Authorization(TAG_MIN_MAC_LENGTH, 160),
+                        KeyFormat::RAW, key_material, &verification_key, &verification_key_chars));
+
+    string message = "This is a message.";
+    string signature = SignMessage(
+        signing_key, message,
+        AuthorizationSetBuilder().Digest(Digest::SHA1).Authorization(TAG_MAC_LENGTH, 160));
+
+    // Signing key should not work.
+    AuthorizationSet out_params;
+    EXPECT_EQ(ErrorCode::INCOMPATIBLE_PURPOSE,
+              Begin(KeyPurpose::VERIFY, signing_key, AuthorizationSetBuilder().Digest(Digest::SHA1),
+                    &out_params, &op_handle_));
+
+    // Verification key should work.
+    VerifyMessage(verification_key, message, signature,
+                  AuthorizationSetBuilder().Digest(Digest::SHA1));
+
+    CheckedDeleteKey(&signing_key);
+    CheckedDeleteKey(&verification_key);
+}
+
+typedef KeymasterHidlTest ExportKeyTest;
+
+/*
+ * ExportKeyTest.RsaUnsupportedKeyFormat
+ *
+ * Verifies that attempting to export RSA keys in PKCS#8 format fails with the correct error.
+ */
+TEST_F(ExportKeyTest, RsaUnsupportedKeyFormat) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .RsaSigningKey(1024, 3)
+                                             .Digest(Digest::NONE)
+                                             .Padding(PaddingMode::NONE)));
+    HidlBuf export_data;
+    ASSERT_EQ(ErrorCode::UNSUPPORTED_KEY_FORMAT, ExportKey(KeyFormat::PKCS8, &export_data));
+}
+
+/*
+ * ExportKeyTest.RsaCorruptedKeyBlob
+ *
+ * Verifies that attempting to export RSA keys from corrupted key blobs fails.  This is essentially
+ * a poor-man's key blob fuzzer.
+ */
+TEST_F(ExportKeyTest, RsaCorruptedKeyBlob) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .RsaSigningKey(1024, 3)
+                                             .Digest(Digest::NONE)
+                                             .Padding(PaddingMode::NONE)));
+    for (size_t i = 0; i < key_blob_.size(); ++i) {
+        HidlBuf corrupted(key_blob_);
+        ++corrupted[i];
+
+        HidlBuf export_data;
+        EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB,
+                  ExportKey(KeyFormat::X509, corrupted, HidlBuf(), HidlBuf(), &export_data))
+            << "Blob corrupted at offset " << i << " erroneously accepted as valid";
+    }
+}
+
+/*
+ * ExportKeyTest.RsaCorruptedKeyBlob
+ *
+ * Verifies that attempting to export ECDSA keys from corrupted key blobs fails.  This is
+ * essentially a poor-man's key blob fuzzer.
+ */
+TEST_F(ExportKeyTest, EcCorruptedKeyBlob) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .EcdsaSigningKey(EcCurve::P_256)
+                                             .Digest(Digest::NONE)));
+    for (size_t i = 0; i < key_blob_.size(); ++i) {
+        HidlBuf corrupted(key_blob_);
+        ++corrupted[i];
+
+        HidlBuf export_data;
+        EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB,
+                  ExportKey(KeyFormat::X509, corrupted, HidlBuf(), HidlBuf(), &export_data))
+            << "Blob corrupted at offset " << i << " erroneously accepted as valid";
+    }
+}
+
+/*
+ * ExportKeyTest.AesKeyUnexportable
+ *
+ * Verifies that attempting to export AES keys fails in the expected way.
+ */
+TEST_F(ExportKeyTest, AesKeyUnexportable) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .AesEncryptionKey(128)
+                                             .EcbMode()
+                                             .Padding(PaddingMode::NONE)));
+
+    HidlBuf export_data;
+    EXPECT_EQ(ErrorCode::UNSUPPORTED_KEY_FORMAT, ExportKey(KeyFormat::X509, &export_data));
+    EXPECT_EQ(ErrorCode::UNSUPPORTED_KEY_FORMAT, ExportKey(KeyFormat::PKCS8, &export_data));
+    EXPECT_EQ(ErrorCode::UNSUPPORTED_KEY_FORMAT, ExportKey(KeyFormat::RAW, &export_data));
+}
+
+class ImportKeyTest : public KeymasterHidlTest {
+   public:
+    template <TagType tag_type, Tag tag, typename ValueT>
+    void CheckCryptoParam(TypedTag<tag_type, tag> ttag, ValueT expected) {
+        SCOPED_TRACE("CheckCryptoParam");
+        if (IsSecure()) {
+            EXPECT_TRUE(contains(key_characteristics_.hardwareEnforced, ttag, expected))
+                << "Tag " << tag << " with value " << expected << " not found";
+            EXPECT_FALSE(contains(key_characteristics_.softwareEnforced, ttag))
+                << "Tag " << tag << " found";
+        } else {
+            EXPECT_TRUE(contains(key_characteristics_.softwareEnforced, ttag, expected))
+                << "Tag " << tag << " with value " << expected << " not found";
+            EXPECT_FALSE(contains(key_characteristics_.hardwareEnforced, ttag))
+                << "Tag " << tag << " found";
+        }
+    }
+
+    void CheckOrigin() {
+        SCOPED_TRACE("CheckOrigin");
+        if (IsSecure()) {
+            EXPECT_TRUE(
+                contains(key_characteristics_.hardwareEnforced, TAG_ORIGIN, KeyOrigin::IMPORTED));
+        } else {
+            EXPECT_TRUE(
+                contains(key_characteristics_.softwareEnforced, TAG_ORIGIN, KeyOrigin::IMPORTED));
+        }
+    }
+};
+
+/*
+ * ImportKeyTest.RsaSuccess
+ *
+ * Verifies that importing and using an RSA key pair works correctly.
+ */
+TEST_F(ImportKeyTest, RsaSuccess) {
+    ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
+                                           .Authorization(TAG_NO_AUTH_REQUIRED)
+                                           .RsaSigningKey(1024, 65537)
+                                           .Digest(Digest::SHA_2_256)
+                                           .Padding(PaddingMode::RSA_PSS),
+                                       KeyFormat::PKCS8, rsa_key));
+
+    CheckCryptoParam(TAG_ALGORITHM, Algorithm::RSA);
+    CheckCryptoParam(TAG_KEY_SIZE, 1024U);
+    CheckCryptoParam(TAG_RSA_PUBLIC_EXPONENT, 65537U);
+    CheckCryptoParam(TAG_DIGEST, Digest::SHA_2_256);
+    CheckCryptoParam(TAG_PADDING, PaddingMode::RSA_PSS);
+    CheckOrigin();
+
+    string message(1024 / 8, 'a');
+    auto params = AuthorizationSetBuilder().Digest(Digest::SHA_2_256).Padding(PaddingMode::RSA_PSS);
+    string signature = SignMessage(message, params);
+    VerifyMessage(message, signature, params);
+}
+
+/*
+ * ImportKeyTest.RsaKeySizeMismatch
+ *
+ * Verifies that importing an RSA key pair with a size that doesn't match the key fails in the
+ * correct way.
+ */
+TEST_F(ImportKeyTest, RsaKeySizeMismatch) {
+    ASSERT_EQ(ErrorCode::IMPORT_PARAMETER_MISMATCH,
+              ImportKey(AuthorizationSetBuilder()
+                            .RsaSigningKey(2048 /* Doesn't match key */, 65537)
+                            .Digest(Digest::NONE)
+                            .Padding(PaddingMode::NONE),
+                        KeyFormat::PKCS8, rsa_key));
+}
+
+/*
+ * ImportKeyTest.RsaPublicExponentMismatch
+ *
+ * Verifies that importing an RSA key pair with a public exponent that doesn't match the key fails
+ * in the correct way.
+ */
+TEST_F(ImportKeyTest, RsaPublicExponentMismatch) {
+    ASSERT_EQ(ErrorCode::IMPORT_PARAMETER_MISMATCH,
+              ImportKey(AuthorizationSetBuilder()
+                            .RsaSigningKey(1024, 3 /* Doesn't match key */)
+                            .Digest(Digest::NONE)
+                            .Padding(PaddingMode::NONE),
+                        KeyFormat::PKCS8, rsa_key));
+}
+
+/*
+ * ImportKeyTest.EcdsaSuccess
+ *
+ * Verifies that importing and using an ECDSA P-256 key pair works correctly.
+ */
+TEST_F(ImportKeyTest, EcdsaSuccess) {
+    ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
+                                           .Authorization(TAG_NO_AUTH_REQUIRED)
+                                           .EcdsaSigningKey(256)
+                                           .Digest(Digest::SHA_2_256),
+                                       KeyFormat::PKCS8, ec_256_key));
+
+    CheckCryptoParam(TAG_ALGORITHM, Algorithm::EC);
+    CheckCryptoParam(TAG_KEY_SIZE, 256U);
+    CheckCryptoParam(TAG_DIGEST, Digest::SHA_2_256);
+    CheckCryptoParam(TAG_EC_CURVE, EcCurve::P_256);
+
+    CheckOrigin();
+
+    string message(32, 'a');
+    auto params = AuthorizationSetBuilder().Digest(Digest::SHA_2_256);
+    string signature = SignMessage(message, params);
+    VerifyMessage(message, signature, params);
+}
+
+/*
+ * ImportKeyTest.Ecdsa521Success
+ *
+ * Verifies that importing and using an ECDSA P-521 key pair works correctly.
+ */
+TEST_F(ImportKeyTest, Ecdsa521Success) {
+    ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
+                                           .Authorization(TAG_NO_AUTH_REQUIRED)
+                                           .EcdsaSigningKey(521)
+                                           .Digest(Digest::SHA_2_256),
+                                       KeyFormat::PKCS8, ec_521_key));
+
+    CheckCryptoParam(TAG_ALGORITHM, Algorithm::EC);
+    CheckCryptoParam(TAG_KEY_SIZE, 521U);
+    CheckCryptoParam(TAG_DIGEST, Digest::SHA_2_256);
+    CheckCryptoParam(TAG_EC_CURVE, EcCurve::P_521);
+    CheckOrigin();
+
+    string message(32, 'a');
+    auto params = AuthorizationSetBuilder().Digest(Digest::SHA_2_256);
+    string signature = SignMessage(message, params);
+    VerifyMessage(message, signature, params);
+}
+
+/*
+ * ImportKeyTest.EcdsaSizeMismatch
+ *
+ * Verifies that importing an ECDSA key pair with a size that doesn't match the key fails in the
+ * correct way.
+ */
+TEST_F(ImportKeyTest, EcdsaSizeMismatch) {
+    ASSERT_EQ(ErrorCode::IMPORT_PARAMETER_MISMATCH,
+              ImportKey(AuthorizationSetBuilder()
+                            .EcdsaSigningKey(224 /* Doesn't match key */)
+                            .Digest(Digest::NONE),
+                        KeyFormat::PKCS8, ec_256_key));
+}
+
+/*
+ * ImportKeyTest.EcdsaCurveMismatch
+ *
+ * Verifies that importing an ECDSA key pair with a curve that doesn't match the key fails in the
+ * correct way.
+ */
+TEST_F(ImportKeyTest, EcdsaCurveMismatch) {
+    ASSERT_EQ(ErrorCode::IMPORT_PARAMETER_MISMATCH,
+              ImportKey(AuthorizationSetBuilder()
+                            .EcdsaSigningKey(EcCurve::P_224 /* Doesn't match key */)
+                            .Digest(Digest::NONE),
+                        KeyFormat::PKCS8, ec_256_key));
+}
+
+/*
+ * ImportKeyTest.AesSuccess
+ *
+ * Verifies that importing and using an AES key works.
+ */
+TEST_F(ImportKeyTest, AesSuccess) {
+    string key = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+    ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
+                                           .Authorization(TAG_NO_AUTH_REQUIRED)
+                                           .AesEncryptionKey(key.size() * 8)
+                                           .EcbMode()
+                                           .Padding(PaddingMode::PKCS7),
+                                       KeyFormat::RAW, key));
+
+    CheckCryptoParam(TAG_ALGORITHM, Algorithm::AES);
+    CheckCryptoParam(TAG_KEY_SIZE, 128U);
+    CheckCryptoParam(TAG_PADDING, PaddingMode::PKCS7);
+    CheckCryptoParam(TAG_BLOCK_MODE, BlockMode::ECB);
+    CheckOrigin();
+
+    string message = "Hello World!";
+    auto params = AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::PKCS7);
+    string ciphertext = EncryptMessage(message, params);
+    string plaintext = DecryptMessage(ciphertext, params);
+    EXPECT_EQ(message, plaintext);
+}
+
+/*
+ * ImportKeyTest.AesSuccess
+ *
+ * Verifies that importing and using an HMAC key works.
+ */
+TEST_F(ImportKeyTest, HmacKeySuccess) {
+    string key = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+    ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
+                                           .Authorization(TAG_NO_AUTH_REQUIRED)
+                                           .HmacKey(key.size() * 8)
+                                           .Digest(Digest::SHA_2_256)
+                                           .Authorization(TAG_MIN_MAC_LENGTH, 256),
+                                       KeyFormat::RAW, key));
+
+    CheckCryptoParam(TAG_ALGORITHM, Algorithm::HMAC);
+    CheckCryptoParam(TAG_KEY_SIZE, 128U);
+    CheckCryptoParam(TAG_DIGEST, Digest::SHA_2_256);
+    CheckOrigin();
+
+    string message = "Hello World!";
+    string signature = MacMessage(message, Digest::SHA_2_256, 256);
+    VerifyMessage(message, signature, AuthorizationSetBuilder().Digest(Digest::SHA_2_256));
+}
+
+typedef KeymasterHidlTest EncryptionOperationsTest;
+
+/*
+ * EncryptionOperationsTest.RsaNoPaddingSuccess
+ *
+ * Verifies that raw RSA encryption works.
+ */
+TEST_F(EncryptionOperationsTest, RsaNoPaddingSuccess) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .RsaEncryptionKey(1024, 3)
+                                             .Padding(PaddingMode::NONE)));
+
+    string message = string(1024 / 8, 'a');
+    auto params = AuthorizationSetBuilder().Padding(PaddingMode::NONE);
+    string ciphertext1 = EncryptMessage(message, params);
+    EXPECT_EQ(1024U / 8, ciphertext1.size());
+
+    string ciphertext2 = EncryptMessage(message, params);
+    EXPECT_EQ(1024U / 8, ciphertext2.size());
+
+    // Unpadded RSA is deterministic
+    EXPECT_EQ(ciphertext1, ciphertext2);
+}
+
+/*
+ * EncryptionOperationsTest.RsaNoPaddingShortMessage
+ *
+ * Verifies that raw RSA encryption of short messages works.
+ */
+TEST_F(EncryptionOperationsTest, RsaNoPaddingShortMessage) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .RsaEncryptionKey(1024, 3)
+                                             .Padding(PaddingMode::NONE)));
+
+    string message = "1";
+    auto params = AuthorizationSetBuilder().Padding(PaddingMode::NONE);
+
+    string ciphertext = EncryptMessage(message, params);
+    EXPECT_EQ(1024U / 8, ciphertext.size());
+
+    string expected_plaintext = string(1024 / 8 - 1, 0) + message;
+    string plaintext = DecryptMessage(ciphertext, params);
+
+    EXPECT_EQ(expected_plaintext, plaintext);
+
+    // Degenerate case, encrypting a numeric 1 yields 0x00..01 as the ciphertext.
+    message = static_cast<char>(1);
+    ciphertext = EncryptMessage(message, params);
+    EXPECT_EQ(1024U / 8, ciphertext.size());
+    EXPECT_EQ(ciphertext, string(1024 / 8 - 1, 0) + message);
+}
+
+/*
+ * EncryptionOperationsTest.RsaNoPaddingTooLong
+ *
+ * Verifies that raw RSA encryption of too-long messages fails in the expected way.
+ */
+TEST_F(EncryptionOperationsTest, RsaNoPaddingTooLong) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .RsaEncryptionKey(1024, 3)
+                                             .Padding(PaddingMode::NONE)));
+
+    string message(1024 / 8 + 1, 'a');
+
+    auto params = AuthorizationSetBuilder().Padding(PaddingMode::NONE);
+    EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params));
+
+    string result;
+    EXPECT_EQ(ErrorCode::INVALID_INPUT_LENGTH, Finish(message, &result));
+}
+
+/*
+ * EncryptionOperationsTest.RsaNoPaddingTooLarge
+ *
+ * Verifies that raw RSA encryption of too-large (numerically) messages fails in the expected way.
+ */
+TEST_F(EncryptionOperationsTest, RsaNoPaddingTooLarge) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .RsaEncryptionKey(1024, 3)
+                                             .Padding(PaddingMode::NONE)));
+
+    HidlBuf exported;
+    ASSERT_EQ(ErrorCode::OK, ExportKey(KeyFormat::X509, &exported));
+
+    const uint8_t* p = exported.data();
+    EVP_PKEY_Ptr pkey(d2i_PUBKEY(nullptr /* alloc new */, &p, exported.size()));
+    RSA_Ptr rsa(EVP_PKEY_get1_RSA(pkey.get()));
+
+    size_t modulus_len = BN_num_bytes(rsa->n);
+    ASSERT_EQ(1024U / 8, modulus_len);
+    std::unique_ptr<uint8_t[]> modulus_buf(new uint8_t[modulus_len]);
+    BN_bn2bin(rsa->n, modulus_buf.get());
+
+    // The modulus is too big to encrypt.
+    string message(reinterpret_cast<const char*>(modulus_buf.get()), modulus_len);
+
+    auto params = AuthorizationSetBuilder().Padding(PaddingMode::NONE);
+    EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params));
+
+    string result;
+    EXPECT_EQ(ErrorCode::INVALID_ARGUMENT, Finish(message, &result));
+
+    // One smaller than the modulus is okay.
+    BN_sub(rsa->n, rsa->n, BN_value_one());
+    modulus_len = BN_num_bytes(rsa->n);
+    ASSERT_EQ(1024U / 8, modulus_len);
+    BN_bn2bin(rsa->n, modulus_buf.get());
+    message = string(reinterpret_cast<const char*>(modulus_buf.get()), modulus_len);
+    EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params));
+    EXPECT_EQ(ErrorCode::OK, Finish(message, &result));
+}
+
+/*
+ * EncryptionOperationsTest.RsaOaepSuccess
+ *
+ * Verifies that RSA-OAEP encryption operations work, with all digests.
+ */
+TEST_F(EncryptionOperationsTest, RsaOaepSuccess) {
+    auto digests = {Digest::MD5,       Digest::SHA1,      Digest::SHA_2_224,
+                    Digest::SHA_2_256, Digest::SHA_2_384, Digest::SHA_2_512};
+
+    size_t key_size = 2048;  // Need largish key for SHA-512 test.
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .RsaEncryptionKey(key_size, 3)
+                                             .Padding(PaddingMode::RSA_OAEP)
+                                             .Digest(digests)));
+
+    string message = "Hello";
+
+    for (auto digest : digests) {
+        auto params = AuthorizationSetBuilder().Digest(digest).Padding(PaddingMode::RSA_OAEP);
+        string ciphertext1 = EncryptMessage(message, params);
+        if (HasNonfatalFailure()) std::cout << "-->" << digest << std::endl;
+        EXPECT_EQ(key_size / 8, ciphertext1.size());
+
+        string ciphertext2 = EncryptMessage(message, params);
+        EXPECT_EQ(key_size / 8, ciphertext2.size());
+
+        // OAEP randomizes padding so every result should be different (with astronomically high
+        // probability).
+        EXPECT_NE(ciphertext1, ciphertext2);
+
+        string plaintext1 = DecryptMessage(ciphertext1, params);
+        EXPECT_EQ(message, plaintext1) << "RSA-OAEP failed with digest " << digest;
+        string plaintext2 = DecryptMessage(ciphertext2, params);
+        EXPECT_EQ(message, plaintext2) << "RSA-OAEP failed with digest " << digest;
+
+        // Decrypting corrupted ciphertext should fail.
+        size_t offset_to_corrupt = random() % ciphertext1.size();
+        char corrupt_byte;
+        do {
+            corrupt_byte = static_cast<char>(random() % 256);
+        } while (corrupt_byte == ciphertext1[offset_to_corrupt]);
+        ciphertext1[offset_to_corrupt] = corrupt_byte;
+
+        EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, params));
+        string result;
+        EXPECT_EQ(ErrorCode::UNKNOWN_ERROR, Finish(ciphertext1, &result));
+        EXPECT_EQ(0U, result.size());
+    }
+}
+
+/*
+ * EncryptionOperationsTest.RsaOaepInvalidDigest
+ *
+ * Verifies that RSA-OAEP encryption operations fail in the correct way when asked to operate
+ * without a digest.
+ */
+TEST_F(EncryptionOperationsTest, RsaOaepInvalidDigest) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .RsaEncryptionKey(1024, 3)
+                                             .Padding(PaddingMode::RSA_OAEP)
+                                             .Digest(Digest::NONE)));
+    string message = "Hello World!";
+
+    auto params = AuthorizationSetBuilder().Padding(PaddingMode::RSA_OAEP).Digest(Digest::NONE);
+    EXPECT_EQ(ErrorCode::INCOMPATIBLE_DIGEST, Begin(KeyPurpose::ENCRYPT, params));
+}
+
+/*
+ * EncryptionOperationsTest.RsaOaepInvalidDigest
+ *
+ * Verifies that RSA-OAEP encryption operations fail in the correct way when asked to decrypt with a
+ * different digest than was used to encrypt.
+ */
+TEST_F(EncryptionOperationsTest, RsaOaepDecryptWithWrongDigest) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .RsaEncryptionKey(1024, 3)
+                                             .Padding(PaddingMode::RSA_OAEP)
+                                             .Digest(Digest::SHA_2_256, Digest::SHA_2_224)));
+    string message = "Hello World!";
+    string ciphertext = EncryptMessage(
+        message,
+        AuthorizationSetBuilder().Digest(Digest::SHA_2_224).Padding(PaddingMode::RSA_OAEP));
+
+    EXPECT_EQ(
+        ErrorCode::OK,
+        Begin(KeyPurpose::DECRYPT,
+              AuthorizationSetBuilder().Digest(Digest::SHA_2_256).Padding(PaddingMode::RSA_OAEP)));
+    string result;
+    EXPECT_EQ(ErrorCode::UNKNOWN_ERROR, Finish(ciphertext, &result));
+    EXPECT_EQ(0U, result.size());
+}
+
+/*
+ * EncryptionOperationsTest.RsaOaepTooLarge
+ *
+ * Verifies that RSA-OAEP encryption operations fail in the correct way when asked to encrypt a
+ * too-large message.
+ */
+TEST_F(EncryptionOperationsTest, RsaOaepTooLarge) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .RsaEncryptionKey(1024, 3)
+                                             .Padding(PaddingMode::RSA_OAEP)
+                                             .Digest(Digest::SHA1)));
+    constexpr size_t digest_size = 160 /* SHA1 */ / 8;
+    constexpr size_t oaep_overhead = 2 * digest_size + 2;
+    string message(1024 / 8 - oaep_overhead + 1, 'a');
+    EXPECT_EQ(ErrorCode::OK,
+              Begin(KeyPurpose::ENCRYPT,
+                    AuthorizationSetBuilder().Padding(PaddingMode::RSA_OAEP).Digest(Digest::SHA1)));
+    string result;
+    EXPECT_EQ(ErrorCode::INVALID_ARGUMENT, Finish(message, &result));
+    EXPECT_EQ(0U, result.size());
+}
+
+/*
+ * EncryptionOperationsTest.RsaPkcs1Success
+ *
+ * Verifies that RSA PKCS encryption/decrypts works.
+ */
+TEST_F(EncryptionOperationsTest, RsaPkcs1Success) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .RsaEncryptionKey(1024, 3)
+                                             .Padding(PaddingMode::RSA_PKCS1_1_5_ENCRYPT)));
+
+    string message = "Hello World!";
+    auto params = AuthorizationSetBuilder().Padding(PaddingMode::RSA_PKCS1_1_5_ENCRYPT);
+    string ciphertext1 = EncryptMessage(message, params);
+    EXPECT_EQ(1024U / 8, ciphertext1.size());
+
+    string ciphertext2 = EncryptMessage(message, params);
+    EXPECT_EQ(1024U / 8, ciphertext2.size());
+
+    // PKCS1 v1.5 randomizes padding so every result should be different.
+    EXPECT_NE(ciphertext1, ciphertext2);
+
+    string plaintext = DecryptMessage(ciphertext1, params);
+    EXPECT_EQ(message, plaintext);
+
+    // Decrypting corrupted ciphertext should fail.
+    size_t offset_to_corrupt = random() % ciphertext1.size();
+    char corrupt_byte;
+    do {
+        corrupt_byte = static_cast<char>(random() % 256);
+    } while (corrupt_byte == ciphertext1[offset_to_corrupt]);
+    ciphertext1[offset_to_corrupt] = corrupt_byte;
+
+    EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, params));
+    string result;
+    EXPECT_EQ(ErrorCode::UNKNOWN_ERROR, Finish(ciphertext1, &result));
+    EXPECT_EQ(0U, result.size());
+}
+
+/*
+ * EncryptionOperationsTest.RsaPkcs1TooLarge
+ *
+ * Verifies that RSA PKCS encryption fails in the correct way when the mssage is too large.
+ */
+TEST_F(EncryptionOperationsTest, RsaPkcs1TooLarge) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .RsaEncryptionKey(1024, 3)
+                                             .Padding(PaddingMode::RSA_PKCS1_1_5_ENCRYPT)));
+    string message(1024 / 8 - 10, 'a');
+
+    auto params = AuthorizationSetBuilder().Padding(PaddingMode::RSA_PKCS1_1_5_ENCRYPT);
+    EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params));
+    string result;
+    EXPECT_EQ(ErrorCode::INVALID_ARGUMENT, Finish(message, &result));
+    EXPECT_EQ(0U, result.size());
+}
+
+/*
+ * EncryptionOperationsTest.EcdsaEncrypt
+ *
+ * Verifies that attempting to use ECDSA keys to encrypt fails in the correct way.
+ */
+TEST_F(EncryptionOperationsTest, EcdsaEncrypt) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .EcdsaSigningKey(224)
+                                             .Digest(Digest::NONE)));
+    auto params = AuthorizationSetBuilder().Digest(Digest::NONE);
+    ASSERT_EQ(ErrorCode::UNSUPPORTED_PURPOSE, Begin(KeyPurpose::ENCRYPT, params));
+    ASSERT_EQ(ErrorCode::UNSUPPORTED_PURPOSE, Begin(KeyPurpose::DECRYPT, params));
+}
+
+/*
+ * EncryptionOperationsTest.HmacEncrypt
+ *
+ * Verifies that attempting to use HMAC keys to encrypt fails in the correct way.
+ */
+TEST_F(EncryptionOperationsTest, HmacEncrypt) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .HmacKey(128)
+                                             .Digest(Digest::SHA_2_256)
+                                             .Padding(PaddingMode::NONE)
+                                             .Authorization(TAG_MIN_MAC_LENGTH, 128)));
+    auto params = AuthorizationSetBuilder()
+                      .Digest(Digest::SHA_2_256)
+                      .Padding(PaddingMode::NONE)
+                      .Authorization(TAG_MAC_LENGTH, 128);
+    ASSERT_EQ(ErrorCode::UNSUPPORTED_PURPOSE, Begin(KeyPurpose::ENCRYPT, params));
+    ASSERT_EQ(ErrorCode::UNSUPPORTED_PURPOSE, Begin(KeyPurpose::DECRYPT, params));
+}
+
+/*
+ * EncryptionOperationsTest.AesEcbRoundTripSuccess
+ *
+ * Verifies that AES ECB mode works.
+ */
+TEST_F(EncryptionOperationsTest, AesEcbRoundTripSuccess) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .AesEncryptionKey(128)
+                                             .Authorization(TAG_BLOCK_MODE, BlockMode::ECB)
+                                             .Padding(PaddingMode::NONE)));
+
+    auto params = AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::NONE);
+
+    // Two-block message.
+    string message = "12345678901234567890123456789012";
+    string ciphertext1 = EncryptMessage(message, params);
+    EXPECT_EQ(message.size(), ciphertext1.size());
+
+    string ciphertext2 = EncryptMessage(string(message), params);
+    EXPECT_EQ(message.size(), ciphertext2.size());
+
+    // ECB is deterministic.
+    EXPECT_EQ(ciphertext1, ciphertext2);
+
+    string plaintext = DecryptMessage(ciphertext1, params);
+    EXPECT_EQ(message, plaintext);
+}
+
+/*
+ * EncryptionOperationsTest.AesEcbRoundTripSuccess
+ *
+ * Verifies that AES encryption fails in the correct way when an unauthorized mode is specified.
+ */
+TEST_F(EncryptionOperationsTest, AesWrongMode) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .AesEncryptionKey(128)
+                                             .Authorization(TAG_BLOCK_MODE, BlockMode::CBC)
+                                             .Padding(PaddingMode::NONE)));
+    // Two-block message.
+    string message = "12345678901234567890123456789012";
+    EXPECT_EQ(
+        ErrorCode::INCOMPATIBLE_BLOCK_MODE,
+        Begin(KeyPurpose::ENCRYPT,
+              AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::NONE)));
+}
+
+/*
+ * EncryptionOperationsTest.AesEcbNoPaddingWrongInputSize
+ *
+ * Verifies that AES encryption fails in the correct way when provided an input that is not a
+ * multiple of the block size and no padding is specified.
+ */
+TEST_F(EncryptionOperationsTest, AesEcbNoPaddingWrongInputSize) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .AesEncryptionKey(128)
+                                             .Authorization(TAG_BLOCK_MODE, BlockMode::ECB)
+                                             .Padding(PaddingMode::NONE)));
+    // Message is slightly shorter than two blocks.
+    string message(16 * 2 - 1, 'a');
+
+    auto params = AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::NONE);
+    EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params));
+    string ciphertext;
+    EXPECT_EQ(ErrorCode::INVALID_INPUT_LENGTH, Finish(message, &ciphertext));
+    EXPECT_EQ(0U, ciphertext.size());
+}
+
+/*
+ * EncryptionOperationsTest.AesEcbPkcs7Padding
+ *
+ * Verifies that AES PKCS7 padding works for any message length.
+ */
+TEST_F(EncryptionOperationsTest, AesEcbPkcs7Padding) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .AesEncryptionKey(128)
+                                             .Authorization(TAG_BLOCK_MODE, BlockMode::ECB)
+                                             .Padding(PaddingMode::PKCS7)));
+
+    auto params = AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::PKCS7);
+
+    // Try various message lengths; all should work.
+    for (size_t i = 0; i < 32; ++i) {
+        string message(i, 'a');
+        string ciphertext = EncryptMessage(message, params);
+        EXPECT_EQ(i + 16 - (i % 16), ciphertext.size());
+        string plaintext = DecryptMessage(ciphertext, params);
+        EXPECT_EQ(message, plaintext);
+    }
+}
+
+/*
+ * EncryptionOperationsTest.AesEcbWrongPadding
+ *
+ * Verifies that AES enryption fails in the correct way when an unauthorized padding mode is
+ * specified.
+ */
+TEST_F(EncryptionOperationsTest, AesEcbWrongPadding) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .AesEncryptionKey(128)
+                                             .Authorization(TAG_BLOCK_MODE, BlockMode::ECB)
+                                             .Padding(PaddingMode::NONE)));
+
+    auto params = AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::PKCS7);
+
+    // Try various message lengths; all should fail
+    for (size_t i = 0; i < 32; ++i) {
+        string message(i, 'a');
+        EXPECT_EQ(ErrorCode::INCOMPATIBLE_PADDING_MODE, Begin(KeyPurpose::ENCRYPT, params));
+    }
+}
+
+/*
+ * EncryptionOperationsTest.AesEcbPkcs7PaddingCorrupted
+ *
+ * Verifies that AES decryption fails in the correct way when the padding is corrupted.
+ */
+TEST_F(EncryptionOperationsTest, AesEcbPkcs7PaddingCorrupted) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .AesEncryptionKey(128)
+                                             .Authorization(TAG_BLOCK_MODE, BlockMode::ECB)
+                                             .Padding(PaddingMode::PKCS7)));
+
+    auto params = AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::PKCS7);
+
+    string message = "a";
+    string ciphertext = EncryptMessage(message, params);
+    EXPECT_EQ(16U, ciphertext.size());
+    EXPECT_NE(ciphertext, message);
+    ++ciphertext[ciphertext.size() / 2];
+
+    EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, params));
+    string plaintext;
+    EXPECT_EQ(ErrorCode::INVALID_INPUT_LENGTH, Finish(message, &plaintext));
+}
+
+HidlBuf CopyIv(const AuthorizationSet& set) {
+    auto iv = set.GetTagValue(TAG_NONCE);
+    EXPECT_TRUE(iv.isOk());
+    return iv.value();
+}
+
+/*
+ * EncryptionOperationsTest.AesCtrRoundTripSuccess
+ *
+ * Verifies that AES CTR mode works.
+ */
+TEST_F(EncryptionOperationsTest, AesCtrRoundTripSuccess) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .AesEncryptionKey(128)
+                                             .Authorization(TAG_BLOCK_MODE, BlockMode::CTR)
+                                             .Padding(PaddingMode::NONE)));
+
+    auto params = AuthorizationSetBuilder().BlockMode(BlockMode::CTR).Padding(PaddingMode::NONE);
+
+    string message = "123";
+    AuthorizationSet out_params;
+    string ciphertext1 = EncryptMessage(message, params, &out_params);
+    HidlBuf iv1 = CopyIv(out_params);
+    EXPECT_EQ(16U, iv1.size());
+
+    EXPECT_EQ(message.size(), ciphertext1.size());
+
+    out_params.Clear();
+    string ciphertext2 = EncryptMessage(message, params, &out_params);
+    HidlBuf iv2 = CopyIv(out_params);
+    EXPECT_EQ(16U, iv2.size());
+
+    // IVs should be random, so ciphertexts should differ.
+    EXPECT_NE(ciphertext1, ciphertext2);
+
+    auto params_iv1 =
+        AuthorizationSetBuilder().Authorizations(params).Authorization(TAG_NONCE, iv1);
+    auto params_iv2 =
+        AuthorizationSetBuilder().Authorizations(params).Authorization(TAG_NONCE, iv2);
+
+    string plaintext = DecryptMessage(ciphertext1, params_iv1);
+    EXPECT_EQ(message, plaintext);
+    plaintext = DecryptMessage(ciphertext2, params_iv2);
+    EXPECT_EQ(message, plaintext);
+
+    // Using the wrong IV will result in a "valid" decryption, but the data will be garbage.
+    plaintext = DecryptMessage(ciphertext1, params_iv2);
+    EXPECT_NE(message, plaintext);
+    plaintext = DecryptMessage(ciphertext2, params_iv1);
+    EXPECT_NE(message, plaintext);
+}
+
+/*
+ * EncryptionOperationsTest.AesIncremental
+ *
+ * Verifies that AES works, all modes, when provided data in various size increments.
+ */
+TEST_F(EncryptionOperationsTest, AesIncremental) {
+    auto block_modes = {
+        BlockMode::ECB, BlockMode::CBC, BlockMode::CTR, BlockMode::GCM,
+    };
+
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .AesEncryptionKey(128)
+                                             .BlockMode(block_modes)
+                                             .Padding(PaddingMode::NONE)
+                                             .Authorization(TAG_MIN_MAC_LENGTH, 128)));
+
+    for (int increment = 1; increment <= 240; ++increment) {
+        for (auto block_mode : block_modes) {
+            string message(240, 'a');
+            auto params = AuthorizationSetBuilder()
+                              .BlockMode(block_mode)
+                              .Padding(PaddingMode::NONE)
+                              .Authorization(TAG_MAC_LENGTH, 128) /* for GCM */;
+
+            AuthorizationSet output_params;
+            EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params, &output_params));
+
+            string ciphertext;
+            size_t input_consumed;
+            string to_send;
+            for (size_t i = 0; i < message.size(); i += increment) {
+                to_send.append(message.substr(i, increment));
+                EXPECT_EQ(ErrorCode::OK, Update(to_send, &ciphertext, &input_consumed));
+                to_send = to_send.substr(input_consumed);
+
+                switch (block_mode) {
+                    case BlockMode::ECB:
+                    case BlockMode::CBC:
+                        // Implementations must take as many blocks as possible, leaving less than
+                        // a block.
+                        EXPECT_LE(to_send.length(), 16U);
+                        break;
+                    case BlockMode::GCM:
+                    case BlockMode::CTR:
+                        // Implementations must always take all the data.
+                        EXPECT_EQ(0U, to_send.length());
+                        break;
+                }
+            }
+            EXPECT_EQ(ErrorCode::OK, Finish(to_send, &ciphertext)) << "Error sending " << to_send;
+
+            switch (block_mode) {
+                case BlockMode::GCM:
+                    EXPECT_EQ(message.size() + 16, ciphertext.size());
+                    break;
+                case BlockMode::CTR:
+                    EXPECT_EQ(message.size(), ciphertext.size());
+                    break;
+                case BlockMode::CBC:
+                case BlockMode::ECB:
+                    EXPECT_EQ(message.size() + message.size() % 16, ciphertext.size());
+                    break;
+            }
+
+            auto iv = output_params.GetTagValue(TAG_NONCE);
+            switch (block_mode) {
+                case BlockMode::CBC:
+                case BlockMode::GCM:
+                case BlockMode::CTR:
+                    ASSERT_TRUE(iv.isOk()) << "No IV for block mode " << block_mode;
+                    EXPECT_EQ(block_mode == BlockMode::GCM ? 12U : 16U, iv.value().size());
+                    params.push_back(TAG_NONCE, iv.value());
+                    break;
+
+                case BlockMode::ECB:
+                    EXPECT_FALSE(iv.isOk()) << "ECB mode should not generate IV";
+                    break;
+            }
+
+            EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, params))
+                << "Decrypt begin() failed for block mode " << block_mode;
+
+            string plaintext;
+            for (size_t i = 0; i < ciphertext.size(); i += increment) {
+                to_send.append(ciphertext.substr(i, increment));
+                EXPECT_EQ(ErrorCode::OK, Update(to_send, &plaintext, &input_consumed));
+                to_send = to_send.substr(input_consumed);
+            }
+            ErrorCode error = Finish(to_send, &plaintext);
+            ASSERT_EQ(ErrorCode::OK, error) << "Decryption failed for block mode " << block_mode
+                                            << " and increment " << increment;
+            if (error == ErrorCode::OK) {
+                ASSERT_EQ(message, plaintext) << "Decryption didn't match for block mode "
+                                              << block_mode << " and increment " << increment;
+            }
+        }
+    }
+}
+
+struct AesCtrSp80038aTestVector {
+    const char* key;
+    const char* nonce;
+    const char* plaintext;
+    const char* ciphertext;
+};
+
+// These test vectors are taken from
+// http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf, section F.5.
+static const AesCtrSp80038aTestVector kAesCtrSp80038aTestVectors[] = {
+    // AES-128
+    {
+        "2b7e151628aed2a6abf7158809cf4f3c", "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
+        "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51"
+        "30c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710",
+        "874d6191b620e3261bef6864990db6ce9806f66b7970fdff8617187bb9fffdff"
+        "5ae4df3edbd5d35e5b4f09020db03eab1e031dda2fbe03d1792170a0f3009cee",
+    },
+    // AES-192
+    {
+        "8e73b0f7da0e6452c810f32b809079e562f8ead2522c6b7b", "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
+        "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51"
+        "30c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710",
+        "1abc932417521ca24f2b0459fe7e6e0b090339ec0aa6faefd5ccc2c6f4ce8e94"
+        "1e36b26bd1ebc670d1bd1d665620abf74f78a7f6d29809585a97daec58c6b050",
+    },
+    // AES-256
+    {
+        "603deb1015ca71be2b73aef0857d77811f352c073b6108d72d9810a30914dff4",
+        "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
+        "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51"
+        "30c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710",
+        "601ec313775789a5b7a7f504bbf3d228f443e3ca4d62b59aca84e990cacaf5c5"
+        "2b0930daa23de94ce87017ba2d84988ddfc9c58db67aada613c2dd08457941a6",
+    },
+};
+
+/*
+ * EncryptionOperationsTest.AesCtrSp80038aTestVector
+ *
+ * Verifies AES CTR implementation against SP800-38A test vectors.
+ */
+TEST_F(EncryptionOperationsTest, AesCtrSp80038aTestVector) {
+    for (size_t i = 0; i < 3; i++) {
+        const AesCtrSp80038aTestVector& test(kAesCtrSp80038aTestVectors[i]);
+        const string key = hex2str(test.key);
+        const string nonce = hex2str(test.nonce);
+        const string plaintext = hex2str(test.plaintext);
+        const string ciphertext = hex2str(test.ciphertext);
+        CheckAesCtrTestVector(key, nonce, plaintext, ciphertext);
+    }
+}
+
+/*
+ * EncryptionOperationsTest.AesCtrIncompatiblePaddingMode
+ *
+ * Verifies that keymaster rejects use of CTR mode with PKCS7 padding in the correct way.
+ */
+TEST_F(EncryptionOperationsTest, AesCtrIncompatiblePaddingMode) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .AesEncryptionKey(128)
+                                             .Authorization(TAG_BLOCK_MODE, BlockMode::CTR)
+                                             .Padding(PaddingMode::PKCS7)));
+    auto params = AuthorizationSetBuilder().BlockMode(BlockMode::CTR).Padding(PaddingMode::NONE);
+    EXPECT_EQ(ErrorCode::INCOMPATIBLE_PADDING_MODE, Begin(KeyPurpose::ENCRYPT, params));
+}
+
+/*
+ * EncryptionOperationsTest.AesCtrInvalidCallerNonce
+ *
+ * Verifies that keymaster fails correctly when the user supplies an incorrect-size nonce.
+ */
+TEST_F(EncryptionOperationsTest, AesCtrInvalidCallerNonce) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .AesEncryptionKey(128)
+                                             .Authorization(TAG_BLOCK_MODE, BlockMode::CTR)
+                                             .Authorization(TAG_CALLER_NONCE)
+                                             .Padding(PaddingMode::NONE)));
+
+    auto params = AuthorizationSetBuilder()
+                      .BlockMode(BlockMode::CTR)
+                      .Padding(PaddingMode::NONE)
+                      .Authorization(TAG_NONCE, HidlBuf(string(1, 'a')));
+    EXPECT_EQ(ErrorCode::INVALID_NONCE, Begin(KeyPurpose::ENCRYPT, params));
+
+    params = AuthorizationSetBuilder()
+                 .BlockMode(BlockMode::CTR)
+                 .Padding(PaddingMode::NONE)
+                 .Authorization(TAG_NONCE, HidlBuf(string(15, 'a')));
+    EXPECT_EQ(ErrorCode::INVALID_NONCE, Begin(KeyPurpose::ENCRYPT, params));
+
+    params = AuthorizationSetBuilder()
+                 .BlockMode(BlockMode::CTR)
+                 .Padding(PaddingMode::NONE)
+                 .Authorization(TAG_NONCE, HidlBuf(string(17, 'a')));
+    EXPECT_EQ(ErrorCode::INVALID_NONCE, Begin(KeyPurpose::ENCRYPT, params));
+}
+
+/*
+ * EncryptionOperationsTest.AesCtrInvalidCallerNonce
+ *
+ * Verifies that keymaster fails correctly when the user supplies an incorrect-size nonce.
+ */
+TEST_F(EncryptionOperationsTest, AesCbcRoundTripSuccess) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .AesEncryptionKey(128)
+                                             .Authorization(TAG_BLOCK_MODE, BlockMode::CBC)
+                                             .Padding(PaddingMode::NONE)));
+    // Two-block message.
+    string message = "12345678901234567890123456789012";
+    auto params = AuthorizationSetBuilder().BlockMode(BlockMode::CBC).Padding(PaddingMode::NONE);
+    AuthorizationSet out_params;
+    string ciphertext1 = EncryptMessage(message, params, &out_params);
+    HidlBuf iv1 = CopyIv(out_params);
+    EXPECT_EQ(message.size(), ciphertext1.size());
+
+    out_params.Clear();
+
+    string ciphertext2 = EncryptMessage(message, params, &out_params);
+    HidlBuf iv2 = CopyIv(out_params);
+    EXPECT_EQ(message.size(), ciphertext2.size());
+
+    // IVs should be random, so ciphertexts should differ.
+    EXPECT_NE(ciphertext1, ciphertext2);
+
+    params.push_back(TAG_NONCE, iv1);
+    string plaintext = DecryptMessage(ciphertext1, params);
+    EXPECT_EQ(message, plaintext);
+}
+
+/*
+ * EncryptionOperationsTest.AesCallerNonce
+ *
+ * Verifies that AES caller-provided nonces work correctly.
+ */
+TEST_F(EncryptionOperationsTest, AesCallerNonce) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .AesEncryptionKey(128)
+                                             .Authorization(TAG_BLOCK_MODE, BlockMode::CBC)
+                                             .Authorization(TAG_CALLER_NONCE)
+                                             .Padding(PaddingMode::NONE)));
+
+    string message = "12345678901234567890123456789012";
+
+    // Don't specify nonce, should get a random one.
+    AuthorizationSetBuilder params =
+        AuthorizationSetBuilder().BlockMode(BlockMode::CBC).Padding(PaddingMode::NONE);
+    AuthorizationSet out_params;
+    string ciphertext = EncryptMessage(message, params, &out_params);
+    EXPECT_EQ(message.size(), ciphertext.size());
+    EXPECT_EQ(16U, out_params.GetTagValue(TAG_NONCE).value().size());
+
+    params.push_back(TAG_NONCE, out_params.GetTagValue(TAG_NONCE).value());
+    string plaintext = DecryptMessage(ciphertext, params);
+    EXPECT_EQ(message, plaintext);
+
+    // Now specify a nonce, should also work.
+    params = AuthorizationSetBuilder()
+                 .BlockMode(BlockMode::CBC)
+                 .Padding(PaddingMode::NONE)
+                 .Authorization(TAG_NONCE, HidlBuf("abcdefghijklmnop"));
+    out_params.Clear();
+    ciphertext = EncryptMessage(message, params, &out_params);
+
+    // Decrypt with correct nonce.
+    plaintext = DecryptMessage(ciphertext, params);
+    EXPECT_EQ(message, plaintext);
+
+    // Try with wrong nonce.
+    params = AuthorizationSetBuilder()
+                 .BlockMode(BlockMode::CBC)
+                 .Padding(PaddingMode::NONE)
+                 .Authorization(TAG_NONCE, HidlBuf("aaaaaaaaaaaaaaaa"));
+    plaintext = DecryptMessage(ciphertext, params);
+    EXPECT_NE(message, plaintext);
+}
+
+/*
+ * EncryptionOperationsTest.AesCallerNonceProhibited
+ *
+ * Verifies that caller-provided nonces are not permitted when not specified in the key
+ * authorizations.
+ */
+TEST_F(EncryptionOperationsTest, AesCallerNonceProhibited) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .AesEncryptionKey(128)
+                                             .Authorization(TAG_BLOCK_MODE, BlockMode::CBC)
+                                             .Padding(PaddingMode::NONE)));
+
+    string message = "12345678901234567890123456789012";
+
+    // Don't specify nonce, should get a random one.
+    AuthorizationSetBuilder params =
+        AuthorizationSetBuilder().BlockMode(BlockMode::CBC).Padding(PaddingMode::NONE);
+    AuthorizationSet out_params;
+    string ciphertext = EncryptMessage(message, params, &out_params);
+    EXPECT_EQ(message.size(), ciphertext.size());
+    EXPECT_EQ(16U, out_params.GetTagValue(TAG_NONCE).value().size());
+
+    params.push_back(TAG_NONCE, out_params.GetTagValue(TAG_NONCE).value());
+    string plaintext = DecryptMessage(ciphertext, params);
+    EXPECT_EQ(message, plaintext);
+
+    // Now specify a nonce, should fail
+    params = AuthorizationSetBuilder()
+                 .BlockMode(BlockMode::CBC)
+                 .Padding(PaddingMode::NONE)
+                 .Authorization(TAG_NONCE, HidlBuf("abcdefghijklmnop"));
+    out_params.Clear();
+    EXPECT_EQ(ErrorCode::CALLER_NONCE_PROHIBITED, Begin(KeyPurpose::ENCRYPT, params, &out_params));
+}
+
+/*
+ * EncryptionOperationsTest.AesGcmRoundTripSuccess
+ *
+ * Verifies that AES GCM mode works.
+ */
+TEST_F(EncryptionOperationsTest, AesGcmRoundTripSuccess) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .AesEncryptionKey(128)
+                                             .Authorization(TAG_BLOCK_MODE, BlockMode::GCM)
+                                             .Padding(PaddingMode::NONE)
+                                             .Authorization(TAG_MIN_MAC_LENGTH, 128)));
+
+    string aad = "foobar";
+    string message = "123456789012345678901234567890123456";
+
+    auto begin_params = AuthorizationSetBuilder()
+                            .BlockMode(BlockMode::GCM)
+                            .Padding(PaddingMode::NONE)
+                            .Authorization(TAG_MAC_LENGTH, 128);
+
+    auto update_params =
+        AuthorizationSetBuilder().Authorization(TAG_ASSOCIATED_DATA, aad.data(), aad.size());
+
+    // Encrypt
+    AuthorizationSet begin_out_params;
+    ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, begin_params, &begin_out_params))
+        << "Begin encrypt";
+    string ciphertext;
+    AuthorizationSet update_out_params;
+    ASSERT_EQ(ErrorCode::OK,
+              Finish(op_handle_, update_params, message, "", &update_out_params, &ciphertext));
+
+    // Grab nonce
+    begin_params.push_back(begin_out_params);
+
+    // Decrypt.
+    ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, begin_params)) << "Begin decrypt";
+    string plaintext;
+    size_t input_consumed;
+    ASSERT_EQ(ErrorCode::OK, Update(op_handle_, update_params, ciphertext, &update_out_params,
+                                    &plaintext, &input_consumed));
+    EXPECT_EQ(ciphertext.size(), input_consumed);
+    EXPECT_EQ(ErrorCode::OK, Finish("", &plaintext));
+
+    EXPECT_EQ(message, plaintext);
+}
+
+/*
+ * EncryptionOperationsTest.AesGcmTooShortTag
+ *
+ * Verifies that AES GCM mode fails correctly when a too-short tag length is specified.
+ */
+TEST_F(EncryptionOperationsTest, AesGcmTooShortTag) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .AesEncryptionKey(128)
+                                             .BlockMode(BlockMode::GCM)
+                                             .Padding(PaddingMode::NONE)
+                                             .Authorization(TAG_MIN_MAC_LENGTH, 128)));
+    string message = "123456789012345678901234567890123456";
+    auto params = AuthorizationSetBuilder()
+                      .BlockMode(BlockMode::GCM)
+                      .Padding(PaddingMode::NONE)
+                      .Authorization(TAG_MAC_LENGTH, 96);
+
+    EXPECT_EQ(ErrorCode::INVALID_MAC_LENGTH, Begin(KeyPurpose::ENCRYPT, params));
+}
+
+/*
+ * EncryptionOperationsTest.AesGcmTooShortTagOnDecrypt
+ *
+ * Verifies that AES GCM mode fails correctly when a too-short tag is provided to decryption.
+ */
+TEST_F(EncryptionOperationsTest, AesGcmTooShortTagOnDecrypt) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .AesEncryptionKey(128)
+                                             .BlockMode(BlockMode::GCM)
+                                             .Padding(PaddingMode::NONE)
+                                             .Authorization(TAG_MIN_MAC_LENGTH, 128)));
+    string aad = "foobar";
+    string message = "123456789012345678901234567890123456";
+    auto params = AuthorizationSetBuilder()
+                      .BlockMode(BlockMode::GCM)
+                      .Padding(PaddingMode::NONE)
+                      .Authorization(TAG_MAC_LENGTH, 128);
+
+    auto finish_params =
+        AuthorizationSetBuilder().Authorization(TAG_ASSOCIATED_DATA, aad.data(), aad.size());
+
+    // Encrypt
+    AuthorizationSet begin_out_params;
+    EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params, &begin_out_params));
+    EXPECT_EQ(1U, begin_out_params.size());
+    ASSERT_TRUE(begin_out_params.GetTagValue(TAG_NONCE).isOk());
+
+    AuthorizationSet finish_out_params;
+    string ciphertext;
+    EXPECT_EQ(ErrorCode::OK, Finish(op_handle_, finish_params, message, "" /* signature */,
+                                    &finish_out_params, &ciphertext));
+
+    params = AuthorizationSetBuilder()
+                 .Authorizations(begin_out_params)
+                 .BlockMode(BlockMode::GCM)
+                 .Padding(PaddingMode::NONE)
+                 .Authorization(TAG_MAC_LENGTH, 96);
+
+    // Decrypt.
+    EXPECT_EQ(ErrorCode::INVALID_MAC_LENGTH, Begin(KeyPurpose::DECRYPT, params));
+}
+
+/*
+ * EncryptionOperationsTest.AesGcmCorruptKey
+ *
+ * Verifies that AES GCM mode fails correctly when the decryption key is incorrect.
+ */
+TEST_F(EncryptionOperationsTest, AesGcmCorruptKey) {
+    const uint8_t nonce_bytes[] = {
+        0xb7, 0x94, 0x37, 0xae, 0x08, 0xff, 0x35, 0x5d, 0x7d, 0x8a, 0x4d, 0x0f,
+    };
+    string nonce = make_string(nonce_bytes);
+    const uint8_t ciphertext_bytes[] = {
+        0xb3, 0xf6, 0x79, 0x9e, 0x8f, 0x93, 0x26, 0xf2, 0xdf, 0x1e, 0x80, 0xfc, 0xd2, 0xcb, 0x16,
+        0xd7, 0x8c, 0x9d, 0xc7, 0xcc, 0x14, 0xbb, 0x67, 0x78, 0x62, 0xdc, 0x6c, 0x63, 0x9b, 0x3a,
+        0x63, 0x38, 0xd2, 0x4b, 0x31, 0x2d, 0x39, 0x89, 0xe5, 0x92, 0x0b, 0x5d, 0xbf, 0xc9, 0x76,
+        0x76, 0x5e, 0xfb, 0xfe, 0x57, 0xbb, 0x38, 0x59, 0x40, 0xa7, 0xa4, 0x3b, 0xdf, 0x05, 0xbd,
+        0xda, 0xe3, 0xc9, 0xd6, 0xa2, 0xfb, 0xbd, 0xfc, 0xc0, 0xcb, 0xa0,
+    };
+    string ciphertext = make_string(ciphertext_bytes);
+
+    auto params = AuthorizationSetBuilder()
+                      .BlockMode(BlockMode::GCM)
+                      .Padding(PaddingMode::NONE)
+                      .Authorization(TAG_MAC_LENGTH, 128)
+                      .Authorization(TAG_NONCE, nonce.data(), nonce.size());
+
+    auto import_params = AuthorizationSetBuilder()
+                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                             .AesEncryptionKey(128)
+                             .BlockMode(BlockMode::GCM)
+                             .Padding(PaddingMode::NONE)
+                             .Authorization(TAG_CALLER_NONCE)
+                             .Authorization(TAG_MIN_MAC_LENGTH, 128);
+
+    // Import correct key and decrypt
+    const uint8_t key_bytes[] = {
+        0xba, 0x76, 0x35, 0x4f, 0x0a, 0xed, 0x6e, 0x8d,
+        0x91, 0xf4, 0x5c, 0x4f, 0xf5, 0xa0, 0x62, 0xdb,
+    };
+    string key = make_string(key_bytes);
+    ASSERT_EQ(ErrorCode::OK, ImportKey(import_params, KeyFormat::RAW, key));
+    string plaintext = DecryptMessage(ciphertext, params);
+    CheckedDeleteKey();
+
+    // Corrupt key and attempt to decrypt
+    key[0] = 0;
+    ASSERT_EQ(ErrorCode::OK, ImportKey(import_params, KeyFormat::RAW, key));
+    EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, params));
+    EXPECT_EQ(ErrorCode::VERIFICATION_FAILED, Finish(ciphertext, &plaintext));
+    CheckedDeleteKey();
+}
+
+/*
+ * EncryptionOperationsTest.AesGcmAadNoData
+ *
+ * Verifies that AES GCM mode works when provided additional authenticated data, but no data to
+ * encrypt.
+ */
+TEST_F(EncryptionOperationsTest, AesGcmAadNoData) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .AesEncryptionKey(128)
+                                             .BlockMode(BlockMode::GCM)
+                                             .Padding(PaddingMode::NONE)
+                                             .Authorization(TAG_MIN_MAC_LENGTH, 128)));
+
+    string aad = "1234567890123456";
+    auto params = AuthorizationSetBuilder()
+                      .BlockMode(BlockMode::GCM)
+                      .Padding(PaddingMode::NONE)
+                      .Authorization(TAG_MAC_LENGTH, 128);
+
+    auto finish_params =
+        AuthorizationSetBuilder().Authorization(TAG_ASSOCIATED_DATA, aad.data(), aad.size());
+
+    // Encrypt
+    AuthorizationSet begin_out_params;
+    EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params, &begin_out_params));
+    string ciphertext;
+    AuthorizationSet finish_out_params;
+    EXPECT_EQ(ErrorCode::OK, Finish(op_handle_, finish_params, "" /* input */, "" /* signature */,
+                                    &finish_out_params, &ciphertext));
+    EXPECT_TRUE(finish_out_params.empty());
+
+    // Grab nonce
+    params.push_back(begin_out_params);
+
+    // Decrypt.
+    EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, params));
+    string plaintext;
+    EXPECT_EQ(ErrorCode::OK, Finish(op_handle_, finish_params, ciphertext, "" /* signature */,
+                                    &finish_out_params, &plaintext));
+
+    EXPECT_TRUE(finish_out_params.empty());
+
+    EXPECT_EQ("", plaintext);
+}
+
+/*
+ * EncryptionOperationsTest.AesGcmMultiPartAad
+ *
+ * Verifies that AES GCM mode works when provided additional authenticated data in multiple chunks.
+ */
+TEST_F(EncryptionOperationsTest, AesGcmMultiPartAad) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .AesEncryptionKey(128)
+                                             .BlockMode(BlockMode::GCM)
+                                             .Padding(PaddingMode::NONE)
+                                             .Authorization(TAG_MIN_MAC_LENGTH, 128)));
+
+    string message = "123456789012345678901234567890123456";
+    auto begin_params = AuthorizationSetBuilder()
+                            .BlockMode(BlockMode::GCM)
+                            .Padding(PaddingMode::NONE)
+                            .Authorization(TAG_MAC_LENGTH, 128);
+    AuthorizationSet begin_out_params;
+
+    auto update_params =
+        AuthorizationSetBuilder().Authorization(TAG_ASSOCIATED_DATA, "foo", (size_t)3);
+
+    EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, begin_params, &begin_out_params));
+
+    // No data, AAD only.
+    string ciphertext;
+    size_t input_consumed;
+    AuthorizationSet update_out_params;
+    EXPECT_EQ(ErrorCode::OK, Update(op_handle_, update_params, "" /* input */, &update_out_params,
+                                    &ciphertext, &input_consumed));
+    EXPECT_EQ(0U, input_consumed);
+    EXPECT_EQ(0U, ciphertext.size());
+    EXPECT_TRUE(update_out_params.empty());
+
+    // AAD and data.
+    EXPECT_EQ(ErrorCode::OK, Update(op_handle_, update_params, message, &update_out_params,
+                                    &ciphertext, &input_consumed));
+    EXPECT_EQ(message.size(), input_consumed);
+    EXPECT_EQ(message.size(), ciphertext.size());
+    EXPECT_TRUE(update_out_params.empty());
+
+    EXPECT_EQ(ErrorCode::OK, Finish("" /* input */, &ciphertext));
+
+    // Grab nonce.
+    begin_params.push_back(begin_out_params);
+
+    // Decrypt
+    update_params =
+        AuthorizationSetBuilder().Authorization(TAG_ASSOCIATED_DATA, "foofoo", (size_t)6);
+
+    EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, begin_params));
+    string plaintext;
+    EXPECT_EQ(ErrorCode::OK, Finish(op_handle_, update_params, ciphertext, "" /* signature */,
+                                    &update_out_params, &plaintext));
+    EXPECT_TRUE(update_out_params.empty());
+    EXPECT_EQ(message, plaintext);
+}
+
+/*
+ * EncryptionOperationsTest.AesGcmAadOutOfOrder
+ *
+ * Verifies that AES GCM mode fails correctly when given AAD after data to encipher.
+ */
+TEST_F(EncryptionOperationsTest, AesGcmAadOutOfOrder) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .AesEncryptionKey(128)
+                                             .BlockMode(BlockMode::GCM)
+                                             .Padding(PaddingMode::NONE)
+                                             .Authorization(TAG_MIN_MAC_LENGTH, 128)));
+
+    string message = "123456789012345678901234567890123456";
+    auto begin_params = AuthorizationSetBuilder()
+                            .BlockMode(BlockMode::GCM)
+                            .Padding(PaddingMode::NONE)
+                            .Authorization(TAG_MAC_LENGTH, 128);
+    AuthorizationSet begin_out_params;
+
+    auto update_params =
+        AuthorizationSetBuilder().Authorization(TAG_ASSOCIATED_DATA, "foo", (size_t)3);
+
+    EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, begin_params, &begin_out_params));
+
+    // No data, AAD only.
+    string ciphertext;
+    size_t input_consumed;
+    AuthorizationSet update_out_params;
+    EXPECT_EQ(ErrorCode::OK, Update(op_handle_, update_params, "" /* input */, &update_out_params,
+                                    &ciphertext, &input_consumed));
+    EXPECT_EQ(0U, input_consumed);
+    EXPECT_EQ(0U, ciphertext.size());
+    EXPECT_TRUE(update_out_params.empty());
+
+    // AAD and data.
+    EXPECT_EQ(ErrorCode::OK, Update(op_handle_, update_params, message, &update_out_params,
+                                    &ciphertext, &input_consumed));
+    EXPECT_EQ(message.size(), input_consumed);
+    EXPECT_EQ(message.size(), ciphertext.size());
+    EXPECT_TRUE(update_out_params.empty());
+
+    // More AAD
+    EXPECT_EQ(ErrorCode::INVALID_TAG, Update(op_handle_, update_params, "", &update_out_params,
+                                             &ciphertext, &input_consumed));
+
+    op_handle_ = kOpHandleSentinel;
+}
+
+/*
+ * EncryptionOperationsTest.AesGcmBadAad
+ *
+ * Verifies that AES GCM decryption fails correctly when additional authenticated date is wrong.
+ */
+TEST_F(EncryptionOperationsTest, AesGcmBadAad) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .AesEncryptionKey(128)
+                                             .BlockMode(BlockMode::GCM)
+                                             .Padding(PaddingMode::NONE)
+                                             .Authorization(TAG_MIN_MAC_LENGTH, 128)));
+
+    string message = "12345678901234567890123456789012";
+    auto begin_params = AuthorizationSetBuilder()
+                            .BlockMode(BlockMode::GCM)
+                            .Padding(PaddingMode::NONE)
+                            .Authorization(TAG_MAC_LENGTH, 128);
+
+    auto finish_params =
+        AuthorizationSetBuilder().Authorization(TAG_ASSOCIATED_DATA, "foobar", (size_t)6);
+
+    // Encrypt
+    AuthorizationSet begin_out_params;
+    EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, begin_params, &begin_out_params));
+    string ciphertext;
+    AuthorizationSet finish_out_params;
+    EXPECT_EQ(ErrorCode::OK, Finish(op_handle_, finish_params, message, "" /* signature */,
+                                    &finish_out_params, &ciphertext));
+
+    // Grab nonce
+    begin_params.push_back(begin_out_params);
+
+    finish_params = AuthorizationSetBuilder().Authorization(TAG_ASSOCIATED_DATA,
+                                                            "barfoo" /* Wrong AAD */, (size_t)6);
+
+    // Decrypt.
+    EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, begin_params, &begin_out_params));
+    string plaintext;
+    EXPECT_EQ(ErrorCode::VERIFICATION_FAILED,
+              Finish(op_handle_, finish_params, ciphertext, "" /* signature */, &finish_out_params,
+                     &plaintext));
+}
+
+/*
+ * EncryptionOperationsTest.AesGcmWrongNonce
+ *
+ * Verifies that AES GCM decryption fails correctly when the nonce is incorrect.
+ */
+TEST_F(EncryptionOperationsTest, AesGcmWrongNonce) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .AesEncryptionKey(128)
+                                             .BlockMode(BlockMode::GCM)
+                                             .Padding(PaddingMode::NONE)
+                                             .Authorization(TAG_MIN_MAC_LENGTH, 128)));
+
+    string message = "12345678901234567890123456789012";
+    auto begin_params = AuthorizationSetBuilder()
+                            .BlockMode(BlockMode::GCM)
+                            .Padding(PaddingMode::NONE)
+                            .Authorization(TAG_MAC_LENGTH, 128);
+
+    auto finish_params =
+        AuthorizationSetBuilder().Authorization(TAG_ASSOCIATED_DATA, "foobar", (size_t)6);
+
+    // Encrypt
+    AuthorizationSet begin_out_params;
+    EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, begin_params, &begin_out_params));
+    string ciphertext;
+    AuthorizationSet finish_out_params;
+    EXPECT_EQ(ErrorCode::OK, Finish(op_handle_, finish_params, message, "" /* signature */,
+                                    &finish_out_params, &ciphertext));
+
+    // Wrong nonce
+    begin_params.push_back(TAG_NONCE, HidlBuf("123456789012"));
+
+    // Decrypt.
+    EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, begin_params, &begin_out_params));
+    string plaintext;
+    EXPECT_EQ(ErrorCode::VERIFICATION_FAILED,
+              Finish(op_handle_, finish_params, ciphertext, "" /* signature */, &finish_out_params,
+                     &plaintext));
+
+    // With wrong nonce, should have gotten garbage plaintext (or none).
+    EXPECT_NE(message, plaintext);
+}
+
+/*
+ * EncryptionOperationsTest.AesGcmCorruptTag
+ *
+ * Verifies that AES GCM decryption fails correctly when the tag is wrong.
+ */
+TEST_F(EncryptionOperationsTest, AesGcmCorruptTag) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .AesEncryptionKey(128)
+                                             .BlockMode(BlockMode::GCM)
+                                             .Padding(PaddingMode::NONE)
+                                             .Authorization(TAG_MIN_MAC_LENGTH, 128)));
+
+    string aad = "1234567890123456";
+    string message = "123456789012345678901234567890123456";
+
+    auto params = AuthorizationSetBuilder()
+                      .BlockMode(BlockMode::GCM)
+                      .Padding(PaddingMode::NONE)
+                      .Authorization(TAG_MAC_LENGTH, 128);
+
+    auto finish_params =
+        AuthorizationSetBuilder().Authorization(TAG_ASSOCIATED_DATA, aad.data(), aad.size());
+
+    // Encrypt
+    AuthorizationSet begin_out_params;
+    EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params, &begin_out_params));
+    string ciphertext;
+    AuthorizationSet finish_out_params;
+    EXPECT_EQ(ErrorCode::OK, Finish(op_handle_, finish_params, message, "" /* signature */,
+                                    &finish_out_params, &ciphertext));
+    EXPECT_TRUE(finish_out_params.empty());
+
+    // Corrupt tag
+    ++(*ciphertext.rbegin());
+
+    // Grab nonce
+    params.push_back(begin_out_params);
+
+    // Decrypt.
+    EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, params));
+    string plaintext;
+    EXPECT_EQ(ErrorCode::VERIFICATION_FAILED,
+              Finish(op_handle_, finish_params, ciphertext, "" /* signature */, &finish_out_params,
+                     &plaintext));
+    EXPECT_TRUE(finish_out_params.empty());
+}
+
+typedef KeymasterHidlTest MaxOperationsTest;
+
+/*
+ * MaxOperationsTest.TestLimitAes
+ *
+ * Verifies that the max uses per boot tag works correctly with AES keys.
+ */
+TEST_F(MaxOperationsTest, TestLimitAes) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .AesEncryptionKey(128)
+                                             .EcbMode()
+                                             .Padding(PaddingMode::NONE)
+                                             .Authorization(TAG_MAX_USES_PER_BOOT, 3)));
+
+    string message = "1234567890123456";
+
+    auto params = AuthorizationSetBuilder().EcbMode().Padding(PaddingMode::NONE);
+
+    EncryptMessage(message, params);
+    EncryptMessage(message, params);
+    EncryptMessage(message, params);
+
+    // Fourth time should fail.
+    EXPECT_EQ(ErrorCode::KEY_MAX_OPS_EXCEEDED, Begin(KeyPurpose::ENCRYPT, params));
+}
+
+/*
+ * MaxOperationsTest.TestLimitAes
+ *
+ * Verifies that the max uses per boot tag works correctly with RSA keys.
+ */
+TEST_F(MaxOperationsTest, TestLimitRsa) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .RsaSigningKey(1024, 3)
+                                             .NoDigestOrPadding()
+                                             .Authorization(TAG_MAX_USES_PER_BOOT, 3)));
+
+    string message = "1234567890123456";
+
+    auto params = AuthorizationSetBuilder().NoDigestOrPadding();
+
+    SignMessage(message, params);
+    SignMessage(message, params);
+    SignMessage(message, params);
+
+    // Fourth time should fail.
+    EXPECT_EQ(ErrorCode::KEY_MAX_OPS_EXCEEDED, Begin(KeyPurpose::SIGN, params));
+}
+
+typedef KeymasterHidlTest AddEntropyTest;
+
+/*
+ * AddEntropyTest.AddEntropy
+ *
+ * Verifies that the addRngEntropy method doesn't blow up.  There's no way to test that entropy is
+ * actually added.
+ */
+TEST_F(AddEntropyTest, AddEntropy) {
+    EXPECT_EQ(ErrorCode::OK, keymaster().addRngEntropy(HidlBuf("foo")));
+}
+
+/*
+ * AddEntropyTest.AddEmptyEntropy
+ *
+ * Verifies that the addRngEntropy method doesn't blow up when given an empty buffer.
+ */
+TEST_F(AddEntropyTest, AddEmptyEntropy) {
+    EXPECT_EQ(ErrorCode::OK, keymaster().addRngEntropy(HidlBuf()));
+}
+
+/*
+ * AddEntropyTest.AddLargeEntropy
+ *
+ * Verifies that the addRngEntropy method doesn't blow up when given a largish amount of data.
+ */
+TEST_F(AddEntropyTest, AddLargeEntropy) {
+    EXPECT_EQ(ErrorCode::OK, keymaster().addRngEntropy(HidlBuf(string(2 * 1024, 'a'))));
+}
+
+typedef KeymasterHidlTest AttestationTest;
+
+/*
+ * AttestationTest.RsaAttestation
+ *
+ * Verifies that attesting to RSA keys works and generates the expected output.
+ */
+TEST_F(AttestationTest, RsaAttestation) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .RsaSigningKey(1024, 3)
+                                             .Digest(Digest::NONE)
+                                             .Padding(PaddingMode::NONE)
+                                             .Authorization(TAG_INCLUDE_UNIQUE_ID)));
+
+    hidl_vec<hidl_vec<uint8_t>> cert_chain;
+    ASSERT_EQ(ErrorCode::OK,
+              AttestKey(AuthorizationSetBuilder()
+                            .Authorization(TAG_ATTESTATION_CHALLENGE, HidlBuf("challenge"))
+                            .Authorization(TAG_ATTESTATION_APPLICATION_ID, HidlBuf("foo")),
+                        &cert_chain));
+    EXPECT_GE(cert_chain.size(), 2U);
+    EXPECT_TRUE(verify_chain(cert_chain));
+    EXPECT_TRUE(verify_attestation_record("challenge", "foo",                     //
+                                          key_characteristics_.softwareEnforced,  //
+                                          key_characteristics_.hardwareEnforced,  //
+                                          cert_chain[0]));
+}
+
+/*
+ * AttestationTest.RsaAttestationRequiresAppId
+ *
+ * Verifies that attesting to RSA requires app ID.
+ */
+TEST_F(AttestationTest, RsaAttestationRequiresAppId) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .RsaSigningKey(1024, 3)
+                                             .Digest(Digest::NONE)
+                                             .Padding(PaddingMode::NONE)
+                                             .Authorization(TAG_INCLUDE_UNIQUE_ID)));
+
+    hidl_vec<hidl_vec<uint8_t>> cert_chain;
+    EXPECT_EQ(ErrorCode::ATTESTATION_APPLICATION_ID_MISSING,
+              AttestKey(AuthorizationSetBuilder().Authorization(TAG_ATTESTATION_CHALLENGE,
+                                                                HidlBuf("challenge")),
+                        &cert_chain));
+}
+
+/*
+ * AttestationTest.EcAttestation
+ *
+ * Verifies that attesting to EC keys works and generates the expected output.
+ */
+TEST_F(AttestationTest, EcAttestation) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .EcdsaSigningKey(EcCurve::P_256)
+                                             .Digest(Digest::SHA_2_256)
+                                             .Authorization(TAG_INCLUDE_UNIQUE_ID)));
+
+    hidl_vec<hidl_vec<uint8_t>> cert_chain;
+    ASSERT_EQ(ErrorCode::OK,
+              AttestKey(AuthorizationSetBuilder()
+                            .Authorization(TAG_ATTESTATION_CHALLENGE, HidlBuf("challenge"))
+                            .Authorization(TAG_ATTESTATION_APPLICATION_ID, HidlBuf("foo")),
+                        &cert_chain));
+    EXPECT_GE(cert_chain.size(), 2U);
+    EXPECT_TRUE(verify_chain(cert_chain));
+
+    EXPECT_TRUE(verify_attestation_record("challenge", "foo",                     //
+                                          key_characteristics_.softwareEnforced,  //
+                                          key_characteristics_.hardwareEnforced,  //
+                                          cert_chain[0]));
+}
+
+/*
+ * AttestationTest.EcAttestationRequiresAttestationAppId
+ *
+ * Verifies that attesting to EC keys requires app ID
+ */
+TEST_F(AttestationTest, EcAttestationRequiresAttestationAppId) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .EcdsaSigningKey(EcCurve::P_256)
+                                             .Digest(Digest::SHA_2_256)
+                                             .Authorization(TAG_INCLUDE_UNIQUE_ID)));
+
+    hidl_vec<hidl_vec<uint8_t>> cert_chain;
+    EXPECT_EQ(ErrorCode::ATTESTATION_APPLICATION_ID_MISSING,
+              AttestKey(AuthorizationSetBuilder().Authorization(TAG_ATTESTATION_CHALLENGE,
+                                                                HidlBuf("challenge")),
+                        &cert_chain));
+}
+
+/*
+ * AttestationTest.AesAttestation
+ *
+ * Verifies that attesting to AES keys fails in the expected way.
+ */
+TEST_F(AttestationTest, AesAttestation) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .AesEncryptionKey(128)
+                                             .EcbMode()
+                                             .Padding(PaddingMode::PKCS7)));
+
+    hidl_vec<hidl_vec<uint8_t>> cert_chain;
+    EXPECT_EQ(ErrorCode::INCOMPATIBLE_ALGORITHM,
+              AttestKey(AuthorizationSetBuilder()
+                            .Authorization(TAG_ATTESTATION_CHALLENGE, HidlBuf("challenge"))
+                            .Authorization(TAG_ATTESTATION_APPLICATION_ID, HidlBuf("foo")),
+                        &cert_chain));
+}
+
+/*
+ * AttestationTest.HmacAttestation
+ *
+ * Verifies that attesting to HMAC keys fails in the expected way.
+ */
+TEST_F(AttestationTest, HmacAttestation) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .HmacKey(128)
+                                             .EcbMode()
+                                             .Digest(Digest::SHA_2_256)
+                                             .Authorization(TAG_MIN_MAC_LENGTH, 128)));
+
+    hidl_vec<hidl_vec<uint8_t>> cert_chain;
+    EXPECT_EQ(ErrorCode::INCOMPATIBLE_ALGORITHM,
+              AttestKey(AuthorizationSetBuilder()
+                            .Authorization(TAG_ATTESTATION_CHALLENGE, HidlBuf("challenge"))
+                            .Authorization(TAG_ATTESTATION_APPLICATION_ID, HidlBuf("foo")),
+                        &cert_chain));
+}
+
+typedef KeymasterHidlTest KeyDeletionTest;
+
+/**
+ * KeyDeletionTest.DeleteKey
+ *
+ * This test checks that if rollback protection is implemented, DeleteKey invalidates a formerly
+ * valid key blob.
+ *
+ * TODO(swillden):  Update to incorporate changes in rollback resistance semantics.
+ */
+TEST_F(KeyDeletionTest, DeleteKey) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .RsaSigningKey(1024, 3)
+                                             .Digest(Digest::NONE)
+                                             .Padding(PaddingMode::NONE)
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)));
+
+    // Delete must work if rollback protection is implemented
+    AuthorizationSet hardwareEnforced(key_characteristics_.hardwareEnforced);
+    bool rollback_protected = hardwareEnforced.Contains(TAG_ROLLBACK_RESISTANCE);
+
+    if (rollback_protected) {
+        ASSERT_EQ(ErrorCode::OK, DeleteKey(true /* keep key blob */));
+    } else {
+        auto delete_result = DeleteKey(true /* keep key blob */);
+        ASSERT_TRUE(delete_result == ErrorCode::OK | delete_result == ErrorCode::UNIMPLEMENTED);
+    }
+
+    string message = "12345678901234567890123456789012";
+    AuthorizationSet begin_out_params;
+
+    if (rollback_protected) {
+        EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB,
+                  Begin(KeyPurpose::SIGN, key_blob_,
+                        AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::NONE),
+                        &begin_out_params, &op_handle_));
+    } else {
+        EXPECT_EQ(ErrorCode::OK,
+                  Begin(KeyPurpose::SIGN, key_blob_,
+                        AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::NONE),
+                        &begin_out_params, &op_handle_));
+    }
+    AbortIfNeeded();
+    key_blob_ = HidlBuf();
+}
+
+/**
+ * KeyDeletionTest.DeleteInvalidKey
+ *
+ * This test checks that the HAL excepts invalid key blobs.
+ *
+ * TODO(swillden):  Update to incorporate changes in rollback resistance semantics.
+ */
+TEST_F(KeyDeletionTest, DeleteInvalidKey) {
+    // Generate key just to check if rollback protection is implemented
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .RsaSigningKey(1024, 3)
+                                             .Digest(Digest::NONE)
+                                             .Padding(PaddingMode::NONE)
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)));
+
+    // Delete must work if rollback protection is implemented
+    AuthorizationSet hardwareEnforced(key_characteristics_.hardwareEnforced);
+    bool rollback_protected = hardwareEnforced.Contains(TAG_ROLLBACK_RESISTANCE);
+
+    // Delete the key we don't care about the result at this point.
+    DeleteKey();
+
+    // Now create an invalid key blob and delete it.
+    key_blob_ = HidlBuf("just some garbage data which is not a valid key blob");
+
+    if (rollback_protected) {
+        ASSERT_EQ(ErrorCode::OK, DeleteKey());
+    } else {
+        auto delete_result = DeleteKey();
+        ASSERT_TRUE(delete_result == ErrorCode::OK | delete_result == ErrorCode::UNIMPLEMENTED);
+    }
+}
+
+/**
+ * KeyDeletionTest.DeleteAllKeys
+ *
+ * This test is disarmed by default. To arm it use --arm_deleteAllKeys.
+ *
+ * BEWARE: This test has serious side effects. All user keys will be lost! This includes
+ * FBE/FDE encryption keys, which means that the device will not even boot until after the
+ * device has been wiped manually (e.g., fastboot flashall -w), and new FBE/FDE keys have
+ * been provisioned. Use this test only on dedicated testing devices that have no valuable
+ * credentials stored in Keystore/Keymaster.
+ *
+ * TODO(swillden):  Update to incorporate changes in rollback resistance semantics.
+ */
+TEST_F(KeyDeletionTest, DeleteAllKeys) {
+    if (!arm_deleteAllKeys) return;
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .RsaSigningKey(1024, 3)
+                                             .Digest(Digest::NONE)
+                                             .Padding(PaddingMode::NONE)
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)));
+
+    // Delete must work if rollback protection is implemented
+    AuthorizationSet hardwareEnforced(key_characteristics_.hardwareEnforced);
+    bool rollback_protected = hardwareEnforced.Contains(TAG_ROLLBACK_RESISTANCE);
+
+    ASSERT_EQ(ErrorCode::OK, DeleteAllKeys());
+
+    string message = "12345678901234567890123456789012";
+    AuthorizationSet begin_out_params;
+
+    if (rollback_protected) {
+        EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB,
+                  Begin(KeyPurpose::SIGN, key_blob_,
+                        AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::NONE),
+                        &begin_out_params, &op_handle_));
+    } else {
+        EXPECT_EQ(ErrorCode::OK,
+                  Begin(KeyPurpose::SIGN, key_blob_,
+                        AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::NONE),
+                        &begin_out_params, &op_handle_));
+    }
+    AbortIfNeeded();
+    key_blob_ = HidlBuf();
+}
+
+using UpgradeKeyTest = KeymasterHidlTest;
+
+/*
+ * UpgradeKeyTest.UpgradeKey
+ *
+ * Verifies that calling upgrade key on an up-to-date key works (i.e. does nothing).
+ */
+TEST_F(UpgradeKeyTest, UpgradeKey) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .AesEncryptionKey(128)
+                                             .Padding(PaddingMode::NONE)
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)));
+
+    auto result = UpgradeKey(key_blob_);
+
+    // Key doesn't need upgrading.  Should get okay, but no new key blob.
+    EXPECT_EQ(result, std::make_pair(ErrorCode::OK, HidlBuf()));
+}
+
+}  // namespace test
+}  // namespace V4_0
+}  // namespace keymaster
+}  // namespace hardware
+}  // namespace android
+
+using android::hardware::keymaster::V4_0::test::KeymasterHidlEnvironment;
+
+int main(int argc, char** argv) {
+    ::testing::AddGlobalTestEnvironment(KeymasterHidlEnvironment::Instance());
+    ::testing::InitGoogleTest(&argc, argv);
+    KeymasterHidlEnvironment::Instance()->init(&argc, argv);
+    for (int i = 1; i < argc; ++i) {
+        if (argv[i][0] == '-') {
+            if (std::string(argv[i]) == "--arm_deleteAllKeys") {
+                arm_deleteAllKeys = true;
+            }
+            if (std::string(argv[i]) == "--dump_attestations") {
+                dump_Attestations = true;
+            }
+        }
+    }
+    int status = RUN_ALL_TESTS();
+    ALOGI("Test result = %d", status);
+    return status;
+}
diff --git a/light/2.0/default/Android.bp b/light/2.0/default/Android.bp
new file mode 100644
index 0000000..8d4eca1
--- /dev/null
+++ b/light/2.0/default/Android.bp
@@ -0,0 +1,53 @@
+// 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_shared {
+    name: "android.hardware.light@2.0-impl",
+    defaults: ["hidl_defaults"],
+    proprietary: true,
+    relative_install_path: "hw",
+    srcs: ["Light.cpp"],
+
+    shared_libs: [
+        "libbase",
+        "liblog",
+        "libhidlbase",
+        "libhidltransport",
+        "libhardware",
+        "libutils",
+        "android.hardware.light@2.0",
+    ],
+
+}
+
+cc_binary {
+    relative_install_path: "hw",
+    defaults: ["hidl_defaults"],
+    proprietary: true,
+    name: "android.hardware.light@2.0-service",
+    init_rc: ["android.hardware.light@2.0-service.rc"],
+    srcs: ["service.cpp"],
+
+    shared_libs: [
+        "liblog",
+        "libbase",
+        "libdl",
+        "libutils",
+        "libhardware",
+        "libhidlbase",
+        "libhidltransport",
+        "android.hardware.light@2.0",
+    ],
+
+}
\ No newline at end of file
diff --git a/light/2.0/default/Android.mk b/light/2.0/default/Android.mk
deleted file mode 100644
index da75e1a..0000000
--- a/light/2.0/default/Android.mk
+++ /dev/null
@@ -1,48 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := android.hardware.light@2.0-impl
-LOCAL_PROPRIETARY_MODULE := true
-LOCAL_MODULE_RELATIVE_PATH := hw
-LOCAL_SRC_FILES := \
-    Light.cpp \
-
-LOCAL_CFLAGS := -Wall -Werror
-
-LOCAL_SHARED_LIBRARIES := \
-    libhidlbase \
-    libhidltransport \
-    libutils \
-    liblog \
-    libcutils \
-    libhardware \
-    libbase \
-    libcutils \
-    android.hardware.light@2.0 \
-
-include $(BUILD_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_MODULE_RELATIVE_PATH := hw
-LOCAL_PROPRIETARY_MODULE := true
-LOCAL_MODULE := android.hardware.light@2.0-service
-LOCAL_INIT_RC := android.hardware.light@2.0-service.rc
-LOCAL_SRC_FILES := \
-    service.cpp \
-
-LOCAL_CFLAGS := -Wall -Werror
-
-LOCAL_SHARED_LIBRARIES := \
-    liblog \
-    libcutils \
-    libdl \
-    libbase \
-    libutils \
-    libhardware \
-
-LOCAL_SHARED_LIBRARIES += \
-    libhidlbase \
-    libhidltransport \
-    android.hardware.light@2.0 \
-
-include $(BUILD_EXECUTABLE)
diff --git a/light/2.0/default/android.hardware.light@2.0-service.rc b/light/2.0/default/android.hardware.light@2.0-service.rc
index c3284c6..f268706 100644
--- a/light/2.0/default/android.hardware.light@2.0-service.rc
+++ b/light/2.0/default/android.hardware.light@2.0-service.rc
@@ -1,4 +1,4 @@
-service light-hal-2-0 /vendor/bin/hw/android.hardware.light@2.0-service
+service vendor.light-hal-2-0 /vendor/bin/hw/android.hardware.light@2.0-service
     class hal
     user system
-    group system
\ No newline at end of file
+    group system
diff --git a/media/1.0/Android.mk b/media/1.0/Android.mk
deleted file mode 100644
index bc44b9e..0000000
--- a/media/1.0/Android.mk
+++ /dev/null
@@ -1,14 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-#######################################
-# media_profiles_V1_0.dtd
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := media_profiles_V1_0.dtd
-LOCAL_SRC_FILES := media_profiles.dtd
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)
-
-include $(BUILD_PREBUILT)
-
diff --git a/media/omx/1.0/vts/OWNERS b/media/omx/1.0/vts/OWNERS
new file mode 100644
index 0000000..e0e0dd1
--- /dev/null
+++ b/media/omx/1.0/vts/OWNERS
@@ -0,0 +1,7 @@
+# Media team
+pawin@google.com
+lajos@google.com
+
+# VTS team
+yim@google.com
+zhuoyao@google.com
\ No newline at end of file
diff --git a/media/res/bbb_opus_stereo_128kbps_48000hz.info b/media/res/bbb_opus_stereo_128kbps_48000hz.info
index 12a6b99..460f98b 100644
--- a/media/res/bbb_opus_stereo_128kbps_48000hz.info
+++ b/media/res/bbb_opus_stereo_128kbps_48000hz.info
@@ -1,504 +1,499 @@
 19 128 0
 8 128 0
 8 128 0
-618 32 0
-398 32 21000
-582 32 41000
-466 32 61000
-434 32 81000
-419 32 101000
-578 32 121000
-591 32 141000
-293 32 161000
-323 32 181000
-303 32 201000
-319 32 221000
-318 32 241000
-307 32 261000
-539 32 281000
-358 32 301000
-334 32 321000
-308 32 341000
-331 32 361000
-327 32 381000
-357 32 401000
-365 32 421000
-375 32 441000
-370 32 461000
-636 32 481000
-497 32 501000
-360 32 521000
-327 32 541000
-438 32 561000
-323 32 581000
-323 32 601000
-308 32 621000
-313 32 641000
-326 32 661000
-329 32 681000
-324 32 701000
-326 32 721000
-332 32 741000
-336 32 761000
-345 32 781000
-352 32 801000
-380 32 821000
-341 32 841000
-341 32 861000
-347 32 881000
-352 32 901000
-339 32 921000
-366 32 941000
-369 32 961000
-367 32 981000
-342 32 1001000
-344 32 1021000
-339 32 1041000
-312 32 1061000
-306 32 1081000
-307 32 1101000
-308 32 1121000
-319 32 1141000
-297 32 1161000
-294 32 1181000
-298 32 1201000
-474 32 1221000
-424 32 1241000
-278 32 1261000
-290 32 1281000
-281 32 1301000
-295 32 1321000
-277 32 1341000
-305 32 1361000
-293 32 1381000
-284 32 1401000
-296 32 1421000
-298 32 1441000
-316 32 1461000
-302 32 1481000
-300 32 1501000
-283 32 1521000
-604 32 1541000
-474 32 1561000
-277 32 1581000
-285 32 1601000
-278 32 1621000
-295 32 1641000
-301 32 1661000
-317 32 1681000
-301 32 1701000
-594 32 1721000
-296 32 1741000
-374 32 1761000
-301 32 1781000
-296 32 1801000
-300 32 1821000
-285 32 1841000
-308 32 1861000
-304 32 1881000
-286 32 1901000
-294 32 1921000
-300 32 1941000
-324 32 1961000
-315 32 1981000
-326 32 2001000
-311 32 2021000
-300 32 2041000
-304 32 2061000
-307 32 2081000
-304 32 2101000
-301 32 2121000
-296 32 2141000
-299 32 2161000
-298 32 2181000
-300 32 2201000
-300 32 2221000
-303 32 2241000
-303 32 2261000
-303 32 2281000
-308 32 2301000
-304 32 2321000
-295 32 2341000
-300 32 2361000
-300 32 2381000
-293 32 2401000
-302 32 2421000
-548 32 2441000
-338 32 2461000
-311 32 2481000
-304 32 2501000
-304 32 2521000
-299 32 2541000
-298 32 2561000
-294 32 2581000
-298 32 2601000
-300 32 2621000
-301 32 2641000
-305 32 2661000
-309 32 2681000
-303 32 2701000
-313 32 2721000
-302 32 2741000
-304 32 2761000
-304 32 2781000
-304 32 2801000
-300 32 2821000
-434 32 2841000
-571 32 2861000
-386 32 2881000
-323 32 2901000
-415 32 2921000
-277 32 2941000
-401 32 2961000
-388 32 2981000
-337 32 3001000
-540 32 3021000
-516 32 3041000
-316 32 3061000
-301 32 3081000
-298 32 3101000
-302 32 3121000
-301 32 3141000
-299 32 3161000
-295 32 3181000
-281 32 3201000
-296 32 3221000
-300 32 3241000
-295 32 3261000
-308 32 3281000
-296 32 3301000
-297 32 3321000
-276 32 3341000
-281 32 3361000
-291 32 3381000
-294 32 3401000
-281 32 3421000
-277 32 3441000
-274 32 3461000
-298 32 3481000
-293 32 3501000
-279 32 3521000
-275 32 3541000
-282 32 3561000
-289 32 3581000
-300 32 3601000
-289 32 3621000
-295 32 3641000
-301 32 3661000
-306 32 3681000
-301 32 3701000
-305 32 3721000
-296 32 3741000
-296 32 3761000
-377 32 3781000
-297 32 3801000
-293 32 3821000
-290 32 3841000
-298 32 3861000
-303 32 3881000
-304 32 3901000
-316 32 3921000
-298 32 3941000
-319 32 3961000
-330 32 3981000
-316 32 4001000
-316 32 4021000
-286 32 4041000
-272 32 4061000
-257 32 4081000
-240 32 4101000
-229 32 4121000
-223 32 4141000
-225 32 4161000
-223 32 4181000
-232 32 4201000
-234 32 4221000
-224 32 4241000
-351 32 4261000
-309 32 4281000
-350 32 4301000
-437 32 4321000
-277 32 4341000
-291 32 4361000
-271 32 4381000
-266 32 4401000
-264 32 4421000
-285 32 4441000
-280 32 4461000
-276 32 4481000
-278 32 4501000
-262 32 4521000
-262 32 4541000
-246 32 4561000
-253 32 4581000
-289 32 4601000
-264 32 4621000
-285 32 4641000
-278 32 4661000
-266 32 4681000
-275 32 4701000
-264 32 4721000
-264 32 4741000
-275 32 4761000
-268 32 4781000
-262 32 4801000
-266 32 4821000
-262 32 4841000
-246 32 4861000
-284 32 4881000
-291 32 4901000
-294 32 4921000
-294 32 4941000
-294 32 4961000
-296 32 4981000
-294 32 5001000
-300 32 5021000
-293 32 5041000
-298 32 5061000
-295 32 5081000
-301 32 5101000
-301 32 5121000
-302 32 5141000
-303 32 5161000
-300 32 5181000
-301 32 5201000
-302 32 5221000
-296 32 5241000
-297 32 5261000
-300 32 5281000
-295 32 5301000
-349 32 5321000
-351 32 5341000
-333 32 5361000
-267 32 5381000
-291 32 5401000
-270 32 5421000
-258 32 5441000
-266 32 5461000
-252 32 5481000
-251 32 5501000
-323 32 5521000
-398 32 5541000
-383 32 5561000
-295 32 5581000
-260 32 5601000
-413 32 5621000
-288 32 5641000
-299 32 5661000
-277 32 5681000
-295 32 5701000
-296 32 5721000
-305 32 5741000
-300 32 5761000
-305 32 5781000
-293 32 5801000
-305 32 5821000
-455 32 5841000
-302 32 5861000
-293 32 5881000
-289 32 5901000
-283 32 5921000
-289 32 5941000
-275 32 5961000
-279 32 5981000
-626 32 6001000
-335 32 6021000
-324 32 6041000
-331 32 6061000
-334 32 6081000
-322 32 6101000
-339 32 6121000
-339 32 6141000
-329 32 6161000
-339 32 6181000
-328 32 6201000
-330 32 6221000
-312 32 6241000
-527 32 6261000
-324 32 6281000
-322 32 6301000
-313 32 6321000
-306 32 6341000
-303 32 6361000
-304 32 6381000
-311 32 6401000
-302 32 6421000
-294 32 6441000
-296 32 6461000
-293 32 6481000
-297 32 6501000
-287 32 6521000
-300 32 6541000
-324 32 6561000
-304 32 6581000
-303 32 6601000
-303 32 6621000
-324 32 6641000
-340 32 6661000
-357 32 6681000
-355 32 6701000
-349 32 6721000
-358 32 6741000
-378 32 6761000
-591 32 6781000
-525 32 6801000
-378 32 6821000
-356 32 6841000
-353 32 6861000
-347 32 6881000
-334 32 6901000
-330 32 6921000
-334 32 6941000
-352 32 6961000
-344 32 6981000
-356 32 7001000
-356 32 7021000
-351 32 7041000
-346 32 7061000
-350 32 7081000
-366 32 7101000
-504 32 7121000
-360 32 7141000
-366 32 7161000
-369 32 7181000
-363 32 7201000
-345 32 7221000
-347 32 7241000
-338 32 7261000
-332 32 7281000
-318 32 7301000
-307 32 7321000
-302 32 7341000
-308 32 7361000
-317 32 7381000
-304 32 7401000
-313 32 7421000
-314 32 7441000
-302 32 7461000
-299 32 7481000
-300 32 7501000
-295 32 7521000
-296 32 7541000
-298 32 7561000
-601 32 7581000
-489 32 7601000
-303 32 7621000
-323 32 7641000
-304 32 7661000
-328 32 7681000
-332 32 7701000
-356 32 7721000
-356 32 7741000
-340 32 7761000
-333 32 7781000
-332 32 7801000
-321 32 7821000
-455 32 7841000
-328 32 7861000
-314 32 7881000
-310 32 7901000
-300 32 7921000
-327 32 7941000
-317 32 7961000
-309 32 7981000
-305 32 8001000
-299 32 8021000
-312 32 8041000
-309 32 8061000
-300 32 8081000
-319 32 8101000
-329 32 8121000
-323 32 8141000
-332 32 8161000
-340 32 8181000
-339 32 8201000
-319 32 8221000
-323 32 8241000
-320 32 8261000
-322 32 8281000
-314 32 8301000
-310 32 8321000
-300 32 8341000
-294 32 8361000
-324 32 8381000
-325 32 8401000
-305 32 8421000
-306 32 8441000
-298 32 8461000
-302 32 8481000
-298 32 8501000
-295 32 8521000
-294 32 8541000
-295 32 8561000
-288 32 8581000
-310 32 8601000
-301 32 8621000
-401 32 8641000
-324 32 8661000
-309 32 8681000
-294 32 8701000
-306 32 8721000
-318 32 8741000
-312 32 8761000
-325 32 8781000
-352 32 8801000
-351 32 8821000
-343 32 8841000
-377 32 8861000
-409 32 8881000
-424 32 8901000
-366 32 8921000
-341 32 8941000
-330 32 8961000
-342 32 8981000
-328 32 9001000
-333 32 9021000
-334 32 9041000
-340 32 9061000
-347 32 9081000
-354 32 9101000
-342 32 9121000
-323 32 9141000
-311 32 9161000
-297 32 9181000
-286 32 9201000
-290 32 9221000
-288 32 9241000
-291 32 9261000
-439 32 9281000
-278 32 9301000
-506 32 9321000
-441 32 9341000
-333 32 9361000
-416 32 9381000
-446 32 9401000
-219 32 9421000
-353 32 9441000
-307 32 9461000
-222 32 9481000
-221 32 9501000
-235 32 9521000
-294 32 9541000
-239 32 9561000
-251 32 9581000
-259 32 9601000
-263 32 9621000
-283 32 9641000
-423 32 9661000
-296 32 9681000
-299 32 9701000
-322 32 9721000
-296 32 9741000
-489 32 9761000
-481 32 9781000
-505 32 9801000
-292 32 9821000
-390 32 9841000
-279 32 9861000
-442 32 9881000
-426 32 9901000
-408 32 9921000
-272 32 9941000
-484 32 9961000
-443 32 9981000
-440 32 10001000
+529 32 0
+329 32 13500
+349 32 33500
+336 32 53500
+383 32 73500
+359 32 93500
+344 32 113500
+343 32 133500
+332 32 153500
+320 32 173500
+319 32 193500
+323 32 213500
+320 32 233500
+328 32 253500
+340 32 273500
+318 32 293500
+319 32 313500
+335 32 333500
+511 32 353500
+395 32 373500
+327 32 393500
+479 32 413500
+332 32 433500
+320 32 453500
+321 32 473500
+310 32 493500
+310 32 513500
+310 32 533500
+326 32 553500
+330 32 573500
+318 32 593500
+309 32 613500
+304 32 633500
+298 32 653500
+294 32 673500
+300 32 693500
+314 32 713500
+304 32 733500
+307 32 753500
+321 32 773500
+333 32 793500
+335 32 813500
+306 32 833500
+315 32 853500
+320 32 873500
+315 32 893500
+308 32 913500
+320 32 933500
+311 32 953500
+311 32 973500
+313 32 993500
+314 32 1013500
+308 32 1033500
+307 32 1053500
+317 32 1073500
+328 32 1093500
+317 32 1113500
+312 32 1133500
+308 32 1153500
+315 32 1173500
+320 32 1193500
+322 32 1213500
+323 32 1233500
+322 32 1253500
+322 32 1273500
+301 32 1293500
+303 32 1313500
+308 32 1333500
+299 32 1353500
+297 32 1373500
+293 32 1393500
+295 32 1413500
+297 32 1433500
+300 32 1453500
+294 32 1473500
+299 32 1493500
+296 32 1513500
+303 32 1533500
+313 32 1553500
+306 32 1573500
+303 32 1593500
+311 32 1613500
+307 32 1633500
+310 32 1653500
+339 32 1673500
+325 32 1693500
+320 32 1713500
+315 32 1733500
+316 32 1753500
+338 32 1773500
+325 32 1793500
+325 32 1813500
+328 32 1833500
+304 32 1853500
+297 32 1873500
+322 32 1893500
+311 32 1913500
+307 32 1933500
+300 32 1953500
+301 32 1973500
+309 32 1993500
+300 32 2013500
+306 32 2033500
+305 32 2053500
+298 32 2073500
+291 32 2093500
+301 32 2113500
+300 32 2133500
+439 32 2153500
+292 32 2173500
+308 32 2193500
+305 32 2213500
+298 32 2233500
+297 32 2253500
+293 32 2273500
+408 32 2293500
+298 32 2313500
+452 32 2333500
+297 32 2353500
+303 32 2373500
+300 32 2393500
+310 32 2413500
+299 32 2433500
+306 32 2453500
+316 32 2473500
+308 32 2493500
+313 32 2513500
+309 32 2533500
+310 32 2553500
+315 32 2573500
+309 32 2593500
+317 32 2613500
+311 32 2633500
+328 32 2653500
+333 32 2673500
+326 32 2693500
+323 32 2713500
+316 32 2733500
+325 32 2753500
+316 32 2773500
+319 32 2793500
+326 32 2813500
+320 32 2833500
+328 32 2853500
+312 32 2873500
+314 32 2893500
+309 32 2913500
+306 32 2933500
+295 32 2953500
+304 32 2973500
+326 32 2993500
+291 32 3013500
+299 32 3033500
+293 32 3053500
+288 32 3073500
+294 32 3093500
+292 32 3113500
+292 32 3133500
+288 32 3153500
+308 32 3173500
+304 32 3193500
+292 32 3213500
+382 32 3233500
+381 32 3253500
+299 32 3273500
+316 32 3293500
+308 32 3313500
+301 32 3333500
+297 32 3353500
+299 32 3373500
+294 32 3393500
+295 32 3413500
+317 32 3433500
+297 32 3453500
+309 32 3473500
+313 32 3493500
+320 32 3513500
+329 32 3533500
+330 32 3553500
+324 32 3573500
+324 32 3593500
+309 32 3613500
+304 32 3633500
+313 32 3653500
+312 32 3673500
+299 32 3693500
+295 32 3713500
+301 32 3733500
+295 32 3753500
+297 32 3773500
+302 32 3793500
+298 32 3813500
+299 32 3833500
+296 32 3853500
+292 32 3873500
+307 32 3893500
+303 32 3913500
+313 32 3933500
+318 32 3953500
+313 32 3973500
+353 32 3993500
+371 32 4013500
+292 32 4033500
+300 32 4053500
+381 32 4073500
+294 32 4093500
+301 32 4113500
+305 32 4133500
+299 32 4153500
+305 32 4173500
+322 32 4193500
+315 32 4213500
+326 32 4233500
+338 32 4253500
+320 32 4273500
+319 32 4293500
+327 32 4313500
+330 32 4333500
+310 32 4353500
+303 32 4373500
+299 32 4393500
+293 32 4413500
+293 32 4433500
+294 32 4453500
+295 32 4473500
+295 32 4493500
+323 32 4513500
+309 32 4533500
+309 32 4553500
+301 32 4573500
+473 32 4593500
+291 32 4613500
+297 32 4633500
+294 32 4653500
+293 32 4673500
+304 32 4693500
+292 32 4713500
+302 32 4733500
+296 32 4753500
+298 32 4773500
+301 32 4793500
+307 32 4813500
+285 32 4833500
+294 32 4853500
+304 32 4873500
+294 32 4893500
+295 32 4913500
+325 32 4933500
+319 32 4953500
+323 32 4973500
+313 32 4993500
+303 32 5013500
+296 32 5033500
+295 32 5053500
+290 32 5073500
+297 32 5093500
+296 32 5113500
+296 32 5133500
+292 32 5153500
+295 32 5173500
+287 32 5193500
+294 32 5213500
+290 32 5233500
+297 32 5253500
+297 32 5273500
+297 32 5293500
+292 32 5313500
+297 32 5333500
+290 32 5353500
+293 32 5373500
+293 32 5393500
+291 32 5413500
+292 32 5433500
+290 32 5453500
+291 32 5473500
+296 32 5493500
+295 32 5513500
+327 32 5533500
+293 32 5553500
+291 32 5573500
+291 32 5593500
+311 32 5613500
+291 32 5633500
+294 32 5653500
+296 32 5673500
+295 32 5693500
+289 32 5713500
+295 32 5733500
+295 32 5753500
+297 32 5773500
+292 32 5793500
+297 32 5813500
+292 32 5833500
+295 32 5853500
+296 32 5873500
+295 32 5893500
+303 32 5913500
+304 32 5933500
+301 32 5953500
+307 32 5973500
+304 32 5993500
+310 32 6013500
+310 32 6033500
+305 32 6053500
+301 32 6073500
+302 32 6093500
+305 32 6113500
+298 32 6133500
+300 32 6153500
+300 32 6173500
+292 32 6193500
+297 32 6213500
+301 32 6233500
+297 32 6253500
+297 32 6273500
+298 32 6293500
+297 32 6313500
+300 32 6333500
+293 32 6353500
+293 32 6373500
+297 32 6393500
+294 32 6413500
+307 32 6433500
+302 32 6453500
+307 32 6473500
+320 32 6493500
+330 32 6513500
+333 32 6533500
+337 32 6553500
+331 32 6573500
+323 32 6593500
+312 32 6613500
+326 32 6633500
+328 32 6653500
+332 32 6673500
+333 32 6693500
+340 32 6713500
+336 32 6733500
+324 32 6753500
+312 32 6773500
+301 32 6793500
+289 32 6813500
+302 32 6833500
+296 32 6853500
+299 32 6873500
+289 32 6893500
+295 32 6913500
+299 32 6933500
+374 32 6953500
+391 32 6973500
+365 32 6993500
+340 32 7013500
+330 32 7033500
+337 32 7053500
+328 32 7073500
+329 32 7093500
+319 32 7113500
+312 32 7133500
+308 32 7153500
+304 32 7173500
+312 32 7193500
+311 32 7213500
+316 32 7233500
+299 32 7253500
+330 32 7273500
+330 32 7293500
+330 32 7313500
+342 32 7333500
+439 32 7353500
+322 32 7373500
+298 32 7393500
+293 32 7413500
+310 32 7433500
+303 32 7453500
+317 32 7473500
+453 32 7493500
+377 32 7513500
+374 32 7533500
+292 32 7553500
+295 32 7573500
+274 32 7593500
+292 32 7613500
+291 32 7633500
+367 32 7653500
+295 32 7673500
+298 32 7693500
+297 32 7713500
+301 32 7733500
+292 32 7753500
+344 32 7773500
+296 32 7793500
+297 32 7813500
+306 32 7833500
+308 32 7853500
+305 32 7873500
+313 32 7893500
+306 32 7913500
+322 32 7933500
+313 32 7953500
+305 32 7973500
+304 32 7993500
+313 32 8013500
+324 32 8033500
+312 32 8053500
+318 32 8073500
+311 32 8093500
+302 32 8113500
+305 32 8133500
+312 32 8153500
+313 32 8173500
+312 32 8193500
+335 32 8213500
+333 32 8233500
+346 32 8253500
+339 32 8273500
+337 32 8293500
+341 32 8313500
+335 32 8333500
+325 32 8353500
+324 32 8373500
+317 32 8393500
+315 32 8413500
+303 32 8433500
+317 32 8453500
+452 32 8473500
+324 32 8493500
+321 32 8513500
+335 32 8533500
+327 32 8553500
+315 32 8573500
+321 32 8593500
+319 32 8613500
+308 32 8633500
+314 32 8653500
+322 32 8673500
+328 32 8693500
+320 32 8713500
+324 32 8733500
+331 32 8753500
+330 32 8773500
+328 32 8793500
+318 32 8813500
+314 32 8833500
+318 32 8853500
+318 32 8873500
+325 32 8893500
+338 32 8913500
+341 32 8933500
+333 32 8953500
+330 32 8973500
+338 32 8993500
+333 32 9013500
+330 32 9033500
+344 32 9053500
+479 32 9073500
+473 32 9093500
+333 32 9113500
+337 32 9133500
+495 32 9153500
+353 32 9173500
+352 32 9193500
+344 32 9213500
+336 32 9233500
+324 32 9253500
+321 32 9273500
+350 32 9293500
+347 32 9313500
+343 32 9333500
+345 32 9353500
+337 32 9373500
+335 32 9393500
+333 32 9413500
+336 32 9433500
+334 32 9453500
+333 32 9473500
+331 32 9493500
+329 32 9513500
+319 32 9533500
+321 32 9553500
+316 32 9573500
+322 32 9593500
+448 32 9613500
+312 32 9633500
+306 32 9653500
+301 32 9673500
+303 32 9693500
+296 32 9713500
+300 32 9733500
+295 32 9753500
+300 32 9773500
+297 32 9793500
+300 32 9813500
+297 32 9833500
+512 32 9853500
+292 32 9873500
+468 32 9893500
diff --git a/media/res/bbb_opus_stereo_128kbps_48000hz.opus b/media/res/bbb_opus_stereo_128kbps_48000hz.opus
index 7b763b2..2b6b870 100644
--- a/media/res/bbb_opus_stereo_128kbps_48000hz.opus
+++ b/media/res/bbb_opus_stereo_128kbps_48000hz.opus
Binary files differ
diff --git a/memtrack/1.0/default/android.hardware.memtrack@1.0-service.rc b/memtrack/1.0/default/android.hardware.memtrack@1.0-service.rc
index c975a18..4327a20 100644
--- a/memtrack/1.0/default/android.hardware.memtrack@1.0-service.rc
+++ b/memtrack/1.0/default/android.hardware.memtrack@1.0-service.rc
@@ -1,4 +1,4 @@
-service memtrack-hal-1-0 /vendor/bin/hw/android.hardware.memtrack@1.0-service
+service vendor.memtrack-hal-1-0 /vendor/bin/hw/android.hardware.memtrack@1.0-service
     class hal
     user system
     group system
diff --git a/nfc/1.0/default/android.hardware.nfc@1.0-service.rc b/nfc/1.0/default/android.hardware.nfc@1.0-service.rc
index c9b8014..3a5c776 100644
--- a/nfc/1.0/default/android.hardware.nfc@1.0-service.rc
+++ b/nfc/1.0/default/android.hardware.nfc@1.0-service.rc
@@ -1,4 +1,4 @@
-service nfc_hal_service /vendor/bin/hw/android.hardware.nfc@1.0-service
+service vendor.nfc_hal_service /vendor/bin/hw/android.hardware.nfc@1.0-service
     class hal
     user nfc
     group nfc
diff --git a/power/1.0/default/android.hardware.power@1.0-service.rc b/power/1.0/default/android.hardware.power@1.0-service.rc
index 1777e90..657c733 100644
--- a/power/1.0/default/android.hardware.power@1.0-service.rc
+++ b/power/1.0/default/android.hardware.power@1.0-service.rc
@@ -1,4 +1,4 @@
-service power-hal-1-0 /vendor/bin/hw/android.hardware.power@1.0-service
+service vendor.power-hal-1-0 /vendor/bin/hw/android.hardware.power@1.0-service
     class hal
     user system
     group system
diff --git a/power/1.2/Android.bp b/power/1.2/Android.bp
new file mode 100644
index 0000000..0eb73e7
--- /dev/null
+++ b/power/1.2/Android.bp
@@ -0,0 +1,23 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.power@1.2",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "types.hal",
+        "IPower.hal",
+    ],
+    interfaces: [
+        "android.hardware.power@1.0",
+        "android.hardware.power@1.1",
+        "android.hidl.base@1.0",
+    ],
+    types: [
+        "PowerHint",
+    ],
+    gen_java: true,
+}
+
diff --git a/power/1.2/IPower.hal b/power/1.2/IPower.hal
new file mode 100644
index 0000000..1c2c7b8
--- /dev/null
+++ b/power/1.2/IPower.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.power@1.2;
+
+import @1.1::IPower;
+
+interface IPower extends @1.1::IPower {
+    /**
+     * called to pass hints on power requirements which
+     * may result in adjustment of power/performance parameters of the
+     * cpufreq governor and other controls.
+     *
+     * A particular platform may choose to ignore any hint.
+     *
+     * @param hint PowerHint which is passed
+     * @param data contains additional information about the hint
+     * and is described along with the comments for each of the hints.
+     */
+    oneway powerHintAsync_1_2(PowerHint hint, int32_t data);
+};
diff --git a/power/1.2/types.hal b/power/1.2/types.hal
new file mode 100644
index 0000000..f7a6cf6
--- /dev/null
+++ b/power/1.2/types.hal
@@ -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.
+ */
+package android.hardware.power@1.2;
+
+import @1.0::PowerHint;
+
+/** Power hint identifiers passed to powerHintAsync_1_2() */
+enum PowerHint : @1.0::PowerHint {
+   /**
+    * This hint indicates that audio stream is being started. Can be used
+    * for device specific optimizations during starting audio stream. The
+    * data parameter is non-zero when stream starts and zero when audio
+    * stream setup is complete.
+    */
+    AUDIO_STREAMING,
+
+   /**
+    * This hint indicates that low latency audio is active. Can be used
+    * for device specific optimizations towards low latency audio. The
+    * data parameter is non-zero when low latency audio starts and
+    * zero when ends.
+    */
+    AUDIO_LOW_LATENCY,
+
+   /**
+    * These hint indicates that camera is being launched. Can be used
+    * for device specific optimizations during camera launch. The data
+    * parameter is non-zero when camera launch starts and zero when launch
+    * is complete.
+    */
+    CAMERA_LAUNCH,
+
+   /**
+    * This hint indicates that camera stream is being started. Can be used
+    * for device specific optimizations during starting camera stream. The
+    * data parameter is non-zero when stream starts and zero when ends.
+    */
+    CAMERA_STREAMING,
+
+   /**
+    * This hint indicates that camera shot is being taken. Can be used
+    * for device specific optimizations during taking camera shot. The
+    * data parameter is non-zero when camera shot starts and zero when ends.
+    */
+    CAMERA_SHOT,
+};
diff --git a/broadcastradio/1.1/tests/Android.bp b/power/1.2/vts/functional/Android.bp
similarity index 70%
rename from broadcastradio/1.1/tests/Android.bp
rename to power/1.2/vts/functional/Android.bp
index fa1fd94..d615e85 100644
--- a/broadcastradio/1.1/tests/Android.bp
+++ b/power/1.2/vts/functional/Android.bp
@@ -15,15 +15,12 @@
 //
 
 cc_test {
-    name: "android.hardware.broadcastradio@1.1-utils-tests",
-    vendor: true,
-    cflags: [
-        "-Wall",
-        "-Wextra",
-        "-Werror",
+    name: "VtsHalPowerV1_2TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: ["VtsHalPowerV1_2TargetTest.cpp"],
+    static_libs: [
+        "android.hardware.power@1.0",
+        "android.hardware.power@1.1",
+        "android.hardware.power@1.2",
     ],
-    srcs: [
-        "WorkerThread_test.cpp",
-    ],
-    static_libs: ["android.hardware.broadcastradio@1.1-utils-lib"],
 }
diff --git a/power/1.2/vts/functional/VtsHalPowerV1_2TargetTest.cpp b/power/1.2/vts/functional/VtsHalPowerV1_2TargetTest.cpp
new file mode 100644
index 0000000..5e92997
--- /dev/null
+++ b/power/1.2/vts/functional/VtsHalPowerV1_2TargetTest.cpp
@@ -0,0 +1,99 @@
+/*
+ * 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 "power_hidl_hal_test"
+#include <android-base/logging.h>
+#include <android/hardware/power/1.2/IPower.h>
+
+#include <VtsHalHidlTargetTestBase.h>
+#include <VtsHalHidlTargetTestEnvBase.h>
+
+using ::android::sp;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::power::V1_2::IPower;
+using ::android::hardware::power::V1_2::PowerHint;
+
+// Test environment for Power HIDL HAL.
+class PowerHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
+   public:
+    // get the test environment singleton
+    static PowerHidlEnvironment* Instance() {
+        static PowerHidlEnvironment* instance = new PowerHidlEnvironment;
+        return instance;
+    }
+
+    virtual void registerTestServices() override { registerTestService<IPower>(); }
+};
+
+class PowerHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+   public:
+    virtual void SetUp() override {
+        power = ::testing::VtsHalHidlTargetTestBase::getService<IPower>(
+            PowerHidlEnvironment::Instance()->getServiceName<IPower>());
+        ASSERT_NE(power, nullptr);
+    }
+
+    sp<IPower> power;
+};
+
+// Sanity check Power::PowerHintAsync_1_2 on good and bad inputs.
+TEST_F(PowerHidlTest, PowerHintAsync_1_2) {
+    std::vector<PowerHint> hints;
+    for (uint32_t i = static_cast<uint32_t>(PowerHint::VSYNC);
+         i <= static_cast<uint32_t>(PowerHint::CAMERA_SHOT); ++i) {
+        hints.emplace_back(static_cast<PowerHint>(i));
+    }
+    PowerHint badHint = static_cast<PowerHint>(0xFF);
+    hints.emplace_back(badHint);
+
+    Return<void> ret;
+    for (auto& hint : hints) {
+        ret = power->powerHintAsync_1_2(hint, 30000);
+        ASSERT_TRUE(ret.isOk());
+
+        ret = power->powerHintAsync_1_2(hint, 0);
+        ASSERT_TRUE(ret.isOk());
+    }
+
+    // Turning these hints on in different orders triggers different code paths,
+    // so iterate over possible orderings.
+    std::vector<PowerHint> hints2 = {PowerHint::AUDIO_STREAMING, PowerHint::CAMERA_LAUNCH,
+                                     PowerHint::CAMERA_STREAMING, PowerHint::CAMERA_SHOT};
+    auto compareHints = [](PowerHint l, PowerHint r) {
+        return static_cast<uint32_t>(l) < static_cast<uint32_t>(r);
+    };
+    std::sort(hints2.begin(), hints2.end(), compareHints);
+    do {
+        for (auto iter = hints2.begin(); iter != hints2.end(); iter++) {
+            ret = power->powerHintAsync_1_2(*iter, 0);
+            ASSERT_TRUE(ret.isOk());
+        }
+        for (auto iter = hints2.begin(); iter != hints2.end(); iter++) {
+            ret = power->powerHintAsync_1_2(*iter, 30000);
+            ASSERT_TRUE(ret.isOk());
+        }
+    } while (std::next_permutation(hints2.begin(), hints2.end(), compareHints));
+}
+
+int main(int argc, char** argv) {
+    ::testing::AddGlobalTestEnvironment(PowerHidlEnvironment::Instance());
+    ::testing::InitGoogleTest(&argc, argv);
+    PowerHidlEnvironment::Instance()->init(&argc, argv);
+    int status = RUN_ALL_TESTS();
+    LOG(INFO) << "Test result = " << status;
+    return status;
+}
diff --git a/radio/1.0/vts/functional/Android.bp b/radio/1.0/vts/functional/Android.bp
index 61136ae..afbb1c4 100644
--- a/radio/1.0/vts/functional/Android.bp
+++ b/radio/1.0/vts/functional/Android.bp
@@ -50,10 +50,13 @@
 
 cc_library_static {
     name: "RadioVtsTestUtilBase",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs : [
         "vts_test_util.cpp"
     ],
+    shared_libs: [
+        "android.hardware.radio@1.0",
+    ],
 }
 
 cc_library_headers {
diff --git a/radio/1.0/vts/functional/radio_hidl_hal_cell_broadcast.cpp b/radio/1.0/vts/functional/radio_hidl_hal_cell_broadcast.cpp
index a81861d..8c4ccf6 100644
--- a/radio/1.0/vts/functional/radio_hidl_hal_cell_broadcast.cpp
+++ b/radio/1.0/vts/functional/radio_hidl_hal_cell_broadcast.cpp
@@ -74,11 +74,10 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_STATE ||
-                    radioRsp->rspInfo.error == RadioError::NONE ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_MODEM_STATE);
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
+                                     {RadioError::NONE, RadioError::INVALID_ARGUMENTS,
+                                      RadioError::INVALID_MODEM_STATE, RadioError::INVALID_STATE},
+                                     CHECK_GENERAL_ERROR));
     }
 }
 
@@ -95,9 +94,10 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() || radioRsp->rspInfo.error == RadioError::INVALID_STATE ||
-                    radioRsp->rspInfo.error == RadioError::NONE ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_MODEM_STATE);
+        ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp->rspInfo.error,
+            {RadioError::NONE, RadioError::INVALID_MODEM_STATE, RadioError::INVALID_STATE},
+            CHECK_GENERAL_ERROR));
     }
 }
 
@@ -122,9 +122,9 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
-                    radioRsp->rspInfo.error == RadioError::NONE);
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
+                                     {RadioError::NONE, RadioError::INVALID_MODEM_STATE},
+                                     CHECK_GENERAL_ERROR));
     }
 }
 
@@ -141,7 +141,8 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() || radioRsp->rspInfo.error == RadioError::NONE);
+        ASSERT_TRUE(
+            CheckAnyOfErrors(radioRsp->rspInfo.error, {RadioError::NONE}, CHECK_GENERAL_ERROR));
     }
 }
 
@@ -159,9 +160,9 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
-                    radioRsp->rspInfo.error == RadioError::NONE);
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
+                                     {RadioError::NONE, RadioError::INVALID_ARGUMENTS},
+                                     CHECK_GENERAL_ERROR));
     }
 }
 
@@ -179,11 +180,10 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_STATE ||
-                    radioRsp->rspInfo.error == RadioError::NONE ||
-                    radioRsp->rspInfo.error == RadioError::OPERATION_NOT_ALLOWED ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_MODEM_STATE);
+        ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp->rspInfo.error,
+            {RadioError::NONE, RadioError::INVALID_ARGUMENTS, RadioError::INVALID_MODEM_STATE,
+             RadioError::INVALID_STATE, RadioError::OPERATION_NOT_ALLOWED},
+            CHECK_GENERAL_ERROR));
     }
 }
diff --git a/radio/1.0/vts/functional/radio_hidl_hal_data.cpp b/radio/1.0/vts/functional/radio_hidl_hal_data.cpp
index df31563..9496688 100644
--- a/radio/1.0/vts/functional/radio_hidl_hal_data.cpp
+++ b/radio/1.0/vts/functional/radio_hidl_hal_data.cpp
@@ -75,11 +75,11 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::NONE ||
-                    radioRsp->rspInfo.error == RadioError::RADIO_NOT_AVAILABLE ||
-                    radioRsp->rspInfo.error == RadioError::OP_NOT_ALLOWED_BEFORE_REG_TO_NW ||
-                    radioRsp->rspInfo.error == RadioError::OP_NOT_ALLOWED_DURING_VOICE_CALL ||
-                    CheckOEMError());
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
+                                     {RadioError::NONE, RadioError::OP_NOT_ALLOWED_BEFORE_REG_TO_NW,
+                                      RadioError::OP_NOT_ALLOWED_DURING_VOICE_CALL,
+                                      RadioError::RADIO_NOT_AVAILABLE, RadioError::SIM_ABSENT},
+                                     CHECK_OEM_ERROR));
     }
 }
 
@@ -98,10 +98,10 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::NONE ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_CALL_ID ||
-                    radioRsp->rspInfo.error == RadioError::SIM_ABSENT || CheckOEMError() ||
-                    radioRsp->rspInfo.error == RadioError::RADIO_NOT_AVAILABLE);
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
+                                     {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE,
+                                      RadioError::SIM_ABSENT, RadioError::INVALID_CALL_ID},
+                                     CHECK_OEM_ERROR));
     }
 }
 
@@ -118,8 +118,9 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::NONE ||
-                    radioRsp->rspInfo.error == RadioError::RADIO_NOT_AVAILABLE);
+        ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp->rspInfo.error,
+            {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::SIM_ABSENT}));
     }
 }
 
@@ -159,10 +160,10 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::NONE ||
-                    radioRsp->rspInfo.error == RadioError::RADIO_NOT_AVAILABLE ||
-                    radioRsp->rspInfo.error == RadioError::SUBSCRIPTION_NOT_AVAILABLE ||
-                    CheckOEMError());
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
+                                     {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE,
+                                      RadioError::SUBSCRIPTION_NOT_AVAILABLE},
+                                     CHECK_OEM_ERROR));
     }
 }
 
@@ -223,9 +224,8 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::NONE ||
-                    radioRsp->rspInfo.error == RadioError::RADIO_NOT_AVAILABLE ||
-                    radioRsp->rspInfo.error == RadioError::SIM_ABSENT ||
-                    radioRsp->rspInfo.error == RadioError::REQUEST_NOT_SUPPORTED);
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
+                                     {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE,
+                                      RadioError::SIM_ABSENT, RadioError::REQUEST_NOT_SUPPORTED}));
     }
 }
diff --git a/radio/1.0/vts/functional/radio_hidl_hal_icc.cpp b/radio/1.0/vts/functional/radio_hidl_hal_icc.cpp
index 130064a..566a516 100644
--- a/radio/1.0/vts/functional/radio_hidl_hal_icc.cpp
+++ b/radio/1.0/vts/functional/radio_hidl_hal_icc.cpp
@@ -24,300 +24,296 @@
     EXPECT_LT(cardStatus.gsmUmtsSubscriptionAppIndex, (int)RadioConst::CARD_MAX_APPS);
     EXPECT_LT(cardStatus.cdmaSubscriptionAppIndex, (int)RadioConst::CARD_MAX_APPS);
     EXPECT_LT(cardStatus.imsSubscriptionAppIndex, (int)RadioConst::CARD_MAX_APPS);
-    }
+}
 
-    /*
-     * Test IRadio.supplyIccPinForApp() for the response returned
-     */
-    TEST_F(RadioHidlTest, supplyIccPinForApp) {
-        int serial = GetRandomSerialNumber();
+/*
+ * Test IRadio.supplyIccPinForApp() for the response returned
+ */
+TEST_F(RadioHidlTest, supplyIccPinForApp) {
+    int serial = GetRandomSerialNumber();
 
-        // Pass wrong password and check PASSWORD_INCORRECT returned for 3GPP and
-        // 3GPP2 apps only
-        for (int i = 0; i < (int)cardStatus.applications.size(); i++) {
-            if (cardStatus.applications[i].appType == AppType::SIM ||
-                cardStatus.applications[i].appType == AppType::USIM ||
-                cardStatus.applications[i].appType == AppType::RUIM ||
-                cardStatus.applications[i].appType == AppType::CSIM) {
-                radio->supplyIccPinForApp(serial, hidl_string("test1"),
-                                          cardStatus.applications[i].aidPtr);
-                EXPECT_EQ(std::cv_status::no_timeout, wait());
-                EXPECT_EQ(serial, radioRsp->rspInfo.serial);
-                EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp->rspInfo.type);
-                EXPECT_EQ(RadioError::PASSWORD_INCORRECT, radioRsp->rspInfo.error);
-            }
-        }
-    }
-
-    /*
-     * Test IRadio.supplyIccPukForApp() for the response returned.
-     */
-    TEST_F(RadioHidlTest, supplyIccPukForApp) {
-        int serial = GetRandomSerialNumber();
-
-        // Pass wrong password and check PASSWORD_INCORRECT returned for 3GPP and
-        // 3GPP2 apps only
-        for (int i = 0; i < (int)cardStatus.applications.size(); i++) {
-            if (cardStatus.applications[i].appType == AppType::SIM ||
-                cardStatus.applications[i].appType == AppType::USIM ||
-                cardStatus.applications[i].appType == AppType::RUIM ||
-                cardStatus.applications[i].appType == AppType::CSIM) {
-                radio->supplyIccPukForApp(serial, hidl_string("test1"), hidl_string("test2"),
-                                          cardStatus.applications[i].aidPtr);
-                EXPECT_EQ(std::cv_status::no_timeout, wait());
-                EXPECT_EQ(serial, radioRsp->rspInfo.serial);
-                EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp->rspInfo.type);
-                EXPECT_EQ(RadioError::PASSWORD_INCORRECT, radioRsp->rspInfo.error);
-            }
-        }
-    }
-
-    /*
-     * Test IRadio.supplyIccPin2ForApp() for the response returned.
-     */
-    TEST_F(RadioHidlTest, supplyIccPin2ForApp) {
-        int serial = GetRandomSerialNumber();
-
-        // Pass wrong password and check PASSWORD_INCORRECT returned for 3GPP and
-        // 3GPP2 apps only
-        for (int i = 0; i < (int)cardStatus.applications.size(); i++) {
-            if (cardStatus.applications[i].appType == AppType::SIM ||
-                cardStatus.applications[i].appType == AppType::USIM ||
-                cardStatus.applications[i].appType == AppType::RUIM ||
-                cardStatus.applications[i].appType == AppType::CSIM) {
-                radio->supplyIccPin2ForApp(serial, hidl_string("test1"),
-                                           cardStatus.applications[i].aidPtr);
-                EXPECT_EQ(std::cv_status::no_timeout, wait());
-                EXPECT_EQ(serial, radioRsp->rspInfo.serial);
-                EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp->rspInfo.type);
-                EXPECT_EQ(RadioError::PASSWORD_INCORRECT, radioRsp->rspInfo.error);
-            }
-        }
-    }
-
-    /*
-     * Test IRadio.supplyIccPuk2ForApp() for the response returned.
-     */
-    TEST_F(RadioHidlTest, supplyIccPuk2ForApp) {
-        int serial = GetRandomSerialNumber();
-
-        // Pass wrong password and check PASSWORD_INCORRECT returned for 3GPP and
-        // 3GPP2 apps only
-        for (int i = 0; i < (int)cardStatus.applications.size(); i++) {
-            if (cardStatus.applications[i].appType == AppType::SIM ||
-                cardStatus.applications[i].appType == AppType::USIM ||
-                cardStatus.applications[i].appType == AppType::RUIM ||
-                cardStatus.applications[i].appType == AppType::CSIM) {
-                radio->supplyIccPuk2ForApp(serial, hidl_string("test1"), hidl_string("test2"),
-                                           cardStatus.applications[i].aidPtr);
-                EXPECT_EQ(std::cv_status::no_timeout, wait());
-                EXPECT_EQ(serial, radioRsp->rspInfo.serial);
-                EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp->rspInfo.type);
-                EXPECT_EQ(RadioError::PASSWORD_INCORRECT, radioRsp->rspInfo.error);
-            }
-        }
-    }
-
-    /*
-     * Test IRadio.changeIccPinForApp() for the response returned.
-     */
-    TEST_F(RadioHidlTest, changeIccPinForApp) {
-        int serial = GetRandomSerialNumber();
-
-        // Pass wrong password and check PASSWORD_INCORRECT returned for 3GPP and
-        // 3GPP2 apps only
-        for (int i = 0; i < (int)cardStatus.applications.size(); i++) {
-            if (cardStatus.applications[i].appType == AppType::SIM ||
-                cardStatus.applications[i].appType == AppType::USIM ||
-                cardStatus.applications[i].appType == AppType::RUIM ||
-                cardStatus.applications[i].appType == AppType::CSIM) {
-                radio->changeIccPinForApp(serial, hidl_string("test1"), hidl_string("test2"),
-                                          cardStatus.applications[i].aidPtr);
-                EXPECT_EQ(std::cv_status::no_timeout, wait());
-                EXPECT_EQ(serial, radioRsp->rspInfo.serial);
-                EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp->rspInfo.type);
-                EXPECT_EQ(RadioError::PASSWORD_INCORRECT, radioRsp->rspInfo.error);
-            }
-        }
-    }
-
-    /*
-     * Test IRadio.changeIccPin2ForApp() for the response returned.
-     */
-    TEST_F(RadioHidlTest, changeIccPin2ForApp) {
-        int serial = GetRandomSerialNumber();
-
-        // Pass wrong password and check PASSWORD_INCORRECT returned for 3GPP and
-        // 3GPP2 apps only
-        for (int i = 0; i < (int)cardStatus.applications.size(); i++) {
-            if (cardStatus.applications[i].appType == AppType::SIM ||
-                cardStatus.applications[i].appType == AppType::USIM ||
-                cardStatus.applications[i].appType == AppType::RUIM ||
-                cardStatus.applications[i].appType == AppType::CSIM) {
-                radio->changeIccPin2ForApp(serial, hidl_string("test1"), hidl_string("test2"),
-                                           cardStatus.applications[i].aidPtr);
-                EXPECT_EQ(std::cv_status::no_timeout, wait());
-                EXPECT_EQ(serial, radioRsp->rspInfo.serial);
-                EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp->rspInfo.type);
-                EXPECT_EQ(RadioError::PASSWORD_INCORRECT, radioRsp->rspInfo.error);
-            }
-        }
-    }
-
-    /*
-     * Test IRadio.getImsiForApp() for the response returned.
-     */
-    TEST_F(RadioHidlTest, getImsiForApp) {
-        int serial = GetRandomSerialNumber();
-
-        // Check success returned while getting imsi for 3GPP and 3GPP2 apps only
-        for (int i = 0; i < (int)cardStatus.applications.size(); i++) {
-            if (cardStatus.applications[i].appType == AppType::SIM ||
-                cardStatus.applications[i].appType == AppType::USIM ||
-                cardStatus.applications[i].appType == AppType::RUIM ||
-                cardStatus.applications[i].appType == AppType::CSIM) {
-                radio->getImsiForApp(serial, cardStatus.applications[i].aidPtr);
-                EXPECT_EQ(std::cv_status::no_timeout, wait());
-                EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp->rspInfo.type);
-                EXPECT_EQ(serial, radioRsp->rspInfo.serial);
-                EXPECT_EQ(RadioError::NONE, radioRsp->rspInfo.error);
-
-                // IMSI (MCC+MNC+MSIN) is at least 6 digits, but not more than 15
-                if (radioRsp->rspInfo.error == RadioError::NONE) {
-                    EXPECT_NE(radioRsp->imsi, hidl_string());
-                    EXPECT_GE((int)(radioRsp->imsi).size(), 6);
-                    EXPECT_LE((int)(radioRsp->imsi).size(), 15);
-                }
-            }
-        }
-    }
-
-    /*
-     * Test IRadio.iccIOForApp() for the response returned.
-     */
-    TEST_F(RadioHidlTest, iccIOForApp) {
-        int serial = GetRandomSerialNumber();
-
-        for (int i = 0; i < (int)cardStatus.applications.size(); i++) {
-            IccIo iccIo;
-            iccIo.command = 0xc0;
-            iccIo.fileId = 0x6f11;
-            iccIo.path = hidl_string("3F007FFF");
-            iccIo.p1 = 0;
-            iccIo.p2 = 0;
-            iccIo.p3 = 0;
-            iccIo.data = hidl_string();
-            iccIo.pin2 = hidl_string();
-            iccIo.aid = cardStatus.applications[i].aidPtr;
-
-            radio->iccIOForApp(serial, iccIo);
-            EXPECT_EQ(std::cv_status::no_timeout, wait());
-            EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp->rspInfo.type);
-            EXPECT_EQ(serial, radioRsp->rspInfo.serial);
-        }
-    }
-
-    /*
-     * Test IRadio.iccTransmitApduBasicChannel() for the response returned.
-     */
-    TEST_F(RadioHidlTest, iccTransmitApduBasicChannel) {
-        int serial = GetRandomSerialNumber();
-        SimApdu msg;
-        memset(&msg, 0, sizeof(msg));
-        msg.data = hidl_string();
-
-        radio->iccTransmitApduBasicChannel(serial, msg);
-        EXPECT_EQ(std::cv_status::no_timeout, wait());
-        EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp->rspInfo.type);
-        EXPECT_EQ(serial, radioRsp->rspInfo.serial);
-
-        // TODO(sanketpadawe): Add test for error code
-    }
-
-    /*
-     * Test IRadio.iccOpenLogicalChannel() for the response returned.
-     */
-    TEST_F(RadioHidlTest, iccOpenLogicalChannel) {
-        int serial = GetRandomSerialNumber();
-        int p2 = 0x04;
-        // Specified in ISO 7816-4 clause 7.1.1 0x04 means that FCP template is requested.
-        for (int i = 0; i < (int)cardStatus.applications.size(); i++) {
-            radio->iccOpenLogicalChannel(serial, cardStatus.applications[i].aidPtr, p2);
+    // Pass wrong password and check PASSWORD_INCORRECT returned for 3GPP and
+    // 3GPP2 apps only
+    for (int i = 0; i < (int)cardStatus.applications.size(); i++) {
+        if (cardStatus.applications[i].appType == AppType::SIM ||
+            cardStatus.applications[i].appType == AppType::USIM ||
+            cardStatus.applications[i].appType == AppType::RUIM ||
+            cardStatus.applications[i].appType == AppType::CSIM) {
+            radio->supplyIccPinForApp(serial, hidl_string("test1"),
+                                      cardStatus.applications[i].aidPtr);
             EXPECT_EQ(std::cv_status::no_timeout, wait());
             EXPECT_EQ(serial, radioRsp->rspInfo.serial);
             EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp->rspInfo.type);
+            EXPECT_EQ(RadioError::PASSWORD_INCORRECT, radioRsp->rspInfo.error);
         }
     }
+}
 
-    /*
-     * Test IRadio.iccCloseLogicalChannel() for the response returned.
-     */
-    TEST_F(RadioHidlTest, iccCloseLogicalChannel) {
-        int serial = GetRandomSerialNumber();
-        // Try closing invalid channel and check INVALID_ARGUMENTS returned as error
-        radio->iccCloseLogicalChannel(serial, 0);
+/*
+ * Test IRadio.supplyIccPukForApp() for the response returned.
+ */
+TEST_F(RadioHidlTest, supplyIccPukForApp) {
+    int serial = GetRandomSerialNumber();
+
+    // Pass wrong password and check PASSWORD_INCORRECT returned for 3GPP and
+    // 3GPP2 apps only
+    for (int i = 0; i < (int)cardStatus.applications.size(); i++) {
+        if (cardStatus.applications[i].appType == AppType::SIM ||
+            cardStatus.applications[i].appType == AppType::USIM ||
+            cardStatus.applications[i].appType == AppType::RUIM ||
+            cardStatus.applications[i].appType == AppType::CSIM) {
+            radio->supplyIccPukForApp(serial, hidl_string("test1"), hidl_string("test2"),
+                                      cardStatus.applications[i].aidPtr);
+            EXPECT_EQ(std::cv_status::no_timeout, wait());
+            EXPECT_EQ(serial, radioRsp->rspInfo.serial);
+            EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp->rspInfo.type);
+            EXPECT_EQ(RadioError::PASSWORD_INCORRECT, radioRsp->rspInfo.error);
+        }
+    }
+}
+
+/*
+ * Test IRadio.supplyIccPin2ForApp() for the response returned.
+ */
+TEST_F(RadioHidlTest, supplyIccPin2ForApp) {
+    int serial = GetRandomSerialNumber();
+
+    // Pass wrong password and check PASSWORD_INCORRECT returned for 3GPP and
+    // 3GPP2 apps only
+    for (int i = 0; i < (int)cardStatus.applications.size(); i++) {
+        if (cardStatus.applications[i].appType == AppType::SIM ||
+            cardStatus.applications[i].appType == AppType::USIM ||
+            cardStatus.applications[i].appType == AppType::RUIM ||
+            cardStatus.applications[i].appType == AppType::CSIM) {
+            radio->supplyIccPin2ForApp(serial, hidl_string("test1"),
+                                       cardStatus.applications[i].aidPtr);
+            EXPECT_EQ(std::cv_status::no_timeout, wait());
+            EXPECT_EQ(serial, radioRsp->rspInfo.serial);
+            EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp->rspInfo.type);
+            EXPECT_EQ(RadioError::PASSWORD_INCORRECT, radioRsp->rspInfo.error);
+        }
+    }
+}
+
+/*
+ * Test IRadio.supplyIccPuk2ForApp() for the response returned.
+ */
+TEST_F(RadioHidlTest, supplyIccPuk2ForApp) {
+    int serial = GetRandomSerialNumber();
+
+    // Pass wrong password and check PASSWORD_INCORRECT returned for 3GPP and
+    // 3GPP2 apps only
+    for (int i = 0; i < (int)cardStatus.applications.size(); i++) {
+        if (cardStatus.applications[i].appType == AppType::SIM ||
+            cardStatus.applications[i].appType == AppType::USIM ||
+            cardStatus.applications[i].appType == AppType::RUIM ||
+            cardStatus.applications[i].appType == AppType::CSIM) {
+            radio->supplyIccPuk2ForApp(serial, hidl_string("test1"), hidl_string("test2"),
+                                       cardStatus.applications[i].aidPtr);
+            EXPECT_EQ(std::cv_status::no_timeout, wait());
+            EXPECT_EQ(serial, radioRsp->rspInfo.serial);
+            EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp->rspInfo.type);
+            EXPECT_EQ(RadioError::PASSWORD_INCORRECT, radioRsp->rspInfo.error);
+        }
+    }
+}
+
+/*
+ * Test IRadio.changeIccPinForApp() for the response returned.
+ */
+TEST_F(RadioHidlTest, changeIccPinForApp) {
+    int serial = GetRandomSerialNumber();
+
+    // Pass wrong password and check PASSWORD_INCORRECT returned for 3GPP and
+    // 3GPP2 apps only
+    for (int i = 0; i < (int)cardStatus.applications.size(); i++) {
+        if (cardStatus.applications[i].appType == AppType::SIM ||
+            cardStatus.applications[i].appType == AppType::USIM ||
+            cardStatus.applications[i].appType == AppType::RUIM ||
+            cardStatus.applications[i].appType == AppType::CSIM) {
+            radio->changeIccPinForApp(serial, hidl_string("test1"), hidl_string("test2"),
+                                      cardStatus.applications[i].aidPtr);
+            EXPECT_EQ(std::cv_status::no_timeout, wait());
+            EXPECT_EQ(serial, radioRsp->rspInfo.serial);
+            EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp->rspInfo.type);
+            EXPECT_EQ(RadioError::PASSWORD_INCORRECT, radioRsp->rspInfo.error);
+        }
+    }
+}
+
+/*
+ * Test IRadio.changeIccPin2ForApp() for the response returned.
+ */
+TEST_F(RadioHidlTest, changeIccPin2ForApp) {
+    int serial = GetRandomSerialNumber();
+
+    // Pass wrong password and check PASSWORD_INCORRECT returned for 3GPP and
+    // 3GPP2 apps only
+    for (int i = 0; i < (int)cardStatus.applications.size(); i++) {
+        if (cardStatus.applications[i].appType == AppType::SIM ||
+            cardStatus.applications[i].appType == AppType::USIM ||
+            cardStatus.applications[i].appType == AppType::RUIM ||
+            cardStatus.applications[i].appType == AppType::CSIM) {
+            radio->changeIccPin2ForApp(serial, hidl_string("test1"), hidl_string("test2"),
+                                       cardStatus.applications[i].aidPtr);
+            EXPECT_EQ(std::cv_status::no_timeout, wait());
+            EXPECT_EQ(serial, radioRsp->rspInfo.serial);
+            EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp->rspInfo.type);
+            EXPECT_EQ(RadioError::PASSWORD_INCORRECT, radioRsp->rspInfo.error);
+        }
+    }
+}
+
+/*
+ * Test IRadio.getImsiForApp() for the response returned.
+ */
+TEST_F(RadioHidlTest, getImsiForApp) {
+    int serial = GetRandomSerialNumber();
+
+    // Check success returned while getting imsi for 3GPP and 3GPP2 apps only
+    for (int i = 0; i < (int)cardStatus.applications.size(); i++) {
+        if (cardStatus.applications[i].appType == AppType::SIM ||
+            cardStatus.applications[i].appType == AppType::USIM ||
+            cardStatus.applications[i].appType == AppType::RUIM ||
+            cardStatus.applications[i].appType == AppType::CSIM) {
+            radio->getImsiForApp(serial, cardStatus.applications[i].aidPtr);
+            EXPECT_EQ(std::cv_status::no_timeout, wait());
+            EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp->rspInfo.type);
+            EXPECT_EQ(serial, radioRsp->rspInfo.serial);
+            EXPECT_EQ(RadioError::NONE, radioRsp->rspInfo.error);
+
+            // IMSI (MCC+MNC+MSIN) is at least 6 digits, but not more than 15
+            if (radioRsp->rspInfo.error == RadioError::NONE) {
+                EXPECT_NE(radioRsp->imsi, hidl_string());
+                EXPECT_GE((int)(radioRsp->imsi).size(), 6);
+                EXPECT_LE((int)(radioRsp->imsi).size(), 15);
+            }
+        }
+    }
+}
+
+/*
+ * Test IRadio.iccIOForApp() for the response returned.
+ */
+TEST_F(RadioHidlTest, iccIOForApp) {
+    int serial = GetRandomSerialNumber();
+
+    for (int i = 0; i < (int)cardStatus.applications.size(); i++) {
+        IccIo iccIo;
+        iccIo.command = 0xc0;
+        iccIo.fileId = 0x6f11;
+        iccIo.path = hidl_string("3F007FFF");
+        iccIo.p1 = 0;
+        iccIo.p2 = 0;
+        iccIo.p3 = 0;
+        iccIo.data = hidl_string();
+        iccIo.pin2 = hidl_string();
+        iccIo.aid = cardStatus.applications[i].aidPtr;
+
+        radio->iccIOForApp(serial, iccIo);
         EXPECT_EQ(std::cv_status::no_timeout, wait());
         EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp->rspInfo.type);
         EXPECT_EQ(serial, radioRsp->rspInfo.serial);
+    }
+}
 
+/*
+ * Test IRadio.iccTransmitApduBasicChannel() for the response returned.
+ */
+TEST_F(RadioHidlTest, iccTransmitApduBasicChannel) {
+    int serial = GetRandomSerialNumber();
+    SimApdu msg;
+    memset(&msg, 0, sizeof(msg));
+    msg.data = hidl_string();
+
+    radio->iccTransmitApduBasicChannel(serial, msg);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp->rspInfo.serial);
+
+    // TODO(sanketpadawe): Add test for error code
+}
+
+/*
+ * Test IRadio.iccOpenLogicalChannel() for the response returned.
+ */
+TEST_F(RadioHidlTest, iccOpenLogicalChannel) {
+    int serial = GetRandomSerialNumber();
+    int p2 = 0x04;
+    // Specified in ISO 7816-4 clause 7.1.1 0x04 means that FCP template is requested.
+    for (int i = 0; i < (int)cardStatus.applications.size(); i++) {
+        radio->iccOpenLogicalChannel(serial, cardStatus.applications[i].aidPtr, p2);
+        EXPECT_EQ(std::cv_status::no_timeout, wait());
+        EXPECT_EQ(serial, radioRsp->rspInfo.serial);
+        EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp->rspInfo.type);
+    }
+}
+
+/*
+ * Test IRadio.iccCloseLogicalChannel() for the response returned.
+ */
+TEST_F(RadioHidlTest, iccCloseLogicalChannel) {
+    int serial = GetRandomSerialNumber();
+    // Try closing invalid channel and check INVALID_ARGUMENTS returned as error
+    radio->iccCloseLogicalChannel(serial, 0);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp->rspInfo.serial);
+
+    EXPECT_EQ(RadioError::INVALID_ARGUMENTS, radioRsp->rspInfo.error);
+}
+
+/*
+ * Test IRadio.iccTransmitApduLogicalChannel() for the response returned.
+ */
+TEST_F(RadioHidlTest, iccTransmitApduLogicalChannel) {
+    int serial = GetRandomSerialNumber();
+    SimApdu msg;
+    memset(&msg, 0, sizeof(msg));
+    msg.data = hidl_string();
+
+    radio->iccTransmitApduLogicalChannel(serial, msg);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp->rspInfo.serial);
+
+    // TODO(sanketpadawe): Add test for error code
+}
+
+/*
+ * Test IRadio.requestIccSimAuthentication() for the response returned.
+ */
+TEST_F(RadioHidlTest, requestIccSimAuthentication) {
+    int serial = GetRandomSerialNumber();
+
+    // Pass wrong challenge string and check RadioError::INVALID_ARGUMENTS
+    // returned as error.
+    for (int i = 0; i < (int)cardStatus.applications.size(); i++) {
+        radio->requestIccSimAuthentication(serial, 0, hidl_string("test"),
+                                           cardStatus.applications[i].aidPtr);
+        EXPECT_EQ(std::cv_status::no_timeout, wait());
+        EXPECT_EQ(serial, radioRsp->rspInfo.serial);
+        EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp->rspInfo.type);
         EXPECT_EQ(RadioError::INVALID_ARGUMENTS, radioRsp->rspInfo.error);
     }
+}
 
-    /*
-     * Test IRadio.iccTransmitApduLogicalChannel() for the response returned.
-     */
-    TEST_F(RadioHidlTest, iccTransmitApduLogicalChannel) {
-        int serial = GetRandomSerialNumber();
-        SimApdu msg;
-        memset(&msg, 0, sizeof(msg));
-        msg.data = hidl_string();
+/*
+ * Test IRadio.supplyNetworkDepersonalization() for the response returned.
+ */
+TEST_F(RadioHidlTest, supplyNetworkDepersonalization) {
+    int serial = GetRandomSerialNumber();
 
-        radio->iccTransmitApduLogicalChannel(serial, msg);
-        EXPECT_EQ(std::cv_status::no_timeout, wait());
-        EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp->rspInfo.type);
-        EXPECT_EQ(serial, radioRsp->rspInfo.serial);
+    radio->supplyNetworkDepersonalization(serial, hidl_string("test"));
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
-        // TODO(sanketpadawe): Add test for error code
+    if (cardStatus.cardState == CardState::ABSENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp->rspInfo.error,
+            {RadioError::NONE, RadioError::INVALID_ARGUMENTS, RadioError::INTERNAL_ERR,
+             RadioError::INVALID_SIM_STATE, RadioError::MODEM_ERR, RadioError::NO_MEMORY,
+             RadioError::PASSWORD_INCORRECT, RadioError::SIM_ABSENT, RadioError::SYSTEM_ERR}));
     }
-
-    /*
-     * Test IRadio.requestIccSimAuthentication() for the response returned.
-     */
-    TEST_F(RadioHidlTest, requestIccSimAuthentication) {
-        int serial = GetRandomSerialNumber();
-
-        // Pass wrong challenge string and check RadioError::INVALID_ARGUMENTS
-        // returned as error.
-        for (int i = 0; i < (int)cardStatus.applications.size(); i++) {
-            radio->requestIccSimAuthentication(serial, 0, hidl_string("test"),
-                                               cardStatus.applications[i].aidPtr);
-            EXPECT_EQ(std::cv_status::no_timeout, wait());
-            EXPECT_EQ(serial, radioRsp->rspInfo.serial);
-            EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp->rspInfo.type);
-            EXPECT_EQ(RadioError::INVALID_ARGUMENTS, radioRsp->rspInfo.error);
-        }
-    }
-
-    /*
-     * Test IRadio.supplyNetworkDepersonalization() for the response returned.
-     */
-    TEST_F(RadioHidlTest, supplyNetworkDepersonalization) {
-        int serial = GetRandomSerialNumber();
-
-        radio->supplyNetworkDepersonalization(serial, hidl_string("test"));
-        EXPECT_EQ(std::cv_status::no_timeout, wait());
-        EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp->rspInfo.type);
-        EXPECT_EQ(serial, radioRsp->rspInfo.serial);
-
-        if (cardStatus.cardState == CardState::ABSENT) {
-            ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::NONE ||
-                        radioRsp->rspInfo.error == RadioError::SYSTEM_ERR ||
-                        radioRsp->rspInfo.error == RadioError::NO_MEMORY ||
-                        radioRsp->rspInfo.error == RadioError::MODEM_ERR ||
-                        radioRsp->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
-                        radioRsp->rspInfo.error == RadioError::INVALID_SIM_STATE ||
-                        radioRsp->rspInfo.error == RadioError::PASSWORD_INCORRECT ||
-                        radioRsp->rspInfo.error == RadioError::INTERNAL_ERR ||
-                        radioRsp->rspInfo.error == RadioError::SIM_ABSENT);
-        }
 }
diff --git a/radio/1.0/vts/functional/radio_hidl_hal_ims.cpp b/radio/1.0/vts/functional/radio_hidl_hal_ims.cpp
index aa9d987..4574678 100644
--- a/radio/1.0/vts/functional/radio_hidl_hal_ims.cpp
+++ b/radio/1.0/vts/functional/radio_hidl_hal_ims.cpp
@@ -31,7 +31,8 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() || radioRsp->rspInfo.error == RadioError::MODEM_ERR);
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error, {RadioError::MODEM_ERR},
+                                     CHECK_GENERAL_ERROR));
     }
 }
 
@@ -70,9 +71,9 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
-                    radioRsp->rspInfo.error == RadioError::MODEM_ERR);
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
+                                     {RadioError::INVALID_ARGUMENTS, RadioError::MODEM_ERR},
+                                     CHECK_GENERAL_ERROR));
     }
 }
 
@@ -94,9 +95,9 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
-                    radioRsp->rspInfo.error == RadioError::MODEM_ERR);
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
+                                     {RadioError::INVALID_ARGUMENTS, RadioError::MODEM_ERR},
+                                     CHECK_GENERAL_ERROR));
     }
 }
 
@@ -116,11 +117,10 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
-                    radioRsp->rspInfo.error == RadioError::NONE ||
-                    radioRsp->rspInfo.error == RadioError::MODEM_ERR ||
-                    radioRsp->rspInfo.error == RadioError::FDN_CHECK_FAILURE);
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
+                                     {RadioError::NONE, RadioError::FDN_CHECK_FAILURE,
+                                      RadioError::INVALID_ARGUMENTS, RadioError::MODEM_ERR},
+                                     CHECK_GENERAL_ERROR));
     }
 }
 
@@ -137,7 +137,8 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() || radioRsp->rspInfo.error == RadioError::MODEM_ERR);
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error, {RadioError::MODEM_ERR},
+                                     CHECK_GENERAL_ERROR));
     }
 }
 
@@ -155,8 +156,8 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::NONE ||
-                    radioRsp->rspInfo.error == RadioError::SIM_ABSENT);
+        ASSERT_TRUE(
+            CheckAnyOfErrors(radioRsp->rspInfo.error, {RadioError::NONE, RadioError::SIM_ABSENT}));
     }
 }
 
@@ -174,7 +175,11 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() || radioRsp->rspInfo.error == RadioError::SIM_ABSENT);
+        ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp->rspInfo.error,
+            {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS, RadioError::RADIO_NOT_AVAILABLE,
+             RadioError::NO_MEMORY, RadioError::SYSTEM_ERR, RadioError::REQUEST_NOT_SUPPORTED,
+             RadioError::CANCELLED}));
     }
 }
 
@@ -191,8 +196,9 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() || radioRsp->rspInfo.error == RadioError::NONE ||
-                    radioRsp->rspInfo.error == RadioError::MODEM_ERR ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_MODEM_STATE);
+        ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp->rspInfo.error,
+            {RadioError::NONE, RadioError::MODEM_ERR, RadioError::INVALID_MODEM_STATE},
+            CHECK_GENERAL_ERROR));
     }
 }
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 8854304..cb0a730 100644
--- a/radio/1.0/vts/functional/radio_hidl_hal_misc.cpp
+++ b/radio/1.0/vts/functional/radio_hidl_hal_misc.cpp
@@ -28,7 +28,7 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::NONE);
+        EXPECT_EQ(RadioError::NONE, radioRsp->rspInfo.error);
     }
 }
 
@@ -44,7 +44,7 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::NONE);
+        EXPECT_EQ(RadioError::NONE, radioRsp->rspInfo.error);
     }
 }
 
@@ -60,7 +60,7 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::NONE);
+        EXPECT_EQ(RadioError::NONE, radioRsp->rspInfo.error);
     }
 }
 
@@ -76,7 +76,7 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::NONE);
+        EXPECT_EQ(RadioError::NONE, radioRsp->rspInfo.error);
     }
 }
 
@@ -92,7 +92,7 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::NONE);
+        EXPECT_EQ(RadioError::NONE, radioRsp->rspInfo.error);
     }
 }
 
@@ -108,10 +108,10 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() ||
-                    radioRsp->rspInfo.error == RadioError::ILLEGAL_SIM_OR_ME ||
-                    radioRsp->rspInfo.error == RadioError::NONE ||
-                    radioRsp->rspInfo.error == RadioError::OPERATION_NOT_ALLOWED);
+        ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp->rspInfo.error,
+            {RadioError::NONE, RadioError::ILLEGAL_SIM_OR_ME, RadioError::OPERATION_NOT_ALLOWED},
+            CHECK_GENERAL_ERROR));
     }
 }
 
@@ -127,11 +127,10 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
-                    radioRsp->rspInfo.error == RadioError::ILLEGAL_SIM_OR_ME ||
-                    radioRsp->rspInfo.error == RadioError::NONE ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_STATE);
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
+                                     {RadioError::NONE, RadioError::ILLEGAL_SIM_OR_ME,
+                                      RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE},
+                                     CHECK_GENERAL_ERROR));
     }
 }
 
@@ -148,11 +147,11 @@
                 radioRsp->rspInfo.type == RadioResponseType::SOLICITED_ACK_EXP);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() || radioRsp->rspInfo.error == RadioError::NONE ||
-                    radioRsp->rspInfo.error == RadioError::DEVICE_IN_USE ||
-                    radioRsp->rspInfo.error == RadioError::CANCELLED ||
-                    radioRsp->rspInfo.error == RadioError::OPERATION_NOT_ALLOWED ||
-                    radioRsp->rspInfo.error == RadioError::MODEM_ERR);
+        ASSERT_TRUE(
+            CheckAnyOfErrors(radioRsp->rspInfo.error,
+                             {RadioError::NONE, RadioError::CANCELLED, RadioError::DEVICE_IN_USE,
+                              RadioError::MODEM_ERR, RadioError::OPERATION_NOT_ALLOWED},
+                             CHECK_GENERAL_ERROR));
   }
 }
 
@@ -168,7 +167,7 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::NONE);
+        EXPECT_EQ(RadioError::NONE, radioRsp->rspInfo.error);
     }
 }
 
@@ -184,7 +183,8 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() || radioRsp->rspInfo.error == RadioError::NONE);
+        ASSERT_TRUE(
+            CheckAnyOfErrors(radioRsp->rspInfo.error, {RadioError::NONE}, CHECK_GENERAL_ERROR));
     }
 }
 
@@ -200,7 +200,7 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::NONE);
+        EXPECT_EQ(RadioError::NONE, radioRsp->rspInfo.error);
     }
 }
 
@@ -216,7 +216,8 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() || radioRsp->rspInfo.error == RadioError::NONE);
+        ASSERT_TRUE(
+            CheckAnyOfErrors(radioRsp->rspInfo.error, {RadioError::NONE}, CHECK_GENERAL_ERROR));
     }
 }
 
@@ -232,7 +233,7 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::NONE);
+        EXPECT_EQ(RadioError::NONE, radioRsp->rspInfo.error);
     }
 }
 
@@ -248,8 +249,9 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::NONE ||
-                    radioRsp->rspInfo.error == RadioError::SIM_ABSENT);
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
+                                     {RadioError::NONE, RadioError::SIM_ABSENT},
+                                     CHECK_GENERAL_ERROR));
     }
 }
 
@@ -265,8 +267,8 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::NONE ||
-                    radioRsp->rspInfo.error == RadioError::SIM_ABSENT);
+        ASSERT_TRUE(
+            CheckAnyOfErrors(radioRsp->rspInfo.error, {RadioError::NONE, RadioError::SIM_ABSENT}));
     }
 }
 
@@ -282,9 +284,9 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::NONE ||
-                    radioRsp->rspInfo.error == RadioError::REQUEST_NOT_SUPPORTED ||
-                    radioRsp->rspInfo.error == RadioError::SIM_ABSENT);
+        ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp->rspInfo.error,
+            {RadioError::NONE, RadioError::SIM_ABSENT, RadioError::REQUEST_NOT_SUPPORTED}));
     }
 }
 
@@ -300,9 +302,10 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() || radioRsp->rspInfo.error == RadioError::NONE ||
-                    radioRsp->rspInfo.error == RadioError::MODEM_ERR ||
-                    radioRsp->rspInfo.error == RadioError::SIM_ABSENT);
+        ASSERT_TRUE(
+            CheckAnyOfErrors(radioRsp->rspInfo.error,
+                             {RadioError::NONE, RadioError::SIM_ABSENT, RadioError::MODEM_ERR},
+                             CHECK_GENERAL_ERROR));
     }
 }
 
@@ -318,7 +321,7 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::NONE);
+        EXPECT_EQ(RadioError::NONE, radioRsp->rspInfo.error);
     }
 }
 
@@ -334,7 +337,7 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::NONE);
+        EXPECT_EQ(RadioError::NONE, radioRsp->rspInfo.error);
     }
 }
 
@@ -350,8 +353,8 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::NONE ||
-                    radioRsp->rspInfo.error == RadioError::REQUEST_NOT_SUPPORTED);
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
+                                     {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
     }
 }
 
@@ -367,8 +370,8 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::NONE ||
-                    radioRsp->rspInfo.error == RadioError::REQUEST_NOT_SUPPORTED);
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
+                                     {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
     }
 }
 
@@ -384,9 +387,9 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::NONE ||
-                    radioRsp->rspInfo.error == RadioError::REQUEST_NOT_SUPPORTED ||
-                    radioRsp->rspInfo.error == RadioError::SIM_ABSENT);
+        ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp->rspInfo.error,
+            {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED, RadioError::SIM_ABSENT}));
     }
 }
 
@@ -402,8 +405,8 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::NONE ||
-                    radioRsp->rspInfo.error == RadioError::EMPTY_RECORD);
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
+                                     {RadioError::NONE, RadioError::EMPTY_RECORD}));
     }
 }
 
@@ -419,9 +422,9 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::NONE ||
-                    radioRsp->rspInfo.error == RadioError::REQUEST_NOT_SUPPORTED ||
-                    radioRsp->rspInfo.error == RadioError::SIM_ABSENT);
+        ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp->rspInfo.error,
+            {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED, RadioError::SIM_ABSENT}));
     }
 }
 
@@ -437,9 +440,9 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::NONE ||
-                    radioRsp->rspInfo.error == RadioError::REQUEST_NOT_SUPPORTED ||
-                    radioRsp->rspInfo.error == RadioError::SIM_ABSENT);
+        ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp->rspInfo.error,
+            {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED, RadioError::SIM_ABSENT}));
     }
 }
 
@@ -455,10 +458,10 @@
     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::SIM_ABSENT ||
-                    radioRsp->rspInfo.error == RadioError::SUBSCRIPTION_NOT_AVAILABLE ||
-                    radioRsp->rspInfo.error == RadioError::NONE);
+        ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp->rspInfo.error,
+            {RadioError::NONE, RadioError::SIM_ABSENT, RadioError::SUBSCRIPTION_NOT_AVAILABLE},
+            CHECK_GENERAL_ERROR));
     }
 }
 
@@ -474,7 +477,7 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::NONE);
+        EXPECT_EQ(RadioError::NONE, radioRsp->rspInfo.error);
     }
 }
 
@@ -490,8 +493,9 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() || radioRsp->rspInfo.error == RadioError::NONE ||
-                    radioRsp->rspInfo.error == RadioError::NO_NETWORK_FOUND);
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
+                                     {RadioError::NONE, RadioError::NO_NETWORK_FOUND},
+                                     CHECK_GENERAL_ERROR));
     }
 }
 
@@ -508,8 +512,8 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::NONE ||
-                    radioRsp->rspInfo.error == RadioError::REQUEST_NOT_SUPPORTED);
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
+                                     {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
     }
 }
 
@@ -525,7 +529,8 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() || radioRsp->rspInfo.error == RadioError::NONE);
+        ASSERT_TRUE(
+            CheckAnyOfErrors(radioRsp->rspInfo.error, {RadioError::NONE}, CHECK_GENERAL_ERROR));
     }
 }
 
@@ -544,7 +549,8 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() || radioRsp->rspInfo.error == RadioError::NONE);
+        ASSERT_TRUE(
+            CheckAnyOfErrors(radioRsp->rspInfo.error, {RadioError::NONE}, CHECK_GENERAL_ERROR));
     }
 }
 
@@ -561,7 +567,8 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() || radioRsp->rspInfo.error == RadioError::NONE);
+        ASSERT_TRUE(
+            CheckAnyOfErrors(radioRsp->rspInfo.error, {RadioError::NONE}, CHECK_GENERAL_ERROR));
     }
 }
 
@@ -577,8 +584,8 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::NONE ||
-                    radioRsp->rspInfo.error == RadioError::REQUEST_NOT_SUPPORTED);
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
+                                     {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
     }
 }
 
@@ -596,11 +603,11 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
-                    radioRsp->rspInfo.error == RadioError::NONE ||
-                    radioRsp->rspInfo.error == RadioError::SUBSCRIPTION_NOT_SUPPORTED ||
-                    radioRsp->rspInfo.error == RadioError::MODEM_ERR);
+        ASSERT_TRUE(
+            CheckAnyOfErrors(radioRsp->rspInfo.error,
+                             {RadioError::NONE, RadioError::INVALID_ARGUMENTS,
+                              RadioError::MODEM_ERR, RadioError::SUBSCRIPTION_NOT_SUPPORTED},
+                             CHECK_GENERAL_ERROR));
     }
 }
 
@@ -616,7 +623,8 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() || radioRsp->rspInfo.error == RadioError::NONE);
+        ASSERT_TRUE(
+            CheckAnyOfErrors(radioRsp->rspInfo.error, {RadioError::NONE}, CHECK_GENERAL_ERROR));
     }
 }
 
@@ -632,7 +640,8 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() || radioRsp->rspInfo.error == RadioError::NONE);
+        ASSERT_TRUE(
+            CheckAnyOfErrors(radioRsp->rspInfo.error, {RadioError::NONE}, CHECK_GENERAL_ERROR));
     }
 }
 
@@ -648,7 +657,7 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::NONE);
+        EXPECT_EQ(RadioError::NONE, radioRsp->rspInfo.error);
     }
 }
 
@@ -667,9 +676,9 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_STATE);
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
+                                     {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE},
+                                     CHECK_GENERAL_ERROR));
     }
 }
 
@@ -685,9 +694,9 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::RADIO_NOT_AVAILABLE ||
-                    radioRsp->rspInfo.error == RadioError::LCE_NOT_SUPPORTED ||
-                    radioRsp->rspInfo.error == RadioError::INTERNAL_ERR);
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
+                                     {RadioError::INTERNAL_ERR, RadioError::LCE_NOT_SUPPORTED,
+                                      RadioError::RADIO_NOT_AVAILABLE, RadioError::SIM_ABSENT}));
     }
 }
 
@@ -703,9 +712,9 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::NONE ||
-                    radioRsp->rspInfo.error == RadioError::LCE_NOT_SUPPORTED ||
-                    radioRsp->rspInfo.error == RadioError::REQUEST_NOT_SUPPORTED);
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
+                                     {RadioError::NONE, RadioError::LCE_NOT_SUPPORTED,
+                                      RadioError::REQUEST_NOT_SUPPORTED, RadioError::SIM_ABSENT}));
     }
 }
 
@@ -721,9 +730,10 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::RADIO_NOT_AVAILABLE || CheckOEMError() ||
-                    radioRsp->rspInfo.error == RadioError::INTERNAL_ERR ||
-                    radioRsp->rspInfo.error == RadioError::NONE);
+        ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp->rspInfo.error,
+            {RadioError::NONE, RadioError::INTERNAL_ERR, RadioError::RADIO_NOT_AVAILABLE},
+            CHECK_OEM_ERROR));
     }
 }
 
@@ -739,8 +749,8 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::NONE ||
-                    radioRsp->rspInfo.error == RadioError::REQUEST_NOT_SUPPORTED);
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
+                                     {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
     }
 }
 
@@ -764,8 +774,8 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::NONE ||
-                    radioRsp->rspInfo.error == RadioError::REQUEST_NOT_SUPPORTED);
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
+                                     {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
     }
 
     /* Reset back to no carrier restriction */
@@ -779,8 +789,8 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::NONE ||
-                    radioRsp->rspInfo.error == RadioError::REQUEST_NOT_SUPPORTED);
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
+                                     {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
     }
 }
 
@@ -796,8 +806,8 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::NONE ||
-                    radioRsp->rspInfo.error == RadioError::REQUEST_NOT_SUPPORTED);
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
+                                     {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
     }
 }
 
@@ -815,8 +825,8 @@
     std::cout << static_cast<int>(radioRsp->rspInfo.error) << std::endl;
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::NONE ||
-                    radioRsp->rspInfo.error == RadioError::REQUEST_NOT_SUPPORTED);
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
+                                     {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
     }
 }
 
@@ -834,8 +844,8 @@
     std::cout << static_cast<int>(radioRsp->rspInfo.error) << std::endl;
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::NONE ||
-                    radioRsp->rspInfo.error == RadioError::REQUEST_NOT_SUPPORTED);
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
+                                     {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
     }
 }
 
@@ -851,7 +861,7 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::NONE ||
-                    radioRsp->rspInfo.error == RadioError::REQUEST_NOT_SUPPORTED);
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
+                                     {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
     }
-}
\ No newline at end of file
+}
diff --git a/radio/1.0/vts/functional/radio_hidl_hal_sms.cpp b/radio/1.0/vts/functional/radio_hidl_hal_sms.cpp
index 271a23a..469f03a 100644
--- a/radio/1.0/vts/functional/radio_hidl_hal_sms.cpp
+++ b/radio/1.0/vts/functional/radio_hidl_hal_sms.cpp
@@ -34,9 +34,10 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_STATE);
+        ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp->rspInfo.error,
+            {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE, RadioError::SIM_ABSENT},
+            CHECK_GENERAL_ERROR));
         EXPECT_EQ(0, radioRsp->sendSmsResult.errorCode);
     }
 }
@@ -60,9 +61,10 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_STATE);
+        ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp->rspInfo.error,
+            {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE, RadioError::SIM_ABSENT},
+            CHECK_GENERAL_ERROR));
     }
 }
 
@@ -81,9 +83,9 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_STATE);
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
+                                     {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE},
+                                     CHECK_GENERAL_ERROR));
     }
 }
 
@@ -143,9 +145,10 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_STATE);
+        ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp->rspInfo.error,
+            {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE, RadioError::SIM_ABSENT},
+            CHECK_GENERAL_ERROR));
     }
 }
 
@@ -167,9 +170,9 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
-                    radioRsp->rspInfo.error == RadioError::NO_SMS_TO_ACK);
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
+                                     {RadioError::INVALID_ARGUMENTS, RadioError::NO_SMS_TO_ACK},
+                                     CHECK_GENERAL_ERROR));
     }
 }
 
@@ -218,8 +221,8 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_ARGUMENTS);
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error, {RadioError::INVALID_ARGUMENTS},
+                                     CHECK_GENERAL_ERROR));
     }
 }
 
@@ -236,8 +239,10 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() || radioRsp->rspInfo.error == RadioError::INVALID_STATE ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_MODEM_STATE);
+        ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp->rspInfo.error,
+            {RadioError::INVALID_MODEM_STATE, RadioError::INVALID_STATE, RadioError::SIM_ABSENT},
+            CHECK_GENERAL_ERROR));
     }
 }
 
@@ -255,9 +260,10 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_SMS_FORMAT);
+        ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp->rspInfo.error,
+            {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_SMS_FORMAT, RadioError::SIM_ABSENT},
+            CHECK_GENERAL_ERROR));
     }
 }
 
@@ -278,14 +284,12 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
-                    radioRsp->rspInfo.error == RadioError::NONE ||
-                    radioRsp->rspInfo.error == RadioError::MODEM_ERR ||
-                    radioRsp->rspInfo.error == RadioError::ENCODING_ERR ||
-                    radioRsp->rspInfo.error == RadioError::NO_RESOURCES ||
-                    radioRsp->rspInfo.error == RadioError::NETWORK_NOT_READY ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_SMSC_ADDRESS);
+        ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp->rspInfo.error,
+            {RadioError::NONE, RadioError::ENCODING_ERR, RadioError::INVALID_ARGUMENTS,
+             RadioError::INVALID_SMSC_ADDRESS, RadioError::MODEM_ERR, RadioError::NETWORK_NOT_READY,
+             RadioError::NO_RESOURCES, RadioError::SIM_ABSENT},
+            CHECK_GENERAL_ERROR));
     }
 }
 
@@ -303,12 +307,12 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
-                    radioRsp->rspInfo.error == RadioError::NONE ||
-                    radioRsp->rspInfo.error == RadioError::MODEM_ERR ||
-                    radioRsp->rspInfo.error == RadioError::NO_SUCH_ENTRY ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_MODEM_STATE);
+        ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp->rspInfo.error,
+            {RadioError::NONE, RadioError::ENCODING_ERR, RadioError::INVALID_ARGUMENTS,
+             RadioError::INVALID_MODEM_STATE, RadioError::NO_SUCH_ENTRY, RadioError::MODEM_ERR,
+             RadioError::SIM_ABSENT},
+            CHECK_GENERAL_ERROR));
     }
 }
 
@@ -354,14 +358,12 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_STATE ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_SMS_FORMAT ||
-                    radioRsp->rspInfo.error == RadioError::NONE ||
-                    radioRsp->rspInfo.error == RadioError::MODEM_ERR ||
-                    radioRsp->rspInfo.error == RadioError::NO_SUCH_ENTRY ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_SMSC_ADDRESS);
+        ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp->rspInfo.error,
+            {RadioError::NONE, RadioError::INVALID_ARGUMENTS, RadioError::INVALID_SMS_FORMAT,
+             RadioError::INVALID_SMSC_ADDRESS, RadioError::INVALID_STATE, RadioError::MODEM_ERR,
+             RadioError::NO_SUCH_ENTRY, RadioError::SIM_ABSENT},
+            CHECK_GENERAL_ERROR));
     }
 }
 
@@ -408,12 +410,11 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
-                    radioRsp->rspInfo.error == RadioError::NONE ||
-                    radioRsp->rspInfo.error == RadioError::MODEM_ERR ||
-                    radioRsp->rspInfo.error == RadioError::NO_SUCH_ENTRY ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_MODEM_STATE);
+        ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp->rspInfo.error,
+            {RadioError::NONE, RadioError::INVALID_ARGUMENTS, RadioError::INVALID_MODEM_STATE,
+             RadioError::MODEM_ERR, RadioError::NO_SUCH_ENTRY, RadioError::SIM_ABSENT},
+            CHECK_GENERAL_ERROR));
     }
 }
 
@@ -431,9 +432,9 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_STATE ||
-                    radioRsp->rspInfo.error == RadioError::MODEM_ERR);
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
+                                     {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE,
+                                      RadioError::MODEM_ERR, RadioError::SIM_ABSENT},
+                                     CHECK_GENERAL_ERROR));
     }
 }
diff --git a/radio/1.0/vts/functional/radio_hidl_hal_stk.cpp b/radio/1.0/vts/functional/radio_hidl_hal_stk.cpp
index c3f7549..411d74c 100644
--- a/radio/1.0/vts/functional/radio_hidl_hal_stk.cpp
+++ b/radio/1.0/vts/functional/radio_hidl_hal_stk.cpp
@@ -34,12 +34,10 @@
     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 ||
-                    radioRsp->rspInfo.error == RadioError::MODEM_ERR ||
-                    radioRsp->rspInfo.error == RadioError::SIM_ABSENT);
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
+                                     {RadioError::NONE, RadioError::INVALID_ARGUMENTS,
+                                      RadioError::MODEM_ERR, RadioError::SIM_ABSENT},
+                                     CHECK_GENERAL_ERROR));
     }
 }
 
@@ -59,11 +57,10 @@
     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 ||
-                    radioRsp->rspInfo.error == RadioError::SIM_ABSENT);
+        ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp->rspInfo.error,
+            {RadioError::NONE, RadioError::INVALID_ARGUMENTS, RadioError::SIM_ABSENT},
+            CHECK_GENERAL_ERROR));
     }
 }
 
@@ -81,10 +78,10 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() || radioRsp->rspInfo.error == RadioError::NONE ||
-                    radioRsp->rspInfo.error == RadioError::MODEM_ERR ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
-                    radioRsp->rspInfo.error == RadioError::SIM_ABSENT);
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
+                                     {RadioError::NONE, RadioError::INVALID_ARGUMENTS,
+                                      RadioError::MODEM_ERR, RadioError::SIM_ABSENT},
+                                     CHECK_GENERAL_ERROR));
     }
 }
 
@@ -101,7 +98,8 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() || radioRsp->rspInfo.error == RadioError::NONE);
+        ASSERT_TRUE(
+            CheckAnyOfErrors(radioRsp->rspInfo.error, {RadioError::NONE}, CHECK_GENERAL_ERROR));
     }
 }
 
@@ -122,8 +120,9 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
-                    radioRsp->rspInfo.error == RadioError::MODEM_ERR);
+        ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp->rspInfo.error,
+            {RadioError::INVALID_ARGUMENTS, RadioError::MODEM_ERR, RadioError::SIM_ABSENT},
+            CHECK_GENERAL_ERROR));
     }
 }
diff --git a/radio/1.0/vts/functional/radio_hidl_hal_test.cpp b/radio/1.0/vts/functional/radio_hidl_hal_test.cpp
index 060b9ee..247e12c 100644
--- a/radio/1.0/vts/functional/radio_hidl_hal_test.cpp
+++ b/radio/1.0/vts/functional/radio_hidl_hal_test.cpp
@@ -69,18 +69,4 @@
     }
     count--;
     return status;
-}
-
-bool RadioHidlTest::CheckGeneralError() {
-    return (radioRsp->rspInfo.error == RadioError::RADIO_NOT_AVAILABLE ||
-            radioRsp->rspInfo.error == RadioError::NO_MEMORY ||
-            radioRsp->rspInfo.error == RadioError::INTERNAL_ERR ||
-            radioRsp->rspInfo.error == RadioError::SYSTEM_ERR ||
-            radioRsp->rspInfo.error == RadioError::REQUEST_NOT_SUPPORTED ||
-            radioRsp->rspInfo.error == RadioError::CANCELLED);
-}
-
-bool RadioHidlTest::CheckOEMError() {
-    return (radioRsp->rspInfo.error >= RadioError::OEM_ERROR_1 &&
-            radioRsp->rspInfo.error <= RadioError::OEM_ERROR_25);
-}
+}
\ No newline at end of file
diff --git a/radio/1.0/vts/functional/radio_hidl_hal_utils_v1_0.h b/radio/1.0/vts/functional/radio_hidl_hal_utils_v1_0.h
index 2a7487f..a5e8701 100644
--- a/radio/1.0/vts/functional/radio_hidl_hal_utils_v1_0.h
+++ b/radio/1.0/vts/functional/radio_hidl_hal_utils_v1_0.h
@@ -529,12 +529,6 @@
     /* Test code calls this function to wait for response */
     std::cv_status wait(int sec = TIMEOUT_PERIOD);
 
-    /* Used for checking General Errors */
-    bool CheckGeneralError();
-
-    /* Used for checking OEM Errors */
-    bool CheckOEMError();
-
     sp<IRadio> radio;
     sp<RadioResponse> radioRsp;
     sp<RadioIndication> radioInd;
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 1d2f199..b3d5648 100644
--- a/radio/1.0/vts/functional/radio_hidl_hal_voice.cpp
+++ b/radio/1.0/vts/functional/radio_hidl_hal_voice.cpp
@@ -28,7 +28,7 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::NONE);
+        EXPECT_EQ(RadioError::NONE, radioRsp->rspInfo.error);
     }
 }
 
@@ -48,18 +48,14 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_STATE ||
-                    radioRsp->rspInfo.error == RadioError::MODEM_ERR ||
-                    radioRsp->rspInfo.error == RadioError::FDN_CHECK_FAILURE ||
-                    radioRsp->rspInfo.error == RadioError::NO_SUBSCRIPTION ||
-                    radioRsp->rspInfo.error == RadioError::NO_NETWORK_FOUND ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_CALL_ID ||
-                    radioRsp->rspInfo.error == RadioError::DEVICE_IN_USE ||
-                    radioRsp->rspInfo.error == RadioError::OPERATION_NOT_ALLOWED ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_MODEM_STATE ||
-                    radioRsp->rspInfo.error == RadioError::CANCELLED);
+        ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp->rspInfo.error,
+            {RadioError::CANCELLED, RadioError::DEVICE_IN_USE, RadioError::FDN_CHECK_FAILURE,
+             RadioError::INVALID_ARGUMENTS, RadioError::INVALID_CALL_ID,
+             RadioError::INVALID_MODEM_STATE, RadioError::INVALID_STATE, RadioError::MODEM_ERR,
+             RadioError::NO_NETWORK_FOUND, RadioError::NO_SUBSCRIPTION,
+             RadioError::OPERATION_NOT_ALLOWED},
+            CHECK_GENERAL_ERROR));
     }
 }
 
@@ -75,10 +71,10 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_STATE ||
-                    radioRsp->rspInfo.error == RadioError::MODEM_ERR);
+        ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp->rspInfo.error,
+            {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE, RadioError::MODEM_ERR},
+            CHECK_GENERAL_ERROR));
     }
 }
 
@@ -94,8 +90,9 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() || radioRsp->rspInfo.error == RadioError::INVALID_STATE ||
-                    radioRsp->rspInfo.error == RadioError::MODEM_ERR);
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
+                                     {RadioError::INVALID_STATE, RadioError::MODEM_ERR},
+                                     CHECK_GENERAL_ERROR));
     }
 }
 
@@ -111,8 +108,9 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() || radioRsp->rspInfo.error == RadioError::INVALID_STATE ||
-                    radioRsp->rspInfo.error == RadioError::MODEM_ERR);
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
+                                     {RadioError::INVALID_STATE, RadioError::MODEM_ERR},
+                                     CHECK_GENERAL_ERROR));
     }
 }
 
@@ -128,8 +126,9 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() || radioRsp->rspInfo.error == RadioError::INVALID_STATE ||
-                    radioRsp->rspInfo.error == RadioError::MODEM_ERR);
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
+                                     {RadioError::INVALID_STATE, RadioError::MODEM_ERR},
+                                     CHECK_GENERAL_ERROR));
     }
 }
 
@@ -145,8 +144,9 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() || radioRsp->rspInfo.error == RadioError::INVALID_STATE ||
-                    radioRsp->rspInfo.error == RadioError::MODEM_ERR);
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
+                                     {RadioError::INVALID_STATE, RadioError::MODEM_ERR},
+                                     CHECK_GENERAL_ERROR));
     }
 }
 
@@ -162,8 +162,9 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() || radioRsp->rspInfo.error == RadioError::INVALID_STATE ||
-                    radioRsp->rspInfo.error == RadioError::MODEM_ERR);
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
+                                     {RadioError::INVALID_STATE, RadioError::MODEM_ERR},
+                                     CHECK_GENERAL_ERROR));
     }
 }
 
@@ -179,7 +180,8 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() || radioRsp->rspInfo.error == RadioError::NONE);
+        ASSERT_TRUE(
+            CheckAnyOfErrors(radioRsp->rspInfo.error, {RadioError::NONE}, CHECK_GENERAL_ERROR));
     }
 }
 
@@ -194,10 +196,10 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_STATE ||
-                    radioRsp->rspInfo.error == RadioError::MODEM_ERR);
+        ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp->rspInfo.error,
+            {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE, RadioError::MODEM_ERR},
+            CHECK_GENERAL_ERROR));
     }
 }
 
@@ -213,9 +215,10 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() || radioRsp->rspInfo.error == RadioError::INVALID_STATE ||
-                    radioRsp->rspInfo.error == RadioError::MODEM_ERR ||
-                    radioRsp->rspInfo.error == RadioError::NONE);
+        ASSERT_TRUE(
+            CheckAnyOfErrors(radioRsp->rspInfo.error,
+                             {RadioError::NONE, RadioError::INVALID_STATE, RadioError::MODEM_ERR},
+                             CHECK_GENERAL_ERROR));
     }
 }
 
@@ -234,10 +237,10 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_STATE ||
-                    radioRsp->rspInfo.error == RadioError::MODEM_ERR);
+        ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp->rspInfo.error,
+            {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE, RadioError::MODEM_ERR},
+            CHECK_GENERAL_ERROR));
     }
 }
 
@@ -256,10 +259,10 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_STATE ||
-                    radioRsp->rspInfo.error == RadioError::MODEM_ERR);
+        ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp->rspInfo.error,
+            {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE, RadioError::MODEM_ERR},
+            CHECK_GENERAL_ERROR));
     }
 }
 
@@ -275,10 +278,10 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
-                    radioRsp->rspInfo.error == RadioError::NONE ||
-                    radioRsp->rspInfo.error == RadioError::MODEM_ERR);
+        ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp->rspInfo.error,
+            {RadioError::NONE, RadioError::INVALID_ARGUMENTS, RadioError::MODEM_ERR},
+            CHECK_GENERAL_ERROR));
     }
 }
 
@@ -294,10 +297,10 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_STATE ||
-                    radioRsp->rspInfo.error == RadioError::MODEM_ERR);
+        ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp->rspInfo.error,
+            {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE, RadioError::MODEM_ERR},
+            CHECK_GENERAL_ERROR));
     }
 }
 
@@ -313,8 +316,9 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() || radioRsp->rspInfo.error == RadioError::INVALID_STATE ||
-                    radioRsp->rspInfo.error == RadioError::MODEM_ERR);
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
+                                     {RadioError::INVALID_STATE, RadioError::MODEM_ERR},
+                                     CHECK_GENERAL_ERROR));
     }
 }
 
@@ -330,10 +334,10 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_STATE ||
-                    radioRsp->rspInfo.error == RadioError::MODEM_ERR);
+        ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp->rspInfo.error,
+            {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE, RadioError::MODEM_ERR},
+            CHECK_GENERAL_ERROR));
     }
 }
 
@@ -349,8 +353,9 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() || radioRsp->rspInfo.error == RadioError::INVALID_STATE ||
-                    radioRsp->rspInfo.error == RadioError::MODEM_ERR);
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
+                                     {RadioError::INVALID_STATE, RadioError::MODEM_ERR},
+                                     CHECK_GENERAL_ERROR));
     }
 }
 
@@ -366,14 +371,11 @@
     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 ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_CALL_ID ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_MODEM_STATE ||
-                    radioRsp->rspInfo.error == RadioError::MODEM_ERR ||
-                    radioRsp->rspInfo.error == RadioError::OPERATION_NOT_ALLOWED);
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
+                                     {RadioError::NONE, RadioError::INVALID_ARGUMENTS,
+                                      RadioError::INVALID_CALL_ID, RadioError::INVALID_MODEM_STATE,
+                                      RadioError::MODEM_ERR, RadioError::OPERATION_NOT_ALLOWED},
+                                     CHECK_GENERAL_ERROR));
     }
 }
 
@@ -389,12 +391,11 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
-                    radioRsp->rspInfo.error == RadioError::NONE ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_CALL_ID ||
-                    radioRsp->rspInfo.error == RadioError::MODEM_ERR ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_MODEM_STATE);
+        ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp->rspInfo.error,
+            {RadioError::NONE, RadioError::INVALID_ARGUMENTS, RadioError::INVALID_CALL_ID,
+             RadioError::INVALID_MODEM_STATE, RadioError::MODEM_ERR},
+            CHECK_GENERAL_ERROR));
     }
 }
 
@@ -410,12 +411,11 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
-                    radioRsp->rspInfo.error == RadioError::NONE ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_CALL_ID ||
-                    radioRsp->rspInfo.error == RadioError::MODEM_ERR ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_MODEM_STATE);
+        ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp->rspInfo.error,
+            {RadioError::NONE, RadioError::INVALID_ARGUMENTS, RadioError::INVALID_CALL_ID,
+             RadioError::INVALID_MODEM_STATE, RadioError::MODEM_ERR},
+            CHECK_GENERAL_ERROR));
     }
 }
 
@@ -431,10 +431,10 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() || radioRsp->rspInfo.error == RadioError::NONE ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_CALL_ID ||
-                    radioRsp->rspInfo.error == RadioError::MODEM_ERR ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_MODEM_STATE);
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
+                                     {RadioError::NONE, RadioError::INVALID_CALL_ID,
+                                      RadioError::INVALID_MODEM_STATE, RadioError::MODEM_ERR},
+                                     CHECK_GENERAL_ERROR));
     }
 }
 
@@ -450,9 +450,9 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
-                    radioRsp->rspInfo.error == RadioError::NONE);
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
+                                     {RadioError::NONE, RadioError::INVALID_ARGUMENTS},
+                                     CHECK_GENERAL_ERROR));
     }
 }
 
@@ -468,7 +468,7 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp->rspInfo.error == RadioError::NONE);
+        EXPECT_EQ(RadioError::NONE, radioRsp->rspInfo.error);
     }
 }
 
@@ -484,10 +484,9 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(CheckGeneralError() ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
-                    radioRsp->rspInfo.error == RadioError::INVALID_STATE ||
-                    radioRsp->rspInfo.error == RadioError::MODEM_ERR ||
-                    radioRsp->rspInfo.error == RadioError::OPERATION_NOT_ALLOWED);
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
+                                     {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE,
+                                      RadioError::MODEM_ERR, RadioError::OPERATION_NOT_ALLOWED},
+                                     CHECK_GENERAL_ERROR));
     }
 }
\ No newline at end of file
diff --git a/radio/1.0/vts/functional/sap_hidl_hal_api.cpp b/radio/1.0/vts/functional/sap_hidl_hal_api.cpp
index bb61487..d0788dd 100644
--- a/radio/1.0/vts/functional/sap_hidl_hal_api.cpp
+++ b/radio/1.0/vts/functional/sap_hidl_hal_api.cpp
@@ -51,10 +51,10 @@
     EXPECT_EQ(std::cv_status::no_timeout, wait());
     EXPECT_EQ(sapCb->sapResponseToken, token);
 
-    ASSERT_TRUE(SapResultCode::GENERIC_FAILURE == sapCb->sapResultCode ||
-                SapResultCode::CARD_NOT_ACCESSSIBLE == sapCb->sapResultCode ||
-                SapResultCode::CARD_ALREADY_POWERED_OFF == sapCb->sapResultCode ||
-                SapResultCode::CARD_REMOVED == sapCb->sapResultCode);
+    ASSERT_TRUE(
+        CheckAnyOfErrors(sapCb->sapResultCode,
+                         {SapResultCode::GENERIC_FAILURE, SapResultCode::CARD_ALREADY_POWERED_OFF,
+                          SapResultCode::CARD_NOT_ACCESSSIBLE, SapResultCode::CARD_REMOVED}));
 }
 
 /*
@@ -67,10 +67,10 @@
     EXPECT_EQ(std::cv_status::no_timeout, wait());
     EXPECT_EQ(sapCb->sapResponseToken, token);
 
-    ASSERT_TRUE(SapResultCode::GENERIC_FAILURE == sapCb->sapResultCode ||
-                SapResultCode::DATA_NOT_AVAILABLE == sapCb->sapResultCode ||
-                SapResultCode::CARD_ALREADY_POWERED_OFF == sapCb->sapResultCode ||
-                SapResultCode::CARD_REMOVED == sapCb->sapResultCode);
+    ASSERT_TRUE(
+        CheckAnyOfErrors(sapCb->sapResultCode,
+                         {SapResultCode::GENERIC_FAILURE, SapResultCode::DATA_NOT_AVAILABLE,
+                          SapResultCode::CARD_ALREADY_POWERED_OFF, SapResultCode::CARD_REMOVED}));
 }
 
 /*
@@ -84,11 +84,10 @@
     EXPECT_EQ(std::cv_status::no_timeout, wait());
     EXPECT_EQ(sapCb->sapResponseToken, token);
 
-    ASSERT_TRUE(SapResultCode::GENERIC_FAILURE == sapCb->sapResultCode ||
-                SapResultCode::CARD_NOT_ACCESSSIBLE == sapCb->sapResultCode ||
-                SapResultCode::CARD_ALREADY_POWERED_OFF == sapCb->sapResultCode ||
-                SapResultCode::CARD_REMOVED == sapCb->sapResultCode ||
-                SapResultCode::CARD_ALREADY_POWERED_ON == sapCb->sapResultCode);
+    ASSERT_TRUE(CheckAnyOfErrors(
+        sapCb->sapResultCode, {SapResultCode::GENERIC_FAILURE, SapResultCode::CARD_NOT_ACCESSSIBLE,
+                               SapResultCode::CARD_ALREADY_POWERED_OFF, SapResultCode::CARD_REMOVED,
+                               SapResultCode::CARD_ALREADY_POWERED_ON}));
 }
 
 /*
@@ -101,10 +100,10 @@
     EXPECT_EQ(std::cv_status::no_timeout, wait());
     EXPECT_EQ(sapCb->sapResponseToken, token);
 
-    ASSERT_TRUE(SapResultCode::GENERIC_FAILURE == sapCb->sapResultCode ||
-                SapResultCode::CARD_NOT_ACCESSSIBLE == sapCb->sapResultCode ||
-                SapResultCode::CARD_ALREADY_POWERED_OFF == sapCb->sapResultCode ||
-                SapResultCode::CARD_REMOVED == sapCb->sapResultCode);
+    ASSERT_TRUE(
+        CheckAnyOfErrors(sapCb->sapResultCode,
+                         {SapResultCode::GENERIC_FAILURE, SapResultCode::CARD_NOT_ACCESSSIBLE,
+                          SapResultCode::CARD_ALREADY_POWERED_OFF, SapResultCode::CARD_REMOVED}));
 }
 
 /*
@@ -117,8 +116,8 @@
     EXPECT_EQ(std::cv_status::no_timeout, wait());
     EXPECT_EQ(sapCb->sapResponseToken, token);
 
-    ASSERT_TRUE(SapResultCode::GENERIC_FAILURE == sapCb->sapResultCode ||
-                SapResultCode::DATA_NOT_AVAILABLE == sapCb->sapResultCode);
+    ASSERT_TRUE(CheckAnyOfErrors(
+        sapCb->sapResultCode, {SapResultCode::GENERIC_FAILURE, SapResultCode::DATA_NOT_AVAILABLE}));
 }
 
 /*
diff --git a/radio/1.0/vts/functional/sap_hidl_hal_test.cpp b/radio/1.0/vts/functional/sap_hidl_hal_test.cpp
index 7720505..fc8cb2a 100644
--- a/radio/1.0/vts/functional/sap_hidl_hal_test.cpp
+++ b/radio/1.0/vts/functional/sap_hidl_hal_test.cpp
@@ -34,19 +34,19 @@
     std::unique_lock<std::mutex> lock(mtx);
     count++;
     cv.notify_one();
-    }
+}
 
-    std::cv_status SapHidlTest::wait() {
-        std::unique_lock<std::mutex> lock(mtx);
+std::cv_status SapHidlTest::wait() {
+    std::unique_lock<std::mutex> lock(mtx);
 
-        std::cv_status status = std::cv_status::no_timeout;
-        auto now = std::chrono::system_clock::now();
-        while (count == 0) {
-            status = cv.wait_until(lock, now + std::chrono::seconds(TIMEOUT_PERIOD));
-            if (status == std::cv_status::timeout) {
-                return status;
-            }
+    std::cv_status status = std::cv_status::no_timeout;
+    auto now = std::chrono::system_clock::now();
+    while (count == 0) {
+        status = cv.wait_until(lock, now + std::chrono::seconds(TIMEOUT_PERIOD));
+        if (status == std::cv_status::timeout) {
+            return status;
         }
-        count--;
-        return status;
-    }
\ No newline at end of file
+    }
+    count--;
+    return status;
+}
\ No newline at end of file
diff --git a/radio/1.0/vts/functional/vts_test_util.cpp b/radio/1.0/vts/functional/vts_test_util.cpp
index c6d1f9f..7d15f35 100644
--- a/radio/1.0/vts/functional/vts_test_util.cpp
+++ b/radio/1.0/vts/functional/vts_test_util.cpp
@@ -15,8 +15,42 @@
  */
 #include <vts_test_util.h>
 #include <iostream>
-using namespace std;
 
 int GetRandomSerialNumber() {
     return rand();
-}
\ No newline at end of file
+}
+
+::testing::AssertionResult CheckAnyOfErrors(RadioError err, std::vector<RadioError> errors,
+                                            CheckFlag flag) {
+    const static vector<RadioError> generalErrors = {
+        RadioError::RADIO_NOT_AVAILABLE,   RadioError::NO_MEMORY,
+        RadioError::INTERNAL_ERR,          RadioError::SYSTEM_ERR,
+        RadioError::REQUEST_NOT_SUPPORTED, RadioError::CANCELLED};
+    if (flag == CHECK_GENERAL_ERROR || flag == CHECK_OEM_AND_GENERAL_ERROR) {
+        for (size_t i = 0; i < generalErrors.size(); i++) {
+            if (err == generalErrors[i]) {
+                return testing::AssertionSuccess();
+            }
+        }
+    }
+    if (flag == CHECK_OEM_ERROR || flag == CHECK_OEM_AND_GENERAL_ERROR) {
+        if (err >= RadioError::OEM_ERROR_1 && err <= RadioError::OEM_ERROR_25) {
+            return testing::AssertionSuccess();
+        }
+    }
+    for (size_t i = 0; i < errors.size(); i++) {
+        if (err == errors[i]) {
+            return testing::AssertionSuccess();
+        }
+    }
+    return testing::AssertionFailure() << "RadioError:" + toString(err) + " is returned";
+}
+
+::testing::AssertionResult CheckAnyOfErrors(SapResultCode err, std::vector<SapResultCode> errors) {
+    for (size_t i = 0; i < errors.size(); i++) {
+        if (err == errors[i]) {
+            return testing::AssertionSuccess();
+        }
+    }
+    return testing::AssertionFailure() << "SapError:" + toString(err) + " is returned";
+}
diff --git a/radio/1.0/vts/functional/vts_test_util.h b/radio/1.0/vts/functional/vts_test_util.h
index 939013f..826f0de 100644
--- a/radio/1.0/vts/functional/vts_test_util.h
+++ b/radio/1.0/vts/functional/vts_test_util.h
@@ -14,4 +14,37 @@
  * limitations under the License.
  */
 
-int GetRandomSerialNumber();
\ No newline at end of file
+#include <android-base/logging.h>
+
+#include <VtsHalHidlTargetTestBase.h>
+
+#include <android/hardware/radio/1.0/types.h>
+
+using ::android::hardware::radio::V1_0::RadioError;
+using ::android::hardware::radio::V1_0::SapResultCode;
+using namespace std;
+
+enum CheckFlag {
+    CHECK_DEFAULT = 0,
+    CHECK_GENERAL_ERROR = 1,
+    CHECK_OEM_ERROR = 2,
+    CHECK_OEM_AND_GENERAL_ERROR = 3,
+    CHECK_SAP_ERROR = 4,
+};
+
+/*
+ * Generate random serial number for radio test
+ */
+int GetRandomSerialNumber();
+
+/*
+ * Check multiple radio error codes which are possibly returned because of the different
+ * vendor/devices implementations. It allows optional checks for general errors or/and oem errors.
+ */
+::testing::AssertionResult CheckAnyOfErrors(RadioError err, std::vector<RadioError> generalError,
+                                            CheckFlag flag = CHECK_DEFAULT);
+/*
+ * Check multiple sap error codes which are possibly returned because of the different
+ * vendor/devices implementations.
+ */
+::testing::AssertionResult CheckAnyOfErrors(SapResultCode err, std::vector<SapResultCode> errors);
diff --git a/radio/1.1/vts/functional/radio_hidl_hal_api.cpp b/radio/1.1/vts/functional/radio_hidl_hal_api.cpp
index 10f8f62..17c2a83 100644
--- a/radio/1.1/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.1/vts/functional/radio_hidl_hal_api.cpp
@@ -29,10 +29,10 @@
     EXPECT_EQ(serial, radioRsp_v1_1->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp_v1_1->rspInfo.error == RadioError::NONE ||
-                    radioRsp_v1_1->rspInfo.error == RadioError::REQUEST_NOT_SUPPORTED ||
-                    radioRsp_v1_1->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
-                    radioRsp_v1_1->rspInfo.error == RadioError::RADIO_NOT_AVAILABLE);
+        ASSERT_TRUE(
+            CheckAnyOfErrors(radioRsp_v1_1->rspInfo.error,
+                             {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED,
+                              RadioError::INVALID_ARGUMENTS, RadioError::RADIO_NOT_AVAILABLE}));
     }
 }
 
@@ -63,11 +63,10 @@
 
     if (cardStatus.cardState == CardState::ABSENT) {
         ALOGI("startNetworkScan, rspInfo.error = %d\n", (int32_t)radioRsp_v1_1->rspInfo.error);
-        ASSERT_TRUE(radioRsp_v1_1->rspInfo.error == RadioError::NONE ||
-                    radioRsp_v1_1->rspInfo.error == RadioError::SIM_ABSENT ||
-                    radioRsp_v1_1->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
-                    radioRsp_v1_1->rspInfo.error == RadioError::REQUEST_NOT_SUPPORTED ||
-                    radioRsp_v1_1->rspInfo.error == RadioError::OPERATION_NOT_ALLOWED);
+        ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp_v1_1->rspInfo.error,
+            {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED, RadioError::INVALID_ARGUMENTS,
+             RadioError::SIM_ABSENT, RadioError::OPERATION_NOT_ALLOWED}));
     }
 }
 
@@ -89,9 +88,9 @@
     if (cardStatus.cardState == CardState::ABSENT) {
         ALOGI("startNetworkScan_InvalidArgument, rspInfo.error = %d\n",
               (int32_t)radioRsp_v1_1->rspInfo.error);
-        ASSERT_TRUE(radioRsp_v1_1->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
-                    radioRsp_v1_1->rspInfo.error == RadioError::SIM_ABSENT ||
-                    radioRsp_v1_1->rspInfo.error == RadioError::REQUEST_NOT_SUPPORTED);
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_1->rspInfo.error,
+                                     {RadioError::INVALID_ARGUMENTS, RadioError::SIM_ABSENT,
+                                      RadioError::REQUEST_NOT_SUPPORTED}));
     }
 }
 
@@ -108,9 +107,9 @@
 
     if (cardStatus.cardState == CardState::ABSENT) {
         ALOGI("stopNetworkScan rspInfo.error = %d\n", (int32_t)radioRsp_v1_1->rspInfo.error);
-        ASSERT_TRUE(radioRsp_v1_1->rspInfo.error == RadioError::NONE ||
-                    radioRsp_v1_1->rspInfo.error == RadioError::SIM_ABSENT ||
-                    radioRsp_v1_1->rspInfo.error == RadioError::REQUEST_NOT_SUPPORTED);
+        ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp_v1_1->rspInfo.error,
+            {RadioError::NONE, RadioError::SIM_ABSENT, RadioError::REQUEST_NOT_SUPPORTED}));
     }
 }
 
@@ -132,8 +131,8 @@
     EXPECT_EQ(serial, radioRsp_v1_1->rspInfo.serial);
 
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp_v1_1->rspInfo.error == RadioError::NONE ||
-                    radioRsp_v1_1->rspInfo.error == RadioError::REQUEST_NOT_SUPPORTED);
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_1->rspInfo.error,
+                                     {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
     }
 }
 
@@ -229,8 +228,9 @@
         EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_1->rspInfo.type);
         EXPECT_EQ(serial, radioRsp_v1_1->rspInfo.serial);
 
-        ASSERT_TRUE(radioRsp_v1_1->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
-                    radioRsp_v1_1->rspInfo.error == RadioError::REQUEST_NOT_SUPPORTED);
+        ASSERT_TRUE(
+            CheckAnyOfErrors(radioRsp_v1_1->rspInfo.error,
+                             {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
     }
 }
 
@@ -245,6 +245,7 @@
     EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_1->rspInfo.type);
     EXPECT_EQ(serial, radioRsp_v1_1->rspInfo.serial);
 
-    ASSERT_TRUE(radioRsp_v1_1->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
-                radioRsp_v1_1->rspInfo.error == RadioError::REQUEST_NOT_SUPPORTED);
+    ASSERT_TRUE(
+        CheckAnyOfErrors(radioRsp_v1_1->rspInfo.error,
+                         {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
 }
diff --git a/radio/1.1/vts/functional/radio_hidl_hal_test.cpp b/radio/1.1/vts/functional/radio_hidl_hal_test.cpp
index f03db20..e1da591 100644
--- a/radio/1.1/vts/functional/radio_hidl_hal_test.cpp
+++ b/radio/1.1/vts/functional/radio_hidl_hal_test.cpp
@@ -20,6 +20,11 @@
     radio_v1_1 =
         ::testing::VtsHalHidlTargetTestBase::getService<::android::hardware::radio::V1_1::IRadio>(
             hidl_string(RADIO_SERVICE_NAME));
+    if (radio_v1_1 == NULL) {
+        sleep(60);
+        radio_v1_1 = ::testing::VtsHalHidlTargetTestBase::getService<
+            ::android::hardware::radio::V1_1::IRadio>(hidl_string(RADIO_SERVICE_NAME));
+    }
     ASSERT_NE(nullptr, radio_v1_1.get());
 
     radioRsp_v1_1 = new (std::nothrow) RadioResponse_v1_1(*this);
@@ -66,17 +71,3 @@
     count--;
     return status;
 }
-
-bool RadioHidlTest_v1_1::CheckGeneralError() {
-    return (radioRsp_v1_1->rspInfo.error == RadioError::RADIO_NOT_AVAILABLE ||
-            radioRsp_v1_1->rspInfo.error == RadioError::NO_MEMORY ||
-            radioRsp_v1_1->rspInfo.error == RadioError::INTERNAL_ERR ||
-            radioRsp_v1_1->rspInfo.error == RadioError::SYSTEM_ERR ||
-            radioRsp_v1_1->rspInfo.error == RadioError::REQUEST_NOT_SUPPORTED ||
-            radioRsp_v1_1->rspInfo.error == RadioError::CANCELLED);
-}
-
-bool RadioHidlTest_v1_1::CheckOEMError() {
-    return (radioRsp_v1_1->rspInfo.error >= RadioError::OEM_ERROR_1 &&
-            radioRsp_v1_1->rspInfo.error <= RadioError::OEM_ERROR_25);
-}
diff --git a/radio/1.2/vts/functional/radio_hidl_hal_api.cpp b/radio/1.2/vts/functional/radio_hidl_hal_api.cpp
index a4f3571..64a598a 100644
--- a/radio/1.2/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.2/vts/functional/radio_hidl_hal_api.cpp
@@ -43,13 +43,13 @@
 
     ALOGI("startNetworkScan, rspInfo.error = %s\n", toString(radioRsp_v1_2->rspInfo.error).c_str());
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp_v1_2->rspInfo.error == RadioError::SIM_ABSENT ||
-                    radioRsp_v1_2->rspInfo.error == RadioError::REQUEST_NOT_SUPPORTED ||
-                    radioRsp_v1_2->rspInfo.error == RadioError::OPERATION_NOT_ALLOWED);
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_2->rspInfo.error,
+                                     {RadioError::SIM_ABSENT, RadioError::REQUEST_NOT_SUPPORTED,
+                                      RadioError::OPERATION_NOT_ALLOWED}));
     } else if (cardStatus.cardState == CardState::PRESENT) {
-        ASSERT_TRUE(radioRsp_v1_2->rspInfo.error == RadioError::NONE ||
-                    radioRsp_v1_2->rspInfo.error == RadioError::REQUEST_NOT_SUPPORTED ||
-                    radioRsp_v1_2->rspInfo.error == RadioError::OPERATION_NOT_ALLOWED);
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_2->rspInfo.error,
+                                     {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED,
+                                      RadioError::OPERATION_NOT_ALLOWED}));
     }
 }
 
@@ -72,12 +72,13 @@
     ALOGI("startNetworkScan_InvalidArgument, rspInfo.error = %s\n",
           toString(radioRsp_v1_2->rspInfo.error).c_str());
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp_v1_2->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
-                    radioRsp_v1_2->rspInfo.error == RadioError::SIM_ABSENT ||
-                    radioRsp_v1_2->rspInfo.error == RadioError::REQUEST_NOT_SUPPORTED);
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_2->rspInfo.error,
+                                     {RadioError::SIM_ABSENT, RadioError::REQUEST_NOT_SUPPORTED,
+                                      RadioError::INVALID_ARGUMENTS}));
     } else if (cardStatus.cardState == CardState::PRESENT) {
-        ASSERT_TRUE(radioRsp_v1_2->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
-                    radioRsp_v1_2->rspInfo.error == RadioError::REQUEST_NOT_SUPPORTED);
+        ASSERT_TRUE(
+            CheckAnyOfErrors(radioRsp_v1_2->rspInfo.error,
+                             {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
     }
 }
 
@@ -109,14 +110,15 @@
     ALOGI("startNetworkScan_InvalidInterval1, rspInfo.error = %s\n",
           toString(radioRsp_v1_2->rspInfo.error).c_str());
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp_v1_2->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
-                    radioRsp_v1_2->rspInfo.error == RadioError::SIM_ABSENT ||
-                    radioRsp_v1_2->rspInfo.error == RadioError::OPERATION_NOT_ALLOWED ||
-                    radioRsp_v1_2->rspInfo.error == RadioError::REQUEST_NOT_SUPPORTED);
+        ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp_v1_2->rspInfo.error,
+            {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS,
+             RadioError::REQUEST_NOT_SUPPORTED, RadioError::OPERATION_NOT_ALLOWED}));
     } else if (cardStatus.cardState == CardState::PRESENT) {
-        ASSERT_TRUE(radioRsp_v1_2->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
-                    radioRsp_v1_2->rspInfo.error == RadioError::OPERATION_NOT_ALLOWED ||
-                    radioRsp_v1_2->rspInfo.error == RadioError::REQUEST_NOT_SUPPORTED);
+        ASSERT_TRUE(
+            CheckAnyOfErrors(radioRsp_v1_2->rspInfo.error,
+                             {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED,
+                              RadioError::OPERATION_NOT_ALLOWED}));
     }
 }
 
@@ -148,14 +150,15 @@
     ALOGI("startNetworkScan_InvalidInterval2, rspInfo.error = %s\n",
           toString(radioRsp_v1_2->rspInfo.error).c_str());
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp_v1_2->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
-                    radioRsp_v1_2->rspInfo.error == RadioError::SIM_ABSENT ||
-                    radioRsp_v1_2->rspInfo.error == RadioError::OPERATION_NOT_ALLOWED ||
-                    radioRsp_v1_2->rspInfo.error == RadioError::REQUEST_NOT_SUPPORTED);
+        ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp_v1_2->rspInfo.error,
+            {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS,
+             RadioError::REQUEST_NOT_SUPPORTED, RadioError::OPERATION_NOT_ALLOWED}));
     } else if (cardStatus.cardState == CardState::PRESENT) {
-        ASSERT_TRUE(radioRsp_v1_2->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
-                    radioRsp_v1_2->rspInfo.error == RadioError::OPERATION_NOT_ALLOWED ||
-                    radioRsp_v1_2->rspInfo.error == RadioError::REQUEST_NOT_SUPPORTED);
+        ASSERT_TRUE(
+            CheckAnyOfErrors(radioRsp_v1_2->rspInfo.error,
+                             {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED,
+                              RadioError::OPERATION_NOT_ALLOWED}));
     }
 }
 
@@ -187,14 +190,15 @@
     ALOGI("startNetworkScan_InvalidMaxSearchTime1, rspInfo.error = %s\n",
           toString(radioRsp_v1_2->rspInfo.error).c_str());
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp_v1_2->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
-                    radioRsp_v1_2->rspInfo.error == RadioError::SIM_ABSENT ||
-                    radioRsp_v1_2->rspInfo.error == RadioError::OPERATION_NOT_ALLOWED ||
-                    radioRsp_v1_2->rspInfo.error == RadioError::REQUEST_NOT_SUPPORTED);
+        ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp_v1_2->rspInfo.error,
+            {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS,
+             RadioError::REQUEST_NOT_SUPPORTED, RadioError::OPERATION_NOT_ALLOWED}));
     } else if (cardStatus.cardState == CardState::PRESENT) {
-        ASSERT_TRUE(radioRsp_v1_2->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
-                    radioRsp_v1_2->rspInfo.error == RadioError::OPERATION_NOT_ALLOWED ||
-                    radioRsp_v1_2->rspInfo.error == RadioError::REQUEST_NOT_SUPPORTED);
+        ASSERT_TRUE(
+            CheckAnyOfErrors(radioRsp_v1_2->rspInfo.error,
+                             {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED,
+                              RadioError::OPERATION_NOT_ALLOWED}));
     }
 }
 
@@ -226,14 +230,15 @@
     ALOGI("startNetworkScan_InvalidMaxSearchTime2, rspInfo.error = %s\n",
           toString(radioRsp_v1_2->rspInfo.error).c_str());
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp_v1_2->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
-                    radioRsp_v1_2->rspInfo.error == RadioError::SIM_ABSENT ||
-                    radioRsp_v1_2->rspInfo.error == RadioError::OPERATION_NOT_ALLOWED ||
-                    radioRsp_v1_2->rspInfo.error == RadioError::REQUEST_NOT_SUPPORTED);
+        ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp_v1_2->rspInfo.error,
+            {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS,
+             RadioError::REQUEST_NOT_SUPPORTED, RadioError::OPERATION_NOT_ALLOWED}));
     } else if (cardStatus.cardState == CardState::PRESENT) {
-        ASSERT_TRUE(radioRsp_v1_2->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
-                    radioRsp_v1_2->rspInfo.error == RadioError::OPERATION_NOT_ALLOWED ||
-                    radioRsp_v1_2->rspInfo.error == RadioError::REQUEST_NOT_SUPPORTED);
+        ASSERT_TRUE(
+            CheckAnyOfErrors(radioRsp_v1_2->rspInfo.error,
+                             {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED,
+                              RadioError::OPERATION_NOT_ALLOWED}));
     }
 }
 
@@ -265,14 +270,15 @@
     ALOGI("startNetworkScan_InvalidPeriodicity1, rspInfo.error = %s\n",
           toString(radioRsp_v1_2->rspInfo.error).c_str());
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp_v1_2->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
-                    radioRsp_v1_2->rspInfo.error == RadioError::SIM_ABSENT ||
-                    radioRsp_v1_2->rspInfo.error == RadioError::OPERATION_NOT_ALLOWED ||
-                    radioRsp_v1_2->rspInfo.error == RadioError::REQUEST_NOT_SUPPORTED);
+        ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp_v1_2->rspInfo.error,
+            {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS,
+             RadioError::REQUEST_NOT_SUPPORTED, RadioError::OPERATION_NOT_ALLOWED}));
     } else if (cardStatus.cardState == CardState::PRESENT) {
-        ASSERT_TRUE(radioRsp_v1_2->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
-                    radioRsp_v1_2->rspInfo.error == RadioError::OPERATION_NOT_ALLOWED ||
-                    radioRsp_v1_2->rspInfo.error == RadioError::REQUEST_NOT_SUPPORTED);
+        ASSERT_TRUE(
+            CheckAnyOfErrors(radioRsp_v1_2->rspInfo.error,
+                             {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED,
+                              RadioError::OPERATION_NOT_ALLOWED}));
     }
 }
 
@@ -304,14 +310,15 @@
     ALOGI("startNetworkScan_InvalidPeriodicity2, rspInfo.error = %s\n",
           toString(radioRsp_v1_2->rspInfo.error).c_str());
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp_v1_2->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
-                    radioRsp_v1_2->rspInfo.error == RadioError::SIM_ABSENT ||
-                    radioRsp_v1_2->rspInfo.error == RadioError::OPERATION_NOT_ALLOWED ||
-                    radioRsp_v1_2->rspInfo.error == RadioError::REQUEST_NOT_SUPPORTED);
+        ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp_v1_2->rspInfo.error,
+            {RadioError::SIM_ABSENT, RadioError::INVALID_ARGUMENTS,
+             RadioError::REQUEST_NOT_SUPPORTED, RadioError::OPERATION_NOT_ALLOWED}));
     } else if (cardStatus.cardState == CardState::PRESENT) {
-        ASSERT_TRUE(radioRsp_v1_2->rspInfo.error == RadioError::INVALID_ARGUMENTS ||
-                    radioRsp_v1_2->rspInfo.error == RadioError::OPERATION_NOT_ALLOWED ||
-                    radioRsp_v1_2->rspInfo.error == RadioError::REQUEST_NOT_SUPPORTED);
+        ASSERT_TRUE(
+            CheckAnyOfErrors(radioRsp_v1_2->rspInfo.error,
+                             {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED,
+                              RadioError::OPERATION_NOT_ALLOWED}));
     }
 }
 
@@ -343,14 +350,14 @@
     ALOGI("startNetworkScan_InvalidArgument, rspInfo.error = %s\n",
           toString(radioRsp_v1_2->rspInfo.error).c_str());
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp_v1_2->rspInfo.error == RadioError::NONE ||
-                    radioRsp_v1_2->rspInfo.error == RadioError::SIM_ABSENT ||
-                    radioRsp_v1_2->rspInfo.error == RadioError::OPERATION_NOT_ALLOWED ||
-                    radioRsp_v1_2->rspInfo.error == RadioError::REQUEST_NOT_SUPPORTED);
+        ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp_v1_2->rspInfo.error,
+            {RadioError::NONE, RadioError::SIM_ABSENT, RadioError::REQUEST_NOT_SUPPORTED,
+             RadioError::OPERATION_NOT_ALLOWED}));
     } else if (cardStatus.cardState == CardState::PRESENT) {
-        ASSERT_TRUE(radioRsp_v1_2->rspInfo.error == RadioError::NONE ||
-                    radioRsp_v1_2->rspInfo.error == RadioError::OPERATION_NOT_ALLOWED ||
-                    radioRsp_v1_2->rspInfo.error == RadioError::REQUEST_NOT_SUPPORTED);
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_2->rspInfo.error,
+                                     {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED,
+                                      RadioError::OPERATION_NOT_ALLOWED}));
     }
 }
 
@@ -383,13 +390,13 @@
     ALOGI("startNetworkScan_InvalidArgument, rspInfo.error = %s\n",
           toString(radioRsp_v1_2->rspInfo.error).c_str());
     if (cardStatus.cardState == CardState::ABSENT) {
-        ASSERT_TRUE(radioRsp_v1_2->rspInfo.error == RadioError::NONE ||
-                    radioRsp_v1_2->rspInfo.error == RadioError::SIM_ABSENT ||
-                    radioRsp_v1_2->rspInfo.error == RadioError::OPERATION_NOT_ALLOWED ||
-                    radioRsp_v1_2->rspInfo.error == RadioError::REQUEST_NOT_SUPPORTED);
+        ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp_v1_2->rspInfo.error,
+            {RadioError::NONE, RadioError::SIM_ABSENT, RadioError::REQUEST_NOT_SUPPORTED,
+             RadioError::OPERATION_NOT_ALLOWED}));
     } else if (cardStatus.cardState == CardState::PRESENT) {
-        ASSERT_TRUE(radioRsp_v1_2->rspInfo.error == RadioError::NONE ||
-                    radioRsp_v1_2->rspInfo.error == RadioError::OPERATION_NOT_ALLOWED ||
-                    radioRsp_v1_2->rspInfo.error == RadioError::REQUEST_NOT_SUPPORTED);
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_2->rspInfo.error,
+                                     {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED,
+                                      RadioError::OPERATION_NOT_ALLOWED}));
     }
 }
diff --git a/radio/1.2/vts/functional/radio_hidl_hal_test.cpp b/radio/1.2/vts/functional/radio_hidl_hal_test.cpp
index 4f05eff..c1ab88b 100644
--- a/radio/1.2/vts/functional/radio_hidl_hal_test.cpp
+++ b/radio/1.2/vts/functional/radio_hidl_hal_test.cpp
@@ -19,6 +19,11 @@
 void RadioHidlTest_v1_2::SetUp() {
     radio_v1_2 = ::testing::VtsHalHidlTargetTestBase::getService<V1_2::IRadio>(
         hidl_string(RADIO_SERVICE_NAME));
+    if (radio_v1_2 == NULL) {
+        sleep(60);
+        radio_v1_2 = ::testing::VtsHalHidlTargetTestBase::getService<V1_2::IRadio>(
+            hidl_string(RADIO_SERVICE_NAME));
+    }
     ASSERT_NE(nullptr, radio_v1_2.get());
 
     radioRsp_v1_2 = new (std::nothrow) RadioResponse_v1_2(*this);
diff --git a/sensors/1.0/default/android.hardware.sensors@1.0-service.rc b/sensors/1.0/default/android.hardware.sensors@1.0-service.rc
index 3e5d0f8..b54842d 100644
--- a/sensors/1.0/default/android.hardware.sensors@1.0-service.rc
+++ b/sensors/1.0/default/android.hardware.sensors@1.0-service.rc
@@ -1,4 +1,4 @@
-service sensors-hal-1-0 /vendor/bin/hw/android.hardware.sensors@1.0-service
+service vendor.sensors-hal-1-0 /vendor/bin/hw/android.hardware.sensors@1.0-service
     class hal
     user system
     group system wakelock
diff --git a/sensors/1.0/vts/functional/Android.bp b/sensors/1.0/vts/functional/Android.bp
index fb8d22e..0ea400e 100644
--- a/sensors/1.0/vts/functional/Android.bp
+++ b/sensors/1.0/vts/functional/Android.bp
@@ -24,7 +24,7 @@
     static_libs: [
         "android.hardware.graphics.allocator@2.0",
         "android.hardware.graphics.mapper@2.0",
-        "android.hardware.sensors@1.0"
-    ]
+        "android.hardware.sensors@1.0",
+    ],
 }
 
diff --git a/soundtrigger/2.0/default/SoundTriggerHalImpl.cpp b/soundtrigger/2.0/default/SoundTriggerHalImpl.cpp
index 996519b..f963fb1 100644
--- a/soundtrigger/2.0/default/SoundTriggerHalImpl.cpp
+++ b/soundtrigger/2.0/default/SoundTriggerHalImpl.cpp
@@ -388,10 +388,12 @@
     halTriggerPhrase->id = triggerPhrase->id;
     halTriggerPhrase->recognition_mode = triggerPhrase->recognitionModes;
     unsigned int i;
-    for (i = 0; i < triggerPhrase->users.size(); i++) {
+
+    halTriggerPhrase->num_users =
+        std::min((int)triggerPhrase->users.size(), SOUND_TRIGGER_MAX_USERS);
+    for (i = 0; i < halTriggerPhrase->num_users; i++) {
         halTriggerPhrase->users[i] = triggerPhrase->users[i];
     }
-    halTriggerPhrase->num_users = i;
 
     strlcpy(halTriggerPhrase->locale,
             triggerPhrase->locale.c_str(), SOUND_TRIGGER_MAX_LOCALE_LEN);
diff --git a/tests/extension/light/2.0/default/android.hardware.tests.extension.light@2.0-service.rc b/tests/extension/light/2.0/default/android.hardware.tests.extension.light@2.0-service.rc
index 8f379ee..0b8515a 100644
--- a/tests/extension/light/2.0/default/android.hardware.tests.extension.light@2.0-service.rc
+++ b/tests/extension/light/2.0/default/android.hardware.tests.extension.light@2.0-service.rc
@@ -1,4 +1,4 @@
-service light-ext-2-0 /vendor/bin/hw/android.hardware.tests.extension.light@2.0-service
+service vendor.light-ext-2-0 /vendor/bin/hw/android.hardware.tests.extension.light@2.0-service
     class hal
     user system
-    group system
\ No newline at end of file
+    group system
diff --git a/tests/memory/1.0/Android.bp b/tests/memory/1.0/Android.bp
index 5038664..cbee247 100644
--- a/tests/memory/1.0/Android.bp
+++ b/tests/memory/1.0/Android.bp
@@ -7,9 +7,9 @@
         "IMemoryTest.hal",
     ],
     interfaces: [
-        "android.hidl.memory.token@1.0",
-        "android.hidl.memory.block@1.0",
         "android.hidl.base@1.0",
+        "android.hidl.memory.block@1.0",
+        "android.hidl.memory.token@1.0",
     ],
     gen_java: false,
 }
diff --git a/thermal/1.0/default/android.hardware.thermal@1.0-service.rc b/thermal/1.0/default/android.hardware.thermal@1.0-service.rc
index cbc0f65..cf9bdee 100644
--- a/thermal/1.0/default/android.hardware.thermal@1.0-service.rc
+++ b/thermal/1.0/default/android.hardware.thermal@1.0-service.rc
@@ -1,4 +1,4 @@
-service thermal-hal-1-0 /vendor/bin/hw/android.hardware.thermal@1.0-service
+service vendor.thermal-hal-1-0 /vendor/bin/hw/android.hardware.thermal@1.0-service
     class hal
     user system
     group system
diff --git a/tv/cec/1.0/default/HdmiCec.cpp b/tv/cec/1.0/default/HdmiCec.cpp
index ebe2681..171bdfe 100644
--- a/tv/cec/1.0/default/HdmiCec.cpp
+++ b/tv/cec/1.0/default/HdmiCec.cpp
@@ -264,8 +264,7 @@
 
 sp<IHdmiCecCallback> HdmiCec::mCallback = nullptr;
 
-HdmiCec::HdmiCec(hdmi_cec_device_t* device) : mDevice(device) {
-}
+HdmiCec::HdmiCec(hdmi_cec_device_t* device) : mDevice(device) {}
 
 // Methods from ::android::hardware::tv::cec::V1_0::IHdmiCec follow.
 Return<Result> HdmiCec::addLogicalAddress(CecLogicalAddress addr) {
@@ -319,8 +318,16 @@
 }
 
 Return<void> HdmiCec::setCallback(const sp<IHdmiCecCallback>& callback) {
-    mCallback = callback;
-    mDevice->register_event_callback(mDevice, eventCallback, nullptr);
+    if (mCallback != nullptr) {
+        mCallback->unlinkToDeath(this);
+        mCallback = nullptr;
+    }
+
+    if (callback != nullptr) {
+        mCallback = callback;
+        mCallback->linkToDeath(this, 0 /*cookie*/);
+        mDevice->register_event_callback(mDevice, eventCallback, nullptr);
+    }
     return Void();
 }
 
diff --git a/tv/cec/1.0/default/HdmiCec.h b/tv/cec/1.0/default/HdmiCec.h
index 34a3bb0..0133abc 100644
--- a/tv/cec/1.0/default/HdmiCec.h
+++ b/tv/cec/1.0/default/HdmiCec.h
@@ -47,7 +47,7 @@
 using ::android::hardware::hidl_string;
 using ::android::sp;
 
-struct HdmiCec : public IHdmiCec {
+struct HdmiCec : public IHdmiCec, public hidl_death_recipient {
     HdmiCec(hdmi_cec_device_t* device);
     // Methods from ::android::hardware::tv::cec::V1_0::IHdmiCec follow.
     Return<Result> addLogicalAddress(CecLogicalAddress addr)  override;
@@ -87,7 +87,12 @@
         }
     }
 
-private:
+    virtual void serviceDied(uint64_t /*cookie*/,
+                             const wp<::android::hidl::base::V1_0::IBase>& /*who*/) {
+        setCallback(nullptr);
+    }
+
+   private:
     static sp<IHdmiCecCallback> mCallback;
     const hdmi_cec_device_t* mDevice;
 };
diff --git a/tv/cec/1.0/default/android.hardware.tv.cec@1.0-service.rc b/tv/cec/1.0/default/android.hardware.tv.cec@1.0-service.rc
index 9c80094..8595099 100644
--- a/tv/cec/1.0/default/android.hardware.tv.cec@1.0-service.rc
+++ b/tv/cec/1.0/default/android.hardware.tv.cec@1.0-service.rc
@@ -1,4 +1,4 @@
-service cec-hal-1-0 /vendor/bin/hw/android.hardware.tv.cec@1.0-service
+service vendor.cec-hal-1-0 /vendor/bin/hw/android.hardware.tv.cec@1.0-service
     class hal
     user system
     group system
diff --git a/tv/input/1.0/default/android.hardware.tv.input@1.0-service.rc b/tv/input/1.0/default/android.hardware.tv.input@1.0-service.rc
index dc6907c..972c654 100644
--- a/tv/input/1.0/default/android.hardware.tv.input@1.0-service.rc
+++ b/tv/input/1.0/default/android.hardware.tv.input@1.0-service.rc
@@ -1,4 +1,4 @@
-service tv-input-1-0 /vendor/bin/hw/android.hardware.tv.input@1.0-service
+service vendor.tv-input-1-0 /vendor/bin/hw/android.hardware.tv.input@1.0-service
     class hal
     user system
     group system
diff --git a/usb/1.0/default/android.hardware.usb@1.0-service.rc b/usb/1.0/default/android.hardware.usb@1.0-service.rc
index 6ea0720..b7a0c63 100644
--- a/usb/1.0/default/android.hardware.usb@1.0-service.rc
+++ b/usb/1.0/default/android.hardware.usb@1.0-service.rc
@@ -1,4 +1,4 @@
-service usb-hal-1-0 /vendor/bin/hw/android.hardware.usb@1.0-service
+service vendor.usb-hal-1-0 /vendor/bin/hw/android.hardware.usb@1.0-service
     class hal
     user system
     group system
diff --git a/vibrator/1.0/default/android.hardware.vibrator@1.0-service.rc b/vibrator/1.0/default/android.hardware.vibrator@1.0-service.rc
index f027065..1123eab 100644
--- a/vibrator/1.0/default/android.hardware.vibrator@1.0-service.rc
+++ b/vibrator/1.0/default/android.hardware.vibrator@1.0-service.rc
@@ -1,4 +1,4 @@
-service vibrator-1-0 /vendor/bin/hw/android.hardware.vibrator@1.0-service
+service vendor.vibrator-1-0 /vendor/bin/hw/android.hardware.vibrator@1.0-service
     class hal
     user system
     group system
diff --git a/vr/1.0/default/android.hardware.vr@1.0-service.rc b/vr/1.0/default/android.hardware.vr@1.0-service.rc
index bcc6416..fc4934c 100644
--- a/vr/1.0/default/android.hardware.vr@1.0-service.rc
+++ b/vr/1.0/default/android.hardware.vr@1.0-service.rc
@@ -1,4 +1,4 @@
-service vr-1-0 /vendor/bin/hw/android.hardware.vr@1.0-service
+service vendor.vr-1-0 /vendor/bin/hw/android.hardware.vr@1.0-service
     class hal
     user system
     group system
diff --git a/wifi/1.1/default/Android.mk b/wifi/1.1/default/Android.mk
deleted file mode 100644
index ee912c5..0000000
--- a/wifi/1.1/default/Android.mk
+++ /dev/null
@@ -1,52 +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 := android.hardware.wifi@1.0-service
-LOCAL_MODULE_RELATIVE_PATH := hw
-LOCAL_PROPRIETARY_MODULE := true
-LOCAL_CPPFLAGS := -Wall -Werror -Wextra
-ifdef WIFI_HIDL_FEATURE_AWARE
-LOCAL_CPPFLAGS += -DWIFI_HIDL_FEATURE_AWARE
-endif
-LOCAL_SRC_FILES := \
-    hidl_struct_util.cpp \
-    hidl_sync_util.cpp \
-    service.cpp \
-    wifi.cpp \
-    wifi_ap_iface.cpp \
-    wifi_chip.cpp \
-    wifi_legacy_hal.cpp \
-    wifi_legacy_hal_stubs.cpp \
-    wifi_mode_controller.cpp \
-    wifi_nan_iface.cpp \
-    wifi_p2p_iface.cpp \
-    wifi_rtt_controller.cpp \
-    wifi_sta_iface.cpp \
-    wifi_status_util.cpp
-LOCAL_SHARED_LIBRARIES := \
-    libbase \
-    libcutils \
-    libhidlbase \
-    libhidltransport \
-    liblog \
-    libnl \
-    libutils \
-    libwifi-hal \
-    libwifi-system-iface \
-    android.hardware.wifi@1.0 \
-    android.hardware.wifi@1.1
-LOCAL_INIT_RC := android.hardware.wifi@1.0-service.rc
-include $(BUILD_EXECUTABLE)
diff --git a/wifi/1.1/default/android.hardware.wifi@1.0-service.rc b/wifi/1.1/default/android.hardware.wifi@1.0-service.rc
deleted file mode 100644
index 696b1f9..0000000
--- a/wifi/1.1/default/android.hardware.wifi@1.0-service.rc
+++ /dev/null
@@ -1,4 +0,0 @@
-service wifi_hal_legacy /vendor/bin/hw/android.hardware.wifi@1.0-service
-    class hal
-    user wifi
-    group wifi gps
diff --git a/wifi/1.1/default/hidl_callback_util.h b/wifi/1.1/default/hidl_callback_util.h
deleted file mode 100644
index fb13622..0000000
--- a/wifi/1.1/default/hidl_callback_util.h
+++ /dev/null
@@ -1,121 +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 HIDL_CALLBACK_UTIL_H_
-#define HIDL_CALLBACK_UTIL_H_
-
-#include <set>
-
-#include <hidl/HidlSupport.h>
-
-namespace {
-// Type of callback invoked by the death handler.
-using on_death_cb_function = std::function<void(uint64_t)>;
-
-// Private class used to keep track of death of individual
-// callbacks stored in HidlCallbackHandler.
-template <typename CallbackType>
-class HidlDeathHandler : public android::hardware::hidl_death_recipient {
- public:
-  HidlDeathHandler(const on_death_cb_function& user_cb_function)
-      : cb_function_(user_cb_function) {}
-  ~HidlDeathHandler() = default;
-
-  // Death notification for callbacks.
-  void serviceDied(
-      uint64_t cookie,
-      const android::wp<android::hidl::base::V1_0::IBase>& /* who */) override {
-    cb_function_(cookie);
-  }
-
- private:
-  on_death_cb_function cb_function_;
-
-  DISALLOW_COPY_AND_ASSIGN(HidlDeathHandler);
-};
-}  // namespace
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_1 {
-namespace implementation {
-namespace hidl_callback_util {
-template <typename CallbackType>
-// Provides a class to manage callbacks for the various HIDL interfaces and
-// handle the death of the process hosting each callback.
-class HidlCallbackHandler {
- public:
-  HidlCallbackHandler()
-      : death_handler_(new HidlDeathHandler<CallbackType>(
-            std::bind(&HidlCallbackHandler::onObjectDeath,
-                      this,
-                      std::placeholders::_1))) {}
-  ~HidlCallbackHandler() = default;
-
-  bool addCallback(const sp<CallbackType>& cb) {
-    // TODO(b/33818800): Can't compare proxies yet. So, use the cookie
-    // (callback proxy's raw pointer) to track the death of individual clients.
-    uint64_t cookie = reinterpret_cast<uint64_t>(cb.get());
-    if (cb_set_.find(cb) != cb_set_.end()) {
-      LOG(WARNING) << "Duplicate death notification registration";
-      return true;
-    }
-    if (!cb->linkToDeath(death_handler_, cookie)) {
-      LOG(ERROR) << "Failed to register death notification";
-      return false;
-    }
-    cb_set_.insert(cb);
-    return true;
-  }
-
-  const std::set<android::sp<CallbackType>>& getCallbacks() { return cb_set_; }
-
-  // Death notification for callbacks.
-  void onObjectDeath(uint64_t cookie) {
-    CallbackType* cb = reinterpret_cast<CallbackType*>(cookie);
-    const auto& iter = cb_set_.find(cb);
-    if (iter == cb_set_.end()) {
-      LOG(ERROR) << "Unknown callback death notification received";
-      return;
-    }
-    cb_set_.erase(iter);
-    LOG(DEBUG) << "Dead callback removed from list";
-  }
-
-  void invalidate() {
-    for (const sp<CallbackType>& cb : cb_set_) {
-      if (!cb->unlinkToDeath(death_handler_)) {
-        LOG(ERROR) << "Failed to deregister death notification";
-      }
-    }
-    cb_set_.clear();
-  }
-
- private:
-  std::set<sp<CallbackType>> cb_set_;
-  sp<HidlDeathHandler<CallbackType>> death_handler_;
-
-  DISALLOW_COPY_AND_ASSIGN(HidlCallbackHandler);
-};
-
-}  // namespace hidl_callback_util
-}  // namespace implementation
-}  // namespace V1_1
-}  // namespace wifi
-}  // namespace hardware
-}  // namespace android
-#endif  // HIDL_CALLBACK_UTIL_H_
diff --git a/wifi/1.1/default/hidl_return_util.h b/wifi/1.1/default/hidl_return_util.h
deleted file mode 100644
index f36c8bd..0000000
--- a/wifi/1.1/default/hidl_return_util.h
+++ /dev/null
@@ -1,133 +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 HIDL_RETURN_UTIL_H_
-#define HIDL_RETURN_UTIL_H_
-
-#include "hidl_sync_util.h"
-#include "wifi_status_util.h"
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_1 {
-namespace implementation {
-namespace hidl_return_util {
-using namespace android::hardware::wifi::V1_0;
-
-/**
- * These utility functions are used to invoke a method on the provided
- * HIDL interface object.
- * These functions checks if the provided HIDL interface object is valid.
- * a) if valid, Invokes the corresponding internal implementation function of
- * the HIDL method. It then invokes the HIDL continuation callback with
- * the status and any returned values.
- * b) if invalid, invokes the HIDL continuation callback with the
- * provided error status and default values.
- */
-// Use for HIDL methods which return only an instance of WifiStatus.
-template <typename ObjT, typename WorkFuncT, typename... Args>
-Return<void> validateAndCall(
-    ObjT* obj,
-    WifiStatusCode status_code_if_invalid,
-    WorkFuncT&& work,
-    const std::function<void(const WifiStatus&)>& hidl_cb,
-    Args&&... args) {
-  const auto lock = hidl_sync_util::acquireGlobalLock();
-  if (obj->isValid()) {
-    hidl_cb((obj->*work)(std::forward<Args>(args)...));
-  } else {
-    hidl_cb(createWifiStatus(status_code_if_invalid));
-  }
-  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>
-Return<void> validateAndCall(
-    ObjT* obj,
-    WifiStatusCode status_code_if_invalid,
-    WorkFuncT&& work,
-    const std::function<void(const WifiStatus&, ReturnT)>& hidl_cb,
-    Args&&... args) {
-  const auto lock = hidl_sync_util::acquireGlobalLock();
-  if (obj->isValid()) {
-    const auto& ret_pair = (obj->*work)(std::forward<Args>(args)...);
-    const WifiStatus& status = std::get<0>(ret_pair);
-    const auto& ret_value = std::get<1>(ret_pair);
-    hidl_cb(status, ret_value);
-  } else {
-    hidl_cb(createWifiStatus(status_code_if_invalid),
-            typename std::remove_reference<ReturnT>::type());
-  }
-  return Void();
-}
-
-// Use for HIDL methods which return instance of WifiStatus and 2 return
-// values.
-template <typename ObjT,
-          typename WorkFuncT,
-          typename ReturnT1,
-          typename ReturnT2,
-          typename... Args>
-Return<void> validateAndCall(
-    ObjT* obj,
-    WifiStatusCode status_code_if_invalid,
-    WorkFuncT&& work,
-    const std::function<void(const WifiStatus&, ReturnT1, ReturnT2)>& hidl_cb,
-    Args&&... args) {
-  const auto lock = hidl_sync_util::acquireGlobalLock();
-  if (obj->isValid()) {
-    const auto& ret_tuple = (obj->*work)(std::forward<Args>(args)...);
-    const WifiStatus& status = std::get<0>(ret_tuple);
-    const auto& ret_value1 = std::get<1>(ret_tuple);
-    const auto& ret_value2 = std::get<2>(ret_tuple);
-    hidl_cb(status, ret_value1, ret_value2);
-  } else {
-    hidl_cb(createWifiStatus(status_code_if_invalid),
-            typename std::remove_reference<ReturnT1>::type(),
-            typename std::remove_reference<ReturnT2>::type());
-  }
-  return Void();
-}
-
-}  // namespace hidl_util
-}  // namespace implementation
-}  // namespace V1_1
-}  // namespace wifi
-}  // namespace hardware
-}  // namespace android
-#endif  // HIDL_RETURN_UTIL_H_
diff --git a/wifi/1.1/default/hidl_struct_util.cpp b/wifi/1.1/default/hidl_struct_util.cpp
deleted file mode 100644
index c53cdc5..0000000
--- a/wifi/1.1/default/hidl_struct_util.cpp
+++ /dev/null
@@ -1,2215 +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.
- */
-
-#include <android-base/logging.h>
-#include <utils/SystemClock.h>
-
-#include "hidl_struct_util.h"
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_1 {
-namespace implementation {
-namespace hidl_struct_util {
-
-hidl_string safeConvertChar(const char* str, size_t max_len) {
-  const char* c = str;
-  size_t size = 0;
-  while (*c && (unsigned char)*c < 128 && size < max_len) {
-    ++size;
-    ++c;
-  }
-  return hidl_string(str, size);
-}
-
-IWifiChip::ChipCapabilityMask convertLegacyLoggerFeatureToHidlChipCapability(
-    uint32_t feature) {
-  using HidlChipCaps = IWifiChip::ChipCapabilityMask;
-  switch (feature) {
-    case legacy_hal::WIFI_LOGGER_MEMORY_DUMP_SUPPORTED:
-      return HidlChipCaps::DEBUG_MEMORY_FIRMWARE_DUMP;
-    case legacy_hal::WIFI_LOGGER_DRIVER_DUMP_SUPPORTED:
-      return HidlChipCaps::DEBUG_MEMORY_DRIVER_DUMP;
-    case legacy_hal::WIFI_LOGGER_CONNECT_EVENT_SUPPORTED:
-      return HidlChipCaps::DEBUG_RING_BUFFER_CONNECT_EVENT;
-    case legacy_hal::WIFI_LOGGER_POWER_EVENT_SUPPORTED:
-      return HidlChipCaps::DEBUG_RING_BUFFER_POWER_EVENT;
-    case legacy_hal::WIFI_LOGGER_WAKE_LOCK_SUPPORTED:
-      return HidlChipCaps::DEBUG_RING_BUFFER_WAKELOCK_EVENT;
-  };
-  CHECK(false) << "Unknown legacy feature: " << feature;
-  return {};
-}
-
-IWifiStaIface::StaIfaceCapabilityMask
-convertLegacyLoggerFeatureToHidlStaIfaceCapability(uint32_t feature) {
-  using HidlStaIfaceCaps = IWifiStaIface::StaIfaceCapabilityMask;
-  switch (feature) {
-    case legacy_hal::WIFI_LOGGER_PACKET_FATE_SUPPORTED:
-      return HidlStaIfaceCaps::DEBUG_PACKET_FATE;
-  };
-  CHECK(false) << "Unknown legacy feature: " << feature;
-  return {};
-}
-
-V1_1::IWifiChip::ChipCapabilityMask convertLegacyFeatureToHidlChipCapability(
-    uint32_t feature) {
-  using HidlChipCaps = V1_1::IWifiChip::ChipCapabilityMask;
-  switch (feature) {
-    case WIFI_FEATURE_SET_TX_POWER_LIMIT:
-      return HidlChipCaps::SET_TX_POWER_LIMIT;
-    case WIFI_FEATURE_D2D_RTT:
-      return HidlChipCaps::D2D_RTT;
-    case WIFI_FEATURE_D2AP_RTT:
-      return HidlChipCaps::D2AP_RTT;
-  };
-  CHECK(false) << "Unknown legacy feature: " << feature;
-  return {};
-}
-
-IWifiStaIface::StaIfaceCapabilityMask
-convertLegacyFeatureToHidlStaIfaceCapability(uint32_t feature) {
-  using HidlStaIfaceCaps = IWifiStaIface::StaIfaceCapabilityMask;
-  switch (feature) {
-    case WIFI_FEATURE_GSCAN:
-      return HidlStaIfaceCaps::BACKGROUND_SCAN;
-    case WIFI_FEATURE_LINK_LAYER_STATS:
-      return HidlStaIfaceCaps::LINK_LAYER_STATS;
-    case WIFI_FEATURE_RSSI_MONITOR:
-      return HidlStaIfaceCaps::RSSI_MONITOR;
-    case WIFI_FEATURE_CONTROL_ROAMING:
-      return HidlStaIfaceCaps::CONTROL_ROAMING;
-    case WIFI_FEATURE_IE_WHITELIST:
-      return HidlStaIfaceCaps::PROBE_IE_WHITELIST;
-    case WIFI_FEATURE_SCAN_RAND:
-      return HidlStaIfaceCaps::SCAN_RAND;
-    case WIFI_FEATURE_INFRA_5G:
-      return HidlStaIfaceCaps::STA_5G;
-    case WIFI_FEATURE_HOTSPOT:
-      return HidlStaIfaceCaps::HOTSPOT;
-    case WIFI_FEATURE_PNO:
-      return HidlStaIfaceCaps::PNO;
-    case WIFI_FEATURE_TDLS:
-      return HidlStaIfaceCaps::TDLS;
-    case WIFI_FEATURE_TDLS_OFFCHANNEL:
-      return HidlStaIfaceCaps::TDLS_OFFCHANNEL;
-    case WIFI_FEATURE_CONFIG_NDO:
-      return HidlStaIfaceCaps::ND_OFFLOAD;
-    case WIFI_FEATURE_MKEEP_ALIVE:
-      return HidlStaIfaceCaps::KEEP_ALIVE;
-  };
-  CHECK(false) << "Unknown legacy feature: " << feature;
-  return {};
-}
-
-bool convertLegacyFeaturesToHidlChipCapabilities(
-    uint32_t legacy_feature_set,
-    uint32_t legacy_logger_feature_set,
-    uint32_t* hidl_caps) {
-  if (!hidl_caps) {
-    return false;
-  }
-  *hidl_caps = {};
-  using HidlChipCaps = IWifiChip::ChipCapabilityMask;
-  for (const auto feature : {legacy_hal::WIFI_LOGGER_MEMORY_DUMP_SUPPORTED,
-                             legacy_hal::WIFI_LOGGER_DRIVER_DUMP_SUPPORTED,
-                             legacy_hal::WIFI_LOGGER_CONNECT_EVENT_SUPPORTED,
-                             legacy_hal::WIFI_LOGGER_POWER_EVENT_SUPPORTED,
-                             legacy_hal::WIFI_LOGGER_WAKE_LOCK_SUPPORTED}) {
-    if (feature & legacy_logger_feature_set) {
-      *hidl_caps |= convertLegacyLoggerFeatureToHidlChipCapability(feature);
-    }
-  }
-  for (const auto feature : {WIFI_FEATURE_SET_TX_POWER_LIMIT,
-                             WIFI_FEATURE_D2D_RTT,
-                             WIFI_FEATURE_D2AP_RTT}) {
-    if (feature & legacy_feature_set) {
-      *hidl_caps |= convertLegacyFeatureToHidlChipCapability(feature);
-    }
-  }
-  // There are no flags for these 3 in the legacy feature set. Adding them to
-  // the set because all the current devices support it.
-  *hidl_caps |= HidlChipCaps::DEBUG_RING_BUFFER_VENDOR_DATA;
-  *hidl_caps |= HidlChipCaps::DEBUG_HOST_WAKE_REASON_STATS;
-  *hidl_caps |= HidlChipCaps::DEBUG_ERROR_ALERTS;
-  return true;
-}
-
-WifiDebugRingBufferFlags convertLegacyDebugRingBufferFlagsToHidl(
-    uint32_t flag) {
-  switch (flag) {
-    case WIFI_RING_BUFFER_FLAG_HAS_BINARY_ENTRIES:
-      return WifiDebugRingBufferFlags::HAS_BINARY_ENTRIES;
-    case WIFI_RING_BUFFER_FLAG_HAS_ASCII_ENTRIES:
-      return WifiDebugRingBufferFlags::HAS_ASCII_ENTRIES;
-  };
-  CHECK(false) << "Unknown legacy flag: " << flag;
-  return {};
-}
-
-bool convertLegacyDebugRingBufferStatusToHidl(
-    const legacy_hal::wifi_ring_buffer_status& legacy_status,
-    WifiDebugRingBufferStatus* hidl_status) {
-  if (!hidl_status) {
-    return false;
-  }
-  *hidl_status = {};
-  hidl_status->ringName = safeConvertChar(reinterpret_cast<const char*>(legacy_status.name),
-        sizeof(legacy_status.name));
-  hidl_status->flags = 0;
-  for (const auto flag : {WIFI_RING_BUFFER_FLAG_HAS_BINARY_ENTRIES,
-                          WIFI_RING_BUFFER_FLAG_HAS_ASCII_ENTRIES}) {
-    if (flag & legacy_status.flags) {
-      hidl_status->flags |=
-          static_cast<std::underlying_type<WifiDebugRingBufferFlags>::type>(
-              convertLegacyDebugRingBufferFlagsToHidl(flag));
-    }
-  }
-  hidl_status->ringId = legacy_status.ring_id;
-  hidl_status->sizeInBytes = legacy_status.ring_buffer_byte_size;
-  // Calculate free size of the ring the buffer. We don't need to send the
-  // exact read/write pointers that were there in the legacy HAL interface.
-  if (legacy_status.written_bytes >= legacy_status.read_bytes) {
-    hidl_status->freeSizeInBytes =
-        legacy_status.ring_buffer_byte_size -
-        (legacy_status.written_bytes - legacy_status.read_bytes);
-  } else {
-    hidl_status->freeSizeInBytes =
-        legacy_status.read_bytes - legacy_status.written_bytes;
-  }
-  hidl_status->verboseLevel = legacy_status.verbose_level;
-  return true;
-}
-
-bool convertLegacyVectorOfDebugRingBufferStatusToHidl(
-    const std::vector<legacy_hal::wifi_ring_buffer_status>& legacy_status_vec,
-    std::vector<WifiDebugRingBufferStatus>* hidl_status_vec) {
-  if (!hidl_status_vec) {
-    return false;
-  }
-  *hidl_status_vec = {};
-  for (const auto& legacy_status : legacy_status_vec) {
-    WifiDebugRingBufferStatus hidl_status;
-    if (!convertLegacyDebugRingBufferStatusToHidl(legacy_status,
-                                                  &hidl_status)) {
-      return false;
-    }
-    hidl_status_vec->push_back(hidl_status);
-  }
-  return true;
-}
-
-bool convertLegacyWakeReasonStatsToHidl(
-    const legacy_hal::WakeReasonStats& legacy_stats,
-    WifiDebugHostWakeReasonStats* hidl_stats) {
-  if (!hidl_stats) {
-    return false;
-  }
-  *hidl_stats = {};
-  hidl_stats->totalCmdEventWakeCnt =
-      legacy_stats.wake_reason_cnt.total_cmd_event_wake;
-  hidl_stats->cmdEventWakeCntPerType = legacy_stats.cmd_event_wake_cnt;
-  hidl_stats->totalDriverFwLocalWakeCnt =
-      legacy_stats.wake_reason_cnt.total_driver_fw_local_wake;
-  hidl_stats->driverFwLocalWakeCntPerType =
-      legacy_stats.driver_fw_local_wake_cnt;
-  hidl_stats->totalRxPacketWakeCnt =
-      legacy_stats.wake_reason_cnt.total_rx_data_wake;
-  hidl_stats->rxPktWakeDetails.rxUnicastCnt =
-      legacy_stats.wake_reason_cnt.rx_wake_details.rx_unicast_cnt;
-  hidl_stats->rxPktWakeDetails.rxMulticastCnt =
-      legacy_stats.wake_reason_cnt.rx_wake_details.rx_multicast_cnt;
-  hidl_stats->rxPktWakeDetails.rxBroadcastCnt =
-      legacy_stats.wake_reason_cnt.rx_wake_details.rx_broadcast_cnt;
-  hidl_stats->rxMulticastPkWakeDetails.ipv4RxMulticastAddrCnt =
-      legacy_stats.wake_reason_cnt.rx_multicast_wake_pkt_info
-          .ipv4_rx_multicast_addr_cnt;
-  hidl_stats->rxMulticastPkWakeDetails.ipv6RxMulticastAddrCnt =
-      legacy_stats.wake_reason_cnt.rx_multicast_wake_pkt_info
-          .ipv6_rx_multicast_addr_cnt;
-  hidl_stats->rxMulticastPkWakeDetails.otherRxMulticastAddrCnt =
-      legacy_stats.wake_reason_cnt.rx_multicast_wake_pkt_info
-          .other_rx_multicast_addr_cnt;
-  hidl_stats->rxIcmpPkWakeDetails.icmpPkt =
-      legacy_stats.wake_reason_cnt.rx_wake_pkt_classification_info.icmp_pkt;
-  hidl_stats->rxIcmpPkWakeDetails.icmp6Pkt =
-      legacy_stats.wake_reason_cnt.rx_wake_pkt_classification_info.icmp6_pkt;
-  hidl_stats->rxIcmpPkWakeDetails.icmp6Ra =
-      legacy_stats.wake_reason_cnt.rx_wake_pkt_classification_info.icmp6_ra;
-  hidl_stats->rxIcmpPkWakeDetails.icmp6Na =
-      legacy_stats.wake_reason_cnt.rx_wake_pkt_classification_info.icmp6_na;
-  hidl_stats->rxIcmpPkWakeDetails.icmp6Ns =
-      legacy_stats.wake_reason_cnt.rx_wake_pkt_classification_info.icmp6_ns;
-  return true;
-}
-
-legacy_hal::wifi_power_scenario convertHidlTxPowerScenarioToLegacy(
-    V1_1::IWifiChip::TxPowerScenario hidl_scenario) {
-  switch (hidl_scenario) {
-    case V1_1::IWifiChip::TxPowerScenario::VOICE_CALL:
-      return legacy_hal::WIFI_POWER_SCENARIO_VOICE_CALL;
-  };
-  CHECK(false);
-}
-
-bool convertLegacyFeaturesToHidlStaCapabilities(
-    uint32_t legacy_feature_set,
-    uint32_t legacy_logger_feature_set,
-    uint32_t* hidl_caps) {
-  if (!hidl_caps) {
-    return false;
-  }
-  *hidl_caps = {};
-  using HidlStaIfaceCaps = IWifiStaIface::StaIfaceCapabilityMask;
-  for (const auto feature : {legacy_hal::WIFI_LOGGER_PACKET_FATE_SUPPORTED}) {
-    if (feature & legacy_logger_feature_set) {
-      *hidl_caps |= convertLegacyLoggerFeatureToHidlStaIfaceCapability(feature);
-    }
-  }
-  for (const auto feature : {WIFI_FEATURE_GSCAN,
-                             WIFI_FEATURE_LINK_LAYER_STATS,
-                             WIFI_FEATURE_RSSI_MONITOR,
-                             WIFI_FEATURE_CONTROL_ROAMING,
-                             WIFI_FEATURE_IE_WHITELIST,
-                             WIFI_FEATURE_SCAN_RAND,
-                             WIFI_FEATURE_INFRA_5G,
-                             WIFI_FEATURE_HOTSPOT,
-                             WIFI_FEATURE_PNO,
-                             WIFI_FEATURE_TDLS,
-                             WIFI_FEATURE_TDLS_OFFCHANNEL,
-                             WIFI_FEATURE_CONFIG_NDO,
-                             WIFI_FEATURE_MKEEP_ALIVE}) {
-    if (feature & legacy_feature_set) {
-      *hidl_caps |= convertLegacyFeatureToHidlStaIfaceCapability(feature);
-    }
-  }
-  // There is no flag for this one in the legacy feature set. Adding it to the
-  // set because all the current devices support it.
-  *hidl_caps |= HidlStaIfaceCaps::APF;
-  return true;
-}
-
-bool convertLegacyApfCapabilitiesToHidl(
-    const legacy_hal::PacketFilterCapabilities& legacy_caps,
-    StaApfPacketFilterCapabilities* hidl_caps) {
-  if (!hidl_caps) {
-    return false;
-  }
-  *hidl_caps = {};
-  hidl_caps->version = legacy_caps.version;
-  hidl_caps->maxLength = legacy_caps.max_len;
-  return true;
-}
-
-uint8_t convertHidlGscanReportEventFlagToLegacy(
-    StaBackgroundScanBucketEventReportSchemeMask hidl_flag) {
-  using HidlFlag = StaBackgroundScanBucketEventReportSchemeMask;
-  switch (hidl_flag) {
-    case HidlFlag::EACH_SCAN:
-      return REPORT_EVENTS_EACH_SCAN;
-    case HidlFlag::FULL_RESULTS:
-      return REPORT_EVENTS_FULL_RESULTS;
-    case HidlFlag::NO_BATCH:
-      return REPORT_EVENTS_NO_BATCH;
-  };
-  CHECK(false);
-}
-
-StaScanDataFlagMask convertLegacyGscanDataFlagToHidl(uint8_t legacy_flag) {
-  switch (legacy_flag) {
-    case legacy_hal::WIFI_SCAN_FLAG_INTERRUPTED:
-      return StaScanDataFlagMask::INTERRUPTED;
-  };
-  CHECK(false) << "Unknown legacy flag: " << legacy_flag;
-  // To silence the compiler warning about reaching the end of non-void
-  // function.
-  return {};
-}
-
-bool convertLegacyGscanCapabilitiesToHidl(
-    const legacy_hal::wifi_gscan_capabilities& legacy_caps,
-    StaBackgroundScanCapabilities* hidl_caps) {
-  if (!hidl_caps) {
-    return false;
-  }
-  *hidl_caps = {};
-  hidl_caps->maxCacheSize = legacy_caps.max_scan_cache_size;
-  hidl_caps->maxBuckets = legacy_caps.max_scan_buckets;
-  hidl_caps->maxApCachePerScan = legacy_caps.max_ap_cache_per_scan;
-  hidl_caps->maxReportingThreshold = legacy_caps.max_scan_reporting_threshold;
-  return true;
-}
-
-legacy_hal::wifi_band convertHidlWifiBandToLegacy(WifiBand band) {
-  switch (band) {
-    case WifiBand::BAND_UNSPECIFIED:
-      return legacy_hal::WIFI_BAND_UNSPECIFIED;
-    case WifiBand::BAND_24GHZ:
-      return legacy_hal::WIFI_BAND_BG;
-    case WifiBand::BAND_5GHZ:
-      return legacy_hal::WIFI_BAND_A;
-    case WifiBand::BAND_5GHZ_DFS:
-      return legacy_hal::WIFI_BAND_A_DFS;
-    case WifiBand::BAND_5GHZ_WITH_DFS:
-      return legacy_hal::WIFI_BAND_A_WITH_DFS;
-    case WifiBand::BAND_24GHZ_5GHZ:
-      return legacy_hal::WIFI_BAND_ABG;
-    case WifiBand::BAND_24GHZ_5GHZ_WITH_DFS:
-      return legacy_hal::WIFI_BAND_ABG_WITH_DFS;
-  };
-  CHECK(false);
-}
-
-bool convertHidlGscanParamsToLegacy(
-    const StaBackgroundScanParameters& hidl_scan_params,
-    legacy_hal::wifi_scan_cmd_params* legacy_scan_params) {
-  if (!legacy_scan_params) {
-    return false;
-  }
-  *legacy_scan_params = {};
-  legacy_scan_params->base_period = hidl_scan_params.basePeriodInMs;
-  legacy_scan_params->max_ap_per_scan = hidl_scan_params.maxApPerScan;
-  legacy_scan_params->report_threshold_percent =
-      hidl_scan_params.reportThresholdPercent;
-  legacy_scan_params->report_threshold_num_scans =
-      hidl_scan_params.reportThresholdNumScans;
-  if (hidl_scan_params.buckets.size() > MAX_BUCKETS) {
-    return false;
-  }
-  legacy_scan_params->num_buckets = hidl_scan_params.buckets.size();
-  for (uint32_t bucket_idx = 0; bucket_idx < hidl_scan_params.buckets.size();
-       bucket_idx++) {
-    const StaBackgroundScanBucketParameters& hidl_bucket_spec =
-        hidl_scan_params.buckets[bucket_idx];
-    legacy_hal::wifi_scan_bucket_spec& legacy_bucket_spec =
-        legacy_scan_params->buckets[bucket_idx];
-    if (hidl_bucket_spec.bucketIdx >= MAX_BUCKETS) {
-      return false;
-    }
-    legacy_bucket_spec.bucket = hidl_bucket_spec.bucketIdx;
-    legacy_bucket_spec.band =
-        convertHidlWifiBandToLegacy(hidl_bucket_spec.band);
-    legacy_bucket_spec.period = hidl_bucket_spec.periodInMs;
-    legacy_bucket_spec.max_period = hidl_bucket_spec.exponentialMaxPeriodInMs;
-    legacy_bucket_spec.base = hidl_bucket_spec.exponentialBase;
-    legacy_bucket_spec.step_count = hidl_bucket_spec.exponentialStepCount;
-    legacy_bucket_spec.report_events = 0;
-    using HidlFlag = StaBackgroundScanBucketEventReportSchemeMask;
-    for (const auto flag :
-         {HidlFlag::EACH_SCAN, HidlFlag::FULL_RESULTS, HidlFlag::NO_BATCH}) {
-      if (hidl_bucket_spec.eventReportScheme &
-          static_cast<std::underlying_type<HidlFlag>::type>(flag)) {
-        legacy_bucket_spec.report_events |=
-            convertHidlGscanReportEventFlagToLegacy(flag);
-      }
-    }
-    if (hidl_bucket_spec.frequencies.size() > MAX_CHANNELS) {
-      return false;
-    }
-    legacy_bucket_spec.num_channels = hidl_bucket_spec.frequencies.size();
-    for (uint32_t freq_idx = 0; freq_idx < hidl_bucket_spec.frequencies.size();
-         freq_idx++) {
-      legacy_bucket_spec.channels[freq_idx].channel =
-          hidl_bucket_spec.frequencies[freq_idx];
-    }
-  }
-  return true;
-}
-
-bool convertLegacyIeToHidl(
-    const legacy_hal::wifi_information_element& legacy_ie,
-    WifiInformationElement* hidl_ie) {
-  if (!hidl_ie) {
-    return false;
-  }
-  *hidl_ie = {};
-  hidl_ie->id = legacy_ie.id;
-  hidl_ie->data =
-      std::vector<uint8_t>(legacy_ie.data, legacy_ie.data + legacy_ie.len);
-  return true;
-}
-
-bool convertLegacyIeBlobToHidl(const uint8_t* ie_blob,
-                               uint32_t ie_blob_len,
-                               std::vector<WifiInformationElement>* hidl_ies) {
-  if (!ie_blob || !hidl_ies) {
-    return false;
-  }
-  *hidl_ies = {};
-  const uint8_t* ies_begin = ie_blob;
-  const uint8_t* ies_end = ie_blob + ie_blob_len;
-  const uint8_t* next_ie = ies_begin;
-  using wifi_ie = legacy_hal::wifi_information_element;
-  constexpr size_t kIeHeaderLen = sizeof(wifi_ie);
-  // Each IE should atleast have the header (i.e |id| & |len| fields).
-  while (next_ie + kIeHeaderLen <= ies_end) {
-    const wifi_ie& legacy_ie = (*reinterpret_cast<const wifi_ie*>(next_ie));
-    uint32_t curr_ie_len = kIeHeaderLen + legacy_ie.len;
-    if (next_ie + curr_ie_len > ies_end) {
-      LOG(ERROR) << "Error parsing IE blob. Next IE: " << (void *)next_ie
-                 << ", Curr IE len: " << curr_ie_len << ", IEs End: " << (void *)ies_end;
-      break;
-    }
-    WifiInformationElement hidl_ie;
-    if (!convertLegacyIeToHidl(legacy_ie, &hidl_ie)) {
-      LOG(ERROR) << "Error converting IE. Id: " << legacy_ie.id
-                 << ", len: " << legacy_ie.len;
-      break;
-    }
-    hidl_ies->push_back(std::move(hidl_ie));
-    next_ie += curr_ie_len;
-  }
-  // Check if the blob has been fully consumed.
-  if (next_ie != ies_end) {
-    LOG(ERROR) << "Failed to fully parse IE blob. Next IE: " << (void *)next_ie
-               << ", IEs End: " << (void *)ies_end;
-  }
-  return true;
-}
-
-bool convertLegacyGscanResultToHidl(
-    const legacy_hal::wifi_scan_result& legacy_scan_result,
-    bool has_ie_data,
-    StaScanResult* hidl_scan_result) {
-  if (!hidl_scan_result) {
-    return false;
-  }
-  *hidl_scan_result = {};
-  hidl_scan_result->timeStampInUs = legacy_scan_result.ts;
-  hidl_scan_result->ssid = std::vector<uint8_t>(
-      legacy_scan_result.ssid,
-      legacy_scan_result.ssid + strnlen(legacy_scan_result.ssid,
-            sizeof(legacy_scan_result.ssid) - 1));
-  memcpy(hidl_scan_result->bssid.data(),
-         legacy_scan_result.bssid,
-         hidl_scan_result->bssid.size());
-  hidl_scan_result->frequency = legacy_scan_result.channel;
-  hidl_scan_result->rssi = legacy_scan_result.rssi;
-  hidl_scan_result->beaconPeriodInMs = legacy_scan_result.beacon_period;
-  hidl_scan_result->capability = legacy_scan_result.capability;
-  if (has_ie_data) {
-    std::vector<WifiInformationElement> ies;
-    if (!convertLegacyIeBlobToHidl(
-            reinterpret_cast<const uint8_t*>(legacy_scan_result.ie_data),
-            legacy_scan_result.ie_length,
-            &ies)) {
-      return false;
-    }
-    hidl_scan_result->informationElements = std::move(ies);
-  }
-  return true;
-}
-
-bool convertLegacyCachedGscanResultsToHidl(
-    const legacy_hal::wifi_cached_scan_results& legacy_cached_scan_result,
-    StaScanData* hidl_scan_data) {
-  if (!hidl_scan_data) {
-    return false;
-  }
-  *hidl_scan_data = {};
-  hidl_scan_data->flags = 0;
-  for (const auto flag : {legacy_hal::WIFI_SCAN_FLAG_INTERRUPTED}) {
-    if (legacy_cached_scan_result.flags & flag) {
-      hidl_scan_data->flags |=
-          static_cast<std::underlying_type<StaScanDataFlagMask>::type>(
-              convertLegacyGscanDataFlagToHidl(flag));
-    }
-  }
-  hidl_scan_data->bucketsScanned = legacy_cached_scan_result.buckets_scanned;
-
-  CHECK(legacy_cached_scan_result.num_results >= 0 &&
-        legacy_cached_scan_result.num_results <= MAX_AP_CACHE_PER_SCAN);
-  std::vector<StaScanResult> hidl_scan_results;
-  for (int32_t result_idx = 0;
-       result_idx < legacy_cached_scan_result.num_results;
-       result_idx++) {
-    StaScanResult hidl_scan_result;
-    if (!convertLegacyGscanResultToHidl(
-            legacy_cached_scan_result.results[result_idx],
-            false,
-            &hidl_scan_result)) {
-      return false;
-    }
-    hidl_scan_results.push_back(hidl_scan_result);
-  }
-  hidl_scan_data->results = std::move(hidl_scan_results);
-  return true;
-}
-
-bool convertLegacyVectorOfCachedGscanResultsToHidl(
-    const std::vector<legacy_hal::wifi_cached_scan_results>&
-        legacy_cached_scan_results,
-    std::vector<StaScanData>* hidl_scan_datas) {
-  if (!hidl_scan_datas) {
-    return false;
-  }
-  *hidl_scan_datas = {};
-  for (const auto& legacy_cached_scan_result : legacy_cached_scan_results) {
-    StaScanData hidl_scan_data;
-    if (!convertLegacyCachedGscanResultsToHidl(legacy_cached_scan_result,
-                                               &hidl_scan_data)) {
-      return false;
-    }
-    hidl_scan_datas->push_back(hidl_scan_data);
-  }
-  return true;
-}
-
-WifiDebugTxPacketFate convertLegacyDebugTxPacketFateToHidl(
-    legacy_hal::wifi_tx_packet_fate fate) {
-  switch (fate) {
-    case legacy_hal::TX_PKT_FATE_ACKED:
-      return WifiDebugTxPacketFate::ACKED;
-    case legacy_hal::TX_PKT_FATE_SENT:
-      return WifiDebugTxPacketFate::SENT;
-    case legacy_hal::TX_PKT_FATE_FW_QUEUED:
-      return WifiDebugTxPacketFate::FW_QUEUED;
-    case legacy_hal::TX_PKT_FATE_FW_DROP_INVALID:
-      return WifiDebugTxPacketFate::FW_DROP_INVALID;
-    case legacy_hal::TX_PKT_FATE_FW_DROP_NOBUFS:
-      return WifiDebugTxPacketFate::FW_DROP_NOBUFS;
-    case legacy_hal::TX_PKT_FATE_FW_DROP_OTHER:
-      return WifiDebugTxPacketFate::FW_DROP_OTHER;
-    case legacy_hal::TX_PKT_FATE_DRV_QUEUED:
-      return WifiDebugTxPacketFate::DRV_QUEUED;
-    case legacy_hal::TX_PKT_FATE_DRV_DROP_INVALID:
-      return WifiDebugTxPacketFate::DRV_DROP_INVALID;
-    case legacy_hal::TX_PKT_FATE_DRV_DROP_NOBUFS:
-      return WifiDebugTxPacketFate::DRV_DROP_NOBUFS;
-    case legacy_hal::TX_PKT_FATE_DRV_DROP_OTHER:
-      return WifiDebugTxPacketFate::DRV_DROP_OTHER;
-  };
-  CHECK(false) << "Unknown legacy fate type: " << fate;
-}
-
-WifiDebugRxPacketFate convertLegacyDebugRxPacketFateToHidl(
-    legacy_hal::wifi_rx_packet_fate fate) {
-  switch (fate) {
-    case legacy_hal::RX_PKT_FATE_SUCCESS:
-      return WifiDebugRxPacketFate::SUCCESS;
-    case legacy_hal::RX_PKT_FATE_FW_QUEUED:
-      return WifiDebugRxPacketFate::FW_QUEUED;
-    case legacy_hal::RX_PKT_FATE_FW_DROP_FILTER:
-      return WifiDebugRxPacketFate::FW_DROP_FILTER;
-    case legacy_hal::RX_PKT_FATE_FW_DROP_INVALID:
-      return WifiDebugRxPacketFate::FW_DROP_INVALID;
-    case legacy_hal::RX_PKT_FATE_FW_DROP_NOBUFS:
-      return WifiDebugRxPacketFate::FW_DROP_NOBUFS;
-    case legacy_hal::RX_PKT_FATE_FW_DROP_OTHER:
-      return WifiDebugRxPacketFate::FW_DROP_OTHER;
-    case legacy_hal::RX_PKT_FATE_DRV_QUEUED:
-      return WifiDebugRxPacketFate::DRV_QUEUED;
-    case legacy_hal::RX_PKT_FATE_DRV_DROP_FILTER:
-      return WifiDebugRxPacketFate::DRV_DROP_FILTER;
-    case legacy_hal::RX_PKT_FATE_DRV_DROP_INVALID:
-      return WifiDebugRxPacketFate::DRV_DROP_INVALID;
-    case legacy_hal::RX_PKT_FATE_DRV_DROP_NOBUFS:
-      return WifiDebugRxPacketFate::DRV_DROP_NOBUFS;
-    case legacy_hal::RX_PKT_FATE_DRV_DROP_OTHER:
-      return WifiDebugRxPacketFate::DRV_DROP_OTHER;
-  };
-  CHECK(false) << "Unknown legacy fate type: " << fate;
-}
-
-WifiDebugPacketFateFrameType convertLegacyDebugPacketFateFrameTypeToHidl(
-    legacy_hal::frame_type type) {
-  switch (type) {
-    case legacy_hal::FRAME_TYPE_UNKNOWN:
-      return WifiDebugPacketFateFrameType::UNKNOWN;
-    case legacy_hal::FRAME_TYPE_ETHERNET_II:
-      return WifiDebugPacketFateFrameType::ETHERNET_II;
-    case legacy_hal::FRAME_TYPE_80211_MGMT:
-      return WifiDebugPacketFateFrameType::MGMT_80211;
-  };
-  CHECK(false) << "Unknown legacy frame type: " << type;
-}
-
-bool convertLegacyDebugPacketFateFrameToHidl(
-    const legacy_hal::frame_info& legacy_frame,
-    WifiDebugPacketFateFrameInfo* hidl_frame) {
-  if (!hidl_frame) {
-    return false;
-  }
-  *hidl_frame = {};
-  hidl_frame->frameType =
-      convertLegacyDebugPacketFateFrameTypeToHidl(legacy_frame.payload_type);
-  hidl_frame->frameLen = legacy_frame.frame_len;
-  hidl_frame->driverTimestampUsec = legacy_frame.driver_timestamp_usec;
-  hidl_frame->firmwareTimestampUsec = legacy_frame.firmware_timestamp_usec;
-  const uint8_t* frame_begin = reinterpret_cast<const uint8_t*>(
-      legacy_frame.frame_content.ethernet_ii_bytes);
-  hidl_frame->frameContent =
-      std::vector<uint8_t>(frame_begin, frame_begin + legacy_frame.frame_len);
-  return true;
-}
-
-bool convertLegacyDebugTxPacketFateToHidl(
-    const legacy_hal::wifi_tx_report& legacy_fate,
-    WifiDebugTxPacketFateReport* hidl_fate) {
-  if (!hidl_fate) {
-    return false;
-  }
-  *hidl_fate = {};
-  hidl_fate->fate = convertLegacyDebugTxPacketFateToHidl(legacy_fate.fate);
-  return convertLegacyDebugPacketFateFrameToHidl(legacy_fate.frame_inf,
-                                                 &hidl_fate->frameInfo);
-}
-
-bool convertLegacyVectorOfDebugTxPacketFateToHidl(
-    const std::vector<legacy_hal::wifi_tx_report>& legacy_fates,
-    std::vector<WifiDebugTxPacketFateReport>* hidl_fates) {
-  if (!hidl_fates) {
-    return false;
-  }
-  *hidl_fates = {};
-  for (const auto& legacy_fate : legacy_fates) {
-    WifiDebugTxPacketFateReport hidl_fate;
-    if (!convertLegacyDebugTxPacketFateToHidl(legacy_fate, &hidl_fate)) {
-      return false;
-    }
-    hidl_fates->push_back(hidl_fate);
-  }
-  return true;
-}
-
-bool convertLegacyDebugRxPacketFateToHidl(
-    const legacy_hal::wifi_rx_report& legacy_fate,
-    WifiDebugRxPacketFateReport* hidl_fate) {
-  if (!hidl_fate) {
-    return false;
-  }
-  *hidl_fate = {};
-  hidl_fate->fate = convertLegacyDebugRxPacketFateToHidl(legacy_fate.fate);
-  return convertLegacyDebugPacketFateFrameToHidl(legacy_fate.frame_inf,
-                                                 &hidl_fate->frameInfo);
-}
-
-bool convertLegacyVectorOfDebugRxPacketFateToHidl(
-    const std::vector<legacy_hal::wifi_rx_report>& legacy_fates,
-    std::vector<WifiDebugRxPacketFateReport>* hidl_fates) {
-  if (!hidl_fates) {
-    return false;
-  }
-  *hidl_fates = {};
-  for (const auto& legacy_fate : legacy_fates) {
-    WifiDebugRxPacketFateReport hidl_fate;
-    if (!convertLegacyDebugRxPacketFateToHidl(legacy_fate, &hidl_fate)) {
-      return false;
-    }
-    hidl_fates->push_back(hidl_fate);
-  }
-  return true;
-}
-
-bool convertLegacyLinkLayerStatsToHidl(
-    const legacy_hal::LinkLayerStats& legacy_stats,
-    StaLinkLayerStats* hidl_stats) {
-  if (!hidl_stats) {
-    return false;
-  }
-  *hidl_stats = {};
-  // iface legacy_stats conversion.
-  hidl_stats->iface.beaconRx = legacy_stats.iface.beacon_rx;
-  hidl_stats->iface.avgRssiMgmt = legacy_stats.iface.rssi_mgmt;
-  hidl_stats->iface.wmeBePktStats.rxMpdu =
-      legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].rx_mpdu;
-  hidl_stats->iface.wmeBePktStats.txMpdu =
-      legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].tx_mpdu;
-  hidl_stats->iface.wmeBePktStats.lostMpdu =
-      legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].mpdu_lost;
-  hidl_stats->iface.wmeBePktStats.retries =
-      legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].retries;
-  hidl_stats->iface.wmeBkPktStats.rxMpdu =
-      legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].rx_mpdu;
-  hidl_stats->iface.wmeBkPktStats.txMpdu =
-      legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].tx_mpdu;
-  hidl_stats->iface.wmeBkPktStats.lostMpdu =
-      legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].mpdu_lost;
-  hidl_stats->iface.wmeBkPktStats.retries =
-      legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].retries;
-  hidl_stats->iface.wmeViPktStats.rxMpdu =
-      legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].rx_mpdu;
-  hidl_stats->iface.wmeViPktStats.txMpdu =
-      legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].tx_mpdu;
-  hidl_stats->iface.wmeViPktStats.lostMpdu =
-      legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].mpdu_lost;
-  hidl_stats->iface.wmeViPktStats.retries =
-      legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].retries;
-  hidl_stats->iface.wmeVoPktStats.rxMpdu =
-      legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].rx_mpdu;
-  hidl_stats->iface.wmeVoPktStats.txMpdu =
-      legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].tx_mpdu;
-  hidl_stats->iface.wmeVoPktStats.lostMpdu =
-      legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].mpdu_lost;
-  hidl_stats->iface.wmeVoPktStats.retries =
-      legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].retries;
-  // radio legacy_stats conversion.
-  std::vector<StaLinkLayerRadioStats> hidl_radios_stats;
-  for (const auto& legacy_radio_stats : legacy_stats.radios) {
-    StaLinkLayerRadioStats hidl_radio_stats;
-    hidl_radio_stats.onTimeInMs = legacy_radio_stats.stats.on_time;
-    hidl_radio_stats.txTimeInMs = legacy_radio_stats.stats.tx_time;
-    hidl_radio_stats.rxTimeInMs = legacy_radio_stats.stats.rx_time;
-    hidl_radio_stats.onTimeInMsForScan = legacy_radio_stats.stats.on_time_scan;
-    hidl_radio_stats.txTimeInMsPerLevel = legacy_radio_stats.tx_time_per_levels;
-    hidl_radios_stats.push_back(hidl_radio_stats);
-  }
-  hidl_stats->radios = hidl_radios_stats;
-  // Timestamp in the HAL wrapper here since it's not provided in the legacy
-  // HAL API.
-  hidl_stats->timeStampInMs = uptimeMillis();
-  return true;
-}
-
-bool convertLegacyRoamingCapabilitiesToHidl(
-    const legacy_hal::wifi_roaming_capabilities& legacy_caps,
-    StaRoamingCapabilities* hidl_caps) {
-  if (!hidl_caps) {
-    return false;
-  }
-  *hidl_caps = {};
-  hidl_caps->maxBlacklistSize = legacy_caps.max_blacklist_size;
-  hidl_caps->maxWhitelistSize = legacy_caps.max_whitelist_size;
-  return true;
-}
-
-bool convertHidlRoamingConfigToLegacy(
-    const StaRoamingConfig& hidl_config,
-    legacy_hal::wifi_roaming_config* legacy_config) {
-  if (!legacy_config) {
-    return false;
-  }
-  *legacy_config = {};
-  if (hidl_config.bssidBlacklist.size() > MAX_BLACKLIST_BSSID ||
-      hidl_config.ssidWhitelist.size() > MAX_WHITELIST_SSID) {
-    return false;
-  }
-  legacy_config->num_blacklist_bssid = hidl_config.bssidBlacklist.size();
-  uint32_t i = 0;
-  for (const auto& bssid : hidl_config.bssidBlacklist) {
-    CHECK(bssid.size() == sizeof(legacy_hal::mac_addr));
-    memcpy(legacy_config->blacklist_bssid[i++], bssid.data(), bssid.size());
-  }
-  legacy_config->num_whitelist_ssid = hidl_config.ssidWhitelist.size();
-  i = 0;
-  for (const auto& ssid : hidl_config.ssidWhitelist) {
-    CHECK(ssid.size() <= sizeof(legacy_hal::ssid_t::ssid_str));
-    legacy_config->whitelist_ssid[i].length = ssid.size();
-    memcpy(legacy_config->whitelist_ssid[i].ssid_str, ssid.data(), ssid.size());
-    i++;
-  }
-  return true;
-}
-
-legacy_hal::fw_roaming_state_t convertHidlRoamingStateToLegacy(
-    StaRoamingState state) {
-  switch (state) {
-    case StaRoamingState::ENABLED:
-      return legacy_hal::ROAMING_ENABLE;
-    case StaRoamingState::DISABLED:
-      return legacy_hal::ROAMING_DISABLE;
-  };
-  CHECK(false);
-}
-
-legacy_hal::NanMatchAlg convertHidlNanMatchAlgToLegacy(NanMatchAlg type) {
-  switch (type) {
-    case NanMatchAlg::MATCH_ONCE:
-      return legacy_hal::NAN_MATCH_ALG_MATCH_ONCE;
-    case NanMatchAlg::MATCH_CONTINUOUS:
-      return legacy_hal::NAN_MATCH_ALG_MATCH_CONTINUOUS;
-    case NanMatchAlg::MATCH_NEVER:
-      return legacy_hal::NAN_MATCH_ALG_MATCH_NEVER;
-  }
-  CHECK(false);
-}
-
-legacy_hal::NanPublishType convertHidlNanPublishTypeToLegacy(NanPublishType type) {
-  switch (type) {
-    case NanPublishType::UNSOLICITED:
-      return legacy_hal::NAN_PUBLISH_TYPE_UNSOLICITED;
-    case NanPublishType::SOLICITED:
-      return legacy_hal::NAN_PUBLISH_TYPE_SOLICITED;
-    case NanPublishType::UNSOLICITED_SOLICITED:
-      return legacy_hal::NAN_PUBLISH_TYPE_UNSOLICITED_SOLICITED;
-  }
-  CHECK(false);
-}
-
-legacy_hal::NanTxType convertHidlNanTxTypeToLegacy(NanTxType type) {
-  switch (type) {
-    case NanTxType::BROADCAST:
-      return legacy_hal::NAN_TX_TYPE_BROADCAST;
-    case NanTxType::UNICAST:
-      return legacy_hal::NAN_TX_TYPE_UNICAST;
-  }
-  CHECK(false);
-}
-
-legacy_hal::NanSubscribeType convertHidlNanSubscribeTypeToLegacy(NanSubscribeType type) {
-  switch (type) {
-    case NanSubscribeType::PASSIVE:
-      return legacy_hal::NAN_SUBSCRIBE_TYPE_PASSIVE;
-    case NanSubscribeType::ACTIVE:
-      return legacy_hal::NAN_SUBSCRIBE_TYPE_ACTIVE;
-  }
-  CHECK(false);
-}
-
-legacy_hal::NanSRFType convertHidlNanSrfTypeToLegacy(NanSrfType type) {
-  switch (type) {
-    case NanSrfType::BLOOM_FILTER:
-      return legacy_hal::NAN_SRF_ATTR_BLOOM_FILTER;
-    case NanSrfType::PARTIAL_MAC_ADDR:
-      return legacy_hal::NAN_SRF_ATTR_PARTIAL_MAC_ADDR;
-  }
-  CHECK(false);
-}
-
-legacy_hal::NanDataPathChannelCfg convertHidlNanDataPathChannelCfgToLegacy(
-    NanDataPathChannelCfg type) {
-  switch (type) {
-    case NanDataPathChannelCfg::CHANNEL_NOT_REQUESTED:
-      return legacy_hal::NAN_DP_CHANNEL_NOT_REQUESTED;
-    case NanDataPathChannelCfg::REQUEST_CHANNEL_SETUP:
-      return legacy_hal::NAN_DP_REQUEST_CHANNEL_SETUP;
-    case NanDataPathChannelCfg::FORCE_CHANNEL_SETUP:
-      return legacy_hal::NAN_DP_FORCE_CHANNEL_SETUP;
-  }
-  CHECK(false);
-}
-
-NanStatusType convertLegacyNanStatusTypeToHidl(
-    legacy_hal::NanStatusType type) {
-  switch (type) {
-    case legacy_hal::NAN_STATUS_SUCCESS:
-      return NanStatusType::SUCCESS;
-    case legacy_hal::NAN_STATUS_INTERNAL_FAILURE:
-      return NanStatusType::INTERNAL_FAILURE;
-    case legacy_hal::NAN_STATUS_PROTOCOL_FAILURE:
-      return NanStatusType::PROTOCOL_FAILURE;
-    case legacy_hal::NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID:
-      return NanStatusType::INVALID_SESSION_ID;
-    case legacy_hal::NAN_STATUS_NO_RESOURCE_AVAILABLE:
-      return NanStatusType::NO_RESOURCES_AVAILABLE;
-    case legacy_hal::NAN_STATUS_INVALID_PARAM:
-      return NanStatusType::INVALID_ARGS;
-    case legacy_hal::NAN_STATUS_INVALID_REQUESTOR_INSTANCE_ID:
-      return NanStatusType::INVALID_PEER_ID;
-    case legacy_hal::NAN_STATUS_INVALID_NDP_ID:
-      return NanStatusType::INVALID_NDP_ID;
-    case legacy_hal::NAN_STATUS_NAN_NOT_ALLOWED:
-      return NanStatusType::NAN_NOT_ALLOWED;
-    case legacy_hal::NAN_STATUS_NO_OTA_ACK:
-      return NanStatusType::NO_OTA_ACK;
-    case legacy_hal::NAN_STATUS_ALREADY_ENABLED:
-      return NanStatusType::ALREADY_ENABLED;
-    case legacy_hal::NAN_STATUS_FOLLOWUP_QUEUE_FULL:
-      return NanStatusType::FOLLOWUP_TX_QUEUE_FULL;
-    case legacy_hal::NAN_STATUS_UNSUPPORTED_CONCURRENCY_NAN_DISABLED:
-      return NanStatusType::UNSUPPORTED_CONCURRENCY_NAN_DISABLED;
-  }
-  CHECK(false);
-}
-
-void convertToWifiNanStatus(legacy_hal::NanStatusType type, const char* str, size_t max_len,
-    WifiNanStatus* wifiNanStatus) {
-  wifiNanStatus->status = convertLegacyNanStatusTypeToHidl(type);
-  wifiNanStatus->description = safeConvertChar(str, max_len);
-}
-
-bool convertHidlNanEnableRequestToLegacy(
-    const NanEnableRequest& hidl_request,
-    legacy_hal::NanEnableRequest* legacy_request) {
-  if (!legacy_request) {
-    LOG(ERROR) << "convertHidlNanEnableRequestToLegacy: null legacy_request";
-    return false;
-  }
-  *legacy_request = {};
-
-  legacy_request->config_2dot4g_support = 1;
-  legacy_request->support_2dot4g_val = hidl_request.operateInBand[
-        (size_t) NanBandIndex::NAN_BAND_24GHZ];
-  legacy_request->config_support_5g = 1;
-  legacy_request->support_5g_val = hidl_request.operateInBand[(size_t) NanBandIndex::NAN_BAND_5GHZ];
-  legacy_request->config_hop_count_limit = 1;
-  legacy_request->hop_count_limit_val = hidl_request.hopCountMax;
-  legacy_request->master_pref = hidl_request.configParams.masterPref;
-  legacy_request->discovery_indication_cfg = 0;
-  legacy_request->discovery_indication_cfg |=
-        hidl_request.configParams.disableDiscoveryAddressChangeIndication ? 0x1 : 0x0;
-  legacy_request->discovery_indication_cfg |=
-        hidl_request.configParams.disableStartedClusterIndication ? 0x2 : 0x0;
-  legacy_request->discovery_indication_cfg |=
-        hidl_request.configParams.disableJoinedClusterIndication ? 0x4 : 0x0;
-  legacy_request->config_sid_beacon = 1;
-  if (hidl_request.configParams.numberOfPublishServiceIdsInBeacon > 127) {
-    LOG(ERROR) << "convertHidlNanEnableRequestToLegacy: numberOfPublishServiceIdsInBeacon > 127";
-    return false;
-  }
-  legacy_request->sid_beacon_val =
-        (hidl_request.configParams.includePublishServiceIdsInBeacon ? 0x1 : 0x0)
-            | (hidl_request.configParams.numberOfPublishServiceIdsInBeacon << 1);
-  legacy_request->config_subscribe_sid_beacon = 1;
-  if (hidl_request.configParams.numberOfSubscribeServiceIdsInBeacon > 127) {
-    LOG(ERROR) << "convertHidlNanEnableRequestToLegacy: numberOfSubscribeServiceIdsInBeacon > 127";
-    return false;
-  }
-  legacy_request->subscribe_sid_beacon_val =
-        (hidl_request.configParams.includeSubscribeServiceIdsInBeacon ? 0x1 : 0x0)
-            | (hidl_request.configParams.numberOfSubscribeServiceIdsInBeacon << 1);
-  legacy_request->config_rssi_window_size = 1;
-  legacy_request->rssi_window_size_val = hidl_request.configParams.rssiWindowSize;
-  legacy_request->config_disc_mac_addr_randomization = 1;
-  legacy_request->disc_mac_addr_rand_interval_sec =
-        hidl_request.configParams.macAddressRandomizationIntervalSec;
-  legacy_request->config_2dot4g_rssi_close = 1;
-  if (hidl_request.configParams.bandSpecificConfig.size() != 2) {
-    LOG(ERROR) << "convertHidlNanEnableRequestToLegacy: bandSpecificConfig.size() != 2";
-    return false;
-  }
-  legacy_request->rssi_close_2dot4g_val =
-        hidl_request.configParams.bandSpecificConfig[
-            (size_t) NanBandIndex::NAN_BAND_24GHZ].rssiClose;
-  legacy_request->config_2dot4g_rssi_middle = 1;
-  legacy_request->rssi_middle_2dot4g_val =
-        hidl_request.configParams.bandSpecificConfig[
-            (size_t) NanBandIndex::NAN_BAND_24GHZ].rssiMiddle;
-  legacy_request->config_2dot4g_rssi_proximity = 1;
-  legacy_request->rssi_proximity_2dot4g_val =
-        hidl_request.configParams.bandSpecificConfig[
-            (size_t) NanBandIndex::NAN_BAND_24GHZ].rssiCloseProximity;
-  legacy_request->config_scan_params = 1;
-  legacy_request->scan_params_val.dwell_time[legacy_hal::NAN_CHANNEL_24G_BAND] =
-        hidl_request.configParams.bandSpecificConfig[
-            (size_t) NanBandIndex::NAN_BAND_24GHZ].dwellTimeMs;
-  legacy_request->scan_params_val.scan_period[legacy_hal::NAN_CHANNEL_24G_BAND] =
-        hidl_request.configParams.bandSpecificConfig[
-            (size_t) NanBandIndex::NAN_BAND_24GHZ].scanPeriodSec;
-  legacy_request->config_dw.config_2dot4g_dw_band = hidl_request.configParams
-        .bandSpecificConfig[(size_t) NanBandIndex::NAN_BAND_24GHZ].validDiscoveryWindowIntervalVal;
-  legacy_request->config_dw.dw_2dot4g_interval_val = hidl_request.configParams
-        .bandSpecificConfig[(size_t) NanBandIndex::NAN_BAND_24GHZ].discoveryWindowIntervalVal;
-  legacy_request->config_5g_rssi_close = 1;
-  legacy_request->rssi_close_5g_val =
-        hidl_request.configParams.bandSpecificConfig[
-            (size_t) NanBandIndex::NAN_BAND_5GHZ].rssiClose;
-  legacy_request->config_5g_rssi_middle = 1;
-  legacy_request->rssi_middle_5g_val =
-        hidl_request.configParams.bandSpecificConfig[
-            (size_t) NanBandIndex::NAN_BAND_5GHZ].rssiMiddle;
-  legacy_request->config_5g_rssi_close_proximity = 1;
-  legacy_request->rssi_close_proximity_5g_val =
-        hidl_request.configParams.bandSpecificConfig[
-            (size_t) NanBandIndex::NAN_BAND_5GHZ].rssiCloseProximity;
-  legacy_request->scan_params_val.dwell_time[legacy_hal::NAN_CHANNEL_5G_BAND_LOW] =
-        hidl_request.configParams.bandSpecificConfig[
-            (size_t) NanBandIndex::NAN_BAND_5GHZ].dwellTimeMs;
-  legacy_request->scan_params_val.scan_period[legacy_hal::NAN_CHANNEL_5G_BAND_LOW] =
-        hidl_request.configParams.bandSpecificConfig[
-            (size_t) NanBandIndex::NAN_BAND_5GHZ].scanPeriodSec;
-  legacy_request->scan_params_val.dwell_time[legacy_hal::NAN_CHANNEL_5G_BAND_HIGH] =
-        hidl_request.configParams.bandSpecificConfig[
-            (size_t) NanBandIndex::NAN_BAND_5GHZ].dwellTimeMs;
-  legacy_request->scan_params_val.scan_period[legacy_hal::NAN_CHANNEL_5G_BAND_HIGH] =
-        hidl_request.configParams.bandSpecificConfig[
-            (size_t) NanBandIndex::NAN_BAND_5GHZ].scanPeriodSec;
-  legacy_request->config_dw.config_5g_dw_band = hidl_request.configParams
-        .bandSpecificConfig[(size_t) NanBandIndex::NAN_BAND_5GHZ].validDiscoveryWindowIntervalVal;
-  legacy_request->config_dw.dw_5g_interval_val = hidl_request.configParams
-        .bandSpecificConfig[(size_t) NanBandIndex::NAN_BAND_5GHZ].discoveryWindowIntervalVal;
-  if (hidl_request.debugConfigs.validClusterIdVals) {
-    legacy_request->cluster_low = hidl_request.debugConfigs.clusterIdBottomRangeVal;
-    legacy_request->cluster_high = hidl_request.debugConfigs.clusterIdTopRangeVal;
-  } else { // need 'else' since not configurable in legacy HAL
-    legacy_request->cluster_low = 0x0000;
-    legacy_request->cluster_high = 0xFFFF;
-  }
-  legacy_request->config_intf_addr = hidl_request.debugConfigs.validIntfAddrVal;
-  memcpy(legacy_request->intf_addr_val, hidl_request.debugConfigs.intfAddrVal.data(), 6);
-  legacy_request->config_oui = hidl_request.debugConfigs.validOuiVal;
-  legacy_request->oui_val = hidl_request.debugConfigs.ouiVal;
-  legacy_request->config_random_factor_force = hidl_request.debugConfigs.validRandomFactorForceVal;
-  legacy_request->random_factor_force_val = hidl_request.debugConfigs.randomFactorForceVal;
-  legacy_request->config_hop_count_force = hidl_request.debugConfigs.validHopCountForceVal;
-  legacy_request->hop_count_force_val = hidl_request.debugConfigs.hopCountForceVal;
-  legacy_request->config_24g_channel = hidl_request.debugConfigs.validDiscoveryChannelVal;
-  legacy_request->channel_24g_val =
-        hidl_request.debugConfigs.discoveryChannelMhzVal[(size_t) NanBandIndex::NAN_BAND_24GHZ];
-  legacy_request->config_5g_channel = hidl_request.debugConfigs.validDiscoveryChannelVal;
-  legacy_request->channel_5g_val = hidl_request.debugConfigs
-        .discoveryChannelMhzVal[(size_t) NanBandIndex::NAN_BAND_5GHZ];
-  legacy_request->config_2dot4g_beacons = hidl_request.debugConfigs.validUseBeaconsInBandVal;
-  legacy_request->beacon_2dot4g_val = hidl_request.debugConfigs
-        .useBeaconsInBandVal[(size_t) NanBandIndex::NAN_BAND_24GHZ];
-  legacy_request->config_5g_beacons = hidl_request.debugConfigs.validUseBeaconsInBandVal;
-  legacy_request->beacon_5g_val = hidl_request.debugConfigs
-        .useBeaconsInBandVal[(size_t) NanBandIndex::NAN_BAND_5GHZ];
-  legacy_request->config_2dot4g_sdf = hidl_request.debugConfigs.validUseSdfInBandVal;
-  legacy_request->sdf_2dot4g_val = hidl_request.debugConfigs
-        .useSdfInBandVal[(size_t) NanBandIndex::NAN_BAND_24GHZ];
-  legacy_request->config_5g_sdf = hidl_request.debugConfigs.validUseSdfInBandVal;
-  legacy_request->sdf_5g_val = hidl_request.debugConfigs
-        .useSdfInBandVal[(size_t) NanBandIndex::NAN_BAND_5GHZ];
-
-  return true;
-}
-
-bool convertHidlNanPublishRequestToLegacy(
-    const NanPublishRequest& hidl_request,
-    legacy_hal::NanPublishRequest* legacy_request) {
-  if (!legacy_request) {
-    LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: null legacy_request";
-    return false;
-  }
-  *legacy_request = {};
-
-  legacy_request->publish_id = hidl_request.baseConfigs.sessionId;
-  legacy_request->ttl = hidl_request.baseConfigs.ttlSec;
-  legacy_request->period = hidl_request.baseConfigs.discoveryWindowPeriod;
-  legacy_request->publish_count = hidl_request.baseConfigs.discoveryCount;
-  legacy_request->service_name_len = hidl_request.baseConfigs.serviceName.size();
-  if (legacy_request->service_name_len > NAN_MAX_SERVICE_NAME_LEN) {
-    LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: service_name_len too large";
-    return false;
-  }
-  memcpy(legacy_request->service_name, hidl_request.baseConfigs.serviceName.data(),
-        legacy_request->service_name_len);
-  legacy_request->publish_match_indicator =
-        convertHidlNanMatchAlgToLegacy(hidl_request.baseConfigs.discoveryMatchIndicator);
-  legacy_request->service_specific_info_len = hidl_request.baseConfigs.serviceSpecificInfo.size();
-  if (legacy_request->service_specific_info_len > NAN_MAX_SERVICE_SPECIFIC_INFO_LEN) {
-    LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: service_specific_info_len too large";
-    return false;
-  }
-  memcpy(legacy_request->service_specific_info,
-        hidl_request.baseConfigs.serviceSpecificInfo.data(),
-        legacy_request->service_specific_info_len);
-  legacy_request->sdea_service_specific_info_len =
-        hidl_request.baseConfigs.extendedServiceSpecificInfo.size();
-  if (legacy_request->sdea_service_specific_info_len > NAN_MAX_SDEA_SERVICE_SPECIFIC_INFO_LEN) {
-    LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: sdea_service_specific_info_len too large";
-    return false;
-  }
-  memcpy(legacy_request->sdea_service_specific_info,
-        hidl_request.baseConfigs.extendedServiceSpecificInfo.data(),
-        legacy_request->sdea_service_specific_info_len);
-  legacy_request->rx_match_filter_len = hidl_request.baseConfigs.rxMatchFilter.size();
-  if (legacy_request->rx_match_filter_len > NAN_MAX_MATCH_FILTER_LEN) {
-    LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: rx_match_filter_len too large";
-    return false;
-  }
-  memcpy(legacy_request->rx_match_filter,
-        hidl_request.baseConfigs.rxMatchFilter.data(),
-        legacy_request->rx_match_filter_len);
-  legacy_request->tx_match_filter_len = hidl_request.baseConfigs.txMatchFilter.size();
-  if (legacy_request->tx_match_filter_len > NAN_MAX_MATCH_FILTER_LEN) {
-    LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: tx_match_filter_len too large";
-    return false;
-  }
-  memcpy(legacy_request->tx_match_filter,
-        hidl_request.baseConfigs.txMatchFilter.data(),
-        legacy_request->tx_match_filter_len);
-  legacy_request->rssi_threshold_flag = hidl_request.baseConfigs.useRssiThreshold;
-  legacy_request->recv_indication_cfg = 0;
-  legacy_request->recv_indication_cfg |=
-        hidl_request.baseConfigs.disableDiscoveryTerminationIndication ? 0x1 : 0x0;
-  legacy_request->recv_indication_cfg |=
-        hidl_request.baseConfigs.disableMatchExpirationIndication ? 0x2 : 0x0;
-  legacy_request->recv_indication_cfg |=
-        hidl_request.baseConfigs.disableFollowupReceivedIndication ? 0x4 : 0x0;
-  legacy_request->recv_indication_cfg |= 0x8;
-  legacy_request->cipher_type = (unsigned int) hidl_request.baseConfigs.securityConfig.cipherType;
-  if (hidl_request.baseConfigs.securityConfig.securityType == NanDataPathSecurityType::PMK) {
-    legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PMK;
-    legacy_request->key_info.body.pmk_info.pmk_len =
-        hidl_request.baseConfigs.securityConfig.pmk.size();
-    if (legacy_request->key_info.body.pmk_info.pmk_len != NAN_PMK_INFO_LEN) {
-      LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: invalid pmk_len";
-      return false;
-    }
-    memcpy(legacy_request->key_info.body.pmk_info.pmk,
-          hidl_request.baseConfigs.securityConfig.pmk.data(),
-          legacy_request->key_info.body.pmk_info.pmk_len);
-  }
-  if (hidl_request.baseConfigs.securityConfig.securityType
-        == NanDataPathSecurityType::PASSPHRASE) {
-    legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PASSPHRASE;
-    legacy_request->key_info.body.passphrase_info.passphrase_len =
-        hidl_request.baseConfigs.securityConfig.passphrase.size();
-    if (legacy_request->key_info.body.passphrase_info.passphrase_len
-            < NAN_SECURITY_MIN_PASSPHRASE_LEN) {
-      LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: passphrase_len too small";
-      return false;
-    }
-    if (legacy_request->key_info.body.passphrase_info.passphrase_len
-            > NAN_SECURITY_MAX_PASSPHRASE_LEN) {
-      LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: passphrase_len too large";
-      return false;
-    }
-    memcpy(legacy_request->key_info.body.passphrase_info.passphrase,
-          hidl_request.baseConfigs.securityConfig.passphrase.data(),
-          legacy_request->key_info.body.passphrase_info.passphrase_len);
-  }
-  legacy_request->sdea_params.security_cfg = (hidl_request.baseConfigs.securityConfig.securityType
-        != NanDataPathSecurityType::OPEN) ? legacy_hal::NAN_DP_CONFIG_SECURITY
-            : legacy_hal::NAN_DP_CONFIG_NO_SECURITY;
-  legacy_request->sdea_params.ranging_state = hidl_request.baseConfigs.rangingRequired ?
-        legacy_hal::NAN_RANGING_ENABLE : legacy_hal::NAN_RANGING_DISABLE;
-  legacy_request->ranging_cfg.ranging_interval_msec = hidl_request.baseConfigs.rangingIntervalMsec;
-  legacy_request->ranging_cfg.config_ranging_indications =
-        hidl_request.baseConfigs.configRangingIndications;
-  legacy_request->ranging_cfg.distance_ingress_cm = hidl_request.baseConfigs.distanceIngressCm;
-  legacy_request->ranging_cfg.distance_egress_cm = hidl_request.baseConfigs.distanceEgressCm;
-  legacy_request->ranging_auto_response = hidl_request.baseConfigs.rangingRequired ?
-        legacy_hal::NAN_RANGING_AUTO_RESPONSE_ENABLE : legacy_hal::NAN_RANGING_AUTO_RESPONSE_DISABLE;
-  legacy_request->sdea_params.range_report = legacy_hal::NAN_DISABLE_RANGE_REPORT;
-  legacy_request->publish_type = convertHidlNanPublishTypeToLegacy(hidl_request.publishType);
-  legacy_request->tx_type = convertHidlNanTxTypeToLegacy(hidl_request.txType);
-  legacy_request->service_responder_policy = hidl_request.autoAcceptDataPathRequests ?
-        legacy_hal::NAN_SERVICE_ACCEPT_POLICY_ALL : legacy_hal::NAN_SERVICE_ACCEPT_POLICY_NONE;
-
-  return true;
-}
-
-bool convertHidlNanSubscribeRequestToLegacy(
-    const NanSubscribeRequest& hidl_request,
-    legacy_hal::NanSubscribeRequest* legacy_request) {
-  if (!legacy_request) {
-    LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: legacy_request is null";
-    return false;
-  }
-  *legacy_request = {};
-
-  legacy_request->subscribe_id = hidl_request.baseConfigs.sessionId;
-  legacy_request->ttl = hidl_request.baseConfigs.ttlSec;
-  legacy_request->period = hidl_request.baseConfigs.discoveryWindowPeriod;
-  legacy_request->subscribe_count = hidl_request.baseConfigs.discoveryCount;
-  legacy_request->service_name_len = hidl_request.baseConfigs.serviceName.size();
-  if (legacy_request->service_name_len > NAN_MAX_SERVICE_NAME_LEN) {
-    LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: service_name_len too large";
-    return false;
-  }
-  memcpy(legacy_request->service_name, hidl_request.baseConfigs.serviceName.data(),
-        legacy_request->service_name_len);
-  legacy_request->subscribe_match_indicator =
-        convertHidlNanMatchAlgToLegacy(hidl_request.baseConfigs.discoveryMatchIndicator);
-  legacy_request->service_specific_info_len = hidl_request.baseConfigs.serviceSpecificInfo.size();
-  if (legacy_request->service_specific_info_len > NAN_MAX_SERVICE_SPECIFIC_INFO_LEN) {
-    LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: service_specific_info_len too large";
-    return false;
-  }
-  memcpy(legacy_request->service_specific_info,
-        hidl_request.baseConfigs.serviceSpecificInfo.data(),
-        legacy_request->service_specific_info_len);
-  legacy_request->sdea_service_specific_info_len =
-        hidl_request.baseConfigs.extendedServiceSpecificInfo.size();
-  if (legacy_request->sdea_service_specific_info_len > NAN_MAX_SDEA_SERVICE_SPECIFIC_INFO_LEN) {
-    LOG(ERROR) <<
-        "convertHidlNanSubscribeRequestToLegacy: sdea_service_specific_info_len too large";
-    return false;
-  }
-  memcpy(legacy_request->sdea_service_specific_info,
-        hidl_request.baseConfigs.extendedServiceSpecificInfo.data(),
-        legacy_request->sdea_service_specific_info_len);
-  legacy_request->rx_match_filter_len = hidl_request.baseConfigs.rxMatchFilter.size();
-  if (legacy_request->rx_match_filter_len > NAN_MAX_MATCH_FILTER_LEN) {
-    LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: rx_match_filter_len too large";
-    return false;
-  }
-  memcpy(legacy_request->rx_match_filter,
-        hidl_request.baseConfigs.rxMatchFilter.data(),
-        legacy_request->rx_match_filter_len);
-  legacy_request->tx_match_filter_len = hidl_request.baseConfigs.txMatchFilter.size();
-  if (legacy_request->tx_match_filter_len > NAN_MAX_MATCH_FILTER_LEN) {
-    LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: tx_match_filter_len too large";
-    return false;
-  }
-  memcpy(legacy_request->tx_match_filter,
-        hidl_request.baseConfigs.txMatchFilter.data(),
-        legacy_request->tx_match_filter_len);
-  legacy_request->rssi_threshold_flag = hidl_request.baseConfigs.useRssiThreshold;
-  legacy_request->recv_indication_cfg = 0;
-  legacy_request->recv_indication_cfg |=
-        hidl_request.baseConfigs.disableDiscoveryTerminationIndication ? 0x1 : 0x0;
-  legacy_request->recv_indication_cfg |=
-        hidl_request.baseConfigs.disableMatchExpirationIndication ? 0x2 : 0x0;
-  legacy_request->recv_indication_cfg |=
-        hidl_request.baseConfigs.disableFollowupReceivedIndication ? 0x4 : 0x0;
-  legacy_request->cipher_type = (unsigned int) hidl_request.baseConfigs.securityConfig.cipherType;
-  if (hidl_request.baseConfigs.securityConfig.securityType == NanDataPathSecurityType::PMK) {
-    legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PMK;
-    legacy_request->key_info.body.pmk_info.pmk_len =
-        hidl_request.baseConfigs.securityConfig.pmk.size();
-    if (legacy_request->key_info.body.pmk_info.pmk_len != NAN_PMK_INFO_LEN) {
-      LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: invalid pmk_len";
-      return false;
-    }
-    memcpy(legacy_request->key_info.body.pmk_info.pmk,
-          hidl_request.baseConfigs.securityConfig.pmk.data(),
-          legacy_request->key_info.body.pmk_info.pmk_len);
-  }
-  if (hidl_request.baseConfigs.securityConfig.securityType == NanDataPathSecurityType::PASSPHRASE) {
-    legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PASSPHRASE;
-    legacy_request->key_info.body.passphrase_info.passphrase_len =
-        hidl_request.baseConfigs.securityConfig.passphrase.size();
-    if (legacy_request->key_info.body.passphrase_info.passphrase_len
-            < NAN_SECURITY_MIN_PASSPHRASE_LEN) {
-      LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: passphrase_len too small";
-      return false;
-    }
-    if (legacy_request->key_info.body.passphrase_info.passphrase_len
-            > NAN_SECURITY_MAX_PASSPHRASE_LEN) {
-      LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: passphrase_len too large";
-      return false;
-    }
-    memcpy(legacy_request->key_info.body.passphrase_info.passphrase,
-          hidl_request.baseConfigs.securityConfig.passphrase.data(),
-          legacy_request->key_info.body.passphrase_info.passphrase_len);
-  }
-  legacy_request->sdea_params.security_cfg = (hidl_request.baseConfigs.securityConfig.securityType
-          != NanDataPathSecurityType::OPEN) ? legacy_hal::NAN_DP_CONFIG_SECURITY
-              : legacy_hal::NAN_DP_CONFIG_NO_SECURITY;
-  legacy_request->sdea_params.ranging_state = hidl_request.baseConfigs.rangingRequired ?
-        legacy_hal::NAN_RANGING_ENABLE : legacy_hal::NAN_RANGING_DISABLE;
-  legacy_request->ranging_cfg.ranging_interval_msec = hidl_request.baseConfigs.rangingIntervalMsec;
-  legacy_request->ranging_cfg.config_ranging_indications =
-        hidl_request.baseConfigs.configRangingIndications;
-  legacy_request->ranging_cfg.distance_ingress_cm = hidl_request.baseConfigs.distanceIngressCm;
-  legacy_request->ranging_cfg.distance_egress_cm = hidl_request.baseConfigs.distanceEgressCm;
-  legacy_request->ranging_auto_response = hidl_request.baseConfigs.rangingRequired ?
-        legacy_hal::NAN_RANGING_AUTO_RESPONSE_ENABLE : legacy_hal::NAN_RANGING_AUTO_RESPONSE_DISABLE;
-  legacy_request->sdea_params.range_report = legacy_hal::NAN_DISABLE_RANGE_REPORT;
-  legacy_request->subscribe_type = convertHidlNanSubscribeTypeToLegacy(hidl_request.subscribeType);
-  legacy_request->serviceResponseFilter = convertHidlNanSrfTypeToLegacy(hidl_request.srfType);
-  legacy_request->serviceResponseInclude = hidl_request.srfRespondIfInAddressSet ?
-        legacy_hal::NAN_SRF_INCLUDE_RESPOND : legacy_hal::NAN_SRF_INCLUDE_DO_NOT_RESPOND;
-  legacy_request->useServiceResponseFilter = hidl_request.shouldUseSrf ?
-        legacy_hal::NAN_USE_SRF : legacy_hal::NAN_DO_NOT_USE_SRF;
-  legacy_request->ssiRequiredForMatchIndication = hidl_request.isSsiRequiredForMatch ?
-        legacy_hal::NAN_SSI_REQUIRED_IN_MATCH_IND : legacy_hal::NAN_SSI_NOT_REQUIRED_IN_MATCH_IND;
-  legacy_request->num_intf_addr_present = hidl_request.intfAddr.size();
-  if (legacy_request->num_intf_addr_present > NAN_MAX_SUBSCRIBE_MAX_ADDRESS) {
-    LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: num_intf_addr_present - too many";
-    return false;
-  }
-  for (int i = 0; i < legacy_request->num_intf_addr_present; i++) {
-    memcpy(legacy_request->intf_addr[i], hidl_request.intfAddr[i].data(), 6);
-  }
-
-  return true;
-}
-
-bool convertHidlNanTransmitFollowupRequestToLegacy(
-    const NanTransmitFollowupRequest& hidl_request,
-    legacy_hal::NanTransmitFollowupRequest* legacy_request) {
-  if (!legacy_request) {
-    LOG(ERROR) << "convertHidlNanTransmitFollowupRequestToLegacy: legacy_request is null";
-    return false;
-  }
-  *legacy_request = {};
-
-  legacy_request->publish_subscribe_id = hidl_request.discoverySessionId;
-  legacy_request->requestor_instance_id = hidl_request.peerId;
-  memcpy(legacy_request->addr, hidl_request.addr.data(), 6);
-  legacy_request->priority = hidl_request.isHighPriority ?
-        legacy_hal::NAN_TX_PRIORITY_HIGH : legacy_hal::NAN_TX_PRIORITY_NORMAL;
-  legacy_request->dw_or_faw = hidl_request.shouldUseDiscoveryWindow ?
-        legacy_hal::NAN_TRANSMIT_IN_DW : legacy_hal::NAN_TRANSMIT_IN_FAW;
-  legacy_request->service_specific_info_len = hidl_request.serviceSpecificInfo.size();
-  if (legacy_request->service_specific_info_len > NAN_MAX_SERVICE_SPECIFIC_INFO_LEN) {
-    LOG(ERROR) <<
-        "convertHidlNanTransmitFollowupRequestToLegacy: service_specific_info_len too large";
-    return false;
-  }
-  memcpy(legacy_request->service_specific_info,
-        hidl_request.serviceSpecificInfo.data(),
-        legacy_request->service_specific_info_len);
-  legacy_request->sdea_service_specific_info_len = hidl_request.extendedServiceSpecificInfo.size();
-  if (legacy_request->sdea_service_specific_info_len > NAN_MAX_SDEA_SERVICE_SPECIFIC_INFO_LEN) {
-    LOG(ERROR) <<
-        "convertHidlNanTransmitFollowupRequestToLegacy: sdea_service_specific_info_len too large";
-    return false;
-  }
-  memcpy(legacy_request->sdea_service_specific_info,
-        hidl_request.extendedServiceSpecificInfo.data(),
-        legacy_request->sdea_service_specific_info_len);
-  legacy_request->recv_indication_cfg = hidl_request.disableFollowupResultIndication ? 0x1 : 0x0;
-
-  return true;
-}
-
-bool convertHidlNanConfigRequestToLegacy(
-    const NanConfigRequest& hidl_request,
-    legacy_hal::NanConfigRequest* legacy_request) {
-  if (!legacy_request) {
-    LOG(ERROR) << "convertHidlNanConfigRequestToLegacy: legacy_request is null";
-    return false;
-  }
-  *legacy_request = {};
-
-  // TODO: b/34059183 tracks missing configurations in legacy HAL or uknown defaults
-  legacy_request->master_pref = hidl_request.masterPref;
-  legacy_request->discovery_indication_cfg = 0;
-  legacy_request->discovery_indication_cfg |=
-        hidl_request.disableDiscoveryAddressChangeIndication ? 0x1 : 0x0;
-  legacy_request->discovery_indication_cfg |=
-        hidl_request.disableStartedClusterIndication ? 0x2 : 0x0;
-  legacy_request->discovery_indication_cfg |=
-        hidl_request.disableJoinedClusterIndication ? 0x4 : 0x0;
-  legacy_request->config_sid_beacon = 1;
-  if (hidl_request.numberOfPublishServiceIdsInBeacon > 127) {
-    LOG(ERROR) << "convertHidlNanConfigRequestToLegacy: numberOfPublishServiceIdsInBeacon > 127";
-    return false;
-  }
-  legacy_request->sid_beacon = (hidl_request.includePublishServiceIdsInBeacon ? 0x1 : 0x0)
-        | (hidl_request.numberOfPublishServiceIdsInBeacon << 1);
-  legacy_request->config_subscribe_sid_beacon = 1;
-  if (hidl_request.numberOfSubscribeServiceIdsInBeacon > 127) {
-    LOG(ERROR) << "convertHidlNanConfigRequestToLegacy: numberOfSubscribeServiceIdsInBeacon > 127";
-    return false;
-  }
-  legacy_request->subscribe_sid_beacon_val =
-        (hidl_request.includeSubscribeServiceIdsInBeacon ? 0x1 : 0x0)
-            | (hidl_request.numberOfSubscribeServiceIdsInBeacon << 1);
-  legacy_request->config_rssi_window_size = 1;
-  legacy_request->rssi_window_size_val = hidl_request.rssiWindowSize;
-  legacy_request->config_disc_mac_addr_randomization = 1;
-  legacy_request->disc_mac_addr_rand_interval_sec =
-        hidl_request.macAddressRandomizationIntervalSec;
-  /* TODO : missing
-  legacy_request->config_2dot4g_rssi_close = 1;
-  legacy_request->rssi_close_2dot4g_val =
-        hidl_request.bandSpecificConfig[
-            (size_t) NanBandIndex::NAN_BAND_24GHZ].rssiClose;
-  legacy_request->config_2dot4g_rssi_middle = 1;
-  legacy_request->rssi_middle_2dot4g_val =
-        hidl_request.bandSpecificConfig[
-            (size_t) NanBandIndex::NAN_BAND_24GHZ].rssiMiddle;
-  legacy_request->config_2dot4g_rssi_proximity = 1;
-  legacy_request->rssi_proximity_2dot4g_val =
-        hidl_request.bandSpecificConfig[
-            (size_t) NanBandIndex::NAN_BAND_24GHZ].rssiCloseProximity;
-  */
-  legacy_request->config_scan_params = 1;
-  legacy_request->scan_params_val.dwell_time[legacy_hal::NAN_CHANNEL_24G_BAND] =
-        hidl_request.bandSpecificConfig[
-            (size_t) NanBandIndex::NAN_BAND_24GHZ].dwellTimeMs;
-  legacy_request->scan_params_val.scan_period[legacy_hal::NAN_CHANNEL_24G_BAND] =
-        hidl_request.bandSpecificConfig[
-            (size_t) NanBandIndex::NAN_BAND_24GHZ].scanPeriodSec;
-  legacy_request->config_dw.config_2dot4g_dw_band = hidl_request
-        .bandSpecificConfig[(size_t) NanBandIndex::NAN_BAND_24GHZ].validDiscoveryWindowIntervalVal;
-  legacy_request->config_dw.dw_2dot4g_interval_val = hidl_request
-        .bandSpecificConfig[(size_t) NanBandIndex::NAN_BAND_24GHZ].discoveryWindowIntervalVal;
-  /* TODO: missing
-  legacy_request->config_5g_rssi_close = 1;
-  legacy_request->rssi_close_5g_val =
-        hidl_request.bandSpecificConfig[
-            (size_t) NanBandIndex::NAN_BAND_5GHZ].rssiClose;
-  legacy_request->config_5g_rssi_middle = 1;
-  legacy_request->rssi_middle_5g_val =
-        hidl_request.bandSpecificConfig[
-            (size_t) NanBandIndex::NAN_BAND_5GHZ].rssiMiddle;
-  */
-  legacy_request->config_5g_rssi_close_proximity = 1;
-  legacy_request->rssi_close_proximity_5g_val =
-        hidl_request.bandSpecificConfig[
-            (size_t) NanBandIndex::NAN_BAND_5GHZ].rssiCloseProximity;
-  legacy_request->scan_params_val.dwell_time[legacy_hal::NAN_CHANNEL_5G_BAND_LOW] =
-        hidl_request.bandSpecificConfig[
-            (size_t) NanBandIndex::NAN_BAND_5GHZ].dwellTimeMs;
-  legacy_request->scan_params_val.scan_period[legacy_hal::NAN_CHANNEL_5G_BAND_LOW] =
-        hidl_request.bandSpecificConfig[
-            (size_t) NanBandIndex::NAN_BAND_5GHZ].scanPeriodSec;
-  legacy_request->scan_params_val.dwell_time[legacy_hal::NAN_CHANNEL_5G_BAND_HIGH] =
-        hidl_request.bandSpecificConfig[
-            (size_t) NanBandIndex::NAN_BAND_5GHZ].dwellTimeMs;
-  legacy_request->scan_params_val.scan_period[legacy_hal::NAN_CHANNEL_5G_BAND_HIGH] =
-        hidl_request.bandSpecificConfig[
-            (size_t) NanBandIndex::NAN_BAND_5GHZ].scanPeriodSec;
-  legacy_request->config_dw.config_5g_dw_band = hidl_request
-        .bandSpecificConfig[(size_t) NanBandIndex::NAN_BAND_5GHZ].validDiscoveryWindowIntervalVal;
-  legacy_request->config_dw.dw_5g_interval_val = hidl_request
-        .bandSpecificConfig[(size_t) NanBandIndex::NAN_BAND_5GHZ].discoveryWindowIntervalVal;
-
-  return true;
-}
-
-bool convertHidlNanDataPathInitiatorRequestToLegacy(
-    const NanInitiateDataPathRequest& hidl_request,
-    legacy_hal::NanDataPathInitiatorRequest* legacy_request) {
-  if (!legacy_request) {
-    LOG(ERROR) << "convertHidlNanDataPathInitiatorRequestToLegacy: legacy_request is null";
-    return false;
-  }
-  *legacy_request = {};
-
-  legacy_request->requestor_instance_id = hidl_request.peerId;
-  memcpy(legacy_request->peer_disc_mac_addr, hidl_request.peerDiscMacAddr.data(), 6);
-  legacy_request->channel_request_type =
-        convertHidlNanDataPathChannelCfgToLegacy(hidl_request.channelRequestType);
-  legacy_request->channel = hidl_request.channel;
-  strcpy(legacy_request->ndp_iface, hidl_request.ifaceName.c_str());
-  legacy_request->ndp_cfg.security_cfg = (hidl_request.securityConfig.securityType
-        != NanDataPathSecurityType::OPEN) ? legacy_hal::NAN_DP_CONFIG_SECURITY
-            : legacy_hal::NAN_DP_CONFIG_NO_SECURITY;
-  legacy_request->app_info.ndp_app_info_len = hidl_request.appInfo.size();
-  if (legacy_request->app_info.ndp_app_info_len > NAN_DP_MAX_APP_INFO_LEN) {
-    LOG(ERROR) << "convertHidlNanDataPathInitiatorRequestToLegacy: ndp_app_info_len too large";
-    return false;
-  }
-  memcpy(legacy_request->app_info.ndp_app_info, hidl_request.appInfo.data(),
-        legacy_request->app_info.ndp_app_info_len);
-  legacy_request->cipher_type = (unsigned int) hidl_request.securityConfig.cipherType;
-  if (hidl_request.securityConfig.securityType == NanDataPathSecurityType::PMK) {
-    legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PMK;
-    legacy_request->key_info.body.pmk_info.pmk_len = hidl_request.securityConfig.pmk.size();
-    if (legacy_request->key_info.body.pmk_info.pmk_len != NAN_PMK_INFO_LEN) {
-      LOG(ERROR) << "convertHidlNanDataPathInitiatorRequestToLegacy: invalid pmk_len";
-      return false;
-    }
-    memcpy(legacy_request->key_info.body.pmk_info.pmk,
-          hidl_request.securityConfig.pmk.data(),
-          legacy_request->key_info.body.pmk_info.pmk_len);
-  }
-  if (hidl_request.securityConfig.securityType == NanDataPathSecurityType::PASSPHRASE) {
-    legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PASSPHRASE;
-    legacy_request->key_info.body.passphrase_info.passphrase_len =
-        hidl_request.securityConfig.passphrase.size();
-    if (legacy_request->key_info.body.passphrase_info.passphrase_len
-            < NAN_SECURITY_MIN_PASSPHRASE_LEN) {
-      LOG(ERROR) << "convertHidlNanDataPathInitiatorRequestToLegacy: passphrase_len too small";
-      return false;
-    }
-    if (legacy_request->key_info.body.passphrase_info.passphrase_len
-            > NAN_SECURITY_MAX_PASSPHRASE_LEN) {
-      LOG(ERROR) << "convertHidlNanDataPathInitiatorRequestToLegacy: passphrase_len too large";
-      return false;
-    }
-    memcpy(legacy_request->key_info.body.passphrase_info.passphrase,
-          hidl_request.securityConfig.passphrase.data(),
-          legacy_request->key_info.body.passphrase_info.passphrase_len);
-  }
-  legacy_request->service_name_len = hidl_request.serviceNameOutOfBand.size();
-  if (legacy_request->service_name_len > NAN_MAX_SERVICE_NAME_LEN) {
-    LOG(ERROR) << "convertHidlNanDataPathInitiatorRequestToLegacy: service_name_len too large";
-    return false;
-  }
-  memcpy(legacy_request->service_name, hidl_request.serviceNameOutOfBand.data(),
-        legacy_request->service_name_len);
-
-  return true;
-}
-
-bool convertHidlNanDataPathIndicationResponseToLegacy(
-    const NanRespondToDataPathIndicationRequest& hidl_request,
-    legacy_hal::NanDataPathIndicationResponse* legacy_request) {
-  if (!legacy_request) {
-    LOG(ERROR) << "convertHidlNanDataPathIndicationResponseToLegacy: legacy_request is null";
-    return false;
-  }
-  *legacy_request = {};
-
-  legacy_request->rsp_code = hidl_request.acceptRequest ?
-        legacy_hal::NAN_DP_REQUEST_ACCEPT : legacy_hal::NAN_DP_REQUEST_REJECT;
-  legacy_request->ndp_instance_id = hidl_request.ndpInstanceId;
-  strcpy(legacy_request->ndp_iface, hidl_request.ifaceName.c_str());
-  legacy_request->ndp_cfg.security_cfg = (hidl_request.securityConfig.securityType
-        != NanDataPathSecurityType::OPEN) ? legacy_hal::NAN_DP_CONFIG_SECURITY
-            : legacy_hal::NAN_DP_CONFIG_NO_SECURITY;
-  legacy_request->app_info.ndp_app_info_len = hidl_request.appInfo.size();
-  if (legacy_request->app_info.ndp_app_info_len > NAN_DP_MAX_APP_INFO_LEN) {
-    LOG(ERROR) << "convertHidlNanDataPathIndicationResponseToLegacy: ndp_app_info_len too large";
-    return false;
-  }
-  memcpy(legacy_request->app_info.ndp_app_info, hidl_request.appInfo.data(),
-        legacy_request->app_info.ndp_app_info_len);
-  legacy_request->cipher_type = (unsigned int) hidl_request.securityConfig.cipherType;
-  if (hidl_request.securityConfig.securityType == NanDataPathSecurityType::PMK) {
-    legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PMK;
-    legacy_request->key_info.body.pmk_info.pmk_len = hidl_request.securityConfig.pmk.size();
-    if (legacy_request->key_info.body.pmk_info.pmk_len != NAN_PMK_INFO_LEN) {
-      LOG(ERROR) << "convertHidlNanDataPathIndicationResponseToLegacy: invalid pmk_len";
-      return false;
-    }
-    memcpy(legacy_request->key_info.body.pmk_info.pmk,
-          hidl_request.securityConfig.pmk.data(),
-          legacy_request->key_info.body.pmk_info.pmk_len);
-  }
-  if (hidl_request.securityConfig.securityType == NanDataPathSecurityType::PASSPHRASE) {
-    legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PASSPHRASE;
-    legacy_request->key_info.body.passphrase_info.passphrase_len =
-        hidl_request.securityConfig.passphrase.size();
-    if (legacy_request->key_info.body.passphrase_info.passphrase_len
-            < NAN_SECURITY_MIN_PASSPHRASE_LEN) {
-      LOG(ERROR) << "convertHidlNanDataPathIndicationResponseToLegacy: passphrase_len too small";
-      return false;
-    }
-    if (legacy_request->key_info.body.passphrase_info.passphrase_len
-            > NAN_SECURITY_MAX_PASSPHRASE_LEN) {
-      LOG(ERROR) << "convertHidlNanDataPathIndicationResponseToLegacy: passphrase_len too large";
-      return false;
-    }
-    memcpy(legacy_request->key_info.body.passphrase_info.passphrase,
-          hidl_request.securityConfig.passphrase.data(),
-          legacy_request->key_info.body.passphrase_info.passphrase_len);
-  }
-  legacy_request->service_name_len = hidl_request.serviceNameOutOfBand.size();
-  if (legacy_request->service_name_len > NAN_MAX_SERVICE_NAME_LEN) {
-    LOG(ERROR) << "convertHidlNanDataPathIndicationResponseToLegacy: service_name_len too large";
-    return false;
-  }
-  memcpy(legacy_request->service_name, hidl_request.serviceNameOutOfBand.data(),
-        legacy_request->service_name_len);
-
-  return true;
-}
-
-bool convertLegacyNanResponseHeaderToHidl(
-    const legacy_hal::NanResponseMsg& legacy_response,
-    WifiNanStatus* wifiNanStatus) {
-  if (!wifiNanStatus) {
-    LOG(ERROR) << "convertLegacyNanResponseHeaderToHidl: wifiNanStatus is null";
-    return false;
-  }
-  *wifiNanStatus = {};
-
-  convertToWifiNanStatus(legacy_response.status, legacy_response.nan_error,
-        sizeof(legacy_response.nan_error), wifiNanStatus);
-  return true;
-}
-
-bool convertLegacyNanCapabilitiesResponseToHidl(
-    const legacy_hal::NanCapabilities& legacy_response,
-    NanCapabilities* hidl_response) {
-  if (!hidl_response) {
-    LOG(ERROR) << "convertLegacyNanCapabilitiesResponseToHidl: hidl_response is null";
-    return false;
-  }
-  *hidl_response = {};
-
-  hidl_response->maxConcurrentClusters = legacy_response.max_concurrent_nan_clusters;
-  hidl_response->maxPublishes = legacy_response.max_publishes;
-  hidl_response->maxSubscribes = legacy_response.max_subscribes;
-  hidl_response->maxServiceNameLen = legacy_response.max_service_name_len;
-  hidl_response->maxMatchFilterLen = legacy_response.max_match_filter_len;
-  hidl_response->maxTotalMatchFilterLen = legacy_response.max_total_match_filter_len;
-  hidl_response->maxServiceSpecificInfoLen = legacy_response.max_service_specific_info_len;
-  hidl_response->maxExtendedServiceSpecificInfoLen =
-    legacy_response.max_sdea_service_specific_info_len;
-  hidl_response->maxNdiInterfaces = legacy_response.max_ndi_interfaces;
-  hidl_response->maxNdpSessions = legacy_response.max_ndp_sessions;
-  hidl_response->maxAppInfoLen = legacy_response.max_app_info_len;
-  hidl_response->maxQueuedTransmitFollowupMsgs = legacy_response.max_queued_transmit_followup_msgs;
-  hidl_response->maxSubscribeInterfaceAddresses = legacy_response.max_subscribe_address;
-  hidl_response->supportedCipherSuites = legacy_response.cipher_suites_supported;
-
-  return true;
-}
-
-bool convertLegacyNanMatchIndToHidl(
-    const legacy_hal::NanMatchInd& legacy_ind,
-    NanMatchInd* hidl_ind) {
-  if (!hidl_ind) {
-    LOG(ERROR) << "convertLegacyNanMatchIndToHidl: hidl_ind is null";
-    return false;
-  }
-  *hidl_ind = {};
-
-  hidl_ind->discoverySessionId = legacy_ind.publish_subscribe_id;
-  hidl_ind->peerId = legacy_ind.requestor_instance_id;
-  hidl_ind->addr = hidl_array<uint8_t, 6>(legacy_ind.addr);
-  hidl_ind->serviceSpecificInfo = std::vector<uint8_t>(legacy_ind.service_specific_info,
-        legacy_ind.service_specific_info + legacy_ind.service_specific_info_len);
-  hidl_ind->extendedServiceSpecificInfo = std::vector<uint8_t>(
-        legacy_ind.sdea_service_specific_info,
-        legacy_ind.sdea_service_specific_info + legacy_ind.sdea_service_specific_info_len);
-  hidl_ind->matchFilter = std::vector<uint8_t>(legacy_ind.sdf_match_filter,
-        legacy_ind.sdf_match_filter + legacy_ind.sdf_match_filter_len);
-  hidl_ind->matchOccuredInBeaconFlag = legacy_ind.match_occured_flag == 1;
-  hidl_ind->outOfResourceFlag = legacy_ind.out_of_resource_flag == 1;
-  hidl_ind->rssiValue = legacy_ind.rssi_value;
-  hidl_ind->peerCipherType = (NanCipherSuiteType) legacy_ind.peer_cipher_type;
-  hidl_ind->peerRequiresSecurityEnabledInNdp =
-        legacy_ind.peer_sdea_params.security_cfg == legacy_hal::NAN_DP_CONFIG_SECURITY;
-  hidl_ind->peerRequiresRanging =
-        legacy_ind.peer_sdea_params.ranging_state == legacy_hal::NAN_RANGING_ENABLE;
-  hidl_ind->rangingMeasurementInCm = legacy_ind.range_info.range_measurement_cm;
-  hidl_ind->rangingIndicationType = legacy_ind.range_info.ranging_event_type;
-
-  return true;
-}
-
-bool convertLegacyNanFollowupIndToHidl(
-    const legacy_hal::NanFollowupInd& legacy_ind,
-    NanFollowupReceivedInd* hidl_ind) {
-  if (!hidl_ind) {
-    LOG(ERROR) << "convertLegacyNanFollowupIndToHidl: hidl_ind is null";
-    return false;
-  }
-  *hidl_ind = {};
-
-  hidl_ind->discoverySessionId = legacy_ind.publish_subscribe_id;
-  hidl_ind->peerId = legacy_ind.requestor_instance_id;
-  hidl_ind->addr = hidl_array<uint8_t, 6>(legacy_ind.addr);
-  hidl_ind->receivedInFaw = legacy_ind.dw_or_faw == 1;
-  hidl_ind->serviceSpecificInfo = std::vector<uint8_t>(legacy_ind.service_specific_info,
-        legacy_ind.service_specific_info + legacy_ind.service_specific_info_len);
-  hidl_ind->extendedServiceSpecificInfo = std::vector<uint8_t>(
-        legacy_ind.sdea_service_specific_info,
-        legacy_ind.sdea_service_specific_info + legacy_ind.sdea_service_specific_info_len);
-
-  return true;
-}
-
-bool convertLegacyNanDataPathRequestIndToHidl(
-    const legacy_hal::NanDataPathRequestInd& legacy_ind,
-    NanDataPathRequestInd* hidl_ind) {
-  if (!hidl_ind) {
-    LOG(ERROR) << "convertLegacyNanDataPathRequestIndToHidl: hidl_ind is null";
-    return false;
-  }
-  *hidl_ind = {};
-
-  hidl_ind->discoverySessionId = legacy_ind.service_instance_id;
-  hidl_ind->peerDiscMacAddr = hidl_array<uint8_t, 6>(legacy_ind.peer_disc_mac_addr);
-  hidl_ind->ndpInstanceId = legacy_ind.ndp_instance_id;
-  hidl_ind->securityRequired =
-        legacy_ind.ndp_cfg.security_cfg == legacy_hal::NAN_DP_CONFIG_SECURITY;
-  hidl_ind->appInfo = std::vector<uint8_t>(legacy_ind.app_info.ndp_app_info,
-        legacy_ind.app_info.ndp_app_info + legacy_ind.app_info.ndp_app_info_len);
-
-  return true;
-}
-
-bool convertLegacyNanDataPathConfirmIndToHidl(
-    const legacy_hal::NanDataPathConfirmInd& legacy_ind,
-    NanDataPathConfirmInd* hidl_ind) {
-  if (!hidl_ind) {
-    LOG(ERROR) << "convertLegacyNanDataPathConfirmIndToHidl: hidl_ind is null";
-    return false;
-  }
-  *hidl_ind = {};
-
-  hidl_ind->ndpInstanceId = legacy_ind.ndp_instance_id;
-  hidl_ind->dataPathSetupSuccess = legacy_ind.rsp_code == legacy_hal::NAN_DP_REQUEST_ACCEPT;
-  hidl_ind->peerNdiMacAddr = hidl_array<uint8_t, 6>(legacy_ind.peer_ndi_mac_addr);
-  hidl_ind->appInfo = std::vector<uint8_t>(legacy_ind.app_info.ndp_app_info,
-          legacy_ind.app_info.ndp_app_info + legacy_ind.app_info.ndp_app_info_len);
-  hidl_ind->status.status = convertLegacyNanStatusTypeToHidl(legacy_ind.reason_code);
-  hidl_ind->status.description = ""; // TODO: b/34059183
-
-  return true;
-}
-
-legacy_hal::wifi_rtt_type convertHidlRttTypeToLegacy(RttType type) {
-  switch (type) {
-    case RttType::ONE_SIDED:
-      return legacy_hal::RTT_TYPE_1_SIDED;
-    case RttType::TWO_SIDED:
-      return legacy_hal::RTT_TYPE_2_SIDED;
-  };
-  CHECK(false);
-}
-
-RttType convertLegacyRttTypeToHidl(legacy_hal::wifi_rtt_type type) {
-  switch (type) {
-    case legacy_hal::RTT_TYPE_1_SIDED:
-      return RttType::ONE_SIDED;
-    case legacy_hal::RTT_TYPE_2_SIDED:
-      return RttType::TWO_SIDED;
-  };
-  CHECK(false) << "Unknown legacy type: " << type;
-}
-
-legacy_hal::rtt_peer_type convertHidlRttPeerTypeToLegacy(RttPeerType type) {
-  switch (type) {
-    case RttPeerType::AP:
-      return legacy_hal::RTT_PEER_AP;
-    case RttPeerType::STA:
-      return legacy_hal::RTT_PEER_STA;
-    case RttPeerType::P2P_GO:
-      return legacy_hal::RTT_PEER_P2P_GO;
-    case RttPeerType::P2P_CLIENT:
-      return legacy_hal::RTT_PEER_P2P_CLIENT;
-    case RttPeerType::NAN:
-      return legacy_hal::RTT_PEER_NAN;
-  };
-  CHECK(false);
-}
-
-legacy_hal::wifi_channel_width convertHidlWifiChannelWidthToLegacy(
-    WifiChannelWidthInMhz type) {
-  switch (type) {
-    case WifiChannelWidthInMhz::WIDTH_20:
-      return legacy_hal::WIFI_CHAN_WIDTH_20;
-    case WifiChannelWidthInMhz::WIDTH_40:
-      return legacy_hal::WIFI_CHAN_WIDTH_40;
-    case WifiChannelWidthInMhz::WIDTH_80:
-      return legacy_hal::WIFI_CHAN_WIDTH_80;
-    case WifiChannelWidthInMhz::WIDTH_160:
-      return legacy_hal::WIFI_CHAN_WIDTH_160;
-    case WifiChannelWidthInMhz::WIDTH_80P80:
-      return legacy_hal::WIFI_CHAN_WIDTH_80P80;
-    case WifiChannelWidthInMhz::WIDTH_5:
-      return legacy_hal::WIFI_CHAN_WIDTH_5;
-    case WifiChannelWidthInMhz::WIDTH_10:
-      return legacy_hal::WIFI_CHAN_WIDTH_10;
-    case WifiChannelWidthInMhz::WIDTH_INVALID:
-      return legacy_hal::WIFI_CHAN_WIDTH_INVALID;
-  };
-  CHECK(false);
-}
-
-WifiChannelWidthInMhz convertLegacyWifiChannelWidthToHidl(
-    legacy_hal::wifi_channel_width type) {
-  switch (type) {
-    case legacy_hal::WIFI_CHAN_WIDTH_20:
-      return WifiChannelWidthInMhz::WIDTH_20;
-    case legacy_hal::WIFI_CHAN_WIDTH_40:
-      return WifiChannelWidthInMhz::WIDTH_40;
-    case legacy_hal::WIFI_CHAN_WIDTH_80:
-      return WifiChannelWidthInMhz::WIDTH_80;
-    case legacy_hal::WIFI_CHAN_WIDTH_160:
-      return WifiChannelWidthInMhz::WIDTH_160;
-    case legacy_hal::WIFI_CHAN_WIDTH_80P80:
-      return WifiChannelWidthInMhz::WIDTH_80P80;
-    case legacy_hal::WIFI_CHAN_WIDTH_5:
-      return WifiChannelWidthInMhz::WIDTH_5;
-    case legacy_hal::WIFI_CHAN_WIDTH_10:
-      return WifiChannelWidthInMhz::WIDTH_10;
-    case legacy_hal::WIFI_CHAN_WIDTH_INVALID:
-      return WifiChannelWidthInMhz::WIDTH_INVALID;
-  };
-  CHECK(false) << "Unknown legacy type: " << type;
-}
-
-legacy_hal::wifi_rtt_preamble convertHidlRttPreambleToLegacy(RttPreamble type) {
-  switch (type) {
-    case RttPreamble::LEGACY:
-      return legacy_hal::WIFI_RTT_PREAMBLE_LEGACY;
-    case RttPreamble::HT:
-      return legacy_hal::WIFI_RTT_PREAMBLE_HT;
-    case RttPreamble::VHT:
-      return legacy_hal::WIFI_RTT_PREAMBLE_VHT;
-  };
-  CHECK(false);
-}
-
-RttPreamble convertLegacyRttPreambleToHidl(legacy_hal::wifi_rtt_preamble type) {
-  switch (type) {
-    case legacy_hal::WIFI_RTT_PREAMBLE_LEGACY:
-      return RttPreamble::LEGACY;
-    case legacy_hal::WIFI_RTT_PREAMBLE_HT:
-      return RttPreamble::HT;
-    case legacy_hal::WIFI_RTT_PREAMBLE_VHT:
-      return RttPreamble::VHT;
-  };
-  CHECK(false) << "Unknown legacy type: " << type;
-}
-
-legacy_hal::wifi_rtt_bw convertHidlRttBwToLegacy(RttBw type) {
-  switch (type) {
-    case RttBw::BW_5MHZ:
-      return legacy_hal::WIFI_RTT_BW_5;
-    case RttBw::BW_10MHZ:
-      return legacy_hal::WIFI_RTT_BW_10;
-    case RttBw::BW_20MHZ:
-      return legacy_hal::WIFI_RTT_BW_20;
-    case RttBw::BW_40MHZ:
-      return legacy_hal::WIFI_RTT_BW_40;
-    case RttBw::BW_80MHZ:
-      return legacy_hal::WIFI_RTT_BW_80;
-    case RttBw::BW_160MHZ:
-      return legacy_hal::WIFI_RTT_BW_160;
-  };
-  CHECK(false);
-}
-
-RttBw convertLegacyRttBwToHidl(legacy_hal::wifi_rtt_bw type) {
-  switch (type) {
-    case legacy_hal::WIFI_RTT_BW_5:
-      return RttBw::BW_5MHZ;
-    case legacy_hal::WIFI_RTT_BW_10:
-      return RttBw::BW_10MHZ;
-    case legacy_hal::WIFI_RTT_BW_20:
-      return RttBw::BW_20MHZ;
-    case legacy_hal::WIFI_RTT_BW_40:
-      return RttBw::BW_40MHZ;
-    case legacy_hal::WIFI_RTT_BW_80:
-      return RttBw::BW_80MHZ;
-    case legacy_hal::WIFI_RTT_BW_160:
-      return RttBw::BW_160MHZ;
-  };
-  CHECK(false) << "Unknown legacy type: " << type;
-}
-
-legacy_hal::wifi_motion_pattern convertHidlRttMotionPatternToLegacy(
-    RttMotionPattern type) {
-  switch (type) {
-    case RttMotionPattern::NOT_EXPECTED:
-      return legacy_hal::WIFI_MOTION_NOT_EXPECTED;
-    case RttMotionPattern::EXPECTED:
-      return legacy_hal::WIFI_MOTION_EXPECTED;
-    case RttMotionPattern::UNKNOWN:
-      return legacy_hal::WIFI_MOTION_UNKNOWN;
-  };
-  CHECK(false);
-}
-
-WifiRatePreamble convertLegacyWifiRatePreambleToHidl(uint8_t preamble) {
-  switch (preamble) {
-    case 0:
-      return WifiRatePreamble::OFDM;
-    case 1:
-      return WifiRatePreamble::CCK;
-    case 2:
-      return WifiRatePreamble::HT;
-    case 3:
-      return WifiRatePreamble::VHT;
-    default:
-      return WifiRatePreamble::RESERVED;
-  };
-  CHECK(false) << "Unknown legacy preamble: " << preamble;
-}
-
-WifiRateNss convertLegacyWifiRateNssToHidl(uint8_t nss) {
-  switch (nss) {
-    case 0:
-      return WifiRateNss::NSS_1x1;
-    case 1:
-      return WifiRateNss::NSS_2x2;
-    case 2:
-      return WifiRateNss::NSS_3x3;
-    case 3:
-      return WifiRateNss::NSS_4x4;
-  };
-  CHECK(false) << "Unknown legacy nss: " << nss;
-  return {};
-}
-
-RttStatus convertLegacyRttStatusToHidl(legacy_hal::wifi_rtt_status status) {
-  switch (status) {
-    case legacy_hal::RTT_STATUS_SUCCESS:
-      return RttStatus::SUCCESS;
-    case legacy_hal::RTT_STATUS_FAILURE:
-      return RttStatus::FAILURE;
-    case legacy_hal::RTT_STATUS_FAIL_NO_RSP:
-      return RttStatus::FAIL_NO_RSP;
-    case legacy_hal::RTT_STATUS_FAIL_REJECTED:
-      return RttStatus::FAIL_REJECTED;
-    case legacy_hal::RTT_STATUS_FAIL_NOT_SCHEDULED_YET:
-      return RttStatus::FAIL_NOT_SCHEDULED_YET;
-    case legacy_hal::RTT_STATUS_FAIL_TM_TIMEOUT:
-      return RttStatus::FAIL_TM_TIMEOUT;
-    case legacy_hal::RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL:
-      return RttStatus::FAIL_AP_ON_DIFF_CHANNEL;
-    case legacy_hal::RTT_STATUS_FAIL_NO_CAPABILITY:
-      return RttStatus::FAIL_NO_CAPABILITY;
-    case legacy_hal::RTT_STATUS_ABORTED:
-      return RttStatus::ABORTED;
-    case legacy_hal::RTT_STATUS_FAIL_INVALID_TS:
-      return RttStatus::FAIL_INVALID_TS;
-    case legacy_hal::RTT_STATUS_FAIL_PROTOCOL:
-      return RttStatus::FAIL_PROTOCOL;
-    case legacy_hal::RTT_STATUS_FAIL_SCHEDULE:
-      return RttStatus::FAIL_SCHEDULE;
-    case legacy_hal::RTT_STATUS_FAIL_BUSY_TRY_LATER:
-      return RttStatus::FAIL_BUSY_TRY_LATER;
-    case legacy_hal::RTT_STATUS_INVALID_REQ:
-      return RttStatus::INVALID_REQ;
-    case legacy_hal::RTT_STATUS_NO_WIFI:
-      return RttStatus::NO_WIFI;
-    case legacy_hal::RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE:
-      return RttStatus::FAIL_FTM_PARAM_OVERRIDE;
-  };
-  CHECK(false) << "Unknown legacy status: " << status;
-}
-
-bool convertHidlWifiChannelInfoToLegacy(
-    const WifiChannelInfo& hidl_info,
-    legacy_hal::wifi_channel_info* legacy_info) {
-  if (!legacy_info) {
-    return false;
-  }
-  *legacy_info = {};
-  legacy_info->width = convertHidlWifiChannelWidthToLegacy(hidl_info.width);
-  legacy_info->center_freq = hidl_info.centerFreq;
-  legacy_info->center_freq0 = hidl_info.centerFreq0;
-  legacy_info->center_freq1 = hidl_info.centerFreq1;
-  return true;
-}
-
-bool convertLegacyWifiChannelInfoToHidl(
-    const legacy_hal::wifi_channel_info& legacy_info,
-    WifiChannelInfo* hidl_info) {
-  if (!hidl_info) {
-    return false;
-  }
-  *hidl_info = {};
-  hidl_info->width = convertLegacyWifiChannelWidthToHidl(legacy_info.width);
-  hidl_info->centerFreq = legacy_info.center_freq;
-  hidl_info->centerFreq0 = legacy_info.center_freq0;
-  hidl_info->centerFreq1 = legacy_info.center_freq1;
-  return true;
-}
-
-bool convertHidlRttConfigToLegacy(const RttConfig& hidl_config,
-                                  legacy_hal::wifi_rtt_config* legacy_config) {
-  if (!legacy_config) {
-    return false;
-  }
-  *legacy_config = {};
-  CHECK(hidl_config.addr.size() == sizeof(legacy_config->addr));
-  memcpy(legacy_config->addr, hidl_config.addr.data(), hidl_config.addr.size());
-  legacy_config->type = convertHidlRttTypeToLegacy(hidl_config.type);
-  legacy_config->peer = convertHidlRttPeerTypeToLegacy(hidl_config.peer);
-  if (!convertHidlWifiChannelInfoToLegacy(hidl_config.channel,
-                                          &legacy_config->channel)) {
-    return false;
-  }
-  legacy_config->burst_period = hidl_config.burstPeriod;
-  legacy_config->num_burst = hidl_config.numBurst;
-  legacy_config->num_frames_per_burst = hidl_config.numFramesPerBurst;
-  legacy_config->num_retries_per_rtt_frame = hidl_config.numRetriesPerRttFrame;
-  legacy_config->num_retries_per_ftmr = hidl_config.numRetriesPerFtmr;
-  legacy_config->LCI_request = hidl_config.mustRequestLci;
-  legacy_config->LCR_request = hidl_config.mustRequestLcr;
-  legacy_config->burst_duration = hidl_config.burstDuration;
-  legacy_config->preamble =
-      convertHidlRttPreambleToLegacy(hidl_config.preamble);
-  legacy_config->bw = convertHidlRttBwToLegacy(hidl_config.bw);
-  return true;
-}
-
-bool convertHidlVectorOfRttConfigToLegacy(
-    const std::vector<RttConfig>& hidl_configs,
-    std::vector<legacy_hal::wifi_rtt_config>* legacy_configs) {
-  if (!legacy_configs) {
-    return false;
-  }
-  *legacy_configs = {};
-  for (const auto& hidl_config : hidl_configs) {
-    legacy_hal::wifi_rtt_config legacy_config;
-    if (!convertHidlRttConfigToLegacy(hidl_config, &legacy_config)) {
-      return false;
-    }
-    legacy_configs->push_back(legacy_config);
-  }
-  return true;
-}
-
-bool convertHidlRttLciInformationToLegacy(
-    const RttLciInformation& hidl_info,
-    legacy_hal::wifi_lci_information* legacy_info) {
-  if (!legacy_info) {
-    return false;
-  }
-  *legacy_info = {};
-  legacy_info->latitude = hidl_info.latitude;
-  legacy_info->longitude = hidl_info.longitude;
-  legacy_info->altitude = hidl_info.altitude;
-  legacy_info->latitude_unc = hidl_info.latitudeUnc;
-  legacy_info->longitude_unc = hidl_info.longitudeUnc;
-  legacy_info->altitude_unc = hidl_info.altitudeUnc;
-  legacy_info->motion_pattern =
-      convertHidlRttMotionPatternToLegacy(hidl_info.motionPattern);
-  legacy_info->floor = hidl_info.floor;
-  legacy_info->height_above_floor = hidl_info.heightAboveFloor;
-  legacy_info->height_unc = hidl_info.heightUnc;
-  return true;
-}
-
-bool convertHidlRttLcrInformationToLegacy(
-    const RttLcrInformation& hidl_info,
-    legacy_hal::wifi_lcr_information* legacy_info) {
-  if (!legacy_info) {
-    return false;
-  }
-  *legacy_info = {};
-  CHECK(hidl_info.countryCode.size() == sizeof(legacy_info->country_code));
-  memcpy(legacy_info->country_code,
-         hidl_info.countryCode.data(),
-         hidl_info.countryCode.size());
-  if (hidl_info.civicInfo.size() > sizeof(legacy_info->civic_info)) {
-    return false;
-  }
-  legacy_info->length = hidl_info.civicInfo.size();
-  memcpy(legacy_info->civic_info,
-         hidl_info.civicInfo.c_str(),
-         hidl_info.civicInfo.size());
-  return true;
-}
-
-bool convertHidlRttResponderToLegacy(
-    const RttResponder& hidl_responder,
-    legacy_hal::wifi_rtt_responder* legacy_responder) {
-  if (!legacy_responder) {
-    return false;
-  }
-  *legacy_responder = {};
-  if (!convertHidlWifiChannelInfoToLegacy(hidl_responder.channel,
-                                          &legacy_responder->channel)) {
-    return false;
-  }
-  legacy_responder->preamble =
-      convertHidlRttPreambleToLegacy(hidl_responder.preamble);
-  return true;
-}
-
-bool convertLegacyRttResponderToHidl(
-    const legacy_hal::wifi_rtt_responder& legacy_responder,
-    RttResponder* hidl_responder) {
-  if (!hidl_responder) {
-    return false;
-  }
-  *hidl_responder = {};
-  if (!convertLegacyWifiChannelInfoToHidl(legacy_responder.channel,
-                                          &hidl_responder->channel)) {
-    return false;
-  }
-  hidl_responder->preamble =
-      convertLegacyRttPreambleToHidl(legacy_responder.preamble);
-  return true;
-}
-
-bool convertLegacyRttCapabilitiesToHidl(
-    const legacy_hal::wifi_rtt_capabilities& legacy_capabilities,
-    RttCapabilities* hidl_capabilities) {
-  if (!hidl_capabilities) {
-    return false;
-  }
-  *hidl_capabilities = {};
-  hidl_capabilities->rttOneSidedSupported =
-      legacy_capabilities.rtt_one_sided_supported;
-  hidl_capabilities->rttFtmSupported = legacy_capabilities.rtt_ftm_supported;
-  hidl_capabilities->lciSupported = legacy_capabilities.lci_support;
-  hidl_capabilities->lcrSupported = legacy_capabilities.lcr_support;
-  hidl_capabilities->responderSupported =
-      legacy_capabilities.responder_supported;
-  hidl_capabilities->preambleSupport = 0;
-  for (const auto flag : {legacy_hal::WIFI_RTT_PREAMBLE_LEGACY,
-                          legacy_hal::WIFI_RTT_PREAMBLE_HT,
-                          legacy_hal::WIFI_RTT_PREAMBLE_VHT}) {
-    if (legacy_capabilities.preamble_support & flag) {
-      hidl_capabilities->preambleSupport |=
-          static_cast<std::underlying_type<RttPreamble>::type>(
-              convertLegacyRttPreambleToHidl(flag));
-    }
-  }
-  hidl_capabilities->bwSupport = 0;
-  for (const auto flag : {legacy_hal::WIFI_RTT_BW_5,
-                          legacy_hal::WIFI_RTT_BW_10,
-                          legacy_hal::WIFI_RTT_BW_20,
-                          legacy_hal::WIFI_RTT_BW_40,
-                          legacy_hal::WIFI_RTT_BW_80,
-                          legacy_hal::WIFI_RTT_BW_160}) {
-    if (legacy_capabilities.bw_support & flag) {
-      hidl_capabilities->bwSupport |=
-          static_cast<std::underlying_type<RttBw>::type>(
-              convertLegacyRttBwToHidl(flag));
-    }
-  }
-  hidl_capabilities->mcVersion = legacy_capabilities.mc_version;
-  return true;
-}
-
-bool convertLegacyWifiRateInfoToHidl(const legacy_hal::wifi_rate& legacy_rate,
-                                     WifiRateInfo* hidl_rate) {
-  if (!hidl_rate) {
-    return false;
-  }
-  *hidl_rate = {};
-  hidl_rate->preamble =
-      convertLegacyWifiRatePreambleToHidl(legacy_rate.preamble);
-  hidl_rate->nss = convertLegacyWifiRateNssToHidl(legacy_rate.nss);
-  hidl_rate->bw = convertLegacyWifiChannelWidthToHidl(
-      static_cast<legacy_hal::wifi_channel_width>(legacy_rate.bw));
-  hidl_rate->rateMcsIdx = legacy_rate.rateMcsIdx;
-  hidl_rate->bitRateInKbps = legacy_rate.bitrate;
-  return true;
-}
-
-bool convertLegacyRttResultToHidl(
-    const legacy_hal::wifi_rtt_result& legacy_result, RttResult* hidl_result) {
-  if (!hidl_result) {
-    return false;
-  }
-  *hidl_result = {};
-  CHECK(sizeof(legacy_result.addr) == hidl_result->addr.size());
-  memcpy(
-      hidl_result->addr.data(), legacy_result.addr, sizeof(legacy_result.addr));
-  hidl_result->burstNum = legacy_result.burst_num;
-  hidl_result->measurementNumber = legacy_result.measurement_number;
-  hidl_result->successNumber = legacy_result.success_number;
-  hidl_result->numberPerBurstPeer = legacy_result.number_per_burst_peer;
-  hidl_result->status = convertLegacyRttStatusToHidl(legacy_result.status);
-  hidl_result->retryAfterDuration = legacy_result.retry_after_duration;
-  hidl_result->type = convertLegacyRttTypeToHidl(legacy_result.type);
-  hidl_result->rssi = legacy_result.rssi;
-  hidl_result->rssiSpread = legacy_result.rssi_spread;
-  if (!convertLegacyWifiRateInfoToHidl(legacy_result.tx_rate,
-                                       &hidl_result->txRate)) {
-    return false;
-  }
-  if (!convertLegacyWifiRateInfoToHidl(legacy_result.rx_rate,
-                                       &hidl_result->rxRate)) {
-    return false;
-  }
-  hidl_result->rtt = legacy_result.rtt;
-  hidl_result->rttSd = legacy_result.rtt_sd;
-  hidl_result->rttSpread = legacy_result.rtt_spread;
-  hidl_result->distanceInMm = legacy_result.distance_mm;
-  hidl_result->distanceSdInMm = legacy_result.distance_sd_mm;
-  hidl_result->distanceSpreadInMm = legacy_result.distance_spread_mm;
-  hidl_result->timeStampInUs = legacy_result.ts;
-  hidl_result->burstDurationInMs = legacy_result.burst_duration;
-  hidl_result->negotiatedBurstNum = legacy_result.negotiated_burst_num;
-  if (legacy_result.LCI && !convertLegacyIeToHidl(*legacy_result.LCI,
-                                                  &hidl_result->lci)) {
-    return false;
-  }
-  if (legacy_result.LCR && !convertLegacyIeToHidl(*legacy_result.LCR,
-                                                  &hidl_result->lcr)) {
-    return false;
-  }
-  return true;
-}
-
-bool convertLegacyVectorOfRttResultToHidl(
-    const std::vector<const legacy_hal::wifi_rtt_result*>& legacy_results,
-    std::vector<RttResult>* hidl_results) {
-  if (!hidl_results) {
-    return false;
-  }
-  *hidl_results = {};
-  for (const auto legacy_result : legacy_results) {
-    RttResult hidl_result;
-    if (!convertLegacyRttResultToHidl(*legacy_result, &hidl_result)) {
-      return false;
-    }
-    hidl_results->push_back(hidl_result);
-  }
-  return true;
-}
-}  // namespace hidl_struct_util
-}  // namespace implementation
-}  // namespace V1_1
-}  // namespace wifi
-}  // namespace hardware
-}  // namespace android
diff --git a/wifi/1.1/default/service.cpp b/wifi/1.1/default/service.cpp
deleted file mode 100644
index b4aed6c..0000000
--- a/wifi/1.1/default/service.cpp
+++ /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.
- */
-
-#include <android-base/logging.h>
-#include <hidl/HidlTransportSupport.h>
-#include <utils/Looper.h>
-#include <utils/StrongPointer.h>
-
-#include "wifi.h"
-
-using android::hardware::configureRpcThreadpool;
-using android::hardware::joinRpcThreadpool;
-
-int main(int /*argc*/, char** argv) {
-  android::base::InitLogging(argv,
-                             android::base::LogdLogger(android::base::SYSTEM));
-  LOG(INFO) << "Wifi Hal is booting up...";
-
-  configureRpcThreadpool(1, true /* callerWillJoin */);
-
-  // Setup hwbinder service
-  android::sp<android::hardware::wifi::V1_1::IWifi> service =
-      new android::hardware::wifi::V1_1::implementation::Wifi();
-  CHECK_EQ(service->registerAsService(), android::NO_ERROR)
-      << "Failed to register wifi HAL";
-
-  joinRpcThreadpool();
-
-  LOG(INFO) << "Wifi Hal is terminating...";
-  return 0;
-}
diff --git a/wifi/1.1/default/wifi.cpp b/wifi/1.1/default/wifi.cpp
deleted file mode 100644
index c46ef95..0000000
--- a/wifi/1.1/default/wifi.cpp
+++ /dev/null
@@ -1,205 +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.
- */
-
-#include <android-base/logging.h>
-
-#include "hidl_return_util.h"
-#include "wifi.h"
-#include "wifi_status_util.h"
-
-namespace {
-// Chip ID to use for the only supported chip.
-static constexpr android::hardware::wifi::V1_0::ChipId kChipId = 0;
-}  // namespace
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_1 {
-namespace implementation {
-using hidl_return_util::validateAndCall;
-using hidl_return_util::validateAndCallWithLock;
-
-Wifi::Wifi()
-    : legacy_hal_(new legacy_hal::WifiLegacyHal()),
-      mode_controller_(new mode_controller::WifiModeController()),
-      run_state_(RunState::STOPPED) {}
-
-bool Wifi::isValid() {
-  // This object is always valid.
-  return true;
-}
-
-Return<void> Wifi::registerEventCallback(
-    const sp<IWifiEventCallback>& event_callback,
-    registerEventCallback_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_UNKNOWN,
-                         &Wifi::registerEventCallbackInternal,
-                         hidl_status_cb,
-                         event_callback);
-}
-
-Return<bool> Wifi::isStarted() {
-  return run_state_ != RunState::STOPPED;
-}
-
-Return<void> Wifi::start(start_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_UNKNOWN,
-                         &Wifi::startInternal,
-                         hidl_status_cb);
-}
-
-Return<void> Wifi::stop(stop_cb hidl_status_cb) {
-  return validateAndCallWithLock(this, WifiStatusCode::ERROR_UNKNOWN,
-                                 &Wifi::stopInternal, hidl_status_cb);
-}
-
-Return<void> Wifi::getChipIds(getChipIds_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_UNKNOWN,
-                         &Wifi::getChipIdsInternal,
-                         hidl_status_cb);
-}
-
-Return<void> Wifi::getChip(ChipId chip_id, getChip_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_UNKNOWN,
-                         &Wifi::getChipInternal,
-                         hidl_status_cb,
-                         chip_id);
-}
-
-WifiStatus Wifi::registerEventCallbackInternal(
-    const sp<IWifiEventCallback>& event_callback) {
-  if (!event_cb_handler_.addCallback(event_callback)) {
-    return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
-  }
-  return createWifiStatus(WifiStatusCode::SUCCESS);
-}
-
-WifiStatus Wifi::startInternal() {
-  if (run_state_ == RunState::STARTED) {
-    return createWifiStatus(WifiStatusCode::SUCCESS);
-  } else if (run_state_ == RunState::STOPPING) {
-    return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE,
-                            "HAL is stopping");
-  }
-  WifiStatus wifi_status = initializeLegacyHal();
-  if (wifi_status.code == WifiStatusCode::SUCCESS) {
-    // Create the chip instance once the HAL is started.
-    chip_ = new WifiChip(kChipId, legacy_hal_, mode_controller_);
-    run_state_ = RunState::STARTED;
-    for (const auto& callback : event_cb_handler_.getCallbacks()) {
-      if (!callback->onStart().isOk()) {
-        LOG(ERROR) << "Failed to invoke onStart callback";
-      };
-    }
-    LOG(INFO) << "Wifi HAL started";
-  } else {
-    for (const auto& callback : event_cb_handler_.getCallbacks()) {
-      if (!callback->onFailure(wifi_status).isOk()) {
-        LOG(ERROR) << "Failed to invoke onFailure callback";
-      }
-    }
-    LOG(ERROR) << "Wifi HAL start failed";
-  }
-  return wifi_status;
-}
-
-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) {
-    return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE,
-                            "HAL is stopping");
-  }
-  // Clear the chip object and its child objects since the HAL is now
-  // stopped.
-  if (chip_.get()) {
-    chip_->invalidate();
-    chip_.clear();
-  }
-  WifiStatus wifi_status = stopLegacyHalAndDeinitializeModeController(lock);
-  if (wifi_status.code == WifiStatusCode::SUCCESS) {
-    for (const auto& callback : event_cb_handler_.getCallbacks()) {
-      if (!callback->onStop().isOk()) {
-        LOG(ERROR) << "Failed to invoke onStop callback";
-      };
-    }
-    LOG(INFO) << "Wifi HAL stopped";
-  } else {
-    for (const auto& callback : event_cb_handler_.getCallbacks()) {
-      if (!callback->onFailure(wifi_status).isOk()) {
-        LOG(ERROR) << "Failed to invoke onFailure callback";
-      }
-    }
-    LOG(ERROR) << "Wifi HAL stop failed";
-  }
-  return wifi_status;
-}
-
-std::pair<WifiStatus, std::vector<ChipId>> Wifi::getChipIdsInternal() {
-  std::vector<ChipId> chip_ids;
-  if (chip_.get()) {
-    chip_ids.emplace_back(kChipId);
-  }
-  return {createWifiStatus(WifiStatusCode::SUCCESS), std::move(chip_ids)};
-}
-
-std::pair<WifiStatus, sp<IWifiChip>> Wifi::getChipInternal(ChipId chip_id) {
-  if (!chip_.get()) {
-    return {createWifiStatus(WifiStatusCode::ERROR_NOT_STARTED), nullptr};
-  }
-  if (chip_id != kChipId) {
-    return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr};
-  }
-  return {createWifiStatus(WifiStatusCode::SUCCESS), chip_};
-}
-
-WifiStatus Wifi::initializeLegacyHal() {
-  legacy_hal::wifi_error legacy_status = legacy_hal_->initialize();
-  if (legacy_status != legacy_hal::WIFI_SUCCESS) {
-    LOG(ERROR) << "Failed to initialize legacy HAL: "
-               << legacyErrorToString(legacy_status);
-    return createWifiStatusFromLegacyError(legacy_status);
-  }
-  return createWifiStatus(WifiStatusCode::SUCCESS);
-}
-
-WifiStatus Wifi::stopLegacyHalAndDeinitializeModeController(
-    /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock) {
-  run_state_ = RunState::STOPPING;
-  legacy_hal::wifi_error legacy_status =
-      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);
-    return createWifiStatusFromLegacyError(legacy_status);
-  }
-  if (!mode_controller_->deinitialize()) {
-    LOG(ERROR) << "Failed to deinitialize firmware mode controller";
-    return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
-  }
-  return createWifiStatus(WifiStatusCode::SUCCESS);
-}
-}  // namespace implementation
-}  // namespace V1_1
-}  // namespace wifi
-}  // namespace hardware
-}  // namespace android
diff --git a/wifi/1.1/default/wifi.h b/wifi/1.1/default/wifi.h
deleted file mode 100644
index 3a64cbd..0000000
--- a/wifi/1.1/default/wifi.h
+++ /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.
- */
-
-#ifndef WIFI_H_
-#define WIFI_H_
-
-#include <functional>
-
-#include <android-base/macros.h>
-#include <android/hardware/wifi/1.1/IWifi.h>
-#include <utils/Looper.h>
-
-#include "hidl_callback_util.h"
-#include "wifi_chip.h"
-#include "wifi_legacy_hal.h"
-#include "wifi_mode_controller.h"
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_1 {
-namespace implementation {
-using namespace android::hardware::wifi::V1_0;
-
-/**
- * Root HIDL interface object used to control the Wifi HAL.
- */
-class Wifi : public V1_1::IWifi {
- public:
-  Wifi();
-
-  bool isValid();
-
-  // HIDL methods exposed.
-  Return<void> registerEventCallback(
-      const sp<IWifiEventCallback>& event_callback,
-      registerEventCallback_cb hidl_status_cb) override;
-  Return<bool> isStarted() override;
-  Return<void> start(start_cb hidl_status_cb) override;
-  Return<void> stop(stop_cb hidl_status_cb) override;
-  Return<void> getChipIds(getChipIds_cb hidl_status_cb) override;
-  Return<void> getChip(ChipId chip_id, getChip_cb hidl_status_cb) override;
-
- private:
-  enum class RunState { STOPPED, STARTED, STOPPING };
-
-  // Corresponding worker functions for the HIDL methods.
-  WifiStatus registerEventCallbackInternal(
-      const sp<IWifiEventCallback>& event_callback);
-  WifiStatus startInternal();
-  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(
-      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.
-  std::shared_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
-  std::shared_ptr<mode_controller::WifiModeController> mode_controller_;
-  RunState run_state_;
-  sp<WifiChip> chip_;
-  hidl_callback_util::HidlCallbackHandler<IWifiEventCallback> event_cb_handler_;
-
-  DISALLOW_COPY_AND_ASSIGN(Wifi);
-};
-
-}  // namespace implementation
-}  // namespace V1_1
-}  // namespace wifi
-}  // namespace hardware
-}  // namespace android
-
-#endif  // WIFI_H_
diff --git a/wifi/1.1/default/wifi_ap_iface.cpp b/wifi/1.1/default/wifi_ap_iface.cpp
deleted file mode 100644
index 150a6cc..0000000
--- a/wifi/1.1/default/wifi_ap_iface.cpp
+++ /dev/null
@@ -1,106 +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.
- */
-
-#include <android-base/logging.h>
-
-#include "hidl_return_util.h"
-#include "hidl_struct_util.h"
-#include "wifi_ap_iface.h"
-#include "wifi_status_util.h"
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_1 {
-namespace implementation {
-using hidl_return_util::validateAndCall;
-
-WifiApIface::WifiApIface(
-    const std::string& ifname,
-    const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal)
-    : ifname_(ifname), legacy_hal_(legacy_hal), is_valid_(true) {}
-
-void WifiApIface::invalidate() {
-  legacy_hal_.reset();
-  is_valid_ = false;
-}
-
-bool WifiApIface::isValid() {
-  return is_valid_;
-}
-
-Return<void> WifiApIface::getName(getName_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                         &WifiApIface::getNameInternal,
-                         hidl_status_cb);
-}
-
-Return<void> WifiApIface::getType(getType_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                         &WifiApIface::getTypeInternal,
-                         hidl_status_cb);
-}
-
-Return<void> WifiApIface::setCountryCode(const hidl_array<int8_t, 2>& code,
-                                         setCountryCode_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                         &WifiApIface::setCountryCodeInternal,
-                         hidl_status_cb,
-                         code);
-}
-
-Return<void> WifiApIface::getValidFrequenciesForBand(
-    WifiBand band, getValidFrequenciesForBand_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                         &WifiApIface::getValidFrequenciesForBandInternal,
-                         hidl_status_cb,
-                         band);
-}
-
-std::pair<WifiStatus, std::string> WifiApIface::getNameInternal() {
-  return {createWifiStatus(WifiStatusCode::SUCCESS), ifname_};
-}
-
-std::pair<WifiStatus, IfaceType> WifiApIface::getTypeInternal() {
-  return {createWifiStatus(WifiStatusCode::SUCCESS), IfaceType::AP};
-}
-
-WifiStatus WifiApIface::setCountryCodeInternal(
-    const std::array<int8_t, 2>& code) {
-  legacy_hal::wifi_error legacy_status =
-      legacy_hal_.lock()->setCountryCode(code);
-  return createWifiStatusFromLegacyError(legacy_status);
-}
-
-std::pair<WifiStatus, std::vector<WifiChannelInMhz>>
-WifiApIface::getValidFrequenciesForBandInternal(WifiBand band) {
-  static_assert(sizeof(WifiChannelInMhz) == sizeof(uint32_t), "Size mismatch");
-  legacy_hal::wifi_error legacy_status;
-  std::vector<uint32_t> valid_frequencies;
-  std::tie(legacy_status, valid_frequencies) =
-      legacy_hal_.lock()->getValidFrequenciesForBand(
-          hidl_struct_util::convertHidlWifiBandToLegacy(band));
-  return {createWifiStatusFromLegacyError(legacy_status), valid_frequencies};
-}
-}  // namespace implementation
-}  // namespace V1_1
-}  // namespace wifi
-}  // namespace hardware
-}  // namespace android
diff --git a/wifi/1.1/default/wifi_ap_iface.h b/wifi/1.1/default/wifi_ap_iface.h
deleted file mode 100644
index 608fe6b..0000000
--- a/wifi/1.1/default/wifi_ap_iface.h
+++ /dev/null
@@ -1,72 +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 WIFI_AP_IFACE_H_
-#define WIFI_AP_IFACE_H_
-
-#include <android-base/macros.h>
-#include <android/hardware/wifi/1.0/IWifiApIface.h>
-
-#include "wifi_legacy_hal.h"
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_1 {
-namespace implementation {
-using namespace android::hardware::wifi::V1_0;
-
-/**
- * HIDL interface object used to control a AP Iface instance.
- */
-class WifiApIface : public V1_0::IWifiApIface {
- public:
-  WifiApIface(const std::string& ifname,
-              const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal);
-  // Refer to |WifiChip::invalidate()|.
-  void invalidate();
-  bool isValid();
-
-  // HIDL methods exposed.
-  Return<void> getName(getName_cb hidl_status_cb) override;
-  Return<void> getType(getType_cb hidl_status_cb) override;
-  Return<void> setCountryCode(const hidl_array<int8_t, 2>& code,
-                              setCountryCode_cb hidl_status_cb) override;
-  Return<void> getValidFrequenciesForBand(
-      WifiBand band, getValidFrequenciesForBand_cb hidl_status_cb) override;
-
- private:
-  // Corresponding worker functions for the HIDL methods.
-  std::pair<WifiStatus, std::string> getNameInternal();
-  std::pair<WifiStatus, IfaceType> getTypeInternal();
-  WifiStatus setCountryCodeInternal(const std::array<int8_t, 2>& code);
-  std::pair<WifiStatus, std::vector<WifiChannelInMhz>>
-  getValidFrequenciesForBandInternal(WifiBand band);
-
-  std::string ifname_;
-  std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
-  bool is_valid_;
-
-  DISALLOW_COPY_AND_ASSIGN(WifiApIface);
-};
-
-}  // namespace implementation
-}  // namespace V1_1
-}  // namespace wifi
-}  // namespace hardware
-}  // namespace android
-
-#endif  // WIFI_AP_IFACE_H_
diff --git a/wifi/1.1/default/wifi_chip.cpp b/wifi/1.1/default/wifi_chip.cpp
deleted file mode 100644
index 2f40234..0000000
--- a/wifi/1.1/default/wifi_chip.cpp
+++ /dev/null
@@ -1,909 +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.
- */
-
-#include <android-base/logging.h>
-
-#include "hidl_return_util.h"
-#include "hidl_struct_util.h"
-#include "wifi_chip.h"
-#include "wifi_feature_flags.h"
-#include "wifi_status_util.h"
-
-namespace {
-using android::sp;
-using android::hardware::hidl_vec;
-using android::hardware::hidl_string;
-using android::hardware::wifi::V1_0::ChipModeId;
-using android::hardware::wifi::V1_0::IWifiChip;
-using android::hardware::wifi::V1_0::IfaceType;
-
-constexpr ChipModeId kStaChipModeId = 0;
-constexpr ChipModeId kApChipModeId = 1;
-constexpr ChipModeId kInvalidModeId = UINT32_MAX;
-
-template <typename Iface>
-void invalidateAndClear(sp<Iface>& iface) {
-  if (iface.get()) {
-    iface->invalidate();
-    iface.clear();
-  }
-}
-}  // namepsace
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_1 {
-namespace implementation {
-using hidl_return_util::validateAndCall;
-
-WifiChip::WifiChip(
-    ChipId chip_id,
-    const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
-    const std::weak_ptr<mode_controller::WifiModeController> mode_controller)
-    : chip_id_(chip_id),
-      legacy_hal_(legacy_hal),
-      mode_controller_(mode_controller),
-      is_valid_(true),
-      current_mode_id_(kInvalidModeId),
-      debug_ring_buffer_cb_registered_(false) {}
-
-void WifiChip::invalidate() {
-  invalidateAndRemoveAllIfaces();
-  legacy_hal_.reset();
-  event_cb_handler_.invalidate();
-  is_valid_ = false;
-}
-
-bool WifiChip::isValid() {
-  return is_valid_;
-}
-
-std::set<sp<IWifiChipEventCallback>> WifiChip::getEventCallbacks() {
-  return event_cb_handler_.getCallbacks();
-}
-
-Return<void> WifiChip::getId(getId_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                         &WifiChip::getIdInternal,
-                         hidl_status_cb);
-}
-
-Return<void> WifiChip::registerEventCallback(
-    const sp<IWifiChipEventCallback>& event_callback,
-    registerEventCallback_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                         &WifiChip::registerEventCallbackInternal,
-                         hidl_status_cb,
-                         event_callback);
-}
-
-Return<void> WifiChip::getCapabilities(getCapabilities_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                         &WifiChip::getCapabilitiesInternal,
-                         hidl_status_cb);
-}
-
-Return<void> WifiChip::getAvailableModes(getAvailableModes_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                         &WifiChip::getAvailableModesInternal,
-                         hidl_status_cb);
-}
-
-Return<void> WifiChip::configureChip(ChipModeId mode_id,
-                                     configureChip_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                         &WifiChip::configureChipInternal,
-                         hidl_status_cb,
-                         mode_id);
-}
-
-Return<void> WifiChip::getMode(getMode_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                         &WifiChip::getModeInternal,
-                         hidl_status_cb);
-}
-
-Return<void> WifiChip::requestChipDebugInfo(
-    requestChipDebugInfo_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                         &WifiChip::requestChipDebugInfoInternal,
-                         hidl_status_cb);
-}
-
-Return<void> WifiChip::requestDriverDebugDump(
-    requestDriverDebugDump_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                         &WifiChip::requestDriverDebugDumpInternal,
-                         hidl_status_cb);
-}
-
-Return<void> WifiChip::requestFirmwareDebugDump(
-    requestFirmwareDebugDump_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                         &WifiChip::requestFirmwareDebugDumpInternal,
-                         hidl_status_cb);
-}
-
-Return<void> WifiChip::createApIface(createApIface_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                         &WifiChip::createApIfaceInternal,
-                         hidl_status_cb);
-}
-
-Return<void> WifiChip::getApIfaceNames(getApIfaceNames_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                         &WifiChip::getApIfaceNamesInternal,
-                         hidl_status_cb);
-}
-
-Return<void> WifiChip::getApIface(const hidl_string& ifname,
-                                  getApIface_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                         &WifiChip::getApIfaceInternal,
-                         hidl_status_cb,
-                         ifname);
-}
-
-Return<void> WifiChip::removeApIface(const hidl_string& ifname,
-                                     removeApIface_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                         &WifiChip::removeApIfaceInternal,
-                         hidl_status_cb,
-                         ifname);
-}
-
-Return<void> WifiChip::createNanIface(createNanIface_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                         &WifiChip::createNanIfaceInternal,
-                         hidl_status_cb);
-}
-
-Return<void> WifiChip::getNanIfaceNames(getNanIfaceNames_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                         &WifiChip::getNanIfaceNamesInternal,
-                         hidl_status_cb);
-}
-
-Return<void> WifiChip::getNanIface(const hidl_string& ifname,
-                                   getNanIface_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                         &WifiChip::getNanIfaceInternal,
-                         hidl_status_cb,
-                         ifname);
-}
-
-Return<void> WifiChip::removeNanIface(const hidl_string& ifname,
-                                      removeNanIface_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                         &WifiChip::removeNanIfaceInternal,
-                         hidl_status_cb,
-                         ifname);
-}
-
-Return<void> WifiChip::createP2pIface(createP2pIface_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                         &WifiChip::createP2pIfaceInternal,
-                         hidl_status_cb);
-}
-
-Return<void> WifiChip::getP2pIfaceNames(getP2pIfaceNames_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                         &WifiChip::getP2pIfaceNamesInternal,
-                         hidl_status_cb);
-}
-
-Return<void> WifiChip::getP2pIface(const hidl_string& ifname,
-                                   getP2pIface_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                         &WifiChip::getP2pIfaceInternal,
-                         hidl_status_cb,
-                         ifname);
-}
-
-Return<void> WifiChip::removeP2pIface(const hidl_string& ifname,
-                                      removeP2pIface_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                         &WifiChip::removeP2pIfaceInternal,
-                         hidl_status_cb,
-                         ifname);
-}
-
-Return<void> WifiChip::createStaIface(createStaIface_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                         &WifiChip::createStaIfaceInternal,
-                         hidl_status_cb);
-}
-
-Return<void> WifiChip::getStaIfaceNames(getStaIfaceNames_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                         &WifiChip::getStaIfaceNamesInternal,
-                         hidl_status_cb);
-}
-
-Return<void> WifiChip::getStaIface(const hidl_string& ifname,
-                                   getStaIface_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                         &WifiChip::getStaIfaceInternal,
-                         hidl_status_cb,
-                         ifname);
-}
-
-Return<void> WifiChip::removeStaIface(const hidl_string& ifname,
-                                      removeStaIface_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                         &WifiChip::removeStaIfaceInternal,
-                         hidl_status_cb,
-                         ifname);
-}
-
-Return<void> WifiChip::createRttController(
-    const sp<IWifiIface>& bound_iface, createRttController_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                         &WifiChip::createRttControllerInternal,
-                         hidl_status_cb,
-                         bound_iface);
-}
-
-Return<void> WifiChip::getDebugRingBuffersStatus(
-    getDebugRingBuffersStatus_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                         &WifiChip::getDebugRingBuffersStatusInternal,
-                         hidl_status_cb);
-}
-
-Return<void> WifiChip::startLoggingToDebugRingBuffer(
-    const hidl_string& ring_name,
-    WifiDebugRingBufferVerboseLevel verbose_level,
-    uint32_t max_interval_in_sec,
-    uint32_t min_data_size_in_bytes,
-    startLoggingToDebugRingBuffer_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                         &WifiChip::startLoggingToDebugRingBufferInternal,
-                         hidl_status_cb,
-                         ring_name,
-                         verbose_level,
-                         max_interval_in_sec,
-                         min_data_size_in_bytes);
-}
-
-Return<void> WifiChip::forceDumpToDebugRingBuffer(
-    const hidl_string& ring_name,
-    forceDumpToDebugRingBuffer_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                         &WifiChip::forceDumpToDebugRingBufferInternal,
-                         hidl_status_cb,
-                         ring_name);
-}
-
-Return<void> WifiChip::stopLoggingToDebugRingBuffer(
-    stopLoggingToDebugRingBuffer_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                         &WifiChip::stopLoggingToDebugRingBufferInternal,
-                         hidl_status_cb);
-}
-
-Return<void> WifiChip::getDebugHostWakeReasonStats(
-    getDebugHostWakeReasonStats_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                         &WifiChip::getDebugHostWakeReasonStatsInternal,
-                         hidl_status_cb);
-}
-
-Return<void> WifiChip::enableDebugErrorAlerts(
-    bool enable, enableDebugErrorAlerts_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                         &WifiChip::enableDebugErrorAlertsInternal,
-                         hidl_status_cb,
-                         enable);
-}
-
-Return<void> WifiChip::selectTxPowerScenario(
-    TxPowerScenario scenario, selectTxPowerScenario_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                         &WifiChip::selectTxPowerScenarioInternal,
-                         hidl_status_cb,
-                         scenario);
-}
-
-Return<void> WifiChip::resetTxPowerScenario(
-    resetTxPowerScenario_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
-                         &WifiChip::resetTxPowerScenarioInternal,
-                         hidl_status_cb);
-}
-
-void WifiChip::invalidateAndRemoveAllIfaces() {
-  invalidateAndClear(ap_iface_);
-  invalidateAndClear(nan_iface_);
-  invalidateAndClear(p2p_iface_);
-  invalidateAndClear(sta_iface_);
-  // Since all the ifaces are invalid now, all RTT controller objects
-  // using those ifaces also need to be invalidated.
-  for (const auto& rtt : rtt_controllers_) {
-    rtt->invalidate();
-  }
-  rtt_controllers_.clear();
-}
-
-std::pair<WifiStatus, ChipId> WifiChip::getIdInternal() {
-  return {createWifiStatus(WifiStatusCode::SUCCESS), chip_id_};
-}
-
-WifiStatus WifiChip::registerEventCallbackInternal(
-    const sp<IWifiChipEventCallback>& event_callback) {
-  if (!event_cb_handler_.addCallback(event_callback)) {
-    return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
-  }
-  return createWifiStatus(WifiStatusCode::SUCCESS);
-}
-
-std::pair<WifiStatus, uint32_t> WifiChip::getCapabilitiesInternal() {
-  legacy_hal::wifi_error legacy_status;
-  uint32_t legacy_feature_set;
-  uint32_t legacy_logger_feature_set;
-  std::tie(legacy_status, legacy_feature_set) =
-      legacy_hal_.lock()->getSupportedFeatureSet();
-  if (legacy_status != legacy_hal::WIFI_SUCCESS) {
-    return {createWifiStatusFromLegacyError(legacy_status), 0};
-  }
-  std::tie(legacy_status, legacy_logger_feature_set) =
-      legacy_hal_.lock()->getLoggerSupportedFeatureSet();
-  if (legacy_status != legacy_hal::WIFI_SUCCESS) {
-    return {createWifiStatusFromLegacyError(legacy_status), 0};
-  }
-  uint32_t hidl_caps;
-  if (!hidl_struct_util::convertLegacyFeaturesToHidlChipCapabilities(
-          legacy_feature_set, legacy_logger_feature_set, &hidl_caps)) {
-    return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), 0};
-  }
-  return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps};
-}
-
-std::pair<WifiStatus, std::vector<IWifiChip::ChipMode>>
-WifiChip::getAvailableModesInternal() {
-  // The chip combination supported for current devices is fixed for now with
-  // 2 separate modes of operation:
-  // Mode 1 (STA mode): Will support 1 STA and 1 P2P or NAN iface operations
-  // concurrently [NAN conditional on wifiHidlFeatureAware]
-  // Mode 2 (AP mode): Will support 1 AP iface operations.
-  // TODO (b/32997844): Read this from some device specific flags in the
-  // makefile.
-  // STA mode iface combinations.
-  const IWifiChip::ChipIfaceCombinationLimit
-      sta_chip_iface_combination_limit_1 = {{IfaceType::STA}, 1};
-  IWifiChip::ChipIfaceCombinationLimit sta_chip_iface_combination_limit_2;
-  if (WifiFeatureFlags::wifiHidlFeatureAware) {
-    sta_chip_iface_combination_limit_2 = {{IfaceType::P2P, IfaceType::NAN},
-                                          1};
-  } else {
-    sta_chip_iface_combination_limit_2 = {{IfaceType::P2P},
-                                          1};
-  }
-  const IWifiChip::ChipIfaceCombination sta_chip_iface_combination = {
-      {sta_chip_iface_combination_limit_1, sta_chip_iface_combination_limit_2}};
-  const IWifiChip::ChipMode sta_chip_mode = {kStaChipModeId,
-                                             {sta_chip_iface_combination}};
-  // AP mode iface combinations.
-  const IWifiChip::ChipIfaceCombinationLimit ap_chip_iface_combination_limit = {
-      {IfaceType::AP}, 1};
-  const IWifiChip::ChipIfaceCombination ap_chip_iface_combination = {
-      {ap_chip_iface_combination_limit}};
-  const IWifiChip::ChipMode ap_chip_mode = {kApChipModeId,
-                                            {ap_chip_iface_combination}};
-  return {createWifiStatus(WifiStatusCode::SUCCESS),
-          {sta_chip_mode, ap_chip_mode}};
-}
-
-WifiStatus WifiChip::configureChipInternal(ChipModeId mode_id) {
-  if (mode_id != kStaChipModeId && mode_id != kApChipModeId) {
-    return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
-  }
-  if (mode_id == current_mode_id_) {
-    LOG(DEBUG) << "Already in the specified mode " << mode_id;
-    return createWifiStatus(WifiStatusCode::SUCCESS);
-  }
-  WifiStatus status = handleChipConfiguration(mode_id);
-  if (status.code != WifiStatusCode::SUCCESS) {
-    for (const auto& callback : event_cb_handler_.getCallbacks()) {
-      if (!callback->onChipReconfigureFailure(status).isOk()) {
-        LOG(ERROR) << "Failed to invoke onChipReconfigureFailure callback";
-      }
-    }
-    return status;
-  }
-  for (const auto& callback : event_cb_handler_.getCallbacks()) {
-    if (!callback->onChipReconfigured(mode_id).isOk()) {
-      LOG(ERROR) << "Failed to invoke onChipReconfigured callback";
-    }
-  }
-  current_mode_id_ = mode_id;
-  return status;
-}
-
-std::pair<WifiStatus, uint32_t> WifiChip::getModeInternal() {
-  if (current_mode_id_ == kInvalidModeId) {
-    return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE),
-            current_mode_id_};
-  }
-  return {createWifiStatus(WifiStatusCode::SUCCESS), current_mode_id_};
-}
-
-std::pair<WifiStatus, IWifiChip::ChipDebugInfo>
-WifiChip::requestChipDebugInfoInternal() {
-  IWifiChip::ChipDebugInfo result;
-  legacy_hal::wifi_error legacy_status;
-  std::string driver_desc;
-  std::tie(legacy_status, driver_desc) = legacy_hal_.lock()->getDriverVersion();
-  if (legacy_status != legacy_hal::WIFI_SUCCESS) {
-    LOG(ERROR) << "Failed to get driver version: "
-               << legacyErrorToString(legacy_status);
-    WifiStatus status = createWifiStatusFromLegacyError(
-        legacy_status, "failed to get driver version");
-    return {status, result};
-  }
-  result.driverDescription = driver_desc.c_str();
-
-  std::string firmware_desc;
-  std::tie(legacy_status, firmware_desc) =
-      legacy_hal_.lock()->getFirmwareVersion();
-  if (legacy_status != legacy_hal::WIFI_SUCCESS) {
-    LOG(ERROR) << "Failed to get firmware version: "
-               << legacyErrorToString(legacy_status);
-    WifiStatus status = createWifiStatusFromLegacyError(
-        legacy_status, "failed to get firmware version");
-    return {status, result};
-  }
-  result.firmwareDescription = firmware_desc.c_str();
-
-  return {createWifiStatus(WifiStatusCode::SUCCESS), result};
-}
-
-std::pair<WifiStatus, std::vector<uint8_t>>
-WifiChip::requestDriverDebugDumpInternal() {
-  legacy_hal::wifi_error legacy_status;
-  std::vector<uint8_t> driver_dump;
-  std::tie(legacy_status, driver_dump) =
-      legacy_hal_.lock()->requestDriverMemoryDump();
-  if (legacy_status != legacy_hal::WIFI_SUCCESS) {
-    LOG(ERROR) << "Failed to get driver debug dump: "
-               << legacyErrorToString(legacy_status);
-    return {createWifiStatusFromLegacyError(legacy_status),
-            std::vector<uint8_t>()};
-  }
-  return {createWifiStatus(WifiStatusCode::SUCCESS), driver_dump};
-}
-
-std::pair<WifiStatus, std::vector<uint8_t>>
-WifiChip::requestFirmwareDebugDumpInternal() {
-  legacy_hal::wifi_error legacy_status;
-  std::vector<uint8_t> firmware_dump;
-  std::tie(legacy_status, firmware_dump) =
-      legacy_hal_.lock()->requestFirmwareMemoryDump();
-  if (legacy_status != legacy_hal::WIFI_SUCCESS) {
-    LOG(ERROR) << "Failed to get firmware debug dump: "
-               << legacyErrorToString(legacy_status);
-    return {createWifiStatusFromLegacyError(legacy_status), {}};
-  }
-  return {createWifiStatus(WifiStatusCode::SUCCESS), firmware_dump};
-}
-
-std::pair<WifiStatus, sp<IWifiApIface>> WifiChip::createApIfaceInternal() {
-  if (current_mode_id_ != kApChipModeId || ap_iface_.get()) {
-    return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
-  }
-  std::string ifname = legacy_hal_.lock()->getApIfaceName();
-  ap_iface_ = new WifiApIface(ifname, legacy_hal_);
-  for (const auto& callback : event_cb_handler_.getCallbacks()) {
-    if (!callback->onIfaceAdded(IfaceType::AP, ifname).isOk()) {
-      LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
-    }
-  }
-  return {createWifiStatus(WifiStatusCode::SUCCESS), ap_iface_};
-}
-
-std::pair<WifiStatus, std::vector<hidl_string>>
-WifiChip::getApIfaceNamesInternal() {
-  if (!ap_iface_.get()) {
-    return {createWifiStatus(WifiStatusCode::SUCCESS), {}};
-  }
-  return {createWifiStatus(WifiStatusCode::SUCCESS),
-          {legacy_hal_.lock()->getApIfaceName()}};
-}
-
-std::pair<WifiStatus, sp<IWifiApIface>> WifiChip::getApIfaceInternal(
-    const std::string& ifname) {
-  if (!ap_iface_.get() || (ifname != legacy_hal_.lock()->getApIfaceName())) {
-    return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr};
-  }
-  return {createWifiStatus(WifiStatusCode::SUCCESS), ap_iface_};
-}
-
-WifiStatus WifiChip::removeApIfaceInternal(const std::string& ifname) {
-  if (!ap_iface_.get() || (ifname != legacy_hal_.lock()->getApIfaceName())) {
-    return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
-  }
-  invalidateAndClear(ap_iface_);
-  for (const auto& callback : event_cb_handler_.getCallbacks()) {
-    if (!callback->onIfaceRemoved(IfaceType::AP, ifname).isOk()) {
-      LOG(ERROR) << "Failed to invoke onIfaceRemoved callback";
-    }
-  }
-  return createWifiStatus(WifiStatusCode::SUCCESS);
-}
-
-std::pair<WifiStatus, sp<IWifiNanIface>> WifiChip::createNanIfaceInternal() {
-  // Only 1 of NAN or P2P iface can be active at a time.
-  if (WifiFeatureFlags::wifiHidlFeatureAware) {
-    if (current_mode_id_ != kStaChipModeId || nan_iface_.get() ||
-        p2p_iface_.get()) {
-      return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
-    }
-    std::string ifname = legacy_hal_.lock()->getNanIfaceName();
-    nan_iface_ = new WifiNanIface(ifname, legacy_hal_);
-    for (const auto& callback : event_cb_handler_.getCallbacks()) {
-      if (!callback->onIfaceAdded(IfaceType::NAN, ifname).isOk()) {
-        LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
-      }
-    }
-    return {createWifiStatus(WifiStatusCode::SUCCESS), nan_iface_};
-  } else {
-    return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
-  }
-}
-
-std::pair<WifiStatus, std::vector<hidl_string>>
-WifiChip::getNanIfaceNamesInternal() {
-  if (!nan_iface_.get()) {
-    return {createWifiStatus(WifiStatusCode::SUCCESS), {}};
-  }
-  return {createWifiStatus(WifiStatusCode::SUCCESS),
-          {legacy_hal_.lock()->getNanIfaceName()}};
-}
-
-std::pair<WifiStatus, sp<IWifiNanIface>> WifiChip::getNanIfaceInternal(
-    const std::string& ifname) {
-  if (!nan_iface_.get() || (ifname != legacy_hal_.lock()->getNanIfaceName())) {
-    return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr};
-  }
-  return {createWifiStatus(WifiStatusCode::SUCCESS), nan_iface_};
-}
-
-WifiStatus WifiChip::removeNanIfaceInternal(const std::string& ifname) {
-  if (!nan_iface_.get() || (ifname != legacy_hal_.lock()->getNanIfaceName())) {
-    return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
-  }
-  invalidateAndClear(nan_iface_);
-  for (const auto& callback : event_cb_handler_.getCallbacks()) {
-    if (!callback->onIfaceRemoved(IfaceType::NAN, ifname).isOk()) {
-      LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
-    }
-  }
-  return createWifiStatus(WifiStatusCode::SUCCESS);
-}
-
-std::pair<WifiStatus, sp<IWifiP2pIface>> WifiChip::createP2pIfaceInternal() {
-  // Only 1 of NAN or P2P iface can be active at a time.
-  if (current_mode_id_ != kStaChipModeId || p2p_iface_.get() ||
-      nan_iface_.get()) {
-    return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
-  }
-  std::string ifname = legacy_hal_.lock()->getP2pIfaceName();
-  p2p_iface_ = new WifiP2pIface(ifname, legacy_hal_);
-  for (const auto& callback : event_cb_handler_.getCallbacks()) {
-    if (!callback->onIfaceAdded(IfaceType::P2P, ifname).isOk()) {
-      LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
-    }
-  }
-  return {createWifiStatus(WifiStatusCode::SUCCESS), p2p_iface_};
-}
-
-std::pair<WifiStatus, std::vector<hidl_string>>
-WifiChip::getP2pIfaceNamesInternal() {
-  if (!p2p_iface_.get()) {
-    return {createWifiStatus(WifiStatusCode::SUCCESS), {}};
-  }
-  return {createWifiStatus(WifiStatusCode::SUCCESS),
-          {legacy_hal_.lock()->getP2pIfaceName()}};
-}
-
-std::pair<WifiStatus, sp<IWifiP2pIface>> WifiChip::getP2pIfaceInternal(
-    const std::string& ifname) {
-  if (!p2p_iface_.get() || (ifname != legacy_hal_.lock()->getP2pIfaceName())) {
-    return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr};
-  }
-  return {createWifiStatus(WifiStatusCode::SUCCESS), p2p_iface_};
-}
-
-WifiStatus WifiChip::removeP2pIfaceInternal(const std::string& ifname) {
-  if (!p2p_iface_.get() || (ifname != legacy_hal_.lock()->getP2pIfaceName())) {
-    return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
-  }
-  invalidateAndClear(p2p_iface_);
-  for (const auto& callback : event_cb_handler_.getCallbacks()) {
-    if (!callback->onIfaceRemoved(IfaceType::P2P, ifname).isOk()) {
-      LOG(ERROR) << "Failed to invoke onIfaceRemoved callback";
-    }
-  }
-  return createWifiStatus(WifiStatusCode::SUCCESS);
-}
-
-std::pair<WifiStatus, sp<IWifiStaIface>> WifiChip::createStaIfaceInternal() {
-  if (current_mode_id_ != kStaChipModeId || sta_iface_.get()) {
-    return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
-  }
-  std::string ifname = legacy_hal_.lock()->getStaIfaceName();
-  sta_iface_ = new WifiStaIface(ifname, legacy_hal_);
-  for (const auto& callback : event_cb_handler_.getCallbacks()) {
-    if (!callback->onIfaceAdded(IfaceType::STA, ifname).isOk()) {
-      LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
-    }
-  }
-  return {createWifiStatus(WifiStatusCode::SUCCESS), sta_iface_};
-}
-
-std::pair<WifiStatus, std::vector<hidl_string>>
-WifiChip::getStaIfaceNamesInternal() {
-  if (!sta_iface_.get()) {
-    return {createWifiStatus(WifiStatusCode::SUCCESS), {}};
-  }
-  return {createWifiStatus(WifiStatusCode::SUCCESS),
-          {legacy_hal_.lock()->getStaIfaceName()}};
-}
-
-std::pair<WifiStatus, sp<IWifiStaIface>> WifiChip::getStaIfaceInternal(
-    const std::string& ifname) {
-  if (!sta_iface_.get() || (ifname != legacy_hal_.lock()->getStaIfaceName())) {
-    return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr};
-  }
-  return {createWifiStatus(WifiStatusCode::SUCCESS), sta_iface_};
-}
-
-WifiStatus WifiChip::removeStaIfaceInternal(const std::string& ifname) {
-  if (!sta_iface_.get() || (ifname != legacy_hal_.lock()->getStaIfaceName())) {
-    return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
-  }
-  invalidateAndClear(sta_iface_);
-  for (const auto& callback : event_cb_handler_.getCallbacks()) {
-    if (!callback->onIfaceRemoved(IfaceType::STA, ifname).isOk()) {
-      LOG(ERROR) << "Failed to invoke onIfaceRemoved callback";
-    }
-  }
-  return createWifiStatus(WifiStatusCode::SUCCESS);
-}
-
-std::pair<WifiStatus, sp<IWifiRttController>>
-WifiChip::createRttControllerInternal(const sp<IWifiIface>& bound_iface) {
-  sp<WifiRttController> rtt = new WifiRttController(bound_iface, legacy_hal_);
-  rtt_controllers_.emplace_back(rtt);
-  return {createWifiStatus(WifiStatusCode::SUCCESS), rtt};
-}
-
-std::pair<WifiStatus, std::vector<WifiDebugRingBufferStatus>>
-WifiChip::getDebugRingBuffersStatusInternal() {
-  legacy_hal::wifi_error legacy_status;
-  std::vector<legacy_hal::wifi_ring_buffer_status>
-      legacy_ring_buffer_status_vec;
-  std::tie(legacy_status, legacy_ring_buffer_status_vec) =
-      legacy_hal_.lock()->getRingBuffersStatus();
-  if (legacy_status != legacy_hal::WIFI_SUCCESS) {
-    return {createWifiStatusFromLegacyError(legacy_status), {}};
-  }
-  std::vector<WifiDebugRingBufferStatus> hidl_ring_buffer_status_vec;
-  if (!hidl_struct_util::convertLegacyVectorOfDebugRingBufferStatusToHidl(
-          legacy_ring_buffer_status_vec, &hidl_ring_buffer_status_vec)) {
-    return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
-  }
-  return {createWifiStatus(WifiStatusCode::SUCCESS),
-          hidl_ring_buffer_status_vec};
-}
-
-WifiStatus WifiChip::startLoggingToDebugRingBufferInternal(
-    const hidl_string& ring_name,
-    WifiDebugRingBufferVerboseLevel verbose_level,
-    uint32_t max_interval_in_sec,
-    uint32_t min_data_size_in_bytes) {
-  WifiStatus status = registerDebugRingBufferCallback();
-  if (status.code != WifiStatusCode::SUCCESS) {
-    return status;
-  }
-  legacy_hal::wifi_error legacy_status =
-      legacy_hal_.lock()->startRingBufferLogging(
-          ring_name,
-          static_cast<
-              std::underlying_type<WifiDebugRingBufferVerboseLevel>::type>(
-              verbose_level),
-          max_interval_in_sec,
-          min_data_size_in_bytes);
-  return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiChip::forceDumpToDebugRingBufferInternal(
-    const hidl_string& ring_name) {
-  WifiStatus status = registerDebugRingBufferCallback();
-  if (status.code != WifiStatusCode::SUCCESS) {
-    return status;
-  }
-  legacy_hal::wifi_error legacy_status =
-      legacy_hal_.lock()->getRingBufferData(ring_name);
-  return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiChip::stopLoggingToDebugRingBufferInternal() {
-  legacy_hal::wifi_error legacy_status =
-      legacy_hal_.lock()->deregisterRingBufferCallbackHandler();
-  return createWifiStatusFromLegacyError(legacy_status);
-}
-
-std::pair<WifiStatus, WifiDebugHostWakeReasonStats>
-WifiChip::getDebugHostWakeReasonStatsInternal() {
-  legacy_hal::wifi_error legacy_status;
-  legacy_hal::WakeReasonStats legacy_stats;
-  std::tie(legacy_status, legacy_stats) =
-      legacy_hal_.lock()->getWakeReasonStats();
-  if (legacy_status != legacy_hal::WIFI_SUCCESS) {
-    return {createWifiStatusFromLegacyError(legacy_status), {}};
-  }
-  WifiDebugHostWakeReasonStats hidl_stats;
-  if (!hidl_struct_util::convertLegacyWakeReasonStatsToHidl(legacy_stats,
-                                                            &hidl_stats)) {
-    return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
-  }
-  return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_stats};
-}
-
-WifiStatus WifiChip::enableDebugErrorAlertsInternal(bool enable) {
-  legacy_hal::wifi_error legacy_status;
-  if (enable) {
-    android::wp<WifiChip> weak_ptr_this(this);
-    const auto& on_alert_callback = [weak_ptr_this](
-        int32_t error_code, std::vector<uint8_t> debug_data) {
-      const auto shared_ptr_this = weak_ptr_this.promote();
-      if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
-        LOG(ERROR) << "Callback invoked on an invalid object";
-        return;
-      }
-      for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
-        if (!callback->onDebugErrorAlert(error_code, debug_data).isOk()) {
-          LOG(ERROR) << "Failed to invoke onDebugErrorAlert callback";
-        }
-      }
-    };
-    legacy_status = legacy_hal_.lock()->registerErrorAlertCallbackHandler(
-        on_alert_callback);
-  } else {
-    legacy_status = legacy_hal_.lock()->deregisterErrorAlertCallbackHandler();
-  }
-  return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiChip::selectTxPowerScenarioInternal(TxPowerScenario scenario) {
-  auto legacy_status = legacy_hal_.lock()->selectTxPowerScenario(
-      hidl_struct_util::convertHidlTxPowerScenarioToLegacy(scenario));
-  return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiChip::resetTxPowerScenarioInternal() {
-  auto legacy_status = legacy_hal_.lock()->resetTxPowerScenario();
-  return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiChip::handleChipConfiguration(ChipModeId mode_id) {
-  // If the chip is already configured in a different mode, stop
-  // the legacy HAL and then start it after firmware mode change.
-  // Currently the underlying implementation has a deadlock issue.
-  // We should return ERROR_NOT_SUPPORTED if chip is already configured in
-  // a different mode.
-  if (current_mode_id_ != kInvalidModeId) {
-    // TODO(b/37446050): Fix the deadlock.
-    return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
-  }
-  bool success;
-  if (mode_id == kStaChipModeId) {
-    success = mode_controller_.lock()->changeFirmwareMode(IfaceType::STA);
-  } else {
-    success = mode_controller_.lock()->changeFirmwareMode(IfaceType::AP);
-  }
-  if (!success) {
-    return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
-  }
-  legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->start();
-  if (legacy_status != legacy_hal::WIFI_SUCCESS) {
-    LOG(ERROR) << "Failed to start legacy HAL: "
-               << legacyErrorToString(legacy_status);
-    return createWifiStatusFromLegacyError(legacy_status);
-  }
-  return createWifiStatus(WifiStatusCode::SUCCESS);
-}
-
-WifiStatus WifiChip::registerDebugRingBufferCallback() {
-  if (debug_ring_buffer_cb_registered_) {
-    return createWifiStatus(WifiStatusCode::SUCCESS);
-  }
-
-  android::wp<WifiChip> weak_ptr_this(this);
-  const auto& on_ring_buffer_data_callback = [weak_ptr_this](
-      const std::string& /* name */,
-      const std::vector<uint8_t>& data,
-      const legacy_hal::wifi_ring_buffer_status& status) {
-    const auto shared_ptr_this = weak_ptr_this.promote();
-    if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
-      LOG(ERROR) << "Callback invoked on an invalid object";
-      return;
-    }
-    WifiDebugRingBufferStatus hidl_status;
-    if (!hidl_struct_util::convertLegacyDebugRingBufferStatusToHidl(
-            status, &hidl_status)) {
-      LOG(ERROR) << "Error converting ring buffer status";
-      return;
-    }
-    for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
-      if (!callback->onDebugRingBufferDataAvailable(hidl_status, data).isOk()) {
-        LOG(ERROR) << "Failed to invoke onDebugRingBufferDataAvailable"
-                   << " callback on: " << toString(callback);
-
-      }
-    }
-  };
-  legacy_hal::wifi_error legacy_status =
-      legacy_hal_.lock()->registerRingBufferCallbackHandler(
-          on_ring_buffer_data_callback);
-
-  if (legacy_status == legacy_hal::WIFI_SUCCESS) {
-    debug_ring_buffer_cb_registered_ = true;
-  }
-  return createWifiStatusFromLegacyError(legacy_status);
-}
-
-}  // namespace implementation
-}  // namespace V1_1
-}  // namespace wifi
-}  // namespace hardware
-}  // namespace android
diff --git a/wifi/1.1/default/wifi_chip.h b/wifi/1.1/default/wifi_chip.h
deleted file mode 100644
index e88100b..0000000
--- a/wifi/1.1/default/wifi_chip.h
+++ /dev/null
@@ -1,217 +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 WIFI_CHIP_H_
-#define WIFI_CHIP_H_
-
-#include <map>
-
-#include <android-base/macros.h>
-#include <android/hardware/wifi/1.1/IWifiChip.h>
-
-#include "hidl_callback_util.h"
-#include "wifi_ap_iface.h"
-#include "wifi_legacy_hal.h"
-#include "wifi_mode_controller.h"
-#include "wifi_nan_iface.h"
-#include "wifi_p2p_iface.h"
-#include "wifi_rtt_controller.h"
-#include "wifi_sta_iface.h"
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_1 {
-namespace implementation {
-using namespace android::hardware::wifi::V1_0;
-
-/**
- * HIDL interface object used to control a Wifi HAL chip instance.
- * Since there is only a single chip instance used today, there is no
- * identifying handle information stored here.
- */
-class WifiChip : public V1_1::IWifiChip {
- public:
-  WifiChip(
-      ChipId chip_id,
-      const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
-      const std::weak_ptr<mode_controller::WifiModeController> mode_controller);
-  // HIDL does not provide a built-in mechanism to let the server invalidate
-  // a HIDL interface object after creation. If any client process holds onto
-  // a reference to the object in their context, any method calls on that
-  // reference will continue to be directed to the server.
-  //
-  // However Wifi HAL needs to control the lifetime of these objects. So, add
-  // a public |invalidate| method to |WifiChip| and it's child objects. This
-  // will be used to mark an object invalid when either:
-  // a) Wifi HAL is stopped, or
-  // b) Wifi Chip is reconfigured.
-  //
-  // All HIDL method implementations should check if the object is still marked
-  // valid before processing them.
-  void invalidate();
-  bool isValid();
-  std::set<sp<IWifiChipEventCallback>> getEventCallbacks();
-
-  // HIDL methods exposed.
-  Return<void> getId(getId_cb hidl_status_cb) override;
-  Return<void> registerEventCallback(
-      const sp<IWifiChipEventCallback>& event_callback,
-      registerEventCallback_cb hidl_status_cb) override;
-  Return<void> getCapabilities(getCapabilities_cb hidl_status_cb) override;
-  Return<void> getAvailableModes(getAvailableModes_cb hidl_status_cb) override;
-  Return<void> configureChip(ChipModeId mode_id,
-                             configureChip_cb hidl_status_cb) override;
-  Return<void> getMode(getMode_cb hidl_status_cb) override;
-  Return<void> requestChipDebugInfo(
-      requestChipDebugInfo_cb hidl_status_cb) override;
-  Return<void> requestDriverDebugDump(
-      requestDriverDebugDump_cb hidl_status_cb) override;
-  Return<void> requestFirmwareDebugDump(
-      requestFirmwareDebugDump_cb hidl_status_cb) override;
-  Return<void> createApIface(createApIface_cb hidl_status_cb) override;
-  Return<void> getApIfaceNames(getApIfaceNames_cb hidl_status_cb) override;
-  Return<void> getApIface(const hidl_string& ifname,
-                          getApIface_cb hidl_status_cb) override;
-  Return<void> removeApIface(const hidl_string& ifname,
-                             removeApIface_cb hidl_status_cb) override;
-  Return<void> createNanIface(createNanIface_cb hidl_status_cb) override;
-  Return<void> getNanIfaceNames(getNanIfaceNames_cb hidl_status_cb) override;
-  Return<void> getNanIface(const hidl_string& ifname,
-                           getNanIface_cb hidl_status_cb) override;
-  Return<void> removeNanIface(const hidl_string& ifname,
-                              removeNanIface_cb hidl_status_cb) override;
-  Return<void> createP2pIface(createP2pIface_cb hidl_status_cb) override;
-  Return<void> getP2pIfaceNames(getP2pIfaceNames_cb hidl_status_cb) override;
-  Return<void> getP2pIface(const hidl_string& ifname,
-                           getP2pIface_cb hidl_status_cb) override;
-  Return<void> removeP2pIface(const hidl_string& ifname,
-                              removeP2pIface_cb hidl_status_cb) override;
-  Return<void> createStaIface(createStaIface_cb hidl_status_cb) override;
-  Return<void> getStaIfaceNames(getStaIfaceNames_cb hidl_status_cb) override;
-  Return<void> getStaIface(const hidl_string& ifname,
-                           getStaIface_cb hidl_status_cb) override;
-  Return<void> removeStaIface(const hidl_string& ifname,
-                              removeStaIface_cb hidl_status_cb) override;
-  Return<void> createRttController(
-      const sp<IWifiIface>& bound_iface,
-      createRttController_cb hidl_status_cb) override;
-  Return<void> getDebugRingBuffersStatus(
-      getDebugRingBuffersStatus_cb hidl_status_cb) override;
-  Return<void> startLoggingToDebugRingBuffer(
-      const hidl_string& ring_name,
-      WifiDebugRingBufferVerboseLevel verbose_level,
-      uint32_t max_interval_in_sec,
-      uint32_t min_data_size_in_bytes,
-      startLoggingToDebugRingBuffer_cb hidl_status_cb) override;
-  Return<void> forceDumpToDebugRingBuffer(
-      const hidl_string& ring_name,
-      forceDumpToDebugRingBuffer_cb hidl_status_cb) override;
-  Return<void> stopLoggingToDebugRingBuffer(
-      stopLoggingToDebugRingBuffer_cb hidl_status_cb) override;
-  Return<void> getDebugHostWakeReasonStats(
-      getDebugHostWakeReasonStats_cb hidl_status_cb) override;
-  Return<void> enableDebugErrorAlerts(
-      bool enable, enableDebugErrorAlerts_cb hidl_status_cb) override;
-  Return<void> selectTxPowerScenario(
-      TxPowerScenario scenario,
-      selectTxPowerScenario_cb hidl_status_cb) override;
-  Return<void> resetTxPowerScenario(
-      resetTxPowerScenario_cb hidl_status_cb) override;
-
- private:
-  void invalidateAndRemoveAllIfaces();
-
-  // Corresponding worker functions for the HIDL methods.
-  std::pair<WifiStatus, ChipId> getIdInternal();
-  WifiStatus registerEventCallbackInternal(
-      const sp<IWifiChipEventCallback>& event_callback);
-  std::pair<WifiStatus, uint32_t> getCapabilitiesInternal();
-  std::pair<WifiStatus, std::vector<ChipMode>> getAvailableModesInternal();
-  WifiStatus configureChipInternal(ChipModeId mode_id);
-  std::pair<WifiStatus, uint32_t> getModeInternal();
-  std::pair<WifiStatus, IWifiChip::ChipDebugInfo>
-  requestChipDebugInfoInternal();
-  std::pair<WifiStatus, std::vector<uint8_t>> requestDriverDebugDumpInternal();
-  std::pair<WifiStatus, std::vector<uint8_t>>
-  requestFirmwareDebugDumpInternal();
-  std::pair<WifiStatus, sp<IWifiApIface>> createApIfaceInternal();
-  std::pair<WifiStatus, std::vector<hidl_string>> getApIfaceNamesInternal();
-  std::pair<WifiStatus, sp<IWifiApIface>> getApIfaceInternal(
-      const std::string& ifname);
-  WifiStatus removeApIfaceInternal(const std::string& ifname);
-  std::pair<WifiStatus, sp<IWifiNanIface>> createNanIfaceInternal();
-  std::pair<WifiStatus, std::vector<hidl_string>> getNanIfaceNamesInternal();
-  std::pair<WifiStatus, sp<IWifiNanIface>> getNanIfaceInternal(
-      const std::string& ifname);
-  WifiStatus removeNanIfaceInternal(const std::string& ifname);
-  std::pair<WifiStatus, sp<IWifiP2pIface>> createP2pIfaceInternal();
-  std::pair<WifiStatus, std::vector<hidl_string>> getP2pIfaceNamesInternal();
-  std::pair<WifiStatus, sp<IWifiP2pIface>> getP2pIfaceInternal(
-      const std::string& ifname);
-  WifiStatus removeP2pIfaceInternal(const std::string& ifname);
-  std::pair<WifiStatus, sp<IWifiStaIface>> createStaIfaceInternal();
-  std::pair<WifiStatus, std::vector<hidl_string>> getStaIfaceNamesInternal();
-  std::pair<WifiStatus, sp<IWifiStaIface>> getStaIfaceInternal(
-      const std::string& ifname);
-  WifiStatus removeStaIfaceInternal(const std::string& ifname);
-  std::pair<WifiStatus, sp<IWifiRttController>> createRttControllerInternal(
-      const sp<IWifiIface>& bound_iface);
-  std::pair<WifiStatus, std::vector<WifiDebugRingBufferStatus>>
-  getDebugRingBuffersStatusInternal();
-  WifiStatus startLoggingToDebugRingBufferInternal(
-      const hidl_string& ring_name,
-      WifiDebugRingBufferVerboseLevel verbose_level,
-      uint32_t max_interval_in_sec,
-      uint32_t min_data_size_in_bytes);
-  WifiStatus forceDumpToDebugRingBufferInternal(const hidl_string& ring_name);
-  WifiStatus stopLoggingToDebugRingBufferInternal();
-  std::pair<WifiStatus, WifiDebugHostWakeReasonStats>
-  getDebugHostWakeReasonStatsInternal();
-  WifiStatus enableDebugErrorAlertsInternal(bool enable);
-  WifiStatus selectTxPowerScenarioInternal(TxPowerScenario scenario);
-  WifiStatus resetTxPowerScenarioInternal();
-
-  WifiStatus handleChipConfiguration(ChipModeId mode_id);
-  WifiStatus registerDebugRingBufferCallback();
-
-  ChipId chip_id_;
-  std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
-  std::weak_ptr<mode_controller::WifiModeController> mode_controller_;
-  sp<WifiApIface> ap_iface_;
-  sp<WifiNanIface> nan_iface_;
-  sp<WifiP2pIface> p2p_iface_;
-  sp<WifiStaIface> sta_iface_;
-  std::vector<sp<WifiRttController>> rtt_controllers_;
-  bool is_valid_;
-  uint32_t current_mode_id_;
-  // The legacy ring buffer callback API has only a global callback
-  // registration mechanism. Use this to check if we have already
-  // registered a callback.
-  bool debug_ring_buffer_cb_registered_;
-  hidl_callback_util::HidlCallbackHandler<IWifiChipEventCallback>
-      event_cb_handler_;
-
-  DISALLOW_COPY_AND_ASSIGN(WifiChip);
-};
-
-}  // namespace implementation
-}  // namespace V1_1
-}  // namespace wifi
-}  // namespace hardware
-}  // namespace android
-
-#endif  // WIFI_CHIP_H_
diff --git a/wifi/1.1/default/wifi_legacy_hal.cpp b/wifi/1.1/default/wifi_legacy_hal.cpp
deleted file mode 100644
index 36da6e5..0000000
--- a/wifi/1.1/default/wifi_legacy_hal.cpp
+++ /dev/null
@@ -1,1345 +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.
- */
-
-#include <array>
-#include <chrono>
-
-#include <android-base/logging.h>
-#include <cutils/properties.h>
-
-#include "hidl_sync_util.h"
-#include "wifi_legacy_hal.h"
-#include "wifi_legacy_hal_stubs.h"
-
-namespace {
-// Constants ported over from the legacy HAL calling code
-// (com_android_server_wifi_WifiNative.cpp). This will all be thrown
-// away when this shim layer is replaced by the real vendor
-// implementation.
-static constexpr uint32_t kMaxVersionStringLength = 256;
-static constexpr uint32_t kMaxCachedGscanResults = 64;
-static constexpr uint32_t kMaxGscanFrequenciesForBand = 64;
-static constexpr uint32_t kLinkLayerStatsDataMpduSizeThreshold = 128;
-static constexpr uint32_t kMaxWakeReasonStatsArraySize = 32;
-static constexpr uint32_t kMaxRingBuffers = 10;
-static constexpr uint32_t kMaxStopCompleteWaitMs = 100;
-
-// Helper function to create a non-const char* for legacy Hal API's.
-std::vector<char> makeCharVec(const std::string& str) {
-  std::vector<char> vec(str.size() + 1);
-  vec.assign(str.begin(), str.end());
-  vec.push_back('\0');
-  return vec;
-}
-}  // namespace
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_1 {
-namespace implementation {
-namespace legacy_hal {
-// 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
-std::function<void(wifi_handle handle)> on_stop_complete_internal_callback;
-void onAsyncStopComplete(wifi_handle handle) {
-  const auto lock = hidl_sync_util::acquireGlobalLock();
-  if (on_stop_complete_internal_callback) {
-    on_stop_complete_internal_callback(handle);
-    // Invalidate this callback since we don't want this firing again.
-    on_stop_complete_internal_callback = nullptr;
-  }
-}
-
-// Callback to be invoked for driver dump.
-std::function<void(char*, int)> on_driver_memory_dump_internal_callback;
-void onSyncDriverMemoryDump(char* buffer, int buffer_size) {
-  if (on_driver_memory_dump_internal_callback) {
-    on_driver_memory_dump_internal_callback(buffer, buffer_size);
-  }
-}
-
-// Callback to be invoked for firmware dump.
-std::function<void(char*, int)> on_firmware_memory_dump_internal_callback;
-void onSyncFirmwareMemoryDump(char* buffer, int buffer_size) {
-  if (on_firmware_memory_dump_internal_callback) {
-    on_firmware_memory_dump_internal_callback(buffer, buffer_size);
-  }
-}
-
-// Callback to be invoked for Gscan events.
-std::function<void(wifi_request_id, wifi_scan_event)>
-    on_gscan_event_internal_callback;
-void onAsyncGscanEvent(wifi_request_id id, wifi_scan_event event) {
-  const auto lock = hidl_sync_util::acquireGlobalLock();
-  if (on_gscan_event_internal_callback) {
-    on_gscan_event_internal_callback(id, event);
-  }
-}
-
-// Callback to be invoked for Gscan full results.
-std::function<void(wifi_request_id, wifi_scan_result*, uint32_t)>
-    on_gscan_full_result_internal_callback;
-void onAsyncGscanFullResult(wifi_request_id id,
-                            wifi_scan_result* result,
-                            uint32_t buckets_scanned) {
-  const auto lock = hidl_sync_util::acquireGlobalLock();
-  if (on_gscan_full_result_internal_callback) {
-    on_gscan_full_result_internal_callback(id, result, buckets_scanned);
-  }
-}
-
-// Callback to be invoked for link layer stats results.
-std::function<void((wifi_request_id, wifi_iface_stat*, int, wifi_radio_stat*))>
-    on_link_layer_stats_result_internal_callback;
-void onSyncLinkLayerStatsResult(wifi_request_id id,
-                                wifi_iface_stat* iface_stat,
-                                int num_radios,
-                                wifi_radio_stat* radio_stat) {
-  if (on_link_layer_stats_result_internal_callback) {
-    on_link_layer_stats_result_internal_callback(
-        id, iface_stat, num_radios, radio_stat);
-  }
-}
-
-// Callback to be invoked for rssi threshold breach.
-std::function<void((wifi_request_id, uint8_t*, int8_t))>
-    on_rssi_threshold_breached_internal_callback;
-void onAsyncRssiThresholdBreached(wifi_request_id id,
-                                  uint8_t* bssid,
-                                  int8_t rssi) {
-  const auto lock = hidl_sync_util::acquireGlobalLock();
-  if (on_rssi_threshold_breached_internal_callback) {
-    on_rssi_threshold_breached_internal_callback(id, bssid, rssi);
-  }
-}
-
-// Callback to be invoked for ring buffer data indication.
-std::function<void(char*, char*, int, wifi_ring_buffer_status*)>
-    on_ring_buffer_data_internal_callback;
-void onAsyncRingBufferData(char* ring_name,
-                           char* buffer,
-                           int buffer_size,
-                           wifi_ring_buffer_status* status) {
-  const auto lock = hidl_sync_util::acquireGlobalLock();
-  if (on_ring_buffer_data_internal_callback) {
-    on_ring_buffer_data_internal_callback(
-        ring_name, buffer, buffer_size, status);
-  }
-}
-
-// Callback to be invoked for error alert indication.
-std::function<void(wifi_request_id, char*, int, int)>
-    on_error_alert_internal_callback;
-void onAsyncErrorAlert(wifi_request_id id,
-                       char* buffer,
-                       int buffer_size,
-                       int err_code) {
-  const auto lock = hidl_sync_util::acquireGlobalLock();
-  if (on_error_alert_internal_callback) {
-    on_error_alert_internal_callback(id, buffer, buffer_size, err_code);
-  }
-}
-
-// Callback to be invoked for rtt results results.
-std::function<void(
-    wifi_request_id, unsigned num_results, wifi_rtt_result* rtt_results[])>
-    on_rtt_results_internal_callback;
-void onAsyncRttResults(wifi_request_id id,
-                       unsigned num_results,
-                       wifi_rtt_result* rtt_results[]) {
-  const auto lock = hidl_sync_util::acquireGlobalLock();
-  if (on_rtt_results_internal_callback) {
-    on_rtt_results_internal_callback(id, num_results, rtt_results);
-    on_rtt_results_internal_callback = nullptr;
-  }
-}
-
-// Callbacks for the various NAN operations.
-// NOTE: These have very little conversions to perform before invoking the user
-// callbacks.
-// So, handle all of them here directly to avoid adding an unnecessary layer.
-std::function<void(transaction_id, const NanResponseMsg&)>
-    on_nan_notify_response_user_callback;
-void onAysncNanNotifyResponse(transaction_id id, NanResponseMsg* msg) {
-  const auto lock = hidl_sync_util::acquireGlobalLock();
-  if (on_nan_notify_response_user_callback && msg) {
-    on_nan_notify_response_user_callback(id, *msg);
-  }
-}
-
-std::function<void(const NanPublishRepliedInd&)>
-    on_nan_event_publish_replied_user_callback;
-void onAysncNanEventPublishReplied(NanPublishRepliedInd* /* event */) {
-  LOG(ERROR) << "onAysncNanEventPublishReplied triggered";
-}
-
-std::function<void(const NanPublishTerminatedInd&)>
-    on_nan_event_publish_terminated_user_callback;
-void onAysncNanEventPublishTerminated(NanPublishTerminatedInd* event) {
-  const auto lock = hidl_sync_util::acquireGlobalLock();
-  if (on_nan_event_publish_terminated_user_callback && event) {
-    on_nan_event_publish_terminated_user_callback(*event);
-  }
-}
-
-std::function<void(const NanMatchInd&)> on_nan_event_match_user_callback;
-void onAysncNanEventMatch(NanMatchInd* event) {
-  const auto lock = hidl_sync_util::acquireGlobalLock();
-  if (on_nan_event_match_user_callback && event) {
-    on_nan_event_match_user_callback(*event);
-  }
-}
-
-std::function<void(const NanMatchExpiredInd&)>
-    on_nan_event_match_expired_user_callback;
-void onAysncNanEventMatchExpired(NanMatchExpiredInd* event) {
-  const auto lock = hidl_sync_util::acquireGlobalLock();
-  if (on_nan_event_match_expired_user_callback && event) {
-    on_nan_event_match_expired_user_callback(*event);
-  }
-}
-
-std::function<void(const NanSubscribeTerminatedInd&)>
-    on_nan_event_subscribe_terminated_user_callback;
-void onAysncNanEventSubscribeTerminated(NanSubscribeTerminatedInd* event) {
-  const auto lock = hidl_sync_util::acquireGlobalLock();
-  if (on_nan_event_subscribe_terminated_user_callback && event) {
-    on_nan_event_subscribe_terminated_user_callback(*event);
-  }
-}
-
-std::function<void(const NanFollowupInd&)> on_nan_event_followup_user_callback;
-void onAysncNanEventFollowup(NanFollowupInd* event) {
-  const auto lock = hidl_sync_util::acquireGlobalLock();
-  if (on_nan_event_followup_user_callback && event) {
-    on_nan_event_followup_user_callback(*event);
-  }
-}
-
-std::function<void(const NanDiscEngEventInd&)>
-    on_nan_event_disc_eng_event_user_callback;
-void onAysncNanEventDiscEngEvent(NanDiscEngEventInd* event) {
-  const auto lock = hidl_sync_util::acquireGlobalLock();
-  if (on_nan_event_disc_eng_event_user_callback && event) {
-    on_nan_event_disc_eng_event_user_callback(*event);
-  }
-}
-
-std::function<void(const NanDisabledInd&)> on_nan_event_disabled_user_callback;
-void onAysncNanEventDisabled(NanDisabledInd* event) {
-  const auto lock = hidl_sync_util::acquireGlobalLock();
-  if (on_nan_event_disabled_user_callback && event) {
-    on_nan_event_disabled_user_callback(*event);
-  }
-}
-
-std::function<void(const NanTCAInd&)> on_nan_event_tca_user_callback;
-void onAysncNanEventTca(NanTCAInd* event) {
-  const auto lock = hidl_sync_util::acquireGlobalLock();
-  if (on_nan_event_tca_user_callback && event) {
-    on_nan_event_tca_user_callback(*event);
-  }
-}
-
-std::function<void(const NanBeaconSdfPayloadInd&)>
-    on_nan_event_beacon_sdf_payload_user_callback;
-void onAysncNanEventBeaconSdfPayload(NanBeaconSdfPayloadInd* event) {
-  const auto lock = hidl_sync_util::acquireGlobalLock();
-  if (on_nan_event_beacon_sdf_payload_user_callback && event) {
-    on_nan_event_beacon_sdf_payload_user_callback(*event);
-  }
-}
-
-std::function<void(const NanDataPathRequestInd&)>
-    on_nan_event_data_path_request_user_callback;
-void onAysncNanEventDataPathRequest(NanDataPathRequestInd* event) {
-  const auto lock = hidl_sync_util::acquireGlobalLock();
-  if (on_nan_event_data_path_request_user_callback && event) {
-    on_nan_event_data_path_request_user_callback(*event);
-  }
-}
-std::function<void(const NanDataPathConfirmInd&)>
-    on_nan_event_data_path_confirm_user_callback;
-void onAysncNanEventDataPathConfirm(NanDataPathConfirmInd* event) {
-  const auto lock = hidl_sync_util::acquireGlobalLock();
-  if (on_nan_event_data_path_confirm_user_callback && event) {
-    on_nan_event_data_path_confirm_user_callback(*event);
-  }
-}
-
-std::function<void(const NanDataPathEndInd&)>
-    on_nan_event_data_path_end_user_callback;
-void onAysncNanEventDataPathEnd(NanDataPathEndInd* event) {
-  const auto lock = hidl_sync_util::acquireGlobalLock();
-  if (on_nan_event_data_path_end_user_callback && event) {
-    on_nan_event_data_path_end_user_callback(*event);
-  }
-}
-
-std::function<void(const NanTransmitFollowupInd&)>
-    on_nan_event_transmit_follow_up_user_callback;
-void onAysncNanEventTransmitFollowUp(NanTransmitFollowupInd* event) {
-  const auto lock = hidl_sync_util::acquireGlobalLock();
-  if (on_nan_event_transmit_follow_up_user_callback && event) {
-    on_nan_event_transmit_follow_up_user_callback(*event);
-  }
-}
-
-std::function<void(const NanRangeRequestInd&)>
-    on_nan_event_range_request_user_callback;
-void onAysncNanEventRangeRequest(NanRangeRequestInd* event) {
-  const auto lock = hidl_sync_util::acquireGlobalLock();
-  if (on_nan_event_range_request_user_callback && event) {
-    on_nan_event_range_request_user_callback(*event);
-  }
-}
-
-std::function<void(const NanRangeReportInd&)>
-    on_nan_event_range_report_user_callback;
-void onAysncNanEventRangeReport(NanRangeReportInd* event) {
-  const auto lock = hidl_sync_util::acquireGlobalLock();
-  if (on_nan_event_range_report_user_callback && event) {
-    on_nan_event_range_report_user_callback(*event);
-  }
-}
-// End of the free-standing "C" style callbacks.
-
-WifiLegacyHal::WifiLegacyHal()
-    : global_handle_(nullptr),
-      wlan_interface_handle_(nullptr),
-      awaiting_event_loop_termination_(false),
-      is_started_(false) {}
-
-wifi_error WifiLegacyHal::initialize() {
-  LOG(DEBUG) << "Initialize legacy HAL";
-  // TODO: Add back the HAL Tool if we need to. All we need from the HAL tool
-  // for now is this function call which we can directly call.
-  if (!initHalFuncTableWithStubs(&global_func_table_)) {
-    LOG(ERROR) << "Failed to initialize legacy hal function table with stubs";
-    return WIFI_ERROR_UNKNOWN;
-  }
-  wifi_error status = init_wifi_vendor_hal_func_table(&global_func_table_);
-  if (status != WIFI_SUCCESS) {
-    LOG(ERROR) << "Failed to initialize legacy hal function table";
-  }
-  return status;
-}
-
-wifi_error WifiLegacyHal::start() {
-  // Ensure that we're starting in a good state.
-  CHECK(global_func_table_.wifi_initialize && !global_handle_ &&
-        !wlan_interface_handle_ && !awaiting_event_loop_termination_);
-  if (is_started_) {
-    LOG(DEBUG) << "Legacy HAL already started";
-    return WIFI_SUCCESS;
-  }
-  LOG(DEBUG) << "Starting legacy HAL";
-  if (!iface_tool_.SetWifiUpState(true)) {
-    LOG(ERROR) << "Failed to set WiFi interface up";
-    return WIFI_ERROR_UNKNOWN;
-  }
-  wifi_error status = global_func_table_.wifi_initialize(&global_handle_);
-  if (status != WIFI_SUCCESS || !global_handle_) {
-    LOG(ERROR) << "Failed to retrieve global handle";
-    return status;
-  }
-  std::thread(&WifiLegacyHal::runEventLoop, this).detach();
-  status = retrieveWlanInterfaceHandle();
-  if (status != WIFI_SUCCESS || !wlan_interface_handle_) {
-    LOG(ERROR) << "Failed to retrieve wlan interface handle";
-    return status;
-  }
-  LOG(DEBUG) << "Legacy HAL start complete";
-  is_started_ = true;
-  return WIFI_SUCCESS;
-}
-
-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";
-    on_stop_complete_user_callback();
-    return WIFI_SUCCESS;
-  }
-  LOG(DEBUG) << "Stopping legacy HAL";
-  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";
-  return WIFI_SUCCESS;
-}
-
-std::string WifiLegacyHal::getApIfaceName() {
-  // Fake name. This interface does not exist in legacy HAL
-  // API's.
-  return "ap0";
-}
-
-std::string WifiLegacyHal::getNanIfaceName() {
-  // Fake name. This interface does not exist in legacy HAL
-  // API's.
-  return "nan0";
-}
-
-std::string WifiLegacyHal::getP2pIfaceName() {
-  std::array<char, PROPERTY_VALUE_MAX> buffer;
-  property_get("wifi.direct.interface", buffer.data(), "p2p0");
-  return buffer.data();
-}
-
-std::string WifiLegacyHal::getStaIfaceName() {
-  std::array<char, PROPERTY_VALUE_MAX> buffer;
-  property_get("wifi.interface", buffer.data(), "wlan0");
-  return buffer.data();
-}
-
-std::pair<wifi_error, std::string> WifiLegacyHal::getDriverVersion() {
-  std::array<char, kMaxVersionStringLength> buffer;
-  buffer.fill(0);
-  wifi_error status = global_func_table_.wifi_get_driver_version(
-      wlan_interface_handle_, buffer.data(), buffer.size());
-  return {status, buffer.data()};
-}
-
-std::pair<wifi_error, std::string> WifiLegacyHal::getFirmwareVersion() {
-  std::array<char, kMaxVersionStringLength> buffer;
-  buffer.fill(0);
-  wifi_error status = global_func_table_.wifi_get_firmware_version(
-      wlan_interface_handle_, buffer.data(), buffer.size());
-  return {status, buffer.data()};
-}
-
-std::pair<wifi_error, std::vector<uint8_t>>
-WifiLegacyHal::requestDriverMemoryDump() {
-  std::vector<uint8_t> driver_dump;
-  on_driver_memory_dump_internal_callback = [&driver_dump](char* buffer,
-                                                           int buffer_size) {
-    driver_dump.insert(driver_dump.end(),
-                       reinterpret_cast<uint8_t*>(buffer),
-                       reinterpret_cast<uint8_t*>(buffer) + buffer_size);
-  };
-  wifi_error status = global_func_table_.wifi_get_driver_memory_dump(
-      wlan_interface_handle_, {onSyncDriverMemoryDump});
-  on_driver_memory_dump_internal_callback = nullptr;
-  return {status, std::move(driver_dump)};
-}
-
-std::pair<wifi_error, std::vector<uint8_t>>
-WifiLegacyHal::requestFirmwareMemoryDump() {
-  std::vector<uint8_t> firmware_dump;
-  on_firmware_memory_dump_internal_callback = [&firmware_dump](
-      char* buffer, int buffer_size) {
-    firmware_dump.insert(firmware_dump.end(),
-                         reinterpret_cast<uint8_t*>(buffer),
-                         reinterpret_cast<uint8_t*>(buffer) + buffer_size);
-  };
-  wifi_error status = global_func_table_.wifi_get_firmware_memory_dump(
-      wlan_interface_handle_, {onSyncFirmwareMemoryDump});
-  on_firmware_memory_dump_internal_callback = nullptr;
-  return {status, std::move(firmware_dump)};
-}
-
-std::pair<wifi_error, uint32_t> WifiLegacyHal::getSupportedFeatureSet() {
-  feature_set set;
-  static_assert(sizeof(set) == sizeof(uint32_t),
-                "Some features can not be represented in output");
-  wifi_error status = global_func_table_.wifi_get_supported_feature_set(
-      wlan_interface_handle_, &set);
-  return {status, static_cast<uint32_t>(set)};
-}
-
-std::pair<wifi_error, PacketFilterCapabilities>
-WifiLegacyHal::getPacketFilterCapabilities() {
-  PacketFilterCapabilities caps;
-  wifi_error status = global_func_table_.wifi_get_packet_filter_capabilities(
-      wlan_interface_handle_, &caps.version, &caps.max_len);
-  return {status, caps};
-}
-
-wifi_error WifiLegacyHal::setPacketFilter(const std::vector<uint8_t>& program) {
-  return global_func_table_.wifi_set_packet_filter(
-      wlan_interface_handle_, program.data(), program.size());
-}
-
-std::pair<wifi_error, wifi_gscan_capabilities>
-WifiLegacyHal::getGscanCapabilities() {
-  wifi_gscan_capabilities caps;
-  wifi_error status = global_func_table_.wifi_get_gscan_capabilities(
-      wlan_interface_handle_, &caps);
-  return {status, caps};
-}
-
-wifi_error WifiLegacyHal::startGscan(
-    wifi_request_id id,
-    const wifi_scan_cmd_params& params,
-    const std::function<void(wifi_request_id)>& on_failure_user_callback,
-    const on_gscan_results_callback& on_results_user_callback,
-    const on_gscan_full_result_callback& on_full_result_user_callback) {
-  // If there is already an ongoing background scan, reject new scan requests.
-  if (on_gscan_event_internal_callback ||
-      on_gscan_full_result_internal_callback) {
-    return WIFI_ERROR_NOT_AVAILABLE;
-  }
-
-  // This callback will be used to either trigger |on_results_user_callback| or
-  // |on_failure_user_callback|.
-  on_gscan_event_internal_callback =
-      [on_failure_user_callback, on_results_user_callback, this](
-          wifi_request_id id, wifi_scan_event event) {
-        switch (event) {
-          case WIFI_SCAN_RESULTS_AVAILABLE:
-          case WIFI_SCAN_THRESHOLD_NUM_SCANS:
-          case WIFI_SCAN_THRESHOLD_PERCENT: {
-            wifi_error status;
-            std::vector<wifi_cached_scan_results> cached_scan_results;
-            std::tie(status, cached_scan_results) = getGscanCachedResults();
-            if (status == WIFI_SUCCESS) {
-              on_results_user_callback(id, cached_scan_results);
-              return;
-            }
-          }
-          // Fall through if failed. Failure to retrieve cached scan results
-          // should trigger a background scan failure.
-          case WIFI_SCAN_FAILED:
-            on_failure_user_callback(id);
-            on_gscan_event_internal_callback = nullptr;
-            on_gscan_full_result_internal_callback = nullptr;
-            return;
-        }
-        LOG(FATAL) << "Unexpected gscan event received: " << event;
-      };
-
-  on_gscan_full_result_internal_callback = [on_full_result_user_callback](
-      wifi_request_id id, wifi_scan_result* result, uint32_t buckets_scanned) {
-    if (result) {
-      on_full_result_user_callback(id, result, buckets_scanned);
-    }
-  };
-
-  wifi_scan_result_handler handler = {onAsyncGscanFullResult,
-                                      onAsyncGscanEvent};
-  wifi_error status = global_func_table_.wifi_start_gscan(
-      id, wlan_interface_handle_, params, handler);
-  if (status != WIFI_SUCCESS) {
-    on_gscan_event_internal_callback = nullptr;
-    on_gscan_full_result_internal_callback = nullptr;
-  }
-  return status;
-}
-
-wifi_error WifiLegacyHal::stopGscan(wifi_request_id id) {
-  // If there is no an ongoing background scan, reject stop requests.
-  // TODO(b/32337212): This needs to be handled by the HIDL object because we
-  // need to return the NOT_STARTED error code.
-  if (!on_gscan_event_internal_callback &&
-      !on_gscan_full_result_internal_callback) {
-    return WIFI_ERROR_NOT_AVAILABLE;
-  }
-  wifi_error status =
-      global_func_table_.wifi_stop_gscan(id, wlan_interface_handle_);
-  // If the request Id is wrong, don't stop the ongoing background scan. Any
-  // other error should be treated as the end of background scan.
-  if (status != WIFI_ERROR_INVALID_REQUEST_ID) {
-    on_gscan_event_internal_callback = nullptr;
-    on_gscan_full_result_internal_callback = nullptr;
-  }
-  return status;
-}
-
-std::pair<wifi_error, std::vector<uint32_t>>
-WifiLegacyHal::getValidFrequenciesForBand(wifi_band band) {
-  static_assert(sizeof(uint32_t) >= sizeof(wifi_channel),
-                "Wifi Channel cannot be represented in output");
-  std::vector<uint32_t> freqs;
-  freqs.resize(kMaxGscanFrequenciesForBand);
-  int32_t num_freqs = 0;
-  wifi_error status = global_func_table_.wifi_get_valid_channels(
-      wlan_interface_handle_,
-      band,
-      freqs.size(),
-      reinterpret_cast<wifi_channel*>(freqs.data()),
-      &num_freqs);
-  CHECK(num_freqs >= 0 &&
-        static_cast<uint32_t>(num_freqs) <= kMaxGscanFrequenciesForBand);
-  freqs.resize(num_freqs);
-  return {status, std::move(freqs)};
-}
-
-wifi_error WifiLegacyHal::setDfsFlag(bool dfs_on) {
-  return global_func_table_.wifi_set_nodfs_flag(
-      wlan_interface_handle_, dfs_on ? 0 : 1);
-}
-
-wifi_error WifiLegacyHal::enableLinkLayerStats(bool debug) {
-  wifi_link_layer_params params;
-  params.mpdu_size_threshold = kLinkLayerStatsDataMpduSizeThreshold;
-  params.aggressive_statistics_gathering = debug;
-  return global_func_table_.wifi_set_link_stats(wlan_interface_handle_, params);
-}
-
-wifi_error WifiLegacyHal::disableLinkLayerStats() {
-  // TODO: Do we care about these responses?
-  uint32_t clear_mask_rsp;
-  uint8_t stop_rsp;
-  return global_func_table_.wifi_clear_link_stats(
-      wlan_interface_handle_, 0xFFFFFFFF, &clear_mask_rsp, 1, &stop_rsp);
-}
-
-std::pair<wifi_error, LinkLayerStats> WifiLegacyHal::getLinkLayerStats() {
-  LinkLayerStats link_stats{};
-  LinkLayerStats* link_stats_ptr = &link_stats;
-
-  on_link_layer_stats_result_internal_callback =
-      [&link_stats_ptr](wifi_request_id /* id */,
-                        wifi_iface_stat* iface_stats_ptr,
-                        int num_radios,
-                        wifi_radio_stat* radio_stats_ptr) {
-        if (iface_stats_ptr != nullptr) {
-          link_stats_ptr->iface = *iface_stats_ptr;
-          link_stats_ptr->iface.num_peers = 0;
-        } else {
-          LOG(ERROR) << "Invalid iface stats in link layer stats";
-        }
-        if (num_radios <= 0 || radio_stats_ptr == nullptr) {
-          LOG(ERROR) << "Invalid radio stats in link layer stats";
-          return;
-        }
-        for (int i = 0; i < num_radios; i++) {
-          LinkLayerRadioStats radio;
-          radio.stats = radio_stats_ptr[i];
-          // Copy over the tx level array to the separate vector.
-          if (radio_stats_ptr[i].num_tx_levels > 0 &&
-              radio_stats_ptr[i].tx_time_per_levels != nullptr) {
-            radio.tx_time_per_levels.assign(
-                radio_stats_ptr[i].tx_time_per_levels,
-                radio_stats_ptr[i].tx_time_per_levels +
-                    radio_stats_ptr[i].num_tx_levels);
-          }
-          radio.stats.num_tx_levels = 0;
-          radio.stats.tx_time_per_levels = nullptr;
-          link_stats_ptr->radios.push_back(radio);
-        }
-      };
-
-  wifi_error status = global_func_table_.wifi_get_link_stats(
-      0, wlan_interface_handle_, {onSyncLinkLayerStatsResult});
-  on_link_layer_stats_result_internal_callback = nullptr;
-  return {status, link_stats};
-}
-
-wifi_error WifiLegacyHal::startRssiMonitoring(
-    wifi_request_id id,
-    int8_t max_rssi,
-    int8_t min_rssi,
-    const on_rssi_threshold_breached_callback&
-        on_threshold_breached_user_callback) {
-  if (on_rssi_threshold_breached_internal_callback) {
-    return WIFI_ERROR_NOT_AVAILABLE;
-  }
-  on_rssi_threshold_breached_internal_callback =
-      [on_threshold_breached_user_callback](
-          wifi_request_id id, uint8_t* bssid_ptr, int8_t rssi) {
-        if (!bssid_ptr) {
-          return;
-        }
-        std::array<uint8_t, 6> bssid_arr;
-        // |bssid_ptr| pointer is assumed to have 6 bytes for the mac address.
-        std::copy(bssid_ptr, bssid_ptr + 6, std::begin(bssid_arr));
-        on_threshold_breached_user_callback(id, bssid_arr, rssi);
-      };
-  wifi_error status = global_func_table_.wifi_start_rssi_monitoring(
-      id,
-      wlan_interface_handle_,
-      max_rssi,
-      min_rssi,
-      {onAsyncRssiThresholdBreached});
-  if (status != WIFI_SUCCESS) {
-    on_rssi_threshold_breached_internal_callback = nullptr;
-  }
-  return status;
-}
-
-wifi_error WifiLegacyHal::stopRssiMonitoring(wifi_request_id id) {
-  if (!on_rssi_threshold_breached_internal_callback) {
-    return WIFI_ERROR_NOT_AVAILABLE;
-  }
-  wifi_error status =
-      global_func_table_.wifi_stop_rssi_monitoring(id, wlan_interface_handle_);
-  // If the request Id is wrong, don't stop the ongoing rssi monitoring. Any
-  // other error should be treated as the end of background scan.
-  if (status != WIFI_ERROR_INVALID_REQUEST_ID) {
-    on_rssi_threshold_breached_internal_callback = nullptr;
-  }
-  return status;
-}
-
-std::pair<wifi_error, wifi_roaming_capabilities>
-WifiLegacyHal::getRoamingCapabilities() {
-  wifi_roaming_capabilities caps;
-  wifi_error status = global_func_table_.wifi_get_roaming_capabilities(
-      wlan_interface_handle_, &caps);
-  return {status, caps};
-}
-
-wifi_error WifiLegacyHal::configureRoaming(const wifi_roaming_config& config) {
-  wifi_roaming_config config_internal = config;
-  return global_func_table_.wifi_configure_roaming(wlan_interface_handle_,
-                                                   &config_internal);
-}
-
-wifi_error WifiLegacyHal::enableFirmwareRoaming(fw_roaming_state_t state) {
-  return global_func_table_.wifi_enable_firmware_roaming(wlan_interface_handle_,
-                                                         state);
-}
-
-wifi_error WifiLegacyHal::configureNdOffload(bool enable) {
-  return global_func_table_.wifi_configure_nd_offload(wlan_interface_handle_,
-                                                      enable);
-}
-
-wifi_error WifiLegacyHal::startSendingOffloadedPacket(
-    uint32_t cmd_id,
-    const std::vector<uint8_t>& ip_packet_data,
-    const std::array<uint8_t, 6>& src_address,
-    const std::array<uint8_t, 6>& dst_address,
-    uint32_t period_in_ms) {
-  std::vector<uint8_t> ip_packet_data_internal(ip_packet_data);
-  std::vector<uint8_t> src_address_internal(
-      src_address.data(), src_address.data() + src_address.size());
-  std::vector<uint8_t> dst_address_internal(
-      dst_address.data(), dst_address.data() + dst_address.size());
-  return global_func_table_.wifi_start_sending_offloaded_packet(
-      cmd_id,
-      wlan_interface_handle_,
-      ip_packet_data_internal.data(),
-      ip_packet_data_internal.size(),
-      src_address_internal.data(),
-      dst_address_internal.data(),
-      period_in_ms);
-}
-
-wifi_error WifiLegacyHal::stopSendingOffloadedPacket(uint32_t cmd_id) {
-  return global_func_table_.wifi_stop_sending_offloaded_packet(
-      cmd_id, wlan_interface_handle_);
-}
-
-wifi_error WifiLegacyHal::setScanningMacOui(const std::array<uint8_t, 3>& oui) {
-  std::vector<uint8_t> oui_internal(oui.data(), oui.data() + oui.size());
-  return global_func_table_.wifi_set_scanning_mac_oui(wlan_interface_handle_,
-                                                      oui_internal.data());
-}
-
-wifi_error WifiLegacyHal::selectTxPowerScenario(wifi_power_scenario scenario) {
-  return global_func_table_.wifi_select_tx_power_scenario(
-      wlan_interface_handle_, scenario);
-}
-
-wifi_error WifiLegacyHal::resetTxPowerScenario() {
-  return global_func_table_.wifi_reset_tx_power_scenario(wlan_interface_handle_);
-}
-
-std::pair<wifi_error, uint32_t> WifiLegacyHal::getLoggerSupportedFeatureSet() {
-  uint32_t supported_features;
-  wifi_error status = global_func_table_.wifi_get_logger_supported_feature_set(
-      wlan_interface_handle_, &supported_features);
-  return {status, supported_features};
-}
-
-wifi_error WifiLegacyHal::startPktFateMonitoring() {
-  return global_func_table_.wifi_start_pkt_fate_monitoring(
-      wlan_interface_handle_);
-}
-
-std::pair<wifi_error, std::vector<wifi_tx_report>>
-WifiLegacyHal::getTxPktFates() {
-  std::vector<wifi_tx_report> tx_pkt_fates;
-  tx_pkt_fates.resize(MAX_FATE_LOG_LEN);
-  size_t num_fates = 0;
-  wifi_error status =
-      global_func_table_.wifi_get_tx_pkt_fates(wlan_interface_handle_,
-                                               tx_pkt_fates.data(),
-                                               tx_pkt_fates.size(),
-                                               &num_fates);
-  CHECK(num_fates <= MAX_FATE_LOG_LEN);
-  tx_pkt_fates.resize(num_fates);
-  return {status, std::move(tx_pkt_fates)};
-}
-
-std::pair<wifi_error, std::vector<wifi_rx_report>>
-WifiLegacyHal::getRxPktFates() {
-  std::vector<wifi_rx_report> rx_pkt_fates;
-  rx_pkt_fates.resize(MAX_FATE_LOG_LEN);
-  size_t num_fates = 0;
-  wifi_error status =
-      global_func_table_.wifi_get_rx_pkt_fates(wlan_interface_handle_,
-                                               rx_pkt_fates.data(),
-                                               rx_pkt_fates.size(),
-                                               &num_fates);
-  CHECK(num_fates <= MAX_FATE_LOG_LEN);
-  rx_pkt_fates.resize(num_fates);
-  return {status, std::move(rx_pkt_fates)};
-}
-
-std::pair<wifi_error, WakeReasonStats> WifiLegacyHal::getWakeReasonStats() {
-  WakeReasonStats stats;
-  stats.cmd_event_wake_cnt.resize(kMaxWakeReasonStatsArraySize);
-  stats.driver_fw_local_wake_cnt.resize(kMaxWakeReasonStatsArraySize);
-
-  // This legacy struct needs separate memory to store the variable sized wake
-  // reason types.
-  stats.wake_reason_cnt.cmd_event_wake_cnt =
-      reinterpret_cast<int32_t*>(stats.cmd_event_wake_cnt.data());
-  stats.wake_reason_cnt.cmd_event_wake_cnt_sz = stats.cmd_event_wake_cnt.size();
-  stats.wake_reason_cnt.cmd_event_wake_cnt_used = 0;
-  stats.wake_reason_cnt.driver_fw_local_wake_cnt =
-      reinterpret_cast<int32_t*>(stats.driver_fw_local_wake_cnt.data());
-  stats.wake_reason_cnt.driver_fw_local_wake_cnt_sz =
-      stats.driver_fw_local_wake_cnt.size();
-  stats.wake_reason_cnt.driver_fw_local_wake_cnt_used = 0;
-
-  wifi_error status = global_func_table_.wifi_get_wake_reason_stats(
-      wlan_interface_handle_, &stats.wake_reason_cnt);
-
-  CHECK(stats.wake_reason_cnt.cmd_event_wake_cnt_used >= 0 &&
-        static_cast<uint32_t>(stats.wake_reason_cnt.cmd_event_wake_cnt_used) <=
-            kMaxWakeReasonStatsArraySize);
-  stats.cmd_event_wake_cnt.resize(
-      stats.wake_reason_cnt.cmd_event_wake_cnt_used);
-  stats.wake_reason_cnt.cmd_event_wake_cnt = nullptr;
-
-  CHECK(stats.wake_reason_cnt.driver_fw_local_wake_cnt_used >= 0 &&
-        static_cast<uint32_t>(
-            stats.wake_reason_cnt.driver_fw_local_wake_cnt_used) <=
-            kMaxWakeReasonStatsArraySize);
-  stats.driver_fw_local_wake_cnt.resize(
-      stats.wake_reason_cnt.driver_fw_local_wake_cnt_used);
-  stats.wake_reason_cnt.driver_fw_local_wake_cnt = nullptr;
-
-  return {status, stats};
-}
-
-wifi_error WifiLegacyHal::registerRingBufferCallbackHandler(
-    const on_ring_buffer_data_callback& on_user_data_callback) {
-  if (on_ring_buffer_data_internal_callback) {
-    return WIFI_ERROR_NOT_AVAILABLE;
-  }
-  on_ring_buffer_data_internal_callback = [on_user_data_callback](
-      char* ring_name,
-      char* buffer,
-      int buffer_size,
-      wifi_ring_buffer_status* status) {
-    if (status && buffer) {
-      std::vector<uint8_t> buffer_vector(
-          reinterpret_cast<uint8_t*>(buffer),
-          reinterpret_cast<uint8_t*>(buffer) + buffer_size);
-      on_user_data_callback(ring_name, buffer_vector, *status);
-    }
-  };
-  wifi_error status = global_func_table_.wifi_set_log_handler(
-      0, wlan_interface_handle_, {onAsyncRingBufferData});
-  if (status != WIFI_SUCCESS) {
-    on_ring_buffer_data_internal_callback = nullptr;
-  }
-  return status;
-}
-
-wifi_error WifiLegacyHal::deregisterRingBufferCallbackHandler() {
-  if (!on_ring_buffer_data_internal_callback) {
-    return WIFI_ERROR_NOT_AVAILABLE;
-  }
-  on_ring_buffer_data_internal_callback = nullptr;
-  return global_func_table_.wifi_reset_log_handler(0, wlan_interface_handle_);
-}
-
-std::pair<wifi_error, std::vector<wifi_ring_buffer_status>>
-WifiLegacyHal::getRingBuffersStatus() {
-  std::vector<wifi_ring_buffer_status> ring_buffers_status;
-  ring_buffers_status.resize(kMaxRingBuffers);
-  uint32_t num_rings = kMaxRingBuffers;
-  wifi_error status = global_func_table_.wifi_get_ring_buffers_status(
-      wlan_interface_handle_, &num_rings, ring_buffers_status.data());
-  CHECK(num_rings <= kMaxRingBuffers);
-  ring_buffers_status.resize(num_rings);
-  return {status, std::move(ring_buffers_status)};
-}
-
-wifi_error WifiLegacyHal::startRingBufferLogging(const std::string& ring_name,
-                                                 uint32_t verbose_level,
-                                                 uint32_t max_interval_sec,
-                                                 uint32_t min_data_size) {
-  return global_func_table_.wifi_start_logging(wlan_interface_handle_,
-                                               verbose_level,
-                                               0,
-                                               max_interval_sec,
-                                               min_data_size,
-                                               makeCharVec(ring_name).data());
-}
-
-wifi_error WifiLegacyHal::getRingBufferData(const std::string& ring_name) {
-  return global_func_table_.wifi_get_ring_data(wlan_interface_handle_,
-                                               makeCharVec(ring_name).data());
-}
-
-wifi_error WifiLegacyHal::registerErrorAlertCallbackHandler(
-    const on_error_alert_callback& on_user_alert_callback) {
-  if (on_error_alert_internal_callback) {
-    return WIFI_ERROR_NOT_AVAILABLE;
-  }
-  on_error_alert_internal_callback = [on_user_alert_callback](
-      wifi_request_id id, char* buffer, int buffer_size, int err_code) {
-    if (buffer) {
-      CHECK(id == 0);
-      on_user_alert_callback(
-          err_code,
-          std::vector<uint8_t>(
-              reinterpret_cast<uint8_t*>(buffer),
-              reinterpret_cast<uint8_t*>(buffer) + buffer_size));
-    }
-  };
-  wifi_error status = global_func_table_.wifi_set_alert_handler(
-      0, wlan_interface_handle_, {onAsyncErrorAlert});
-  if (status != WIFI_SUCCESS) {
-    on_error_alert_internal_callback = nullptr;
-  }
-  return status;
-}
-
-wifi_error WifiLegacyHal::deregisterErrorAlertCallbackHandler() {
-  if (!on_error_alert_internal_callback) {
-    return WIFI_ERROR_NOT_AVAILABLE;
-  }
-  on_error_alert_internal_callback = nullptr;
-  return global_func_table_.wifi_reset_alert_handler(0, wlan_interface_handle_);
-}
-
-wifi_error WifiLegacyHal::startRttRangeRequest(
-    wifi_request_id id,
-    const std::vector<wifi_rtt_config>& rtt_configs,
-    const on_rtt_results_callback& on_results_user_callback) {
-  if (on_rtt_results_internal_callback) {
-    return WIFI_ERROR_NOT_AVAILABLE;
-  }
-
-  on_rtt_results_internal_callback = [on_results_user_callback](
-      wifi_request_id id,
-      unsigned num_results,
-      wifi_rtt_result* rtt_results[]) {
-    if (num_results > 0 && !rtt_results) {
-      LOG(ERROR) << "Unexpected nullptr in RTT results";
-      return;
-    }
-    std::vector<const wifi_rtt_result*> rtt_results_vec;
-    std::copy_if(
-        rtt_results,
-        rtt_results + num_results,
-        back_inserter(rtt_results_vec),
-        [](wifi_rtt_result* rtt_result) { return rtt_result != nullptr; });
-    on_results_user_callback(id, rtt_results_vec);
-  };
-
-  std::vector<wifi_rtt_config> rtt_configs_internal(rtt_configs);
-  wifi_error status =
-      global_func_table_.wifi_rtt_range_request(id,
-                                                wlan_interface_handle_,
-                                                rtt_configs.size(),
-                                                rtt_configs_internal.data(),
-                                                {onAsyncRttResults});
-  if (status != WIFI_SUCCESS) {
-    on_rtt_results_internal_callback = nullptr;
-  }
-  return status;
-}
-
-wifi_error WifiLegacyHal::cancelRttRangeRequest(
-    wifi_request_id id, const std::vector<std::array<uint8_t, 6>>& mac_addrs) {
-  if (!on_rtt_results_internal_callback) {
-    return WIFI_ERROR_NOT_AVAILABLE;
-  }
-  static_assert(sizeof(mac_addr) == sizeof(std::array<uint8_t, 6>),
-                "MAC address size mismatch");
-  // TODO: How do we handle partial cancels (i.e only a subset of enabled mac
-  // addressed are cancelled).
-  std::vector<std::array<uint8_t, 6>> mac_addrs_internal(mac_addrs);
-  wifi_error status = global_func_table_.wifi_rtt_range_cancel(
-      id,
-      wlan_interface_handle_,
-      mac_addrs.size(),
-      reinterpret_cast<mac_addr*>(mac_addrs_internal.data()));
-  // If the request Id is wrong, don't stop the ongoing range request. Any
-  // other error should be treated as the end of rtt ranging.
-  if (status != WIFI_ERROR_INVALID_REQUEST_ID) {
-    on_rtt_results_internal_callback = nullptr;
-  }
-  return status;
-}
-
-std::pair<wifi_error, wifi_rtt_capabilities>
-WifiLegacyHal::getRttCapabilities() {
-  wifi_rtt_capabilities rtt_caps;
-  wifi_error status = global_func_table_.wifi_get_rtt_capabilities(
-      wlan_interface_handle_, &rtt_caps);
-  return {status, rtt_caps};
-}
-
-std::pair<wifi_error, wifi_rtt_responder> WifiLegacyHal::getRttResponderInfo() {
-  wifi_rtt_responder rtt_responder;
-  wifi_error status = global_func_table_.wifi_rtt_get_responder_info(
-      wlan_interface_handle_, &rtt_responder);
-  return {status, rtt_responder};
-}
-
-wifi_error WifiLegacyHal::enableRttResponder(
-    wifi_request_id id,
-    const wifi_channel_info& channel_hint,
-    uint32_t max_duration_secs,
-    const wifi_rtt_responder& info) {
-  wifi_rtt_responder info_internal(info);
-  return global_func_table_.wifi_enable_responder(id,
-                                                  wlan_interface_handle_,
-                                                  channel_hint,
-                                                  max_duration_secs,
-                                                  &info_internal);
-}
-
-wifi_error WifiLegacyHal::disableRttResponder(wifi_request_id id) {
-  return global_func_table_.wifi_disable_responder(id, wlan_interface_handle_);
-}
-
-wifi_error WifiLegacyHal::setRttLci(wifi_request_id id,
-                                    const wifi_lci_information& info) {
-  wifi_lci_information info_internal(info);
-  return global_func_table_.wifi_set_lci(
-      id, wlan_interface_handle_, &info_internal);
-}
-
-wifi_error WifiLegacyHal::setRttLcr(wifi_request_id id,
-                                    const wifi_lcr_information& info) {
-  wifi_lcr_information info_internal(info);
-  return global_func_table_.wifi_set_lcr(
-      id, wlan_interface_handle_, &info_internal);
-}
-
-wifi_error WifiLegacyHal::nanRegisterCallbackHandlers(
-    const NanCallbackHandlers& user_callbacks) {
-  on_nan_notify_response_user_callback = user_callbacks.on_notify_response;
-  on_nan_event_publish_terminated_user_callback =
-      user_callbacks.on_event_publish_terminated;
-  on_nan_event_match_user_callback = user_callbacks.on_event_match;
-  on_nan_event_match_expired_user_callback =
-      user_callbacks.on_event_match_expired;
-  on_nan_event_subscribe_terminated_user_callback =
-      user_callbacks.on_event_subscribe_terminated;
-  on_nan_event_followup_user_callback = user_callbacks.on_event_followup;
-  on_nan_event_disc_eng_event_user_callback =
-      user_callbacks.on_event_disc_eng_event;
-  on_nan_event_disabled_user_callback = user_callbacks.on_event_disabled;
-  on_nan_event_tca_user_callback = user_callbacks.on_event_tca;
-  on_nan_event_beacon_sdf_payload_user_callback =
-      user_callbacks.on_event_beacon_sdf_payload;
-  on_nan_event_data_path_request_user_callback =
-      user_callbacks.on_event_data_path_request;
-  on_nan_event_data_path_confirm_user_callback =
-      user_callbacks.on_event_data_path_confirm;
-  on_nan_event_data_path_end_user_callback =
-      user_callbacks.on_event_data_path_end;
-  on_nan_event_transmit_follow_up_user_callback =
-      user_callbacks.on_event_transmit_follow_up;
-  on_nan_event_range_request_user_callback =
-      user_callbacks.on_event_range_request;
-  on_nan_event_range_report_user_callback =
-      user_callbacks.on_event_range_report;
-
-  return global_func_table_.wifi_nan_register_handler(
-      wlan_interface_handle_,
-      {onAysncNanNotifyResponse,
-       onAysncNanEventPublishReplied,
-       onAysncNanEventPublishTerminated,
-       onAysncNanEventMatch,
-       onAysncNanEventMatchExpired,
-       onAysncNanEventSubscribeTerminated,
-       onAysncNanEventFollowup,
-       onAysncNanEventDiscEngEvent,
-       onAysncNanEventDisabled,
-       onAysncNanEventTca,
-       onAysncNanEventBeaconSdfPayload,
-       onAysncNanEventDataPathRequest,
-       onAysncNanEventDataPathConfirm,
-       onAysncNanEventDataPathEnd,
-       onAysncNanEventTransmitFollowUp,
-       onAysncNanEventRangeRequest,
-       onAysncNanEventRangeReport});
-}
-
-wifi_error WifiLegacyHal::nanEnableRequest(transaction_id id,
-                                           const NanEnableRequest& msg) {
-  NanEnableRequest msg_internal(msg);
-  return global_func_table_.wifi_nan_enable_request(
-      id, wlan_interface_handle_, &msg_internal);
-}
-
-wifi_error WifiLegacyHal::nanDisableRequest(transaction_id id) {
-  return global_func_table_.wifi_nan_disable_request(id,
-                                                     wlan_interface_handle_);
-}
-
-wifi_error WifiLegacyHal::nanPublishRequest(transaction_id id,
-                                            const NanPublishRequest& msg) {
-  NanPublishRequest msg_internal(msg);
-  return global_func_table_.wifi_nan_publish_request(
-      id, wlan_interface_handle_, &msg_internal);
-}
-
-wifi_error WifiLegacyHal::nanPublishCancelRequest(
-    transaction_id id, const NanPublishCancelRequest& msg) {
-  NanPublishCancelRequest msg_internal(msg);
-  return global_func_table_.wifi_nan_publish_cancel_request(
-      id, wlan_interface_handle_, &msg_internal);
-}
-
-wifi_error WifiLegacyHal::nanSubscribeRequest(transaction_id id,
-                                              const NanSubscribeRequest& msg) {
-  NanSubscribeRequest msg_internal(msg);
-  return global_func_table_.wifi_nan_subscribe_request(
-      id, wlan_interface_handle_, &msg_internal);
-}
-
-wifi_error WifiLegacyHal::nanSubscribeCancelRequest(
-    transaction_id id, const NanSubscribeCancelRequest& msg) {
-  NanSubscribeCancelRequest msg_internal(msg);
-  return global_func_table_.wifi_nan_subscribe_cancel_request(
-      id, wlan_interface_handle_, &msg_internal);
-}
-
-wifi_error WifiLegacyHal::nanTransmitFollowupRequest(
-    transaction_id id, const NanTransmitFollowupRequest& msg) {
-  NanTransmitFollowupRequest msg_internal(msg);
-  return global_func_table_.wifi_nan_transmit_followup_request(
-      id, wlan_interface_handle_, &msg_internal);
-}
-
-wifi_error WifiLegacyHal::nanStatsRequest(transaction_id id,
-                                          const NanStatsRequest& msg) {
-  NanStatsRequest msg_internal(msg);
-  return global_func_table_.wifi_nan_stats_request(
-      id, wlan_interface_handle_, &msg_internal);
-}
-
-wifi_error WifiLegacyHal::nanConfigRequest(transaction_id id,
-                                           const NanConfigRequest& msg) {
-  NanConfigRequest msg_internal(msg);
-  return global_func_table_.wifi_nan_config_request(
-      id, wlan_interface_handle_, &msg_internal);
-}
-
-wifi_error WifiLegacyHal::nanTcaRequest(transaction_id id,
-                                        const NanTCARequest& msg) {
-  NanTCARequest msg_internal(msg);
-  return global_func_table_.wifi_nan_tca_request(
-      id, wlan_interface_handle_, &msg_internal);
-}
-
-wifi_error WifiLegacyHal::nanBeaconSdfPayloadRequest(
-    transaction_id id, const NanBeaconSdfPayloadRequest& msg) {
-  NanBeaconSdfPayloadRequest msg_internal(msg);
-  return global_func_table_.wifi_nan_beacon_sdf_payload_request(
-      id, wlan_interface_handle_, &msg_internal);
-}
-
-std::pair<wifi_error, NanVersion> WifiLegacyHal::nanGetVersion() {
-  NanVersion version;
-  wifi_error status =
-      global_func_table_.wifi_nan_get_version(global_handle_, &version);
-  return {status, version};
-}
-
-wifi_error WifiLegacyHal::nanGetCapabilities(transaction_id id) {
-  return global_func_table_.wifi_nan_get_capabilities(id,
-                                                      wlan_interface_handle_);
-}
-
-wifi_error WifiLegacyHal::nanDataInterfaceCreate(
-    transaction_id id, const std::string& iface_name) {
-  return global_func_table_.wifi_nan_data_interface_create(
-      id, wlan_interface_handle_, makeCharVec(iface_name).data());
-}
-
-wifi_error WifiLegacyHal::nanDataInterfaceDelete(
-    transaction_id id, const std::string& iface_name) {
-  return global_func_table_.wifi_nan_data_interface_delete(
-      id, wlan_interface_handle_, makeCharVec(iface_name).data());
-}
-
-wifi_error WifiLegacyHal::nanDataRequestInitiator(
-    transaction_id id, const NanDataPathInitiatorRequest& msg) {
-  NanDataPathInitiatorRequest msg_internal(msg);
-  return global_func_table_.wifi_nan_data_request_initiator(
-      id, wlan_interface_handle_, &msg_internal);
-}
-
-wifi_error WifiLegacyHal::nanDataIndicationResponse(
-    transaction_id id, const NanDataPathIndicationResponse& msg) {
-  NanDataPathIndicationResponse msg_internal(msg);
-  return global_func_table_.wifi_nan_data_indication_response(
-      id, wlan_interface_handle_, &msg_internal);
-}
-
-typedef struct {
-    u8 num_ndp_instances;
-    NanDataPathId ndp_instance_id;
-} NanDataPathEndSingleNdpIdRequest;
-
-wifi_error WifiLegacyHal::nanDataEnd(transaction_id id,
-                                     uint32_t ndpInstanceId) {
-  NanDataPathEndSingleNdpIdRequest msg;
-  msg.num_ndp_instances = 1;
-  msg.ndp_instance_id = ndpInstanceId;
-  wifi_error status = global_func_table_.wifi_nan_data_end(
-      id, wlan_interface_handle_, (NanDataPathEndRequest*)&msg);
-  return status;
-}
-
-wifi_error WifiLegacyHal::setCountryCode(std::array<int8_t, 2> code) {
-  std::string code_str(code.data(), code.data() + code.size());
-  return global_func_table_.wifi_set_country_code(wlan_interface_handle_,
-                                                  code_str.c_str());
-}
-
-wifi_error WifiLegacyHal::retrieveWlanInterfaceHandle() {
-  const std::string& ifname_to_find = getStaIfaceName();
-  wifi_interface_handle* iface_handles = nullptr;
-  int num_iface_handles = 0;
-  wifi_error status = global_func_table_.wifi_get_ifaces(
-      global_handle_, &num_iface_handles, &iface_handles);
-  if (status != WIFI_SUCCESS) {
-    LOG(ERROR) << "Failed to enumerate interface handles";
-    return status;
-  }
-  for (int i = 0; i < num_iface_handles; ++i) {
-    std::array<char, IFNAMSIZ> current_ifname;
-    current_ifname.fill(0);
-    status = global_func_table_.wifi_get_iface_name(
-        iface_handles[i], current_ifname.data(), current_ifname.size());
-    if (status != WIFI_SUCCESS) {
-      LOG(WARNING) << "Failed to get interface handle name";
-      continue;
-    }
-    if (ifname_to_find == current_ifname.data()) {
-      wlan_interface_handle_ = iface_handles[i];
-      return WIFI_SUCCESS;
-    }
-  }
-  return WIFI_ERROR_UNKNOWN;
-}
-
-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>>
-WifiLegacyHal::getGscanCachedResults() {
-  std::vector<wifi_cached_scan_results> cached_scan_results;
-  cached_scan_results.resize(kMaxCachedGscanResults);
-  int32_t num_results = 0;
-  wifi_error status = global_func_table_.wifi_get_cached_gscan_results(
-      wlan_interface_handle_,
-      true /* always flush */,
-      cached_scan_results.size(),
-      cached_scan_results.data(),
-      &num_results);
-  CHECK(num_results >= 0 &&
-        static_cast<uint32_t>(num_results) <= kMaxCachedGscanResults);
-  cached_scan_results.resize(num_results);
-  // Check for invalid IE lengths in these cached scan results and correct it.
-  for (auto& cached_scan_result : cached_scan_results) {
-    int num_scan_results = cached_scan_result.num_results;
-    for (int i = 0; i < num_scan_results; i++) {
-      auto& scan_result = cached_scan_result.results[i];
-      if (scan_result.ie_length > 0) {
-        LOG(DEBUG) << "Cached scan result has non-zero IE length "
-                   << scan_result.ie_length;
-        scan_result.ie_length = 0;
-      }
-    }
-  }
-  return {status, std::move(cached_scan_results)};
-}
-
-void WifiLegacyHal::invalidate() {
-  global_handle_ = nullptr;
-  wlan_interface_handle_ = nullptr;
-  on_driver_memory_dump_internal_callback = nullptr;
-  on_firmware_memory_dump_internal_callback = nullptr;
-  on_gscan_event_internal_callback = nullptr;
-  on_gscan_full_result_internal_callback = nullptr;
-  on_link_layer_stats_result_internal_callback = nullptr;
-  on_rssi_threshold_breached_internal_callback = nullptr;
-  on_ring_buffer_data_internal_callback = nullptr;
-  on_error_alert_internal_callback = nullptr;
-  on_rtt_results_internal_callback = nullptr;
-  on_nan_notify_response_user_callback = nullptr;
-  on_nan_event_publish_terminated_user_callback = nullptr;
-  on_nan_event_match_user_callback = nullptr;
-  on_nan_event_match_expired_user_callback = nullptr;
-  on_nan_event_subscribe_terminated_user_callback = nullptr;
-  on_nan_event_followup_user_callback = nullptr;
-  on_nan_event_disc_eng_event_user_callback = nullptr;
-  on_nan_event_disabled_user_callback = nullptr;
-  on_nan_event_tca_user_callback = nullptr;
-  on_nan_event_beacon_sdf_payload_user_callback = nullptr;
-  on_nan_event_data_path_request_user_callback = nullptr;
-  on_nan_event_data_path_confirm_user_callback = nullptr;
-  on_nan_event_data_path_end_user_callback = nullptr;
-  on_nan_event_transmit_follow_up_user_callback = nullptr;
-  on_nan_event_range_request_user_callback = nullptr;
-  on_nan_event_range_report_user_callback = nullptr;
-}
-
-}  // namespace legacy_hal
-}  // namespace implementation
-}  // namespace V1_1
-}  // namespace wifi
-}  // namespace hardware
-}  // namespace android
diff --git a/wifi/1.1/default/wifi_legacy_hal.h b/wifi/1.1/default/wifi_legacy_hal.h
deleted file mode 100644
index 5498803..0000000
--- a/wifi/1.1/default/wifi_legacy_hal.h
+++ /dev/null
@@ -1,312 +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 WIFI_LEGACY_HAL_H_
-#define WIFI_LEGACY_HAL_H_
-
-#include <functional>
-#include <thread>
-#include <vector>
-#include <condition_variable>
-
-#include <wifi_system/interface_tool.h>
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_1 {
-namespace implementation {
-// This is in a separate namespace to prevent typename conflicts between
-// the legacy HAL types and the HIDL interface types.
-namespace legacy_hal {
-// Wrap all the types defined inside the legacy HAL header files inside this
-// namespace.
-#include <hardware_legacy/wifi_hal.h>
-
-// APF capabilities supported by the iface.
-struct PacketFilterCapabilities {
-  uint32_t version;
-  uint32_t max_len;
-};
-
-// WARNING: We don't care about the variable sized members of either
-// |wifi_iface_stat|, |wifi_radio_stat| structures. So, using the pragma
-// to escape the compiler warnings regarding this.
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wgnu-variable-sized-type-not-at-end"
-// The |wifi_radio_stat.tx_time_per_levels| stats is provided as a pointer in
-// |wifi_radio_stat| structure in the legacy HAL API. Separate that out
-// into a separate return element to avoid passing pointers around.
-struct LinkLayerRadioStats {
-  wifi_radio_stat stats;
-  std::vector<uint32_t> tx_time_per_levels;
-};
-
-struct LinkLayerStats {
-  wifi_iface_stat iface;
-  std::vector<LinkLayerRadioStats> radios;
-};
-#pragma GCC diagnostic pop
-
-// The |WLAN_DRIVER_WAKE_REASON_CNT.cmd_event_wake_cnt| and
-// |WLAN_DRIVER_WAKE_REASON_CNT.driver_fw_local_wake_cnt| stats is provided
-// as a pointer in |WLAN_DRIVER_WAKE_REASON_CNT| structure in the legacy HAL
-// API. Separate that out into a separate return elements to avoid passing
-// pointers around.
-struct WakeReasonStats {
-  WLAN_DRIVER_WAKE_REASON_CNT wake_reason_cnt;
-  std::vector<uint32_t> cmd_event_wake_cnt;
-  std::vector<uint32_t> driver_fw_local_wake_cnt;
-};
-
-// NAN response and event callbacks struct.
-struct NanCallbackHandlers {
-  // NotifyResponse invoked to notify the status of the Request.
-  std::function<void(transaction_id, const NanResponseMsg&)> on_notify_response;
-  // Various event callbacks.
-  std::function<void(const NanPublishTerminatedInd&)>
-      on_event_publish_terminated;
-  std::function<void(const NanMatchInd&)> on_event_match;
-  std::function<void(const NanMatchExpiredInd&)> on_event_match_expired;
-  std::function<void(const NanSubscribeTerminatedInd&)>
-      on_event_subscribe_terminated;
-  std::function<void(const NanFollowupInd&)> on_event_followup;
-  std::function<void(const NanDiscEngEventInd&)> on_event_disc_eng_event;
-  std::function<void(const NanDisabledInd&)> on_event_disabled;
-  std::function<void(const NanTCAInd&)> on_event_tca;
-  std::function<void(const NanBeaconSdfPayloadInd&)>
-      on_event_beacon_sdf_payload;
-  std::function<void(const NanDataPathRequestInd&)> on_event_data_path_request;
-  std::function<void(const NanDataPathConfirmInd&)> on_event_data_path_confirm;
-  std::function<void(const NanDataPathEndInd&)> on_event_data_path_end;
-  std::function<void(const NanTransmitFollowupInd&)>
-      on_event_transmit_follow_up;
-  std::function<void(const NanRangeRequestInd&)>
-      on_event_range_request;
-  std::function<void(const NanRangeReportInd&)>
-      on_event_range_report;
-};
-
-// Full scan results contain IE info and are hence passed by reference, to
-// preserve the variable length array member |ie_data|. Callee must not retain
-// the pointer.
-using on_gscan_full_result_callback =
-    std::function<void(wifi_request_id, const wifi_scan_result*, uint32_t)>;
-// These scan results don't contain any IE info, so no need to pass by
-// reference.
-using on_gscan_results_callback = std::function<void(
-    wifi_request_id, const std::vector<wifi_cached_scan_results>&)>;
-
-// Invoked when the rssi value breaches the thresholds set.
-using on_rssi_threshold_breached_callback =
-    std::function<void(wifi_request_id, std::array<uint8_t, 6>, int8_t)>;
-
-// Callback for RTT range request results.
-// Rtt results contain IE info and are hence passed by reference, to
-// preserve the |LCI| and |LCR| pointers. Callee must not retain
-// the pointer.
-using on_rtt_results_callback = std::function<void(
-    wifi_request_id, const std::vector<const wifi_rtt_result*>&)>;
-
-// Callback for ring buffer data.
-using on_ring_buffer_data_callback =
-    std::function<void(const std::string&,
-                       const std::vector<uint8_t>&,
-                       const wifi_ring_buffer_status&)>;
-
-// Callback for alerts.
-using on_error_alert_callback =
-    std::function<void(int32_t, const std::vector<uint8_t>&)>;
-/**
- * Class that encapsulates all legacy HAL interactions.
- * This class manages the lifetime of the event loop thread used by legacy HAL.
- *
- * Note: aThere will only be a single instance of this class created in the Wifi
- * object and will be valid for the lifetime of the process.
- */
-class WifiLegacyHal {
- public:
-  WifiLegacyHal();
-  // Names to use for the different types of iface.
-  std::string getApIfaceName();
-  std::string getNanIfaceName();
-  std::string getP2pIfaceName();
-  std::string getStaIfaceName();
-
-  // Initialize the legacy HAL function table.
-  wifi_error initialize();
-  // Start the legacy HAL and the event looper thread.
-  wifi_error start();
-  // 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();
-  std::pair<wifi_error, std::vector<uint8_t>> requestDriverMemoryDump();
-  std::pair<wifi_error, std::vector<uint8_t>> requestFirmwareMemoryDump();
-  std::pair<wifi_error, uint32_t> getSupportedFeatureSet();
-  // APF functions.
-  std::pair<wifi_error, PacketFilterCapabilities> getPacketFilterCapabilities();
-  wifi_error setPacketFilter(const std::vector<uint8_t>& program);
-  // Gscan functions.
-  std::pair<wifi_error, wifi_gscan_capabilities> getGscanCapabilities();
-  // These API's provides a simplified interface over the legacy Gscan API's:
-  // a) All scan events from the legacy HAL API other than the
-  //    |WIFI_SCAN_FAILED| are treated as notification of results.
-  //    This method then retrieves the cached scan results from the legacy
-  //    HAL API and triggers the externally provided |on_results_user_callback|
-  //    on success.
-  // b) |WIFI_SCAN_FAILED| scan event or failure to retrieve cached scan results
-  //    triggers the externally provided |on_failure_user_callback|.
-  // c) Full scan result event triggers the externally provided
-  //    |on_full_result_user_callback|.
-  wifi_error startGscan(
-      wifi_request_id id,
-      const wifi_scan_cmd_params& params,
-      const std::function<void(wifi_request_id)>& on_failure_callback,
-      const on_gscan_results_callback& on_results_callback,
-      const on_gscan_full_result_callback& on_full_result_callback);
-  wifi_error stopGscan(wifi_request_id id);
-  std::pair<wifi_error, std::vector<uint32_t>> getValidFrequenciesForBand(
-      wifi_band band);
-  wifi_error setDfsFlag(bool dfs_on);
-  // Link layer stats functions.
-  wifi_error enableLinkLayerStats(bool debug);
-  wifi_error disableLinkLayerStats();
-  std::pair<wifi_error, LinkLayerStats> getLinkLayerStats();
-  // RSSI monitor functions.
-  wifi_error startRssiMonitoring(wifi_request_id id,
-                                 int8_t max_rssi,
-                                 int8_t min_rssi,
-                                 const on_rssi_threshold_breached_callback&
-                                     on_threshold_breached_callback);
-  wifi_error stopRssiMonitoring(wifi_request_id id);
-  std::pair<wifi_error, wifi_roaming_capabilities> getRoamingCapabilities();
-  wifi_error configureRoaming(const wifi_roaming_config& config);
-  wifi_error enableFirmwareRoaming(fw_roaming_state_t state);
-  wifi_error configureNdOffload(bool enable);
-  wifi_error startSendingOffloadedPacket(
-      uint32_t cmd_id,
-      const std::vector<uint8_t>& ip_packet_data,
-      const std::array<uint8_t, 6>& src_address,
-      const std::array<uint8_t, 6>& dst_address,
-      uint32_t period_in_ms);
-  wifi_error stopSendingOffloadedPacket(uint32_t cmd_id);
-  wifi_error setScanningMacOui(const std::array<uint8_t, 3>& oui);
-  wifi_error selectTxPowerScenario(wifi_power_scenario scenario);
-  wifi_error resetTxPowerScenario();
-  // Logger/debug functions.
-  std::pair<wifi_error, uint32_t> getLoggerSupportedFeatureSet();
-  wifi_error startPktFateMonitoring();
-  std::pair<wifi_error, std::vector<wifi_tx_report>> getTxPktFates();
-  std::pair<wifi_error, std::vector<wifi_rx_report>> getRxPktFates();
-  std::pair<wifi_error, WakeReasonStats> getWakeReasonStats();
-  wifi_error registerRingBufferCallbackHandler(
-      const on_ring_buffer_data_callback& on_data_callback);
-  wifi_error deregisterRingBufferCallbackHandler();
-  std::pair<wifi_error, std::vector<wifi_ring_buffer_status>>
-  getRingBuffersStatus();
-  wifi_error startRingBufferLogging(const std::string& ring_name,
-                                    uint32_t verbose_level,
-                                    uint32_t max_interval_sec,
-                                    uint32_t min_data_size);
-  wifi_error getRingBufferData(const std::string& ring_name);
-  wifi_error registerErrorAlertCallbackHandler(
-      const on_error_alert_callback& on_alert_callback);
-  wifi_error deregisterErrorAlertCallbackHandler();
-  // RTT functions.
-  wifi_error startRttRangeRequest(
-      wifi_request_id id,
-      const std::vector<wifi_rtt_config>& rtt_configs,
-      const on_rtt_results_callback& on_results_callback);
-  wifi_error cancelRttRangeRequest(
-      wifi_request_id id, const std::vector<std::array<uint8_t, 6>>& mac_addrs);
-  std::pair<wifi_error, wifi_rtt_capabilities> getRttCapabilities();
-  std::pair<wifi_error, wifi_rtt_responder> getRttResponderInfo();
-  wifi_error enableRttResponder(wifi_request_id id,
-                                const wifi_channel_info& channel_hint,
-                                uint32_t max_duration_secs,
-                                const wifi_rtt_responder& info);
-  wifi_error disableRttResponder(wifi_request_id id);
-  wifi_error setRttLci(wifi_request_id id, const wifi_lci_information& info);
-  wifi_error setRttLcr(wifi_request_id id, const wifi_lcr_information& info);
-  // NAN functions.
-  wifi_error nanRegisterCallbackHandlers(const NanCallbackHandlers& callbacks);
-  wifi_error nanEnableRequest(transaction_id id, const NanEnableRequest& msg);
-  wifi_error nanDisableRequest(transaction_id id);
-  wifi_error nanPublishRequest(transaction_id id, const NanPublishRequest& msg);
-  wifi_error nanPublishCancelRequest(transaction_id id,
-                                     const NanPublishCancelRequest& msg);
-  wifi_error nanSubscribeRequest(transaction_id id,
-                                 const NanSubscribeRequest& msg);
-  wifi_error nanSubscribeCancelRequest(transaction_id id,
-                                       const NanSubscribeCancelRequest& msg);
-  wifi_error nanTransmitFollowupRequest(transaction_id id,
-                                        const NanTransmitFollowupRequest& msg);
-  wifi_error nanStatsRequest(transaction_id id, const NanStatsRequest& msg);
-  wifi_error nanConfigRequest(transaction_id id, const NanConfigRequest& msg);
-  wifi_error nanTcaRequest(transaction_id id, const NanTCARequest& msg);
-  wifi_error nanBeaconSdfPayloadRequest(transaction_id id,
-                                        const NanBeaconSdfPayloadRequest& msg);
-  std::pair<wifi_error, NanVersion> nanGetVersion();
-  wifi_error nanGetCapabilities(transaction_id id);
-  wifi_error nanDataInterfaceCreate(transaction_id id,
-                                    const std::string& iface_name);
-  wifi_error nanDataInterfaceDelete(transaction_id id,
-                                    const std::string& iface_name);
-  wifi_error nanDataRequestInitiator(transaction_id id,
-                                     const NanDataPathInitiatorRequest& msg);
-  wifi_error nanDataIndicationResponse(
-      transaction_id id, const NanDataPathIndicationResponse& msg);
-  wifi_error nanDataEnd(transaction_id id, uint32_t ndpInstanceId);
-  // AP functions.
-  wifi_error setCountryCode(std::array<int8_t, 2> code);
-
- private:
-  // Retrieve the interface handle to be used for the "wlan" interface.
-  wifi_error retrieveWlanInterfaceHandle();
-  // Run the legacy HAL event loop thread.
-  void runEventLoop();
-  // Retrieve the cached gscan results to pass the results back to the external
-  // callbacks.
-  std::pair<wifi_error, std::vector<wifi_cached_scan_results>>
-  getGscanCachedResults();
-  void invalidate();
-
-  // Global function table of legacy HAL.
-  wifi_hal_fn global_func_table_;
-  // Opaque handle to be used for all global operations.
-  wifi_handle global_handle_;
-  // Opaque handle to be used for all wlan0 interface specific operations.
-  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_;
-};
-
-}  // namespace legacy_hal
-}  // namespace implementation
-}  // namespace V1_1
-}  // namespace wifi
-}  // namespace hardware
-}  // namespace android
-
-#endif  // WIFI_LEGACY_HAL_H_
diff --git a/wifi/1.1/default/wifi_legacy_hal_stubs.cpp b/wifi/1.1/default/wifi_legacy_hal_stubs.cpp
deleted file mode 100644
index c02e3ba..0000000
--- a/wifi/1.1/default/wifi_legacy_hal_stubs.cpp
+++ /dev/null
@@ -1,144 +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.
- */
-
-#include "wifi_legacy_hal_stubs.h"
-
-// TODO: Remove these stubs from HalTool in libwifi-system.
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_1 {
-namespace implementation {
-namespace legacy_hal {
-template <typename>
-struct stubFunction;
-
-template <typename R, typename... Args>
-struct stubFunction<R (*)(Args...)> {
-  static constexpr R invoke(Args...) { return WIFI_ERROR_NOT_SUPPORTED; }
-};
-template <typename... Args>
-struct stubFunction<void (*)(Args...)> {
-  static constexpr void invoke(Args...) {}
-};
-
-template <typename T>
-void populateStubFor(T* val) {
-  *val = &stubFunction<T>::invoke;
-}
-
-bool initHalFuncTableWithStubs(wifi_hal_fn* hal_fn) {
-  if (hal_fn == nullptr) {
-    return false;
-  }
-  populateStubFor(&hal_fn->wifi_initialize);
-  populateStubFor(&hal_fn->wifi_cleanup);
-  populateStubFor(&hal_fn->wifi_event_loop);
-  populateStubFor(&hal_fn->wifi_get_error_info);
-  populateStubFor(&hal_fn->wifi_get_supported_feature_set);
-  populateStubFor(&hal_fn->wifi_get_concurrency_matrix);
-  populateStubFor(&hal_fn->wifi_set_scanning_mac_oui);
-  populateStubFor(&hal_fn->wifi_get_supported_channels);
-  populateStubFor(&hal_fn->wifi_is_epr_supported);
-  populateStubFor(&hal_fn->wifi_get_ifaces);
-  populateStubFor(&hal_fn->wifi_get_iface_name);
-  populateStubFor(&hal_fn->wifi_set_iface_event_handler);
-  populateStubFor(&hal_fn->wifi_reset_iface_event_handler);
-  populateStubFor(&hal_fn->wifi_start_gscan);
-  populateStubFor(&hal_fn->wifi_stop_gscan);
-  populateStubFor(&hal_fn->wifi_get_cached_gscan_results);
-  populateStubFor(&hal_fn->wifi_set_bssid_hotlist);
-  populateStubFor(&hal_fn->wifi_reset_bssid_hotlist);
-  populateStubFor(&hal_fn->wifi_set_significant_change_handler);
-  populateStubFor(&hal_fn->wifi_reset_significant_change_handler);
-  populateStubFor(&hal_fn->wifi_get_gscan_capabilities);
-  populateStubFor(&hal_fn->wifi_set_link_stats);
-  populateStubFor(&hal_fn->wifi_get_link_stats);
-  populateStubFor(&hal_fn->wifi_clear_link_stats);
-  populateStubFor(&hal_fn->wifi_get_valid_channels);
-  populateStubFor(&hal_fn->wifi_rtt_range_request);
-  populateStubFor(&hal_fn->wifi_rtt_range_cancel);
-  populateStubFor(&hal_fn->wifi_get_rtt_capabilities);
-  populateStubFor(&hal_fn->wifi_rtt_get_responder_info);
-  populateStubFor(&hal_fn->wifi_enable_responder);
-  populateStubFor(&hal_fn->wifi_disable_responder);
-  populateStubFor(&hal_fn->wifi_set_nodfs_flag);
-  populateStubFor(&hal_fn->wifi_start_logging);
-  populateStubFor(&hal_fn->wifi_set_epno_list);
-  populateStubFor(&hal_fn->wifi_reset_epno_list);
-  populateStubFor(&hal_fn->wifi_set_country_code);
-  populateStubFor(&hal_fn->wifi_get_firmware_memory_dump);
-  populateStubFor(&hal_fn->wifi_set_log_handler);
-  populateStubFor(&hal_fn->wifi_reset_log_handler);
-  populateStubFor(&hal_fn->wifi_set_alert_handler);
-  populateStubFor(&hal_fn->wifi_reset_alert_handler);
-  populateStubFor(&hal_fn->wifi_get_firmware_version);
-  populateStubFor(&hal_fn->wifi_get_ring_buffers_status);
-  populateStubFor(&hal_fn->wifi_get_logger_supported_feature_set);
-  populateStubFor(&hal_fn->wifi_get_ring_data);
-  populateStubFor(&hal_fn->wifi_enable_tdls);
-  populateStubFor(&hal_fn->wifi_disable_tdls);
-  populateStubFor(&hal_fn->wifi_get_tdls_status);
-  populateStubFor(&hal_fn->wifi_get_tdls_capabilities);
-  populateStubFor(&hal_fn->wifi_get_driver_version);
-  populateStubFor(&hal_fn->wifi_set_passpoint_list);
-  populateStubFor(&hal_fn->wifi_reset_passpoint_list);
-  populateStubFor(&hal_fn->wifi_set_lci);
-  populateStubFor(&hal_fn->wifi_set_lcr);
-  populateStubFor(&hal_fn->wifi_start_sending_offloaded_packet);
-  populateStubFor(&hal_fn->wifi_stop_sending_offloaded_packet);
-  populateStubFor(&hal_fn->wifi_start_rssi_monitoring);
-  populateStubFor(&hal_fn->wifi_stop_rssi_monitoring);
-  populateStubFor(&hal_fn->wifi_get_wake_reason_stats);
-  populateStubFor(&hal_fn->wifi_configure_nd_offload);
-  populateStubFor(&hal_fn->wifi_get_driver_memory_dump);
-  populateStubFor(&hal_fn->wifi_start_pkt_fate_monitoring);
-  populateStubFor(&hal_fn->wifi_get_tx_pkt_fates);
-  populateStubFor(&hal_fn->wifi_get_rx_pkt_fates);
-  populateStubFor(&hal_fn->wifi_nan_enable_request);
-  populateStubFor(&hal_fn->wifi_nan_disable_request);
-  populateStubFor(&hal_fn->wifi_nan_publish_request);
-  populateStubFor(&hal_fn->wifi_nan_publish_cancel_request);
-  populateStubFor(&hal_fn->wifi_nan_subscribe_request);
-  populateStubFor(&hal_fn->wifi_nan_subscribe_cancel_request);
-  populateStubFor(&hal_fn->wifi_nan_transmit_followup_request);
-  populateStubFor(&hal_fn->wifi_nan_stats_request);
-  populateStubFor(&hal_fn->wifi_nan_config_request);
-  populateStubFor(&hal_fn->wifi_nan_tca_request);
-  populateStubFor(&hal_fn->wifi_nan_beacon_sdf_payload_request);
-  populateStubFor(&hal_fn->wifi_nan_register_handler);
-  populateStubFor(&hal_fn->wifi_nan_get_version);
-  populateStubFor(&hal_fn->wifi_nan_get_capabilities);
-  populateStubFor(&hal_fn->wifi_nan_data_interface_create);
-  populateStubFor(&hal_fn->wifi_nan_data_interface_delete);
-  populateStubFor(&hal_fn->wifi_nan_data_request_initiator);
-  populateStubFor(&hal_fn->wifi_nan_data_indication_response);
-  populateStubFor(&hal_fn->wifi_nan_data_end);
-  populateStubFor(&hal_fn->wifi_get_packet_filter_capabilities);
-  populateStubFor(&hal_fn->wifi_set_packet_filter);
-  populateStubFor(&hal_fn->wifi_get_roaming_capabilities);
-  populateStubFor(&hal_fn->wifi_enable_firmware_roaming);
-  populateStubFor(&hal_fn->wifi_configure_roaming);
-  populateStubFor(&hal_fn->wifi_select_tx_power_scenario);
-  populateStubFor(&hal_fn->wifi_reset_tx_power_scenario);
-  return true;
-}
-}  // namespace legacy_hal
-}  // namespace implementation
-}  // namespace V1_1
-}  // namespace wifi
-}  // namespace hardware
-}  // namespace android
diff --git a/wifi/1.1/default/wifi_mode_controller.cpp b/wifi/1.1/default/wifi_mode_controller.cpp
deleted file mode 100644
index b8a44c2..0000000
--- a/wifi/1.1/default/wifi_mode_controller.cpp
+++ /dev/null
@@ -1,86 +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.
- */
-
-#include <android-base/logging.h>
-#include <android-base/macros.h>
-#include <private/android_filesystem_config.h>
-
-#include "wifi_mode_controller.h"
-
-using android::hardware::wifi::V1_0::IfaceType;
-using android::wifi_hal::DriverTool;
-
-namespace {
-int convertIfaceTypeToFirmwareMode(IfaceType type) {
-  int mode;
-  switch (type) {
-    case IfaceType::AP:
-      mode = DriverTool::kFirmwareModeAp;
-      break;
-    case IfaceType::P2P:
-      mode = DriverTool::kFirmwareModeP2p;
-      break;
-    case IfaceType::NAN:
-      // NAN is exposed in STA mode currently.
-      mode = DriverTool::kFirmwareModeSta;
-      break;
-    case IfaceType::STA:
-      mode = DriverTool::kFirmwareModeSta;
-      break;
-  }
-  return mode;
-}
-}
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_1 {
-namespace implementation {
-namespace mode_controller {
-
-WifiModeController::WifiModeController() : driver_tool_(new DriverTool) {}
-
-bool WifiModeController::isFirmwareModeChangeNeeded(IfaceType type) {
-  return driver_tool_->IsFirmwareModeChangeNeeded(
-      convertIfaceTypeToFirmwareMode(type));
-}
-
-bool WifiModeController::changeFirmwareMode(IfaceType type) {
-  if (!driver_tool_->LoadDriver()) {
-    LOG(ERROR) << "Failed to load WiFi driver";
-    return false;
-  }
-  if (!driver_tool_->ChangeFirmwareMode(convertIfaceTypeToFirmwareMode(type))) {
-    LOG(ERROR) << "Failed to change firmware mode";
-    return false;
-  }
-  return true;
-}
-
-bool WifiModeController::deinitialize() {
-  if (!driver_tool_->UnloadDriver()) {
-    LOG(ERROR) << "Failed to unload WiFi driver";
-    return false;
-  }
-  return true;
-}
-}  // namespace mode_controller
-}  // namespace implementation
-}  // namespace V1_1
-}  // namespace wifi
-}  // namespace hardware
-}  // namespace android
diff --git a/wifi/1.1/default/wifi_nan_iface.cpp b/wifi/1.1/default/wifi_nan_iface.cpp
deleted file mode 100644
index a111d06..0000000
--- a/wifi/1.1/default/wifi_nan_iface.cpp
+++ /dev/null
@@ -1,769 +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.
- */
-
-#include <android-base/logging.h>
-
-#include "hidl_return_util.h"
-#include "hidl_struct_util.h"
-#include "wifi_nan_iface.h"
-#include "wifi_status_util.h"
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_1 {
-namespace implementation {
-using hidl_return_util::validateAndCall;
-
-WifiNanIface::WifiNanIface(
-    const std::string& ifname,
-    const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal)
-    : ifname_(ifname), legacy_hal_(legacy_hal), is_valid_(true) {
-  // Register all the callbacks here. these should be valid for the lifetime
-  // of the object. Whenever the mode changes legacy HAL will remove
-  // all of these callbacks.
-  legacy_hal::NanCallbackHandlers callback_handlers;
-  android::wp<WifiNanIface> weak_ptr_this(this);
-
-  // Callback for response.
-  callback_handlers.on_notify_response = [weak_ptr_this](
-      legacy_hal::transaction_id id, const legacy_hal::NanResponseMsg& msg) {
-    const auto shared_ptr_this = weak_ptr_this.promote();
-    if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
-      LOG(ERROR) << "Callback invoked on an invalid object";
-      return;
-    }
-    WifiNanStatus wifiNanStatus;
-    if (!hidl_struct_util::convertLegacyNanResponseHeaderToHidl(msg,
-                                                                &wifiNanStatus)) {
-      LOG(ERROR) << "Failed to convert nan response header";
-      return;
-    }
-
-    switch (msg.response_type) {
-    case legacy_hal::NAN_RESPONSE_ENABLED: {
-        for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
-          if (!callback->notifyEnableResponse(id, wifiNanStatus).isOk()) {
-            LOG(ERROR) << "Failed to invoke the callback";
-          }
-        }
-        break;
-    }
-    case legacy_hal::NAN_RESPONSE_DISABLED: {
-        for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
-          if (!callback->notifyDisableResponse(id, wifiNanStatus).isOk()) {
-            LOG(ERROR) << "Failed to invoke the callback";
-          }
-        }
-        break;
-    }
-    case legacy_hal::NAN_RESPONSE_PUBLISH: {
-        for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
-          if (!callback->notifyStartPublishResponse(id, wifiNanStatus,
-                        msg.body.publish_response.publish_id).isOk()) {
-            LOG(ERROR) << "Failed to invoke the callback";
-          }
-        }
-        break;
-    }
-    case legacy_hal::NAN_RESPONSE_PUBLISH_CANCEL: {
-        for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
-          if (!callback->notifyStopPublishResponse(id, wifiNanStatus).isOk()) {
-            LOG(ERROR) << "Failed to invoke the callback";
-          }
-        }
-        break;
-    }
-    case legacy_hal::NAN_RESPONSE_TRANSMIT_FOLLOWUP: {
-        for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
-          if (!callback->notifyTransmitFollowupResponse(id, wifiNanStatus).isOk()) {
-            LOG(ERROR) << "Failed to invoke the callback";
-          }
-        }
-        break;
-    }
-    case legacy_hal::NAN_RESPONSE_SUBSCRIBE: {
-        for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
-          if (!callback->notifyStartSubscribeResponse(id, wifiNanStatus,
-                        msg.body.subscribe_response.subscribe_id).isOk()) {
-            LOG(ERROR) << "Failed to invoke the callback";
-          }
-        }
-        break;
-    }
-    case legacy_hal::NAN_RESPONSE_SUBSCRIBE_CANCEL: {
-        for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
-          if (!callback->notifyStopSubscribeResponse(id, wifiNanStatus).isOk()) {
-            LOG(ERROR) << "Failed to invoke the callback";
-          }
-        }
-        break;
-    }
-    case legacy_hal::NAN_RESPONSE_CONFIG: {
-        for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
-          if (!callback->notifyConfigResponse(id, wifiNanStatus).isOk()) {
-            LOG(ERROR) << "Failed to invoke the callback";
-          }
-        }
-        break;
-     }
-    case legacy_hal::NAN_GET_CAPABILITIES: {
-        NanCapabilities hidl_struct;
-        if (!hidl_struct_util::convertLegacyNanCapabilitiesResponseToHidl(
-                msg.body.nan_capabilities, &hidl_struct)) {
-            LOG(ERROR) << "Failed to convert nan capabilities response";
-            return;
-        }
-        for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
-          if (!callback->notifyCapabilitiesResponse(id, wifiNanStatus,
-                                                    hidl_struct).isOk()) {
-            LOG(ERROR) << "Failed to invoke the callback";
-          }
-        }
-        break;
-    }
-    case legacy_hal::NAN_DP_INTERFACE_CREATE: {
-        for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
-          if (!callback->notifyCreateDataInterfaceResponse(id, wifiNanStatus).isOk()) {
-            LOG(ERROR) << "Failed to invoke the callback";
-          }
-        }
-        break;
-    }
-    case legacy_hal::NAN_DP_INTERFACE_DELETE: {
-        for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
-          if (!callback->notifyDeleteDataInterfaceResponse(id, wifiNanStatus).isOk()) {
-            LOG(ERROR) << "Failed to invoke the callback";
-          }
-        }
-        break;
-    }
-    case legacy_hal::NAN_DP_INITIATOR_RESPONSE: {
-        for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
-          if (!callback->notifyInitiateDataPathResponse(id, wifiNanStatus,
-                msg.body.data_request_response.ndp_instance_id).isOk()) {
-            LOG(ERROR) << "Failed to invoke the callback";
-          }
-        }
-        break;
-    }
-    case legacy_hal::NAN_DP_RESPONDER_RESPONSE: {
-        for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
-          if (!callback->notifyRespondToDataPathIndicationResponse(id, wifiNanStatus).isOk()) {
-            LOG(ERROR) << "Failed to invoke the callback";
-          }
-        }
-        break;
-    }
-    case legacy_hal::NAN_DP_END: {
-        for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
-          if (!callback->notifyTerminateDataPathResponse(id, wifiNanStatus).isOk()) {
-            LOG(ERROR) << "Failed to invoke the callback";
-          }
-        }
-        break;
-    }
-    case legacy_hal::NAN_RESPONSE_BEACON_SDF_PAYLOAD:
-        /* fall through */
-    case legacy_hal::NAN_RESPONSE_TCA:
-        /* fall through */
-    case legacy_hal::NAN_RESPONSE_STATS:
-        /* fall through */
-    case legacy_hal::NAN_RESPONSE_ERROR:
-        /* fall through */
-    default:
-        LOG(ERROR) << "Unknown or unhandled response type: " << msg.response_type;
-        return;
-    }
-  };
-
-  callback_handlers.on_event_disc_eng_event = [weak_ptr_this](
-        const legacy_hal::NanDiscEngEventInd& msg) {
-      const auto shared_ptr_this = weak_ptr_this.promote();
-      if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
-        LOG(ERROR) << "Callback invoked on an invalid object";
-        return;
-      }
-      NanClusterEventInd hidl_struct;
-      // event types defined identically - hence can be cast
-      hidl_struct.eventType = (NanClusterEventType) msg.event_type;
-      hidl_struct.addr = msg.data.mac_addr.addr;
-
-      for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
-        if (!callback->eventClusterEvent(hidl_struct).isOk()) {
-            LOG(ERROR) << "Failed to invoke the callback";
-        }
-      }
-  };
-
-  callback_handlers.on_event_disabled = [weak_ptr_this](
-        const legacy_hal::NanDisabledInd& msg) {
-      const auto shared_ptr_this = weak_ptr_this.promote();
-      if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
-        LOG(ERROR) << "Callback invoked on an invalid object";
-        return;
-      }
-      WifiNanStatus status;
-      hidl_struct_util::convertToWifiNanStatus(msg.reason, msg.nan_reason, sizeof(msg.nan_reason),
-            &status);
-
-      for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
-        if (!callback->eventDisabled(status).isOk()) {
-            LOG(ERROR) << "Failed to invoke the callback";
-        }
-      }
-  };
-
-  callback_handlers.on_event_publish_terminated = [weak_ptr_this](
-        const legacy_hal::NanPublishTerminatedInd& msg) {
-      const auto shared_ptr_this = weak_ptr_this.promote();
-      if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
-        LOG(ERROR) << "Callback invoked on an invalid object";
-        return;
-      }
-      WifiNanStatus status;
-      hidl_struct_util::convertToWifiNanStatus(msg.reason, msg.nan_reason, sizeof(msg.nan_reason),
-            &status);
-
-      for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
-        if (!callback->eventPublishTerminated(msg.publish_id, status).isOk()) {
-            LOG(ERROR) << "Failed to invoke the callback";
-        }
-      }
-  };
-
-  callback_handlers.on_event_subscribe_terminated = [weak_ptr_this](
-        const legacy_hal::NanSubscribeTerminatedInd& msg) {
-      const auto shared_ptr_this = weak_ptr_this.promote();
-      if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
-        LOG(ERROR) << "Callback invoked on an invalid object";
-        return;
-      }
-      WifiNanStatus status;
-      hidl_struct_util::convertToWifiNanStatus(msg.reason, msg.nan_reason, sizeof(msg.nan_reason),
-            &status);
-
-      for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
-        if (!callback->eventSubscribeTerminated(msg.subscribe_id, status).isOk()) {
-            LOG(ERROR) << "Failed to invoke the callback";
-        }
-      }
-  };
-
-  callback_handlers.on_event_match = [weak_ptr_this](
-        const legacy_hal::NanMatchInd& msg) {
-      const auto shared_ptr_this = weak_ptr_this.promote();
-      if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
-        LOG(ERROR) << "Callback invoked on an invalid object";
-        return;
-      }
-      NanMatchInd hidl_struct;
-      if (!hidl_struct_util::convertLegacyNanMatchIndToHidl(
-            msg, &hidl_struct)) {
-          LOG(ERROR) << "Failed to convert nan capabilities response";
-          return;
-      }
-
-      for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
-        if (!callback->eventMatch(hidl_struct).isOk()) {
-            LOG(ERROR) << "Failed to invoke the callback";
-        }
-      }
-  };
-
-  callback_handlers.on_event_match_expired = [weak_ptr_this](
-        const legacy_hal::NanMatchExpiredInd& msg) {
-      const auto shared_ptr_this = weak_ptr_this.promote();
-      if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
-        LOG(ERROR) << "Callback invoked on an invalid object";
-        return;
-      }
-      for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
-        if (!callback->eventMatchExpired(msg.publish_subscribe_id,
-                msg.requestor_instance_id).isOk()) {
-            LOG(ERROR) << "Failed to invoke the callback";
-        }
-      }
-  };
-
-  callback_handlers.on_event_followup = [weak_ptr_this](
-        const legacy_hal::NanFollowupInd& msg) {
-      const auto shared_ptr_this = weak_ptr_this.promote();
-      if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
-        LOG(ERROR) << "Callback invoked on an invalid object";
-        return;
-      }
-      NanFollowupReceivedInd hidl_struct;
-      if (!hidl_struct_util::convertLegacyNanFollowupIndToHidl(
-            msg, &hidl_struct)) {
-          LOG(ERROR) << "Failed to convert nan capabilities response";
-          return;
-      }
-
-      for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
-        if (!callback->eventFollowupReceived(hidl_struct).isOk()) {
-            LOG(ERROR) << "Failed to invoke the callback";
-        }
-      }
-  };
-
-  callback_handlers.on_event_transmit_follow_up = [weak_ptr_this](
-        const legacy_hal::NanTransmitFollowupInd& msg) {
-      const auto shared_ptr_this = weak_ptr_this.promote();
-      if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
-        LOG(ERROR) << "Callback invoked on an invalid object";
-        return;
-      }
-      WifiNanStatus status;
-      hidl_struct_util::convertToWifiNanStatus(msg.reason, msg.nan_reason, sizeof(msg.nan_reason),
-            &status);
-
-      for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
-        if (!callback->eventTransmitFollowup(msg.id, status).isOk()) {
-            LOG(ERROR) << "Failed to invoke the callback";
-        }
-      }
-  };
-
-  callback_handlers.on_event_data_path_request = [weak_ptr_this](
-        const legacy_hal::NanDataPathRequestInd& msg) {
-      const auto shared_ptr_this = weak_ptr_this.promote();
-      if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
-        LOG(ERROR) << "Callback invoked on an invalid object";
-        return;
-      }
-      NanDataPathRequestInd hidl_struct;
-      if (!hidl_struct_util::convertLegacyNanDataPathRequestIndToHidl(
-            msg, &hidl_struct)) {
-          LOG(ERROR) << "Failed to convert nan capabilities response";
-          return;
-      }
-
-      for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
-        if (!callback->eventDataPathRequest(hidl_struct).isOk()) {
-            LOG(ERROR) << "Failed to invoke the callback";
-        }
-      }
-  };
-
-  callback_handlers.on_event_data_path_confirm = [weak_ptr_this](
-        const legacy_hal::NanDataPathConfirmInd& msg) {
-      const auto shared_ptr_this = weak_ptr_this.promote();
-      if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
-        LOG(ERROR) << "Callback invoked on an invalid object";
-        return;
-      }
-      NanDataPathConfirmInd hidl_struct;
-      if (!hidl_struct_util::convertLegacyNanDataPathConfirmIndToHidl(
-            msg, &hidl_struct)) {
-          LOG(ERROR) << "Failed to convert nan capabilities response";
-          return;
-      }
-
-      for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
-        if (!callback->eventDataPathConfirm(hidl_struct).isOk()) {
-            LOG(ERROR) << "Failed to invoke the callback";
-        }
-      }
-  };
-
-  callback_handlers.on_event_data_path_end = [weak_ptr_this](
-        const legacy_hal::NanDataPathEndInd& msg) {
-      const auto shared_ptr_this = weak_ptr_this.promote();
-      if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
-        LOG(ERROR) << "Callback invoked on an invalid object";
-        return;
-      }
-      for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
-        for (int i = 0; i < msg.num_ndp_instances; ++i) {
-            if (!callback->eventDataPathTerminated(msg.ndp_instance_id[i]).isOk()) {
-                LOG(ERROR) << "Failed to invoke the callback";
-            }
-        }
-      }
-  };
-
-  callback_handlers.on_event_beacon_sdf_payload = [weak_ptr_this](
-        const legacy_hal::NanBeaconSdfPayloadInd& /* msg */) {
-      LOG(ERROR) << "on_event_beacon_sdf_payload - should not be called";
-  };
-
-  callback_handlers.on_event_range_request = [weak_ptr_this](
-        const legacy_hal::NanRangeRequestInd& /* msg */) {
-      LOG(ERROR) << "on_event_range_request - should not be called";
-  };
-
-  callback_handlers.on_event_range_report = [weak_ptr_this](
-        const legacy_hal::NanRangeReportInd& /* msg */) {
-      LOG(ERROR) << "on_event_range_report - should not be called";
-  };
-
-  legacy_hal::wifi_error legacy_status =
-      legacy_hal_.lock()->nanRegisterCallbackHandlers(callback_handlers);
-  if (legacy_status != legacy_hal::WIFI_SUCCESS) {
-    LOG(ERROR) << "Failed to register nan callbacks. Invalidating object";
-    invalidate();
-  }
-}
-
-void WifiNanIface::invalidate() {
-  // send commands to HAL to actually disable and destroy interfaces
-  legacy_hal_.lock()->nanDisableRequest(0xFFFF);
-  legacy_hal_.lock()->nanDataInterfaceDelete(0xFFFE, "aware_data0");
-  legacy_hal_.lock()->nanDataInterfaceDelete(0xFFFD, "aware_data1");
-
-  legacy_hal_.reset();
-  event_cb_handler_.invalidate();
-  is_valid_ = false;
-}
-
-bool WifiNanIface::isValid() {
-  return is_valid_;
-}
-
-std::set<sp<IWifiNanIfaceEventCallback>> WifiNanIface::getEventCallbacks() {
-  return event_cb_handler_.getCallbacks();
-}
-
-Return<void> WifiNanIface::getName(getName_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                         &WifiNanIface::getNameInternal,
-                         hidl_status_cb);
-}
-
-Return<void> WifiNanIface::getType(getType_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                         &WifiNanIface::getTypeInternal,
-                         hidl_status_cb);
-}
-
-Return<void> WifiNanIface::registerEventCallback(
-    const sp<IWifiNanIfaceEventCallback>& callback,
-    registerEventCallback_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                         &WifiNanIface::registerEventCallbackInternal,
-                         hidl_status_cb,
-                         callback);
-}
-
-Return<void> WifiNanIface::getCapabilitiesRequest(uint16_t cmd_id,
-                                                  getCapabilitiesRequest_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                         &WifiNanIface::getCapabilitiesRequestInternal,
-                         hidl_status_cb,
-                         cmd_id);
-}
-
-Return<void> WifiNanIface::enableRequest(uint16_t cmd_id,
-                                         const NanEnableRequest& msg,
-                                         enableRequest_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                         &WifiNanIface::enableRequestInternal,
-                         hidl_status_cb,
-                         cmd_id,
-                         msg);
-}
-
-Return<void> WifiNanIface::configRequest(uint16_t cmd_id,
-                                         const NanConfigRequest& msg,
-                                         configRequest_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                         &WifiNanIface::configRequestInternal,
-                         hidl_status_cb,
-                         cmd_id,
-                         msg);
-}
-
-Return<void> WifiNanIface::disableRequest(uint16_t cmd_id,
-                                          disableRequest_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                         &WifiNanIface::disableRequestInternal,
-                         hidl_status_cb,
-                         cmd_id);
-}
-
-Return<void> WifiNanIface::startPublishRequest(uint16_t cmd_id,
-                                               const NanPublishRequest& msg,
-                                               startPublishRequest_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                         &WifiNanIface::startPublishRequestInternal,
-                         hidl_status_cb,
-                         cmd_id,
-                         msg);
-}
-
-Return<void> WifiNanIface::stopPublishRequest(
-    uint16_t cmd_id,
-    uint8_t sessionId,
-    stopPublishRequest_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                         &WifiNanIface::stopPublishRequestInternal,
-                         hidl_status_cb,
-                         cmd_id,
-                         sessionId);
-}
-
-Return<void> WifiNanIface::startSubscribeRequest(
-    uint16_t cmd_id,
-    const NanSubscribeRequest& msg,
-    startSubscribeRequest_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                         &WifiNanIface::startSubscribeRequestInternal,
-                         hidl_status_cb,
-                         cmd_id,
-                         msg);
-}
-
-Return<void> WifiNanIface::stopSubscribeRequest(
-    uint16_t cmd_id,
-    uint8_t sessionId,
-    stopSubscribeRequest_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                         &WifiNanIface::stopSubscribeRequestInternal,
-                         hidl_status_cb,
-                         cmd_id,
-                         sessionId);
-}
-
-Return<void> WifiNanIface::transmitFollowupRequest(
-    uint16_t cmd_id,
-    const NanTransmitFollowupRequest& msg,
-    transmitFollowupRequest_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                         &WifiNanIface::transmitFollowupRequestInternal,
-                         hidl_status_cb,
-                         cmd_id,
-                         msg);
-}
-
-Return<void> WifiNanIface::createDataInterfaceRequest(
-    uint16_t cmd_id,
-    const hidl_string& iface_name,
-    createDataInterfaceRequest_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                         &WifiNanIface::createDataInterfaceRequestInternal,
-                         hidl_status_cb,
-                         cmd_id,
-                         iface_name);
-}
-
-Return<void> WifiNanIface::deleteDataInterfaceRequest(
-    uint16_t cmd_id,
-    const hidl_string& iface_name,
-    deleteDataInterfaceRequest_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                         &WifiNanIface::deleteDataInterfaceRequestInternal,
-                         hidl_status_cb,
-                         cmd_id,
-                         iface_name);
-}
-
-Return<void> WifiNanIface::initiateDataPathRequest(
-    uint16_t cmd_id,
-    const NanInitiateDataPathRequest& msg,
-    initiateDataPathRequest_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                         &WifiNanIface::initiateDataPathRequestInternal,
-                         hidl_status_cb,
-                         cmd_id,
-                         msg);
-}
-
-Return<void> WifiNanIface::respondToDataPathIndicationRequest(
-    uint16_t cmd_id,
-    const NanRespondToDataPathIndicationRequest& msg,
-    respondToDataPathIndicationRequest_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                         &WifiNanIface::respondToDataPathIndicationRequestInternal,
-                         hidl_status_cb,
-                         cmd_id,
-                         msg);
-}
-
-Return<void> WifiNanIface::terminateDataPathRequest(uint16_t cmd_id, uint32_t ndpInstanceId,
-    terminateDataPathRequest_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                         &WifiNanIface::terminateDataPathRequestInternal,
-                         hidl_status_cb,
-                         cmd_id,
-                         ndpInstanceId);
-}
-
-std::pair<WifiStatus, std::string> WifiNanIface::getNameInternal() {
-  return {createWifiStatus(WifiStatusCode::SUCCESS), ifname_};
-}
-
-std::pair<WifiStatus, IfaceType> WifiNanIface::getTypeInternal() {
-  return {createWifiStatus(WifiStatusCode::SUCCESS), IfaceType::NAN};
-}
-
-WifiStatus WifiNanIface::registerEventCallbackInternal(
-    const sp<IWifiNanIfaceEventCallback>& callback) {
-  if (!event_cb_handler_.addCallback(callback)) {
-    return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
-  }
-  return createWifiStatus(WifiStatusCode::SUCCESS);
-}
-
-WifiStatus WifiNanIface::getCapabilitiesRequestInternal(uint16_t cmd_id) {
-  legacy_hal::wifi_error legacy_status =
-        legacy_hal_.lock()->nanGetCapabilities(cmd_id);
-  return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiNanIface::enableRequestInternal(uint16_t cmd_id,
-                                               const NanEnableRequest& msg) {
-  legacy_hal::NanEnableRequest legacy_msg;
-  if (!hidl_struct_util::convertHidlNanEnableRequestToLegacy(msg, &legacy_msg)) {
-    return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
-  }
-  legacy_hal::wifi_error legacy_status =
-      legacy_hal_.lock()->nanEnableRequest(cmd_id, legacy_msg);
-  return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiNanIface::configRequestInternal(
-    uint16_t cmd_id, const NanConfigRequest& msg) {
-  legacy_hal::NanConfigRequest legacy_msg;
-  if (!hidl_struct_util::convertHidlNanConfigRequestToLegacy(msg,
-                                                             &legacy_msg)) {
-    return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
-  }
-  legacy_hal::wifi_error legacy_status =
-      legacy_hal_.lock()->nanConfigRequest(cmd_id, legacy_msg);
-  return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiNanIface::disableRequestInternal(uint16_t cmd_id) {
-  legacy_hal::wifi_error legacy_status =
-      legacy_hal_.lock()->nanDisableRequest(cmd_id);
-  return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiNanIface::startPublishRequestInternal(uint16_t cmd_id,
-                                                     const NanPublishRequest& msg) {
-  legacy_hal::NanPublishRequest legacy_msg;
-  if (!hidl_struct_util::convertHidlNanPublishRequestToLegacy(msg,
-                                                              &legacy_msg)) {
-    return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
-  }
-  legacy_hal::wifi_error legacy_status =
-      legacy_hal_.lock()->nanPublishRequest(cmd_id, legacy_msg);
-  return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiNanIface::stopPublishRequestInternal(
-    uint16_t cmd_id, uint8_t sessionId) {
-  legacy_hal::NanPublishCancelRequest legacy_msg;
-  legacy_msg.publish_id = sessionId;
-  legacy_hal::wifi_error legacy_status =
-      legacy_hal_.lock()->nanPublishCancelRequest(cmd_id, legacy_msg);
-  return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiNanIface::startSubscribeRequestInternal(
-    uint16_t cmd_id, const NanSubscribeRequest& msg) {
-  legacy_hal::NanSubscribeRequest legacy_msg;
-  if (!hidl_struct_util::convertHidlNanSubscribeRequestToLegacy(msg,
-                                                                &legacy_msg)) {
-    return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
-  }
-  legacy_hal::wifi_error legacy_status =
-      legacy_hal_.lock()->nanSubscribeRequest(cmd_id, legacy_msg);
-  return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiNanIface::stopSubscribeRequestInternal(
-    uint16_t cmd_id, uint8_t sessionId) {
-  legacy_hal::NanSubscribeCancelRequest legacy_msg;
-  legacy_msg.subscribe_id = sessionId;
-  legacy_hal::wifi_error legacy_status =
-      legacy_hal_.lock()->nanSubscribeCancelRequest(cmd_id, legacy_msg);
-  return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiNanIface::transmitFollowupRequestInternal(
-    uint16_t cmd_id, const NanTransmitFollowupRequest& msg) {
-  legacy_hal::NanTransmitFollowupRequest legacy_msg;
-  if (!hidl_struct_util::convertHidlNanTransmitFollowupRequestToLegacy(msg, &legacy_msg)) {
-    return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
-  }
-  legacy_hal::wifi_error legacy_status =
-      legacy_hal_.lock()->nanTransmitFollowupRequest(cmd_id, legacy_msg);
-  return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiNanIface::createDataInterfaceRequestInternal(
-    uint16_t cmd_id, const std::string& iface_name) {
-  legacy_hal::wifi_error legacy_status =
-      legacy_hal_.lock()->nanDataInterfaceCreate(cmd_id, iface_name);
-  return createWifiStatusFromLegacyError(legacy_status);
-}
-WifiStatus WifiNanIface::deleteDataInterfaceRequestInternal(
-    uint16_t cmd_id, const std::string& iface_name) {
-  legacy_hal::wifi_error legacy_status =
-      legacy_hal_.lock()->nanDataInterfaceDelete(cmd_id, iface_name);
-  return createWifiStatusFromLegacyError(legacy_status);
-}
-WifiStatus WifiNanIface::initiateDataPathRequestInternal(
-    uint16_t cmd_id, const NanInitiateDataPathRequest& msg) {
-  legacy_hal::NanDataPathInitiatorRequest legacy_msg;
-  if (!hidl_struct_util::convertHidlNanDataPathInitiatorRequestToLegacy(msg, &legacy_msg)) {
-    return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
-  }
-  legacy_hal::wifi_error legacy_status =
-      legacy_hal_.lock()->nanDataRequestInitiator(cmd_id, legacy_msg);
-  return createWifiStatusFromLegacyError(legacy_status);
-}
-WifiStatus WifiNanIface::respondToDataPathIndicationRequestInternal(
-    uint16_t cmd_id, const NanRespondToDataPathIndicationRequest& msg) {
-  legacy_hal::NanDataPathIndicationResponse legacy_msg;
-  if (!hidl_struct_util::convertHidlNanDataPathIndicationResponseToLegacy(msg, &legacy_msg)) {
-    return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
-  }
-  legacy_hal::wifi_error legacy_status =
-      legacy_hal_.lock()->nanDataIndicationResponse(cmd_id, legacy_msg);
-  return createWifiStatusFromLegacyError(legacy_status);
-}
-WifiStatus WifiNanIface::terminateDataPathRequestInternal(
-    uint16_t cmd_id, uint32_t ndpInstanceId) {
-  legacy_hal::wifi_error legacy_status =
-      legacy_hal_.lock()->nanDataEnd(cmd_id, ndpInstanceId);
-  return createWifiStatusFromLegacyError(legacy_status);
-}
-
-}  // namespace implementation
-}  // namespace V1_1
-}  // namespace wifi
-}  // namespace hardware
-}  // namespace android
diff --git a/wifi/1.1/default/wifi_nan_iface.h b/wifi/1.1/default/wifi_nan_iface.h
deleted file mode 100644
index 260d8ab..0000000
--- a/wifi/1.1/default/wifi_nan_iface.h
+++ /dev/null
@@ -1,141 +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 WIFI_NAN_IFACE_H_
-#define WIFI_NAN_IFACE_H_
-
-#include <android-base/macros.h>
-#include <android/hardware/wifi/1.0/IWifiNanIface.h>
-#include <android/hardware/wifi/1.0/IWifiNanIfaceEventCallback.h>
-
-#include "hidl_callback_util.h"
-#include "wifi_legacy_hal.h"
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_1 {
-namespace implementation {
-using namespace android::hardware::wifi::V1_0;
-
-/**
- * HIDL interface object used to control a NAN Iface instance.
- */
-class WifiNanIface : public V1_0::IWifiNanIface {
- public:
-  WifiNanIface(const std::string& ifname,
-               const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal);
-  // Refer to |WifiChip::invalidate()|.
-  void invalidate();
-  bool isValid();
-
-  // HIDL methods exposed.
-  Return<void> getName(getName_cb hidl_status_cb) override;
-  Return<void> getType(getType_cb hidl_status_cb) override;
-  Return<void> registerEventCallback(
-      const sp<IWifiNanIfaceEventCallback>& callback,
-      registerEventCallback_cb hidl_status_cb) override;
-  Return<void> getCapabilitiesRequest(uint16_t cmd_id,
-                                      getCapabilitiesRequest_cb hidl_status_cb) override;
-  Return<void> enableRequest(uint16_t cmd_id,
-                             const NanEnableRequest& msg,
-                             enableRequest_cb hidl_status_cb) override;
-  Return<void> configRequest(uint16_t cmd_id,
-                             const NanConfigRequest& msg,
-                             configRequest_cb hidl_status_cb) override;
-  Return<void> disableRequest(uint16_t cmd_id,
-                              disableRequest_cb hidl_status_cb) override;
-  Return<void> startPublishRequest(uint16_t cmd_id,
-                                   const NanPublishRequest& msg,
-                                   startPublishRequest_cb hidl_status_cb) override;
-  Return<void> stopPublishRequest(uint16_t cmd_id,
-                                  uint8_t sessionId,
-                                  stopPublishRequest_cb hidl_status_cb) override;
-  Return<void> startSubscribeRequest(uint16_t cmd_id,
-                                     const NanSubscribeRequest& msg,
-                                    startSubscribeRequest_cb hidl_status_cb) override;
-  Return<void> stopSubscribeRequest(uint16_t cmd_id,
-                                    uint8_t sessionId,
-                                    stopSubscribeRequest_cb hidl_status_cb) override;
-  Return<void> transmitFollowupRequest(uint16_t cmd_id,
-                                       const NanTransmitFollowupRequest& msg,
-                                       transmitFollowupRequest_cb hidl_status_cb) override;
-  Return<void> createDataInterfaceRequest(uint16_t cmd_id,
-                                          const hidl_string& iface_name,
-                                          createDataInterfaceRequest_cb hidl_status_cb) override;
-  Return<void> deleteDataInterfaceRequest(uint16_t cmd_id,
-                                          const hidl_string& iface_name,
-                                          deleteDataInterfaceRequest_cb hidl_status_cb) override;
-  Return<void> initiateDataPathRequest(uint16_t cmd_id,
-                                       const NanInitiateDataPathRequest& msg,
-                                       initiateDataPathRequest_cb hidl_status_cb) override;
-  Return<void> respondToDataPathIndicationRequest(
-      uint16_t cmd_id,
-      const NanRespondToDataPathIndicationRequest& msg,
-      respondToDataPathIndicationRequest_cb hidl_status_cb) override;
-  Return<void> terminateDataPathRequest(uint16_t cmd_id,
-                                        uint32_t ndpInstanceId,
-                                        terminateDataPathRequest_cb hidl_status_cb) override;
-
- private:
-  // Corresponding worker functions for the HIDL methods.
-  std::pair<WifiStatus, std::string> getNameInternal();
-  std::pair<WifiStatus, IfaceType> getTypeInternal();
-  WifiStatus registerEventCallbackInternal(
-      const sp<IWifiNanIfaceEventCallback>& callback);
-  WifiStatus getCapabilitiesRequestInternal(uint16_t cmd_id);
-  WifiStatus enableRequestInternal(uint16_t cmd_id,
-                                   const NanEnableRequest& msg);
-  WifiStatus configRequestInternal(uint16_t cmd_id,
-                                   const NanConfigRequest& msg);
-  WifiStatus disableRequestInternal(uint16_t cmd_id);
-  WifiStatus startPublishRequestInternal(uint16_t cmd_id,
-                                         const NanPublishRequest& msg);
-  WifiStatus stopPublishRequestInternal(uint16_t cmd_id, uint8_t sessionId);
-  WifiStatus startSubscribeRequestInternal(uint16_t cmd_id,
-                                           const NanSubscribeRequest& msg);
-  WifiStatus stopSubscribeRequestInternal(uint16_t cmd_id, uint8_t sessionId);
-  WifiStatus transmitFollowupRequestInternal(
-      uint16_t cmd_id, const NanTransmitFollowupRequest& msg);
-  WifiStatus createDataInterfaceRequestInternal(uint16_t cmd_id,
-                                                const std::string& iface_name);
-  WifiStatus deleteDataInterfaceRequestInternal(uint16_t cmd_id,
-                                                const std::string& iface_name);
-  WifiStatus initiateDataPathRequestInternal(
-      uint16_t cmd_id, const NanInitiateDataPathRequest& msg);
-  WifiStatus respondToDataPathIndicationRequestInternal(
-      uint16_t cmd_id, const NanRespondToDataPathIndicationRequest& msg);
-  WifiStatus terminateDataPathRequestInternal(
-      uint16_t cmd_id, uint32_t ndpInstanceId);
-
-  std::set<sp<IWifiNanIfaceEventCallback>> getEventCallbacks();
-
-  std::string ifname_;
-  std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
-  bool is_valid_;
-  hidl_callback_util::HidlCallbackHandler<IWifiNanIfaceEventCallback>
-      event_cb_handler_;
-
-  DISALLOW_COPY_AND_ASSIGN(WifiNanIface);
-};
-
-}  // namespace implementation
-}  // namespace V1_1
-}  // namespace wifi
-}  // namespace hardware
-}  // namespace android
-
-#endif  // WIFI_NAN_IFACE_H_
diff --git a/wifi/1.1/default/wifi_rtt_controller.cpp b/wifi/1.1/default/wifi_rtt_controller.cpp
deleted file mode 100644
index 9ef702d..0000000
--- a/wifi/1.1/default/wifi_rtt_controller.cpp
+++ /dev/null
@@ -1,297 +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.
- */
-
-#include <android-base/logging.h>
-
-#include "hidl_return_util.h"
-#include "hidl_struct_util.h"
-#include "wifi_rtt_controller.h"
-#include "wifi_status_util.h"
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_1 {
-namespace implementation {
-using hidl_return_util::validateAndCall;
-
-WifiRttController::WifiRttController(
-    const sp<IWifiIface>& bound_iface,
-    const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal)
-    : bound_iface_(bound_iface), legacy_hal_(legacy_hal), is_valid_(true) {}
-
-void WifiRttController::invalidate() {
-  legacy_hal_.reset();
-  event_callbacks_.clear();
-  is_valid_ = false;
-}
-
-bool WifiRttController::isValid() {
-  return is_valid_;
-}
-
-std::vector<sp<IWifiRttControllerEventCallback>>
-WifiRttController::getEventCallbacks() {
-  return event_callbacks_;
-}
-
-Return<void> WifiRttController::getBoundIface(getBoundIface_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
-                         &WifiRttController::getBoundIfaceInternal,
-                         hidl_status_cb);
-}
-
-Return<void> WifiRttController::registerEventCallback(
-    const sp<IWifiRttControllerEventCallback>& callback,
-    registerEventCallback_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
-                         &WifiRttController::registerEventCallbackInternal,
-                         hidl_status_cb,
-                         callback);
-}
-
-Return<void> WifiRttController::rangeRequest(
-    uint32_t cmd_id,
-    const hidl_vec<RttConfig>& rtt_configs,
-    rangeRequest_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
-                         &WifiRttController::rangeRequestInternal,
-                         hidl_status_cb,
-                         cmd_id,
-                         rtt_configs);
-}
-
-Return<void> WifiRttController::rangeCancel(
-    uint32_t cmd_id,
-    const hidl_vec<hidl_array<uint8_t, 6>>& addrs,
-    rangeCancel_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
-                         &WifiRttController::rangeCancelInternal,
-                         hidl_status_cb,
-                         cmd_id,
-                         addrs);
-}
-
-Return<void> WifiRttController::getCapabilities(
-    getCapabilities_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
-                         &WifiRttController::getCapabilitiesInternal,
-                         hidl_status_cb);
-}
-
-Return<void> WifiRttController::setLci(uint32_t cmd_id,
-                                       const RttLciInformation& lci,
-                                       setLci_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
-                         &WifiRttController::setLciInternal,
-                         hidl_status_cb,
-                         cmd_id,
-                         lci);
-}
-
-Return<void> WifiRttController::setLcr(uint32_t cmd_id,
-                                       const RttLcrInformation& lcr,
-                                       setLcr_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
-                         &WifiRttController::setLcrInternal,
-                         hidl_status_cb,
-                         cmd_id,
-                         lcr);
-}
-
-Return<void> WifiRttController::getResponderInfo(
-    getResponderInfo_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
-                         &WifiRttController::getResponderInfoInternal,
-                         hidl_status_cb);
-}
-
-Return<void> WifiRttController::enableResponder(
-    uint32_t cmd_id,
-    const WifiChannelInfo& channel_hint,
-    uint32_t max_duration_seconds,
-    const RttResponder& info,
-    enableResponder_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
-                         &WifiRttController::enableResponderInternal,
-                         hidl_status_cb,
-                         cmd_id,
-                         channel_hint,
-                         max_duration_seconds,
-                         info);
-}
-
-Return<void> WifiRttController::disableResponder(
-    uint32_t cmd_id, disableResponder_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
-                         &WifiRttController::disableResponderInternal,
-                         hidl_status_cb,
-                         cmd_id);
-}
-
-std::pair<WifiStatus, sp<IWifiIface>>
-WifiRttController::getBoundIfaceInternal() {
-  return {createWifiStatus(WifiStatusCode::SUCCESS), bound_iface_};
-}
-
-WifiStatus WifiRttController::registerEventCallbackInternal(
-    const sp<IWifiRttControllerEventCallback>& callback) {
-  // TODO(b/31632518): remove the callback when the client is destroyed
-  event_callbacks_.emplace_back(callback);
-  return createWifiStatus(WifiStatusCode::SUCCESS);
-}
-
-WifiStatus WifiRttController::rangeRequestInternal(
-    uint32_t cmd_id, const std::vector<RttConfig>& rtt_configs) {
-  std::vector<legacy_hal::wifi_rtt_config> legacy_configs;
-  if (!hidl_struct_util::convertHidlVectorOfRttConfigToLegacy(
-          rtt_configs, &legacy_configs)) {
-    return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
-  }
-  android::wp<WifiRttController> weak_ptr_this(this);
-  const auto& on_results_callback = [weak_ptr_this](
-      legacy_hal::wifi_request_id id,
-      const std::vector<const legacy_hal::wifi_rtt_result*>& results) {
-    const auto shared_ptr_this = weak_ptr_this.promote();
-    if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
-      LOG(ERROR) << "Callback invoked on an invalid object";
-      return;
-    }
-    std::vector<RttResult> hidl_results;
-    if (!hidl_struct_util::convertLegacyVectorOfRttResultToHidl(
-            results, &hidl_results)) {
-      LOG(ERROR) << "Failed to convert rtt results to HIDL structs";
-      return;
-    }
-    for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
-      callback->onResults(id, hidl_results);
-    }
-  };
-  legacy_hal::wifi_error legacy_status =
-      legacy_hal_.lock()->startRttRangeRequest(
-          cmd_id, legacy_configs, on_results_callback);
-  return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiRttController::rangeCancelInternal(
-    uint32_t cmd_id, const std::vector<hidl_array<uint8_t, 6>>& addrs) {
-  std::vector<std::array<uint8_t, 6>> legacy_addrs;
-  for (const auto& addr : addrs) {
-    legacy_addrs.push_back(addr);
-  }
-  legacy_hal::wifi_error legacy_status =
-      legacy_hal_.lock()->cancelRttRangeRequest(cmd_id, legacy_addrs);
-  return createWifiStatusFromLegacyError(legacy_status);
-}
-
-std::pair<WifiStatus, RttCapabilities>
-WifiRttController::getCapabilitiesInternal() {
-  legacy_hal::wifi_error legacy_status;
-  legacy_hal::wifi_rtt_capabilities legacy_caps;
-  std::tie(legacy_status, legacy_caps) =
-      legacy_hal_.lock()->getRttCapabilities();
-  if (legacy_status != legacy_hal::WIFI_SUCCESS) {
-    return {createWifiStatusFromLegacyError(legacy_status), {}};
-  }
-  RttCapabilities hidl_caps;
-  if (!hidl_struct_util::convertLegacyRttCapabilitiesToHidl(legacy_caps,
-                                                            &hidl_caps)) {
-    return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
-  }
-  return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps};
-}
-
-WifiStatus WifiRttController::setLciInternal(uint32_t cmd_id,
-                                             const RttLciInformation& lci) {
-  legacy_hal::wifi_lci_information legacy_lci;
-  if (!hidl_struct_util::convertHidlRttLciInformationToLegacy(lci,
-                                                              &legacy_lci)) {
-    return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
-  }
-  legacy_hal::wifi_error legacy_status =
-      legacy_hal_.lock()->setRttLci(cmd_id, legacy_lci);
-  return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiRttController::setLcrInternal(uint32_t cmd_id,
-                                             const RttLcrInformation& lcr) {
-  legacy_hal::wifi_lcr_information legacy_lcr;
-  if (!hidl_struct_util::convertHidlRttLcrInformationToLegacy(lcr,
-                                                              &legacy_lcr)) {
-    return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
-  }
-  legacy_hal::wifi_error legacy_status =
-      legacy_hal_.lock()->setRttLcr(cmd_id, legacy_lcr);
-  return createWifiStatusFromLegacyError(legacy_status);
-}
-
-std::pair<WifiStatus, RttResponder>
-WifiRttController::getResponderInfoInternal() {
-  legacy_hal::wifi_error legacy_status;
-  legacy_hal::wifi_rtt_responder legacy_responder;
-  std::tie(legacy_status, legacy_responder) =
-      legacy_hal_.lock()->getRttResponderInfo();
-  if (legacy_status != legacy_hal::WIFI_SUCCESS) {
-    return {createWifiStatusFromLegacyError(legacy_status), {}};
-  }
-  RttResponder hidl_responder;
-  if (!hidl_struct_util::convertLegacyRttResponderToHidl(legacy_responder,
-                                                         &hidl_responder)) {
-    return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
-  }
-  return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_responder};
-}
-
-WifiStatus WifiRttController::enableResponderInternal(
-    uint32_t cmd_id,
-    const WifiChannelInfo& channel_hint,
-    uint32_t max_duration_seconds,
-    const RttResponder& info) {
-  legacy_hal::wifi_channel_info legacy_channel_info;
-  if (!hidl_struct_util::convertHidlWifiChannelInfoToLegacy(
-          channel_hint, &legacy_channel_info)) {
-    return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
-  }
-  legacy_hal::wifi_rtt_responder legacy_responder;
-  if (!hidl_struct_util::convertHidlRttResponderToLegacy(info,
-                                                         &legacy_responder)) {
-    return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
-  }
-  legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->enableRttResponder(
-      cmd_id, legacy_channel_info, max_duration_seconds, legacy_responder);
-  return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiRttController::disableResponderInternal(uint32_t cmd_id) {
-  legacy_hal::wifi_error legacy_status =
-      legacy_hal_.lock()->disableRttResponder(cmd_id);
-  return createWifiStatusFromLegacyError(legacy_status);
-}
-}  // namespace implementation
-}  // namespace V1_1
-}  // namespace wifi
-}  // namespace hardware
-}  // namespace android
diff --git a/wifi/1.1/default/wifi_rtt_controller.h b/wifi/1.1/default/wifi_rtt_controller.h
deleted file mode 100644
index 5437885..0000000
--- a/wifi/1.1/default/wifi_rtt_controller.h
+++ /dev/null
@@ -1,105 +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 WIFI_RTT_CONTROLLER_H_
-#define WIFI_RTT_CONTROLLER_H_
-
-#include <android-base/macros.h>
-#include <android/hardware/wifi/1.0/IWifiIface.h>
-#include <android/hardware/wifi/1.0/IWifiRttController.h>
-#include <android/hardware/wifi/1.0/IWifiRttControllerEventCallback.h>
-
-#include "wifi_legacy_hal.h"
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_1 {
-namespace implementation {
-
-/**
- * HIDL interface object used to control all RTT operations.
- */
-class WifiRttController : public V1_0::IWifiRttController {
- public:
-  WifiRttController(const sp<IWifiIface>& bound_iface,
-                    const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal);
-  // Refer to |WifiChip::invalidate()|.
-  void invalidate();
-  bool isValid();
-  std::vector<sp<IWifiRttControllerEventCallback>> getEventCallbacks();
-
-  // HIDL methods exposed.
-  Return<void> getBoundIface(getBoundIface_cb hidl_status_cb) override;
-  Return<void> registerEventCallback(
-      const sp<IWifiRttControllerEventCallback>& callback,
-      registerEventCallback_cb hidl_status_cb) override;
-  Return<void> rangeRequest(uint32_t cmd_id,
-                            const hidl_vec<RttConfig>& rtt_configs,
-                            rangeRequest_cb hidl_status_cb) override;
-  Return<void> rangeCancel(uint32_t cmd_id,
-                           const hidl_vec<hidl_array<uint8_t, 6>>& addrs,
-                           rangeCancel_cb hidl_status_cb) override;
-  Return<void> getCapabilities(getCapabilities_cb hidl_status_cb) override;
-  Return<void> setLci(uint32_t cmd_id,
-                      const RttLciInformation& lci,
-                      setLci_cb hidl_status_cb) override;
-  Return<void> setLcr(uint32_t cmd_id,
-                      const RttLcrInformation& lcr,
-                      setLcr_cb hidl_status_cb) override;
-  Return<void> getResponderInfo(getResponderInfo_cb hidl_status_cb) override;
-  Return<void> enableResponder(uint32_t cmd_id,
-                               const WifiChannelInfo& channel_hint,
-                               uint32_t max_duration_seconds,
-                               const RttResponder& info,
-                               enableResponder_cb hidl_status_cb) override;
-  Return<void> disableResponder(uint32_t cmd_id,
-                                disableResponder_cb hidl_status_cb) override;
-
- private:
-  // Corresponding worker functions for the HIDL methods.
-  std::pair<WifiStatus, sp<IWifiIface>> getBoundIfaceInternal();
-  WifiStatus registerEventCallbackInternal(
-      const sp<IWifiRttControllerEventCallback>& callback);
-  WifiStatus rangeRequestInternal(uint32_t cmd_id,
-                                  const std::vector<RttConfig>& rtt_configs);
-  WifiStatus rangeCancelInternal(
-      uint32_t cmd_id, const std::vector<hidl_array<uint8_t, 6>>& addrs);
-  std::pair<WifiStatus, RttCapabilities> getCapabilitiesInternal();
-  WifiStatus setLciInternal(uint32_t cmd_id, const RttLciInformation& lci);
-  WifiStatus setLcrInternal(uint32_t cmd_id, const RttLcrInformation& lcr);
-  std::pair<WifiStatus, RttResponder> getResponderInfoInternal();
-  WifiStatus enableResponderInternal(uint32_t cmd_id,
-                                     const WifiChannelInfo& channel_hint,
-                                     uint32_t max_duration_seconds,
-                                     const RttResponder& info);
-  WifiStatus disableResponderInternal(uint32_t cmd_id);
-
-  sp<IWifiIface> bound_iface_;
-  std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
-  std::vector<sp<IWifiRttControllerEventCallback>> event_callbacks_;
-  bool is_valid_;
-
-  DISALLOW_COPY_AND_ASSIGN(WifiRttController);
-};
-
-}  // namespace implementation
-}  // namespace V1_1
-}  // namespace wifi
-}  // namespace hardware
-}  // namespace android
-
-#endif  // WIFI_RTT_CONTROLLER_H_
diff --git a/wifi/1.1/default/wifi_sta_iface.cpp b/wifi/1.1/default/wifi_sta_iface.cpp
deleted file mode 100644
index 28f3f02..0000000
--- a/wifi/1.1/default/wifi_sta_iface.cpp
+++ /dev/null
@@ -1,629 +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.
- */
-
-#include <android-base/logging.h>
-
-#include "hidl_return_util.h"
-#include "hidl_struct_util.h"
-#include "wifi_sta_iface.h"
-#include "wifi_status_util.h"
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_1 {
-namespace implementation {
-using hidl_return_util::validateAndCall;
-
-WifiStaIface::WifiStaIface(
-    const std::string& ifname,
-    const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal)
-    : ifname_(ifname), legacy_hal_(legacy_hal), is_valid_(true) {
-  // Turn on DFS channel usage for STA iface.
-  legacy_hal::wifi_error legacy_status =
-      legacy_hal_.lock()->setDfsFlag(true);
-  if (legacy_status != legacy_hal::WIFI_SUCCESS) {
-    LOG(ERROR) << "Failed to set DFS flag; DFS channels may be unavailable.";
-  }
-}
-
-void WifiStaIface::invalidate() {
-  legacy_hal_.reset();
-  event_cb_handler_.invalidate();
-  is_valid_ = false;
-}
-
-bool WifiStaIface::isValid() {
-  return is_valid_;
-}
-
-std::set<sp<IWifiStaIfaceEventCallback>> WifiStaIface::getEventCallbacks() {
-  return event_cb_handler_.getCallbacks();
-}
-
-Return<void> WifiStaIface::getName(getName_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                         &WifiStaIface::getNameInternal,
-                         hidl_status_cb);
-}
-
-Return<void> WifiStaIface::getType(getType_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                         &WifiStaIface::getTypeInternal,
-                         hidl_status_cb);
-}
-
-Return<void> WifiStaIface::registerEventCallback(
-    const sp<IWifiStaIfaceEventCallback>& callback,
-    registerEventCallback_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                         &WifiStaIface::registerEventCallbackInternal,
-                         hidl_status_cb,
-                         callback);
-}
-
-Return<void> WifiStaIface::getCapabilities(getCapabilities_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                         &WifiStaIface::getCapabilitiesInternal,
-                         hidl_status_cb);
-}
-
-Return<void> WifiStaIface::getApfPacketFilterCapabilities(
-    getApfPacketFilterCapabilities_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                         &WifiStaIface::getApfPacketFilterCapabilitiesInternal,
-                         hidl_status_cb);
-}
-
-Return<void> WifiStaIface::installApfPacketFilter(
-    uint32_t cmd_id,
-    const hidl_vec<uint8_t>& program,
-    installApfPacketFilter_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                         &WifiStaIface::installApfPacketFilterInternal,
-                         hidl_status_cb,
-                         cmd_id,
-                         program);
-}
-
-Return<void> WifiStaIface::getBackgroundScanCapabilities(
-    getBackgroundScanCapabilities_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                         &WifiStaIface::getBackgroundScanCapabilitiesInternal,
-                         hidl_status_cb);
-}
-
-Return<void> WifiStaIface::getValidFrequenciesForBand(
-    WifiBand band, getValidFrequenciesForBand_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                         &WifiStaIface::getValidFrequenciesForBandInternal,
-                         hidl_status_cb,
-                         band);
-}
-
-Return<void> WifiStaIface::startBackgroundScan(
-    uint32_t cmd_id,
-    const StaBackgroundScanParameters& params,
-    startBackgroundScan_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                         &WifiStaIface::startBackgroundScanInternal,
-                         hidl_status_cb,
-                         cmd_id,
-                         params);
-}
-
-Return<void> WifiStaIface::stopBackgroundScan(
-    uint32_t cmd_id, stopBackgroundScan_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                         &WifiStaIface::stopBackgroundScanInternal,
-                         hidl_status_cb,
-                         cmd_id);
-}
-
-Return<void> WifiStaIface::enableLinkLayerStatsCollection(
-    bool debug, enableLinkLayerStatsCollection_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                         &WifiStaIface::enableLinkLayerStatsCollectionInternal,
-                         hidl_status_cb,
-                         debug);
-}
-
-Return<void> WifiStaIface::disableLinkLayerStatsCollection(
-    disableLinkLayerStatsCollection_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                         &WifiStaIface::disableLinkLayerStatsCollectionInternal,
-                         hidl_status_cb);
-}
-
-Return<void> WifiStaIface::getLinkLayerStats(
-    getLinkLayerStats_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                         &WifiStaIface::getLinkLayerStatsInternal,
-                         hidl_status_cb);
-}
-
-Return<void> WifiStaIface::startRssiMonitoring(
-    uint32_t cmd_id,
-    int32_t max_rssi,
-    int32_t min_rssi,
-    startRssiMonitoring_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                         &WifiStaIface::startRssiMonitoringInternal,
-                         hidl_status_cb,
-                         cmd_id,
-                         max_rssi,
-                         min_rssi);
-}
-
-Return<void> WifiStaIface::stopRssiMonitoring(
-    uint32_t cmd_id, stopRssiMonitoring_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                         &WifiStaIface::stopRssiMonitoringInternal,
-                         hidl_status_cb,
-                         cmd_id);
-}
-
-Return<void> WifiStaIface::getRoamingCapabilities(
-    getRoamingCapabilities_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                         &WifiStaIface::getRoamingCapabilitiesInternal,
-                         hidl_status_cb);
-}
-
-Return<void> WifiStaIface::configureRoaming(
-    const StaRoamingConfig& config, configureRoaming_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                         &WifiStaIface::configureRoamingInternal,
-                         hidl_status_cb,
-                         config);
-}
-
-Return<void> WifiStaIface::setRoamingState(StaRoamingState state,
-                                           setRoamingState_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                         &WifiStaIface::setRoamingStateInternal,
-                         hidl_status_cb,
-                         state);
-}
-
-Return<void> WifiStaIface::enableNdOffload(bool enable,
-                                           enableNdOffload_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                         &WifiStaIface::enableNdOffloadInternal,
-                         hidl_status_cb,
-                         enable);
-}
-
-Return<void> WifiStaIface::startSendingKeepAlivePackets(
-    uint32_t cmd_id,
-    const hidl_vec<uint8_t>& ip_packet_data,
-    uint16_t ether_type,
-    const hidl_array<uint8_t, 6>& src_address,
-    const hidl_array<uint8_t, 6>& dst_address,
-    uint32_t period_in_ms,
-    startSendingKeepAlivePackets_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                         &WifiStaIface::startSendingKeepAlivePacketsInternal,
-                         hidl_status_cb,
-                         cmd_id,
-                         ip_packet_data,
-                         ether_type,
-                         src_address,
-                         dst_address,
-                         period_in_ms);
-}
-
-Return<void> WifiStaIface::stopSendingKeepAlivePackets(
-    uint32_t cmd_id, stopSendingKeepAlivePackets_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                         &WifiStaIface::stopSendingKeepAlivePacketsInternal,
-                         hidl_status_cb,
-                         cmd_id);
-}
-
-Return<void> WifiStaIface::setScanningMacOui(
-    const hidl_array<uint8_t, 3>& oui, setScanningMacOui_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                         &WifiStaIface::setScanningMacOuiInternal,
-                         hidl_status_cb,
-                         oui);
-}
-
-Return<void> WifiStaIface::startDebugPacketFateMonitoring(
-    startDebugPacketFateMonitoring_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                         &WifiStaIface::startDebugPacketFateMonitoringInternal,
-                         hidl_status_cb);
-}
-
-Return<void> WifiStaIface::getDebugTxPacketFates(
-    getDebugTxPacketFates_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                         &WifiStaIface::getDebugTxPacketFatesInternal,
-                         hidl_status_cb);
-}
-
-Return<void> WifiStaIface::getDebugRxPacketFates(
-    getDebugRxPacketFates_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                         &WifiStaIface::getDebugRxPacketFatesInternal,
-                         hidl_status_cb);
-}
-
-std::pair<WifiStatus, std::string> WifiStaIface::getNameInternal() {
-  return {createWifiStatus(WifiStatusCode::SUCCESS), ifname_};
-}
-
-std::pair<WifiStatus, IfaceType> WifiStaIface::getTypeInternal() {
-  return {createWifiStatus(WifiStatusCode::SUCCESS), IfaceType::STA};
-}
-
-WifiStatus WifiStaIface::registerEventCallbackInternal(
-    const sp<IWifiStaIfaceEventCallback>& callback) {
-  if (!event_cb_handler_.addCallback(callback)) {
-    return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
-  }
-  return createWifiStatus(WifiStatusCode::SUCCESS);
-}
-
-std::pair<WifiStatus, uint32_t> WifiStaIface::getCapabilitiesInternal() {
-  legacy_hal::wifi_error legacy_status;
-  uint32_t legacy_feature_set;
-  std::tie(legacy_status, legacy_feature_set) =
-      legacy_hal_.lock()->getSupportedFeatureSet();
-  if (legacy_status != legacy_hal::WIFI_SUCCESS) {
-    return {createWifiStatusFromLegacyError(legacy_status), 0};
-  }
-  uint32_t legacy_logger_feature_set;
-  std::tie(legacy_status, legacy_logger_feature_set) =
-      legacy_hal_.lock()->getLoggerSupportedFeatureSet();
-  if (legacy_status != legacy_hal::WIFI_SUCCESS) {
-    // some devices don't support querying logger feature set
-    legacy_logger_feature_set = 0;
-  }
-  uint32_t hidl_caps;
-  if (!hidl_struct_util::convertLegacyFeaturesToHidlStaCapabilities(
-          legacy_feature_set, legacy_logger_feature_set, &hidl_caps)) {
-    return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), 0};
-  }
-  return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps};
-}
-
-std::pair<WifiStatus, StaApfPacketFilterCapabilities>
-WifiStaIface::getApfPacketFilterCapabilitiesInternal() {
-  legacy_hal::wifi_error legacy_status;
-  legacy_hal::PacketFilterCapabilities legacy_caps;
-  std::tie(legacy_status, legacy_caps) =
-      legacy_hal_.lock()->getPacketFilterCapabilities();
-  if (legacy_status != legacy_hal::WIFI_SUCCESS) {
-    return {createWifiStatusFromLegacyError(legacy_status), {}};
-  }
-  StaApfPacketFilterCapabilities hidl_caps;
-  if (!hidl_struct_util::convertLegacyApfCapabilitiesToHidl(legacy_caps,
-                                                            &hidl_caps)) {
-    return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
-  }
-  return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps};
-}
-
-WifiStatus WifiStaIface::installApfPacketFilterInternal(
-    uint32_t /* cmd_id */, const std::vector<uint8_t>& program) {
-  legacy_hal::wifi_error legacy_status =
-      legacy_hal_.lock()->setPacketFilter(program);
-  return createWifiStatusFromLegacyError(legacy_status);
-}
-
-std::pair<WifiStatus, StaBackgroundScanCapabilities>
-WifiStaIface::getBackgroundScanCapabilitiesInternal() {
-  legacy_hal::wifi_error legacy_status;
-  legacy_hal::wifi_gscan_capabilities legacy_caps;
-  std::tie(legacy_status, legacy_caps) =
-      legacy_hal_.lock()->getGscanCapabilities();
-  if (legacy_status != legacy_hal::WIFI_SUCCESS) {
-    return {createWifiStatusFromLegacyError(legacy_status), {}};
-  }
-  StaBackgroundScanCapabilities hidl_caps;
-  if (!hidl_struct_util::convertLegacyGscanCapabilitiesToHidl(legacy_caps,
-                                                              &hidl_caps)) {
-    return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
-  }
-  return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps};
-}
-
-std::pair<WifiStatus, std::vector<WifiChannelInMhz>>
-WifiStaIface::getValidFrequenciesForBandInternal(WifiBand band) {
-  static_assert(sizeof(WifiChannelInMhz) == sizeof(uint32_t), "Size mismatch");
-  legacy_hal::wifi_error legacy_status;
-  std::vector<uint32_t> valid_frequencies;
-  std::tie(legacy_status, valid_frequencies) =
-      legacy_hal_.lock()->getValidFrequenciesForBand(
-          hidl_struct_util::convertHidlWifiBandToLegacy(band));
-  return {createWifiStatusFromLegacyError(legacy_status), valid_frequencies};
-}
-
-WifiStatus WifiStaIface::startBackgroundScanInternal(
-    uint32_t cmd_id, const StaBackgroundScanParameters& params) {
-  legacy_hal::wifi_scan_cmd_params legacy_params;
-  if (!hidl_struct_util::convertHidlGscanParamsToLegacy(params,
-                                                        &legacy_params)) {
-    return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
-  }
-  android::wp<WifiStaIface> weak_ptr_this(this);
-  const auto& on_failure_callback =
-      [weak_ptr_this](legacy_hal::wifi_request_id id) {
-        const auto shared_ptr_this = weak_ptr_this.promote();
-        if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
-          LOG(ERROR) << "Callback invoked on an invalid object";
-          return;
-        }
-        for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
-          if (!callback->onBackgroundScanFailure(id).isOk()) {
-            LOG(ERROR) << "Failed to invoke onBackgroundScanFailure callback";
-          }
-        }
-      };
-  const auto& on_results_callback = [weak_ptr_this](
-      legacy_hal::wifi_request_id id,
-      const std::vector<legacy_hal::wifi_cached_scan_results>& results) {
-    const auto shared_ptr_this = weak_ptr_this.promote();
-    if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
-      LOG(ERROR) << "Callback invoked on an invalid object";
-      return;
-    }
-    std::vector<StaScanData> hidl_scan_datas;
-    if (!hidl_struct_util::convertLegacyVectorOfCachedGscanResultsToHidl(
-            results, &hidl_scan_datas)) {
-      LOG(ERROR) << "Failed to convert scan results to HIDL structs";
-      return;
-    }
-    for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
-      if (!callback->onBackgroundScanResults(id, hidl_scan_datas).isOk()) {
-        LOG(ERROR) << "Failed to invoke onBackgroundScanResults callback";
-      }
-    }
-  };
-  const auto& on_full_result_callback = [weak_ptr_this](
-      legacy_hal::wifi_request_id id,
-      const legacy_hal::wifi_scan_result* result,
-      uint32_t buckets_scanned) {
-    const auto shared_ptr_this = weak_ptr_this.promote();
-    if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
-      LOG(ERROR) << "Callback invoked on an invalid object";
-      return;
-    }
-    StaScanResult hidl_scan_result;
-    if (!hidl_struct_util::convertLegacyGscanResultToHidl(
-            *result, true, &hidl_scan_result)) {
-      LOG(ERROR) << "Failed to convert full scan results to HIDL structs";
-      return;
-    }
-    for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
-      if (!callback->onBackgroundFullScanResult(
-              id, buckets_scanned, hidl_scan_result).isOk()) {
-        LOG(ERROR) << "Failed to invoke onBackgroundFullScanResult callback";
-      }
-    }
-  };
-  legacy_hal::wifi_error legacy_status =
-      legacy_hal_.lock()->startGscan(cmd_id,
-                                     legacy_params,
-                                     on_failure_callback,
-                                     on_results_callback,
-                                     on_full_result_callback);
-  return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiStaIface::stopBackgroundScanInternal(uint32_t cmd_id) {
-  legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->stopGscan(cmd_id);
-  return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiStaIface::enableLinkLayerStatsCollectionInternal(bool debug) {
-  legacy_hal::wifi_error legacy_status =
-      legacy_hal_.lock()->enableLinkLayerStats(debug);
-  return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiStaIface::disableLinkLayerStatsCollectionInternal() {
-  legacy_hal::wifi_error legacy_status =
-      legacy_hal_.lock()->disableLinkLayerStats();
-  return createWifiStatusFromLegacyError(legacy_status);
-}
-
-std::pair<WifiStatus, StaLinkLayerStats>
-WifiStaIface::getLinkLayerStatsInternal() {
-  legacy_hal::wifi_error legacy_status;
-  legacy_hal::LinkLayerStats legacy_stats;
-  std::tie(legacy_status, legacy_stats) =
-      legacy_hal_.lock()->getLinkLayerStats();
-  if (legacy_status != legacy_hal::WIFI_SUCCESS) {
-    return {createWifiStatusFromLegacyError(legacy_status), {}};
-  }
-  StaLinkLayerStats hidl_stats;
-  if (!hidl_struct_util::convertLegacyLinkLayerStatsToHidl(legacy_stats,
-                                                           &hidl_stats)) {
-    return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
-  }
-  return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_stats};
-}
-
-WifiStatus WifiStaIface::startRssiMonitoringInternal(uint32_t cmd_id,
-                                                     int32_t max_rssi,
-                                                     int32_t min_rssi) {
-  android::wp<WifiStaIface> weak_ptr_this(this);
-  const auto& on_threshold_breached_callback = [weak_ptr_this](
-      legacy_hal::wifi_request_id id,
-      std::array<uint8_t, 6> bssid,
-      int8_t rssi) {
-    const auto shared_ptr_this = weak_ptr_this.promote();
-    if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
-      LOG(ERROR) << "Callback invoked on an invalid object";
-      return;
-    }
-    for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
-      if (!callback->onRssiThresholdBreached(id, bssid, rssi).isOk()) {
-        LOG(ERROR) << "Failed to invoke onRssiThresholdBreached callback";
-      }
-    }
-  };
-  legacy_hal::wifi_error legacy_status =
-      legacy_hal_.lock()->startRssiMonitoring(
-          cmd_id, max_rssi, min_rssi, on_threshold_breached_callback);
-  return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiStaIface::stopRssiMonitoringInternal(uint32_t cmd_id) {
-  legacy_hal::wifi_error legacy_status =
-      legacy_hal_.lock()->stopRssiMonitoring(cmd_id);
-  return createWifiStatusFromLegacyError(legacy_status);
-}
-
-std::pair<WifiStatus, StaRoamingCapabilities>
-WifiStaIface::getRoamingCapabilitiesInternal() {
-  legacy_hal::wifi_error legacy_status;
-  legacy_hal::wifi_roaming_capabilities legacy_caps;
-  std::tie(legacy_status, legacy_caps) =
-      legacy_hal_.lock()->getRoamingCapabilities();
-  if (legacy_status != legacy_hal::WIFI_SUCCESS) {
-    return {createWifiStatusFromLegacyError(legacy_status), {}};
-  }
-  StaRoamingCapabilities hidl_caps;
-  if (!hidl_struct_util::convertLegacyRoamingCapabilitiesToHidl(legacy_caps,
-                                                                &hidl_caps)) {
-    return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
-  }
-  return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps};
-}
-
-WifiStatus WifiStaIface::configureRoamingInternal(
-    const StaRoamingConfig& config) {
-  legacy_hal::wifi_roaming_config legacy_config;
-  if (!hidl_struct_util::convertHidlRoamingConfigToLegacy(config,
-                                                          &legacy_config)) {
-    return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
-  }
-  legacy_hal::wifi_error legacy_status =
-      legacy_hal_.lock()->configureRoaming(legacy_config);
-  return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiStaIface::setRoamingStateInternal(StaRoamingState state) {
-  legacy_hal::wifi_error legacy_status =
-      legacy_hal_.lock()->enableFirmwareRoaming(
-          hidl_struct_util::convertHidlRoamingStateToLegacy(state));
-  return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiStaIface::enableNdOffloadInternal(bool enable) {
-  legacy_hal::wifi_error legacy_status =
-      legacy_hal_.lock()->configureNdOffload(enable);
-  return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiStaIface::startSendingKeepAlivePacketsInternal(
-    uint32_t cmd_id,
-    const std::vector<uint8_t>& ip_packet_data,
-    uint16_t /* ether_type */,
-    const std::array<uint8_t, 6>& src_address,
-    const std::array<uint8_t, 6>& dst_address,
-    uint32_t period_in_ms) {
-  legacy_hal::wifi_error legacy_status =
-      legacy_hal_.lock()->startSendingOffloadedPacket(
-          cmd_id, ip_packet_data, src_address, dst_address, period_in_ms);
-  return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiStaIface::stopSendingKeepAlivePacketsInternal(uint32_t cmd_id) {
-  legacy_hal::wifi_error legacy_status =
-      legacy_hal_.lock()->stopSendingOffloadedPacket(cmd_id);
-  return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiStaIface::setScanningMacOuiInternal(
-    const std::array<uint8_t, 3>& oui) {
-  legacy_hal::wifi_error legacy_status =
-      legacy_hal_.lock()->setScanningMacOui(oui);
-  return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiStaIface::startDebugPacketFateMonitoringInternal() {
-  legacy_hal::wifi_error legacy_status =
-      legacy_hal_.lock()->startPktFateMonitoring();
-  return createWifiStatusFromLegacyError(legacy_status);
-}
-
-std::pair<WifiStatus, std::vector<WifiDebugTxPacketFateReport>>
-WifiStaIface::getDebugTxPacketFatesInternal() {
-  legacy_hal::wifi_error legacy_status;
-  std::vector<legacy_hal::wifi_tx_report> legacy_fates;
-  std::tie(legacy_status, legacy_fates) = legacy_hal_.lock()->getTxPktFates();
-  if (legacy_status != legacy_hal::WIFI_SUCCESS) {
-    return {createWifiStatusFromLegacyError(legacy_status), {}};
-  }
-  std::vector<WifiDebugTxPacketFateReport> hidl_fates;
-  if (!hidl_struct_util::convertLegacyVectorOfDebugTxPacketFateToHidl(
-          legacy_fates, &hidl_fates)) {
-    return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
-  }
-  return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_fates};
-}
-
-std::pair<WifiStatus, std::vector<WifiDebugRxPacketFateReport>>
-WifiStaIface::getDebugRxPacketFatesInternal() {
-  legacy_hal::wifi_error legacy_status;
-  std::vector<legacy_hal::wifi_rx_report> legacy_fates;
-  std::tie(legacy_status, legacy_fates) = legacy_hal_.lock()->getRxPktFates();
-  if (legacy_status != legacy_hal::WIFI_SUCCESS) {
-    return {createWifiStatusFromLegacyError(legacy_status), {}};
-  }
-  std::vector<WifiDebugRxPacketFateReport> hidl_fates;
-  if (!hidl_struct_util::convertLegacyVectorOfDebugRxPacketFateToHidl(
-          legacy_fates, &hidl_fates)) {
-    return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
-  }
-  return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_fates};
-}
-
-}  // namespace implementation
-}  // namespace V1_1
-}  // namespace wifi
-}  // namespace hardware
-}  // namespace android
diff --git a/wifi/1.1/default/wifi_sta_iface.h b/wifi/1.1/default/wifi_sta_iface.h
deleted file mode 100644
index 587a5de..0000000
--- a/wifi/1.1/default/wifi_sta_iface.h
+++ /dev/null
@@ -1,168 +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 WIFI_STA_IFACE_H_
-#define WIFI_STA_IFACE_H_
-
-#include <android-base/macros.h>
-#include <android/hardware/wifi/1.0/IWifiStaIface.h>
-#include <android/hardware/wifi/1.0/IWifiStaIfaceEventCallback.h>
-
-#include "hidl_callback_util.h"
-#include "wifi_legacy_hal.h"
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_1 {
-namespace implementation {
-using namespace android::hardware::wifi::V1_0;
-
-/**
- * HIDL interface object used to control a STA Iface instance.
- */
-class WifiStaIface : public V1_0::IWifiStaIface {
- public:
-  WifiStaIface(const std::string& ifname,
-               const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal);
-  // Refer to |WifiChip::invalidate()|.
-  void invalidate();
-  bool isValid();
-  std::set<sp<IWifiStaIfaceEventCallback>> getEventCallbacks();
-
-  // HIDL methods exposed.
-  Return<void> getName(getName_cb hidl_status_cb) override;
-  Return<void> getType(getType_cb hidl_status_cb) override;
-  Return<void> registerEventCallback(
-      const sp<IWifiStaIfaceEventCallback>& callback,
-      registerEventCallback_cb hidl_status_cb) override;
-  Return<void> getCapabilities(getCapabilities_cb hidl_status_cb) override;
-  Return<void> getApfPacketFilterCapabilities(
-      getApfPacketFilterCapabilities_cb hidl_status_cb) override;
-  Return<void> installApfPacketFilter(
-      uint32_t cmd_id,
-      const hidl_vec<uint8_t>& program,
-      installApfPacketFilter_cb hidl_status_cb) override;
-  Return<void> getBackgroundScanCapabilities(
-      getBackgroundScanCapabilities_cb hidl_status_cb) override;
-  Return<void> getValidFrequenciesForBand(
-      WifiBand band, getValidFrequenciesForBand_cb hidl_status_cb) override;
-  Return<void> startBackgroundScan(
-      uint32_t cmd_id,
-      const StaBackgroundScanParameters& params,
-      startBackgroundScan_cb hidl_status_cb) override;
-  Return<void> stopBackgroundScan(
-      uint32_t cmd_id, stopBackgroundScan_cb hidl_status_cb) override;
-  Return<void> enableLinkLayerStatsCollection(
-      bool debug, enableLinkLayerStatsCollection_cb hidl_status_cb) override;
-  Return<void> disableLinkLayerStatsCollection(
-      disableLinkLayerStatsCollection_cb hidl_status_cb) override;
-  Return<void> getLinkLayerStats(getLinkLayerStats_cb hidl_status_cb) override;
-  Return<void> startRssiMonitoring(
-      uint32_t cmd_id,
-      int32_t max_rssi,
-      int32_t min_rssi,
-      startRssiMonitoring_cb hidl_status_cb) override;
-  Return<void> stopRssiMonitoring(
-      uint32_t cmd_id, stopRssiMonitoring_cb hidl_status_cb) override;
-  Return<void> getRoamingCapabilities(
-      getRoamingCapabilities_cb hidl_status_cb) override;
-  Return<void> configureRoaming(const StaRoamingConfig& config,
-                                configureRoaming_cb hidl_status_cb) override;
-  Return<void> setRoamingState(StaRoamingState state,
-                               setRoamingState_cb hidl_status_cb) override;
-  Return<void> enableNdOffload(bool enable,
-                               enableNdOffload_cb hidl_status_cb) override;
-  Return<void> startSendingKeepAlivePackets(
-      uint32_t cmd_id,
-      const hidl_vec<uint8_t>& ip_packet_data,
-      uint16_t ether_type,
-      const hidl_array<uint8_t, 6>& src_address,
-      const hidl_array<uint8_t, 6>& dst_address,
-      uint32_t period_in_ms,
-      startSendingKeepAlivePackets_cb hidl_status_cb) override;
-  Return<void> stopSendingKeepAlivePackets(
-      uint32_t cmd_id, stopSendingKeepAlivePackets_cb hidl_status_cb) override;
-  Return<void> setScanningMacOui(const hidl_array<uint8_t, 3>& oui,
-                                 setScanningMacOui_cb hidl_status_cb) override;
-  Return<void> startDebugPacketFateMonitoring(
-      startDebugPacketFateMonitoring_cb hidl_status_cb) override;
-  Return<void> getDebugTxPacketFates(
-      getDebugTxPacketFates_cb hidl_status_cb) override;
-  Return<void> getDebugRxPacketFates(
-      getDebugRxPacketFates_cb hidl_status_cb) override;
-
- private:
-  // Corresponding worker functions for the HIDL methods.
-  std::pair<WifiStatus, std::string> getNameInternal();
-  std::pair<WifiStatus, IfaceType> getTypeInternal();
-  WifiStatus registerEventCallbackInternal(
-      const sp<IWifiStaIfaceEventCallback>& callback);
-  std::pair<WifiStatus, uint32_t> getCapabilitiesInternal();
-  std::pair<WifiStatus, StaApfPacketFilterCapabilities>
-  getApfPacketFilterCapabilitiesInternal();
-  WifiStatus installApfPacketFilterInternal(
-      uint32_t cmd_id, const std::vector<uint8_t>& program);
-  std::pair<WifiStatus, StaBackgroundScanCapabilities>
-  getBackgroundScanCapabilitiesInternal();
-  std::pair<WifiStatus, std::vector<WifiChannelInMhz>>
-  getValidFrequenciesForBandInternal(WifiBand band);
-  WifiStatus startBackgroundScanInternal(
-      uint32_t cmd_id, const StaBackgroundScanParameters& params);
-  WifiStatus stopBackgroundScanInternal(uint32_t cmd_id);
-  WifiStatus enableLinkLayerStatsCollectionInternal(bool debug);
-  WifiStatus disableLinkLayerStatsCollectionInternal();
-  std::pair<WifiStatus, StaLinkLayerStats> getLinkLayerStatsInternal();
-  WifiStatus startRssiMonitoringInternal(uint32_t cmd_id,
-                                         int32_t max_rssi,
-                                         int32_t min_rssi);
-  WifiStatus stopRssiMonitoringInternal(uint32_t cmd_id);
-  std::pair<WifiStatus, StaRoamingCapabilities>
-  getRoamingCapabilitiesInternal();
-  WifiStatus configureRoamingInternal(const StaRoamingConfig& config);
-  WifiStatus setRoamingStateInternal(StaRoamingState state);
-  WifiStatus enableNdOffloadInternal(bool enable);
-  WifiStatus startSendingKeepAlivePacketsInternal(
-      uint32_t cmd_id,
-      const std::vector<uint8_t>& ip_packet_data,
-      uint16_t ether_type,
-      const std::array<uint8_t, 6>& src_address,
-      const std::array<uint8_t, 6>& dst_address,
-      uint32_t period_in_ms);
-  WifiStatus stopSendingKeepAlivePacketsInternal(uint32_t cmd_id);
-  WifiStatus setScanningMacOuiInternal(const std::array<uint8_t, 3>& oui);
-  WifiStatus startDebugPacketFateMonitoringInternal();
-  std::pair<WifiStatus, std::vector<WifiDebugTxPacketFateReport>>
-  getDebugTxPacketFatesInternal();
-  std::pair<WifiStatus, std::vector<WifiDebugRxPacketFateReport>>
-  getDebugRxPacketFatesInternal();
-
-  std::string ifname_;
-  std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
-  bool is_valid_;
-  hidl_callback_util::HidlCallbackHandler<IWifiStaIfaceEventCallback>
-      event_cb_handler_;
-
-  DISALLOW_COPY_AND_ASSIGN(WifiStaIface);
-};
-
-}  // namespace implementation
-}  // namespace V1_1
-}  // namespace wifi
-}  // namespace hardware
-}  // namespace android
-
-#endif  // WIFI_STA_IFACE_H_
diff --git a/wifi/1.1/default/wifi_status_util.cpp b/wifi/1.1/default/wifi_status_util.cpp
deleted file mode 100644
index 3a85e09..0000000
--- a/wifi/1.1/default/wifi_status_util.cpp
+++ /dev/null
@@ -1,106 +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.
- */
-
-#include "wifi_status_util.h"
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_1 {
-namespace implementation {
-
-std::string legacyErrorToString(legacy_hal::wifi_error error) {
-  switch (error) {
-    case legacy_hal::WIFI_SUCCESS:
-      return "SUCCESS";
-    case legacy_hal::WIFI_ERROR_UNINITIALIZED:
-      return "UNINITIALIZED";
-    case legacy_hal::WIFI_ERROR_NOT_AVAILABLE:
-      return "NOT_AVAILABLE";
-    case legacy_hal::WIFI_ERROR_NOT_SUPPORTED:
-      return "NOT_SUPPORTED";
-    case legacy_hal::WIFI_ERROR_INVALID_ARGS:
-      return "INVALID_ARGS";
-    case legacy_hal::WIFI_ERROR_INVALID_REQUEST_ID:
-      return "INVALID_REQUEST_ID";
-    case legacy_hal::WIFI_ERROR_TIMED_OUT:
-      return "TIMED_OUT";
-    case legacy_hal::WIFI_ERROR_TOO_MANY_REQUESTS:
-      return "TOO_MANY_REQUESTS";
-    case legacy_hal::WIFI_ERROR_OUT_OF_MEMORY:
-      return "OUT_OF_MEMORY";
-    case legacy_hal::WIFI_ERROR_BUSY:
-      return "BUSY";
-    case legacy_hal::WIFI_ERROR_UNKNOWN:
-      return "UNKNOWN";
-  }
-}
-
-WifiStatus createWifiStatus(WifiStatusCode code,
-                            const std::string& description) {
-  return {code, description};
-}
-
-WifiStatus createWifiStatus(WifiStatusCode code) {
-  return createWifiStatus(code, "");
-}
-
-WifiStatus createWifiStatusFromLegacyError(legacy_hal::wifi_error error,
-                                           const std::string& desc) {
-  switch (error) {
-    case legacy_hal::WIFI_ERROR_UNINITIALIZED:
-    case legacy_hal::WIFI_ERROR_NOT_AVAILABLE:
-      return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE, desc);
-
-    case legacy_hal::WIFI_ERROR_NOT_SUPPORTED:
-      return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED, desc);
-
-    case legacy_hal::WIFI_ERROR_INVALID_ARGS:
-    case legacy_hal::WIFI_ERROR_INVALID_REQUEST_ID:
-      return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS, desc);
-
-    case legacy_hal::WIFI_ERROR_TIMED_OUT:
-      return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN,
-                              desc + ", timed out");
-
-    case legacy_hal::WIFI_ERROR_TOO_MANY_REQUESTS:
-      return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN,
-                              desc + ", too many requests");
-
-    case legacy_hal::WIFI_ERROR_OUT_OF_MEMORY:
-      return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN,
-                              desc + ", out of memory");
-
-    case legacy_hal::WIFI_ERROR_BUSY:
-      return createWifiStatus(WifiStatusCode::ERROR_BUSY);
-
-    case legacy_hal::WIFI_ERROR_NONE:
-      return createWifiStatus(WifiStatusCode::SUCCESS, desc);
-
-    case legacy_hal::WIFI_ERROR_UNKNOWN:
-      return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN, "unknown");
-  }
-}
-
-WifiStatus createWifiStatusFromLegacyError(legacy_hal::wifi_error error) {
-  return createWifiStatusFromLegacyError(error, "");
-}
-
-}  // namespace implementation
-}  // namespace V1_1
-}  // namespace wifi
-}  // namespace hardware
-}  // namespace android
diff --git a/wifi/1.2/Android.bp b/wifi/1.2/Android.bp
new file mode 100644
index 0000000..49752a1
--- /dev/null
+++ b/wifi/1.2/Android.bp
@@ -0,0 +1,20 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.wifi@1.2",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "IWifi.hal",
+        "IWifiChip.hal",
+    ],
+    interfaces: [
+        "android.hardware.wifi@1.0",
+        "android.hardware.wifi@1.1",
+        "android.hidl.base@1.0",
+    ],
+    gen_java: true,
+}
+
diff --git a/wifi/1.2/IWifi.hal b/wifi/1.2/IWifi.hal
new file mode 100644
index 0000000..7f47027
--- /dev/null
+++ b/wifi/1.2/IWifi.hal
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+package android.hardware.wifi@1.2;
+
+import @1.1::IWifi;
+
+/**
+ * This is the root of the HAL module and is the interface returned when
+ * loading an implementation of the Wi-Fi HAL. There must be at most one
+ * module loaded in the system.
+ * IWifi.getChip() may return either a @1.0::IWifiChip or @1.1::IWifiChip
+ * or @1.2:IWifiChip
+ */
+interface IWifi extends @1.1::IWifi {
+};
diff --git a/wifi/1.2/IWifiChip.hal b/wifi/1.2/IWifiChip.hal
new file mode 100644
index 0000000..72cbf81
--- /dev/null
+++ b/wifi/1.2/IWifiChip.hal
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+
+package android.hardware.wifi@1.2;
+
+import @1.1::IWifiChip;
+
+/**
+ * Interface that represents a chip that must be configured as a single unit.
+ * The HAL/driver/firmware will be responsible for determining which phy is used
+ * to perform operations like NAN, RTT, etc.
+ */
+interface IWifiChip extends @1.1::IWifiChip {
+};
diff --git a/wifi/1.2/default/Android.mk b/wifi/1.2/default/Android.mk
new file mode 100644
index 0000000..95414bc
--- /dev/null
+++ b/wifi/1.2/default/Android.mk
@@ -0,0 +1,118 @@
+# 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)
+
+###
+### android.hardware.wifi static library
+###
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.wifi@1.0-service-lib
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_PROPRIETARY_MODULE := true
+LOCAL_CPPFLAGS := -Wall -Werror -Wextra
+ifdef WIFI_HIDL_FEATURE_AWARE
+LOCAL_CPPFLAGS += -DWIFI_HIDL_FEATURE_AWARE
+endif
+ifdef WIFI_HIDL_FEATURE_DUAL_INTERFACE
+LOCAL_CPPFLAGS += -DWIFI_HIDL_FEATURE_DUAL_INTERFACE
+endif
+LOCAL_SRC_FILES := \
+    hidl_struct_util.cpp \
+    hidl_sync_util.cpp \
+    wifi.cpp \
+    wifi_ap_iface.cpp \
+    wifi_chip.cpp \
+    wifi_feature_flags.cpp \
+    wifi_legacy_hal.cpp \
+    wifi_legacy_hal_stubs.cpp \
+    wifi_mode_controller.cpp \
+    wifi_nan_iface.cpp \
+    wifi_p2p_iface.cpp \
+    wifi_rtt_controller.cpp \
+    wifi_sta_iface.cpp \
+    wifi_status_util.cpp
+LOCAL_SHARED_LIBRARIES := \
+    libbase \
+    libcutils \
+    libhidlbase \
+    libhidltransport \
+    liblog \
+    libnl \
+    libutils \
+    libwifi-hal \
+    libwifi-system-iface \
+    android.hardware.wifi@1.0 \
+    android.hardware.wifi@1.1 \
+    android.hardware.wifi@1.2
+LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
+include $(BUILD_STATIC_LIBRARY)
+
+###
+### android.hardware.wifi daemon
+###
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.wifi@1.0-service
+LOCAL_MODULE_RELATIVE_PATH := hw
+LOCAL_PROPRIETARY_MODULE := true
+LOCAL_CPPFLAGS := -Wall -Werror -Wextra
+LOCAL_SRC_FILES := \
+    service.cpp
+LOCAL_SHARED_LIBRARIES := \
+    libbase \
+    libcutils \
+    libhidlbase \
+    libhidltransport \
+    liblog \
+    libnl \
+    libutils \
+    libwifi-hal \
+    libwifi-system-iface \
+    android.hardware.wifi@1.0 \
+    android.hardware.wifi@1.1 \
+    android.hardware.wifi@1.2
+LOCAL_STATIC_LIBRARIES := \
+    android.hardware.wifi@1.0-service-lib
+LOCAL_INIT_RC := android.hardware.wifi@1.0-service.rc
+include $(BUILD_EXECUTABLE)
+
+###
+### android.hardware.wifi unit tests.
+###
+include $(CLEAR_VARS)
+LOCAL_MODULE := android.hardware.wifi@1.0-service-tests
+LOCAL_PROPRIETARY_MODULE := true
+LOCAL_SRC_FILES := \
+    tests/main.cpp \
+    tests/mock_wifi_feature_flags.cpp \
+    tests/mock_wifi_legacy_hal.cpp \
+    tests/mock_wifi_mode_controller.cpp \
+    tests/wifi_chip_unit_tests.cpp
+LOCAL_STATIC_LIBRARIES := \
+    libgmock \
+    libgtest \
+    android.hardware.wifi@1.0-service-lib
+LOCAL_SHARED_LIBRARIES := \
+    libbase \
+    libcutils \
+    libhidlbase \
+    libhidltransport \
+    liblog \
+    libnl \
+    libutils \
+    libwifi-hal \
+    libwifi-system-iface \
+    android.hardware.wifi@1.0 \
+    android.hardware.wifi@1.1 \
+    android.hardware.wifi@1.2
+include $(BUILD_NATIVE_TEST)
diff --git a/wifi/1.1/default/OWNERS b/wifi/1.2/default/OWNERS
similarity index 100%
rename from wifi/1.1/default/OWNERS
rename to wifi/1.2/default/OWNERS
diff --git a/wifi/1.1/default/THREADING.README b/wifi/1.2/default/THREADING.README
similarity index 100%
rename from wifi/1.1/default/THREADING.README
rename to wifi/1.2/default/THREADING.README
diff --git a/wifi/1.2/default/android.hardware.wifi@1.0-service.rc b/wifi/1.2/default/android.hardware.wifi@1.0-service.rc
new file mode 100644
index 0000000..eecb6d0
--- /dev/null
+++ b/wifi/1.2/default/android.hardware.wifi@1.0-service.rc
@@ -0,0 +1,4 @@
+service vendor.wifi_hal_legacy /vendor/bin/hw/android.hardware.wifi@1.0-service
+    class hal
+    user wifi
+    group wifi gps
diff --git a/wifi/1.2/default/hidl_callback_util.h b/wifi/1.2/default/hidl_callback_util.h
new file mode 100644
index 0000000..97f312a
--- /dev/null
+++ b/wifi/1.2/default/hidl_callback_util.h
@@ -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.
+ */
+
+#ifndef HIDL_CALLBACK_UTIL_H_
+#define HIDL_CALLBACK_UTIL_H_
+
+#include <set>
+
+#include <hidl/HidlSupport.h>
+
+namespace {
+// Type of callback invoked by the death handler.
+using on_death_cb_function = std::function<void(uint64_t)>;
+
+// Private class used to keep track of death of individual
+// callbacks stored in HidlCallbackHandler.
+template <typename CallbackType>
+class HidlDeathHandler : public android::hardware::hidl_death_recipient {
+   public:
+    HidlDeathHandler(const on_death_cb_function& user_cb_function)
+        : cb_function_(user_cb_function) {}
+    ~HidlDeathHandler() = default;
+
+    // Death notification for callbacks.
+    void serviceDied(
+        uint64_t cookie,
+        const android::wp<android::hidl::base::V1_0::IBase>& /* who */)
+        override {
+        cb_function_(cookie);
+    }
+
+   private:
+    on_death_cb_function cb_function_;
+
+    DISALLOW_COPY_AND_ASSIGN(HidlDeathHandler);
+};
+}  // namespace
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace V1_2 {
+namespace implementation {
+namespace hidl_callback_util {
+template <typename CallbackType>
+// Provides a class to manage callbacks for the various HIDL interfaces and
+// handle the death of the process hosting each callback.
+class HidlCallbackHandler {
+   public:
+    HidlCallbackHandler()
+        : death_handler_(new HidlDeathHandler<CallbackType>(
+              std::bind(&HidlCallbackHandler::onObjectDeath, this,
+                        std::placeholders::_1))) {}
+    ~HidlCallbackHandler() = default;
+
+    bool addCallback(const sp<CallbackType>& cb) {
+        // TODO(b/33818800): Can't compare proxies yet. So, use the cookie
+        // (callback proxy's raw pointer) to track the death of individual
+        // clients.
+        uint64_t cookie = reinterpret_cast<uint64_t>(cb.get());
+        if (cb_set_.find(cb) != cb_set_.end()) {
+            LOG(WARNING) << "Duplicate death notification registration";
+            return true;
+        }
+        if (!cb->linkToDeath(death_handler_, cookie)) {
+            LOG(ERROR) << "Failed to register death notification";
+            return false;
+        }
+        cb_set_.insert(cb);
+        return true;
+    }
+
+    const std::set<android::sp<CallbackType>>& getCallbacks() {
+        return cb_set_;
+    }
+
+    // Death notification for callbacks.
+    void onObjectDeath(uint64_t cookie) {
+        CallbackType* cb = reinterpret_cast<CallbackType*>(cookie);
+        const auto& iter = cb_set_.find(cb);
+        if (iter == cb_set_.end()) {
+            LOG(ERROR) << "Unknown callback death notification received";
+            return;
+        }
+        cb_set_.erase(iter);
+        LOG(DEBUG) << "Dead callback removed from list";
+    }
+
+    void invalidate() {
+        for (const sp<CallbackType>& cb : cb_set_) {
+            if (!cb->unlinkToDeath(death_handler_)) {
+                LOG(ERROR) << "Failed to deregister death notification";
+            }
+        }
+        cb_set_.clear();
+    }
+
+   private:
+    std::set<sp<CallbackType>> cb_set_;
+    sp<HidlDeathHandler<CallbackType>> death_handler_;
+
+    DISALLOW_COPY_AND_ASSIGN(HidlCallbackHandler);
+};
+
+}  // namespace hidl_callback_util
+}  // namespace implementation
+}  // namespace V1_2
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
+#endif  // HIDL_CALLBACK_UTIL_H_
diff --git a/wifi/1.2/default/hidl_return_util.h b/wifi/1.2/default/hidl_return_util.h
new file mode 100644
index 0000000..914c1b4
--- /dev/null
+++ b/wifi/1.2/default/hidl_return_util.h
@@ -0,0 +1,120 @@
+/*
+ * 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 HIDL_RETURN_UTIL_H_
+#define HIDL_RETURN_UTIL_H_
+
+#include "hidl_sync_util.h"
+#include "wifi_status_util.h"
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace V1_2 {
+namespace implementation {
+namespace hidl_return_util {
+using namespace android::hardware::wifi::V1_0;
+
+/**
+ * These utility functions are used to invoke a method on the provided
+ * HIDL interface object.
+ * These functions checks if the provided HIDL interface object is valid.
+ * a) if valid, Invokes the corresponding internal implementation function of
+ * the HIDL method. It then invokes the HIDL continuation callback with
+ * the status and any returned values.
+ * b) if invalid, invokes the HIDL continuation callback with the
+ * provided error status and default values.
+ */
+// Use for HIDL methods which return only an instance of WifiStatus.
+template <typename ObjT, typename WorkFuncT, typename... Args>
+Return<void> validateAndCall(
+    ObjT* obj, WifiStatusCode status_code_if_invalid, WorkFuncT&& work,
+    const std::function<void(const WifiStatus&)>& hidl_cb, Args&&... args) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (obj->isValid()) {
+        hidl_cb((obj->*work)(std::forward<Args>(args)...));
+    } else {
+        hidl_cb(createWifiStatus(status_code_if_invalid));
+    }
+    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>
+Return<void> validateAndCall(
+    ObjT* obj, WifiStatusCode status_code_if_invalid, WorkFuncT&& work,
+    const std::function<void(const WifiStatus&, ReturnT)>& hidl_cb,
+    Args&&... args) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (obj->isValid()) {
+        const auto& ret_pair = (obj->*work)(std::forward<Args>(args)...);
+        const WifiStatus& status = std::get<0>(ret_pair);
+        const auto& ret_value = std::get<1>(ret_pair);
+        hidl_cb(status, ret_value);
+    } else {
+        hidl_cb(createWifiStatus(status_code_if_invalid),
+                typename std::remove_reference<ReturnT>::type());
+    }
+    return Void();
+}
+
+// Use for HIDL methods which return instance of WifiStatus and 2 return
+// values.
+template <typename ObjT, typename WorkFuncT, typename ReturnT1,
+          typename ReturnT2, typename... Args>
+Return<void> validateAndCall(
+    ObjT* obj, WifiStatusCode status_code_if_invalid, WorkFuncT&& work,
+    const std::function<void(const WifiStatus&, ReturnT1, ReturnT2)>& hidl_cb,
+    Args&&... args) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (obj->isValid()) {
+        const auto& ret_tuple = (obj->*work)(std::forward<Args>(args)...);
+        const WifiStatus& status = std::get<0>(ret_tuple);
+        const auto& ret_value1 = std::get<1>(ret_tuple);
+        const auto& ret_value2 = std::get<2>(ret_tuple);
+        hidl_cb(status, ret_value1, ret_value2);
+    } else {
+        hidl_cb(createWifiStatus(status_code_if_invalid),
+                typename std::remove_reference<ReturnT1>::type(),
+                typename std::remove_reference<ReturnT2>::type());
+    }
+    return Void();
+}
+
+}  // namespace hidl_return_util
+}  // namespace implementation
+}  // namespace V1_2
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
+#endif  // HIDL_RETURN_UTIL_H_
diff --git a/wifi/1.2/default/hidl_struct_util.cpp b/wifi/1.2/default/hidl_struct_util.cpp
new file mode 100644
index 0000000..5d48109
--- /dev/null
+++ b/wifi/1.2/default/hidl_struct_util.cpp
@@ -0,0 +1,2424 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+#include <utils/SystemClock.h>
+
+#include "hidl_struct_util.h"
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace V1_2 {
+namespace implementation {
+namespace hidl_struct_util {
+
+hidl_string safeConvertChar(const char* str, size_t max_len) {
+    const char* c = str;
+    size_t size = 0;
+    while (*c && (unsigned char)*c < 128 && size < max_len) {
+        ++size;
+        ++c;
+    }
+    return hidl_string(str, size);
+}
+
+IWifiChip::ChipCapabilityMask convertLegacyLoggerFeatureToHidlChipCapability(
+    uint32_t feature) {
+    using HidlChipCaps = IWifiChip::ChipCapabilityMask;
+    switch (feature) {
+        case legacy_hal::WIFI_LOGGER_MEMORY_DUMP_SUPPORTED:
+            return HidlChipCaps::DEBUG_MEMORY_FIRMWARE_DUMP;
+        case legacy_hal::WIFI_LOGGER_DRIVER_DUMP_SUPPORTED:
+            return HidlChipCaps::DEBUG_MEMORY_DRIVER_DUMP;
+        case legacy_hal::WIFI_LOGGER_CONNECT_EVENT_SUPPORTED:
+            return HidlChipCaps::DEBUG_RING_BUFFER_CONNECT_EVENT;
+        case legacy_hal::WIFI_LOGGER_POWER_EVENT_SUPPORTED:
+            return HidlChipCaps::DEBUG_RING_BUFFER_POWER_EVENT;
+        case legacy_hal::WIFI_LOGGER_WAKE_LOCK_SUPPORTED:
+            return HidlChipCaps::DEBUG_RING_BUFFER_WAKELOCK_EVENT;
+    };
+    CHECK(false) << "Unknown legacy feature: " << feature;
+    return {};
+}
+
+IWifiStaIface::StaIfaceCapabilityMask
+convertLegacyLoggerFeatureToHidlStaIfaceCapability(uint32_t feature) {
+    using HidlStaIfaceCaps = IWifiStaIface::StaIfaceCapabilityMask;
+    switch (feature) {
+        case legacy_hal::WIFI_LOGGER_PACKET_FATE_SUPPORTED:
+            return HidlStaIfaceCaps::DEBUG_PACKET_FATE;
+    };
+    CHECK(false) << "Unknown legacy feature: " << feature;
+    return {};
+}
+
+V1_1::IWifiChip::ChipCapabilityMask convertLegacyFeatureToHidlChipCapability(
+    uint32_t feature) {
+    using HidlChipCaps = V1_1::IWifiChip::ChipCapabilityMask;
+    switch (feature) {
+        case WIFI_FEATURE_SET_TX_POWER_LIMIT:
+            return HidlChipCaps::SET_TX_POWER_LIMIT;
+        case WIFI_FEATURE_D2D_RTT:
+            return HidlChipCaps::D2D_RTT;
+        case WIFI_FEATURE_D2AP_RTT:
+            return HidlChipCaps::D2AP_RTT;
+    };
+    CHECK(false) << "Unknown legacy feature: " << feature;
+    return {};
+}
+
+IWifiStaIface::StaIfaceCapabilityMask
+convertLegacyFeatureToHidlStaIfaceCapability(uint32_t feature) {
+    using HidlStaIfaceCaps = IWifiStaIface::StaIfaceCapabilityMask;
+    switch (feature) {
+        case WIFI_FEATURE_GSCAN:
+            return HidlStaIfaceCaps::BACKGROUND_SCAN;
+        case WIFI_FEATURE_LINK_LAYER_STATS:
+            return HidlStaIfaceCaps::LINK_LAYER_STATS;
+        case WIFI_FEATURE_RSSI_MONITOR:
+            return HidlStaIfaceCaps::RSSI_MONITOR;
+        case WIFI_FEATURE_CONTROL_ROAMING:
+            return HidlStaIfaceCaps::CONTROL_ROAMING;
+        case WIFI_FEATURE_IE_WHITELIST:
+            return HidlStaIfaceCaps::PROBE_IE_WHITELIST;
+        case WIFI_FEATURE_SCAN_RAND:
+            return HidlStaIfaceCaps::SCAN_RAND;
+        case WIFI_FEATURE_INFRA_5G:
+            return HidlStaIfaceCaps::STA_5G;
+        case WIFI_FEATURE_HOTSPOT:
+            return HidlStaIfaceCaps::HOTSPOT;
+        case WIFI_FEATURE_PNO:
+            return HidlStaIfaceCaps::PNO;
+        case WIFI_FEATURE_TDLS:
+            return HidlStaIfaceCaps::TDLS;
+        case WIFI_FEATURE_TDLS_OFFCHANNEL:
+            return HidlStaIfaceCaps::TDLS_OFFCHANNEL;
+        case WIFI_FEATURE_CONFIG_NDO:
+            return HidlStaIfaceCaps::ND_OFFLOAD;
+        case WIFI_FEATURE_MKEEP_ALIVE:
+            return HidlStaIfaceCaps::KEEP_ALIVE;
+    };
+    CHECK(false) << "Unknown legacy feature: " << feature;
+    return {};
+}
+
+bool convertLegacyFeaturesToHidlChipCapabilities(
+    uint32_t legacy_feature_set, uint32_t legacy_logger_feature_set,
+    uint32_t* hidl_caps) {
+    if (!hidl_caps) {
+        return false;
+    }
+    *hidl_caps = {};
+    using HidlChipCaps = IWifiChip::ChipCapabilityMask;
+    for (const auto feature : {legacy_hal::WIFI_LOGGER_MEMORY_DUMP_SUPPORTED,
+                               legacy_hal::WIFI_LOGGER_DRIVER_DUMP_SUPPORTED,
+                               legacy_hal::WIFI_LOGGER_CONNECT_EVENT_SUPPORTED,
+                               legacy_hal::WIFI_LOGGER_POWER_EVENT_SUPPORTED,
+                               legacy_hal::WIFI_LOGGER_WAKE_LOCK_SUPPORTED}) {
+        if (feature & legacy_logger_feature_set) {
+            *hidl_caps |=
+                convertLegacyLoggerFeatureToHidlChipCapability(feature);
+        }
+    }
+    for (const auto feature : {WIFI_FEATURE_SET_TX_POWER_LIMIT,
+                               WIFI_FEATURE_D2D_RTT, WIFI_FEATURE_D2AP_RTT}) {
+        if (feature & legacy_feature_set) {
+            *hidl_caps |= convertLegacyFeatureToHidlChipCapability(feature);
+        }
+    }
+    // There are no flags for these 3 in the legacy feature set. Adding them to
+    // the set because all the current devices support it.
+    *hidl_caps |= HidlChipCaps::DEBUG_RING_BUFFER_VENDOR_DATA;
+    *hidl_caps |= HidlChipCaps::DEBUG_HOST_WAKE_REASON_STATS;
+    *hidl_caps |= HidlChipCaps::DEBUG_ERROR_ALERTS;
+    return true;
+}
+
+WifiDebugRingBufferFlags convertLegacyDebugRingBufferFlagsToHidl(
+    uint32_t flag) {
+    switch (flag) {
+        case WIFI_RING_BUFFER_FLAG_HAS_BINARY_ENTRIES:
+            return WifiDebugRingBufferFlags::HAS_BINARY_ENTRIES;
+        case WIFI_RING_BUFFER_FLAG_HAS_ASCII_ENTRIES:
+            return WifiDebugRingBufferFlags::HAS_ASCII_ENTRIES;
+    };
+    CHECK(false) << "Unknown legacy flag: " << flag;
+    return {};
+}
+
+bool convertLegacyDebugRingBufferStatusToHidl(
+    const legacy_hal::wifi_ring_buffer_status& legacy_status,
+    WifiDebugRingBufferStatus* hidl_status) {
+    if (!hidl_status) {
+        return false;
+    }
+    *hidl_status = {};
+    hidl_status->ringName =
+        safeConvertChar(reinterpret_cast<const char*>(legacy_status.name),
+                        sizeof(legacy_status.name));
+    hidl_status->flags = 0;
+    for (const auto flag : {WIFI_RING_BUFFER_FLAG_HAS_BINARY_ENTRIES,
+                            WIFI_RING_BUFFER_FLAG_HAS_ASCII_ENTRIES}) {
+        if (flag & legacy_status.flags) {
+            hidl_status->flags |= static_cast<
+                std::underlying_type<WifiDebugRingBufferFlags>::type>(
+                convertLegacyDebugRingBufferFlagsToHidl(flag));
+        }
+    }
+    hidl_status->ringId = legacy_status.ring_id;
+    hidl_status->sizeInBytes = legacy_status.ring_buffer_byte_size;
+    // Calculate free size of the ring the buffer. We don't need to send the
+    // exact read/write pointers that were there in the legacy HAL interface.
+    if (legacy_status.written_bytes >= legacy_status.read_bytes) {
+        hidl_status->freeSizeInBytes =
+            legacy_status.ring_buffer_byte_size -
+            (legacy_status.written_bytes - legacy_status.read_bytes);
+    } else {
+        hidl_status->freeSizeInBytes =
+            legacy_status.read_bytes - legacy_status.written_bytes;
+    }
+    hidl_status->verboseLevel = legacy_status.verbose_level;
+    return true;
+}
+
+bool convertLegacyVectorOfDebugRingBufferStatusToHidl(
+    const std::vector<legacy_hal::wifi_ring_buffer_status>& legacy_status_vec,
+    std::vector<WifiDebugRingBufferStatus>* hidl_status_vec) {
+    if (!hidl_status_vec) {
+        return false;
+    }
+    *hidl_status_vec = {};
+    for (const auto& legacy_status : legacy_status_vec) {
+        WifiDebugRingBufferStatus hidl_status;
+        if (!convertLegacyDebugRingBufferStatusToHidl(legacy_status,
+                                                      &hidl_status)) {
+            return false;
+        }
+        hidl_status_vec->push_back(hidl_status);
+    }
+    return true;
+}
+
+bool convertLegacyWakeReasonStatsToHidl(
+    const legacy_hal::WakeReasonStats& legacy_stats,
+    WifiDebugHostWakeReasonStats* hidl_stats) {
+    if (!hidl_stats) {
+        return false;
+    }
+    *hidl_stats = {};
+    hidl_stats->totalCmdEventWakeCnt =
+        legacy_stats.wake_reason_cnt.total_cmd_event_wake;
+    hidl_stats->cmdEventWakeCntPerType = legacy_stats.cmd_event_wake_cnt;
+    hidl_stats->totalDriverFwLocalWakeCnt =
+        legacy_stats.wake_reason_cnt.total_driver_fw_local_wake;
+    hidl_stats->driverFwLocalWakeCntPerType =
+        legacy_stats.driver_fw_local_wake_cnt;
+    hidl_stats->totalRxPacketWakeCnt =
+        legacy_stats.wake_reason_cnt.total_rx_data_wake;
+    hidl_stats->rxPktWakeDetails.rxUnicastCnt =
+        legacy_stats.wake_reason_cnt.rx_wake_details.rx_unicast_cnt;
+    hidl_stats->rxPktWakeDetails.rxMulticastCnt =
+        legacy_stats.wake_reason_cnt.rx_wake_details.rx_multicast_cnt;
+    hidl_stats->rxPktWakeDetails.rxBroadcastCnt =
+        legacy_stats.wake_reason_cnt.rx_wake_details.rx_broadcast_cnt;
+    hidl_stats->rxMulticastPkWakeDetails.ipv4RxMulticastAddrCnt =
+        legacy_stats.wake_reason_cnt.rx_multicast_wake_pkt_info
+            .ipv4_rx_multicast_addr_cnt;
+    hidl_stats->rxMulticastPkWakeDetails.ipv6RxMulticastAddrCnt =
+        legacy_stats.wake_reason_cnt.rx_multicast_wake_pkt_info
+            .ipv6_rx_multicast_addr_cnt;
+    hidl_stats->rxMulticastPkWakeDetails.otherRxMulticastAddrCnt =
+        legacy_stats.wake_reason_cnt.rx_multicast_wake_pkt_info
+            .other_rx_multicast_addr_cnt;
+    hidl_stats->rxIcmpPkWakeDetails.icmpPkt =
+        legacy_stats.wake_reason_cnt.rx_wake_pkt_classification_info.icmp_pkt;
+    hidl_stats->rxIcmpPkWakeDetails.icmp6Pkt =
+        legacy_stats.wake_reason_cnt.rx_wake_pkt_classification_info.icmp6_pkt;
+    hidl_stats->rxIcmpPkWakeDetails.icmp6Ra =
+        legacy_stats.wake_reason_cnt.rx_wake_pkt_classification_info.icmp6_ra;
+    hidl_stats->rxIcmpPkWakeDetails.icmp6Na =
+        legacy_stats.wake_reason_cnt.rx_wake_pkt_classification_info.icmp6_na;
+    hidl_stats->rxIcmpPkWakeDetails.icmp6Ns =
+        legacy_stats.wake_reason_cnt.rx_wake_pkt_classification_info.icmp6_ns;
+    return true;
+}
+
+legacy_hal::wifi_power_scenario convertHidlTxPowerScenarioToLegacy(
+    V1_1::IWifiChip::TxPowerScenario hidl_scenario) {
+    switch (hidl_scenario) {
+        case V1_1::IWifiChip::TxPowerScenario::VOICE_CALL:
+            return legacy_hal::WIFI_POWER_SCENARIO_VOICE_CALL;
+    };
+    CHECK(false);
+}
+
+bool convertLegacyFeaturesToHidlStaCapabilities(
+    uint32_t legacy_feature_set, uint32_t legacy_logger_feature_set,
+    uint32_t* hidl_caps) {
+    if (!hidl_caps) {
+        return false;
+    }
+    *hidl_caps = {};
+    using HidlStaIfaceCaps = IWifiStaIface::StaIfaceCapabilityMask;
+    for (const auto feature : {legacy_hal::WIFI_LOGGER_PACKET_FATE_SUPPORTED}) {
+        if (feature & legacy_logger_feature_set) {
+            *hidl_caps |=
+                convertLegacyLoggerFeatureToHidlStaIfaceCapability(feature);
+        }
+    }
+    for (const auto feature :
+         {WIFI_FEATURE_GSCAN, WIFI_FEATURE_LINK_LAYER_STATS,
+          WIFI_FEATURE_RSSI_MONITOR, WIFI_FEATURE_CONTROL_ROAMING,
+          WIFI_FEATURE_IE_WHITELIST, WIFI_FEATURE_SCAN_RAND,
+          WIFI_FEATURE_INFRA_5G, WIFI_FEATURE_HOTSPOT, WIFI_FEATURE_PNO,
+          WIFI_FEATURE_TDLS, WIFI_FEATURE_TDLS_OFFCHANNEL,
+          WIFI_FEATURE_CONFIG_NDO, WIFI_FEATURE_MKEEP_ALIVE}) {
+        if (feature & legacy_feature_set) {
+            *hidl_caps |= convertLegacyFeatureToHidlStaIfaceCapability(feature);
+        }
+    }
+    // There is no flag for this one in the legacy feature set. Adding it to the
+    // set because all the current devices support it.
+    *hidl_caps |= HidlStaIfaceCaps::APF;
+    return true;
+}
+
+bool convertLegacyApfCapabilitiesToHidl(
+    const legacy_hal::PacketFilterCapabilities& legacy_caps,
+    StaApfPacketFilterCapabilities* hidl_caps) {
+    if (!hidl_caps) {
+        return false;
+    }
+    *hidl_caps = {};
+    hidl_caps->version = legacy_caps.version;
+    hidl_caps->maxLength = legacy_caps.max_len;
+    return true;
+}
+
+uint8_t convertHidlGscanReportEventFlagToLegacy(
+    StaBackgroundScanBucketEventReportSchemeMask hidl_flag) {
+    using HidlFlag = StaBackgroundScanBucketEventReportSchemeMask;
+    switch (hidl_flag) {
+        case HidlFlag::EACH_SCAN:
+            return REPORT_EVENTS_EACH_SCAN;
+        case HidlFlag::FULL_RESULTS:
+            return REPORT_EVENTS_FULL_RESULTS;
+        case HidlFlag::NO_BATCH:
+            return REPORT_EVENTS_NO_BATCH;
+    };
+    CHECK(false);
+}
+
+StaScanDataFlagMask convertLegacyGscanDataFlagToHidl(uint8_t legacy_flag) {
+    switch (legacy_flag) {
+        case legacy_hal::WIFI_SCAN_FLAG_INTERRUPTED:
+            return StaScanDataFlagMask::INTERRUPTED;
+    };
+    CHECK(false) << "Unknown legacy flag: " << legacy_flag;
+    // To silence the compiler warning about reaching the end of non-void
+    // function.
+    return {};
+}
+
+bool convertLegacyGscanCapabilitiesToHidl(
+    const legacy_hal::wifi_gscan_capabilities& legacy_caps,
+    StaBackgroundScanCapabilities* hidl_caps) {
+    if (!hidl_caps) {
+        return false;
+    }
+    *hidl_caps = {};
+    hidl_caps->maxCacheSize = legacy_caps.max_scan_cache_size;
+    hidl_caps->maxBuckets = legacy_caps.max_scan_buckets;
+    hidl_caps->maxApCachePerScan = legacy_caps.max_ap_cache_per_scan;
+    hidl_caps->maxReportingThreshold = legacy_caps.max_scan_reporting_threshold;
+    return true;
+}
+
+legacy_hal::wifi_band convertHidlWifiBandToLegacy(WifiBand band) {
+    switch (band) {
+        case WifiBand::BAND_UNSPECIFIED:
+            return legacy_hal::WIFI_BAND_UNSPECIFIED;
+        case WifiBand::BAND_24GHZ:
+            return legacy_hal::WIFI_BAND_BG;
+        case WifiBand::BAND_5GHZ:
+            return legacy_hal::WIFI_BAND_A;
+        case WifiBand::BAND_5GHZ_DFS:
+            return legacy_hal::WIFI_BAND_A_DFS;
+        case WifiBand::BAND_5GHZ_WITH_DFS:
+            return legacy_hal::WIFI_BAND_A_WITH_DFS;
+        case WifiBand::BAND_24GHZ_5GHZ:
+            return legacy_hal::WIFI_BAND_ABG;
+        case WifiBand::BAND_24GHZ_5GHZ_WITH_DFS:
+            return legacy_hal::WIFI_BAND_ABG_WITH_DFS;
+    };
+    CHECK(false);
+}
+
+bool convertHidlGscanParamsToLegacy(
+    const StaBackgroundScanParameters& hidl_scan_params,
+    legacy_hal::wifi_scan_cmd_params* legacy_scan_params) {
+    if (!legacy_scan_params) {
+        return false;
+    }
+    *legacy_scan_params = {};
+    legacy_scan_params->base_period = hidl_scan_params.basePeriodInMs;
+    legacy_scan_params->max_ap_per_scan = hidl_scan_params.maxApPerScan;
+    legacy_scan_params->report_threshold_percent =
+        hidl_scan_params.reportThresholdPercent;
+    legacy_scan_params->report_threshold_num_scans =
+        hidl_scan_params.reportThresholdNumScans;
+    if (hidl_scan_params.buckets.size() > MAX_BUCKETS) {
+        return false;
+    }
+    legacy_scan_params->num_buckets = hidl_scan_params.buckets.size();
+    for (uint32_t bucket_idx = 0; bucket_idx < hidl_scan_params.buckets.size();
+         bucket_idx++) {
+        const StaBackgroundScanBucketParameters& hidl_bucket_spec =
+            hidl_scan_params.buckets[bucket_idx];
+        legacy_hal::wifi_scan_bucket_spec& legacy_bucket_spec =
+            legacy_scan_params->buckets[bucket_idx];
+        if (hidl_bucket_spec.bucketIdx >= MAX_BUCKETS) {
+            return false;
+        }
+        legacy_bucket_spec.bucket = hidl_bucket_spec.bucketIdx;
+        legacy_bucket_spec.band =
+            convertHidlWifiBandToLegacy(hidl_bucket_spec.band);
+        legacy_bucket_spec.period = hidl_bucket_spec.periodInMs;
+        legacy_bucket_spec.max_period =
+            hidl_bucket_spec.exponentialMaxPeriodInMs;
+        legacy_bucket_spec.base = hidl_bucket_spec.exponentialBase;
+        legacy_bucket_spec.step_count = hidl_bucket_spec.exponentialStepCount;
+        legacy_bucket_spec.report_events = 0;
+        using HidlFlag = StaBackgroundScanBucketEventReportSchemeMask;
+        for (const auto flag : {HidlFlag::EACH_SCAN, HidlFlag::FULL_RESULTS,
+                                HidlFlag::NO_BATCH}) {
+            if (hidl_bucket_spec.eventReportScheme &
+                static_cast<std::underlying_type<HidlFlag>::type>(flag)) {
+                legacy_bucket_spec.report_events |=
+                    convertHidlGscanReportEventFlagToLegacy(flag);
+            }
+        }
+        if (hidl_bucket_spec.frequencies.size() > MAX_CHANNELS) {
+            return false;
+        }
+        legacy_bucket_spec.num_channels = hidl_bucket_spec.frequencies.size();
+        for (uint32_t freq_idx = 0;
+             freq_idx < hidl_bucket_spec.frequencies.size(); freq_idx++) {
+            legacy_bucket_spec.channels[freq_idx].channel =
+                hidl_bucket_spec.frequencies[freq_idx];
+        }
+    }
+    return true;
+}
+
+bool convertLegacyIeToHidl(
+    const legacy_hal::wifi_information_element& legacy_ie,
+    WifiInformationElement* hidl_ie) {
+    if (!hidl_ie) {
+        return false;
+    }
+    *hidl_ie = {};
+    hidl_ie->id = legacy_ie.id;
+    hidl_ie->data =
+        std::vector<uint8_t>(legacy_ie.data, legacy_ie.data + legacy_ie.len);
+    return true;
+}
+
+bool convertLegacyIeBlobToHidl(const uint8_t* ie_blob, uint32_t ie_blob_len,
+                               std::vector<WifiInformationElement>* hidl_ies) {
+    if (!ie_blob || !hidl_ies) {
+        return false;
+    }
+    *hidl_ies = {};
+    const uint8_t* ies_begin = ie_blob;
+    const uint8_t* ies_end = ie_blob + ie_blob_len;
+    const uint8_t* next_ie = ies_begin;
+    using wifi_ie = legacy_hal::wifi_information_element;
+    constexpr size_t kIeHeaderLen = sizeof(wifi_ie);
+    // Each IE should atleast have the header (i.e |id| & |len| fields).
+    while (next_ie + kIeHeaderLen <= ies_end) {
+        const wifi_ie& legacy_ie = (*reinterpret_cast<const wifi_ie*>(next_ie));
+        uint32_t curr_ie_len = kIeHeaderLen + legacy_ie.len;
+        if (next_ie + curr_ie_len > ies_end) {
+            LOG(ERROR) << "Error parsing IE blob. Next IE: " << (void*)next_ie
+                       << ", Curr IE len: " << curr_ie_len
+                       << ", IEs End: " << (void*)ies_end;
+            break;
+        }
+        WifiInformationElement hidl_ie;
+        if (!convertLegacyIeToHidl(legacy_ie, &hidl_ie)) {
+            LOG(ERROR) << "Error converting IE. Id: " << legacy_ie.id
+                       << ", len: " << legacy_ie.len;
+            break;
+        }
+        hidl_ies->push_back(std::move(hidl_ie));
+        next_ie += curr_ie_len;
+    }
+    // Check if the blob has been fully consumed.
+    if (next_ie != ies_end) {
+        LOG(ERROR) << "Failed to fully parse IE blob. Next IE: "
+                   << (void*)next_ie << ", IEs End: " << (void*)ies_end;
+    }
+    return true;
+}
+
+bool convertLegacyGscanResultToHidl(
+    const legacy_hal::wifi_scan_result& legacy_scan_result, bool has_ie_data,
+    StaScanResult* hidl_scan_result) {
+    if (!hidl_scan_result) {
+        return false;
+    }
+    *hidl_scan_result = {};
+    hidl_scan_result->timeStampInUs = legacy_scan_result.ts;
+    hidl_scan_result->ssid = std::vector<uint8_t>(
+        legacy_scan_result.ssid,
+        legacy_scan_result.ssid + strnlen(legacy_scan_result.ssid,
+                                          sizeof(legacy_scan_result.ssid) - 1));
+    memcpy(hidl_scan_result->bssid.data(), legacy_scan_result.bssid,
+           hidl_scan_result->bssid.size());
+    hidl_scan_result->frequency = legacy_scan_result.channel;
+    hidl_scan_result->rssi = legacy_scan_result.rssi;
+    hidl_scan_result->beaconPeriodInMs = legacy_scan_result.beacon_period;
+    hidl_scan_result->capability = legacy_scan_result.capability;
+    if (has_ie_data) {
+        std::vector<WifiInformationElement> ies;
+        if (!convertLegacyIeBlobToHidl(
+                reinterpret_cast<const uint8_t*>(legacy_scan_result.ie_data),
+                legacy_scan_result.ie_length, &ies)) {
+            return false;
+        }
+        hidl_scan_result->informationElements = std::move(ies);
+    }
+    return true;
+}
+
+bool convertLegacyCachedGscanResultsToHidl(
+    const legacy_hal::wifi_cached_scan_results& legacy_cached_scan_result,
+    StaScanData* hidl_scan_data) {
+    if (!hidl_scan_data) {
+        return false;
+    }
+    *hidl_scan_data = {};
+    hidl_scan_data->flags = 0;
+    for (const auto flag : {legacy_hal::WIFI_SCAN_FLAG_INTERRUPTED}) {
+        if (legacy_cached_scan_result.flags & flag) {
+            hidl_scan_data->flags |=
+                static_cast<std::underlying_type<StaScanDataFlagMask>::type>(
+                    convertLegacyGscanDataFlagToHidl(flag));
+        }
+    }
+    hidl_scan_data->bucketsScanned = legacy_cached_scan_result.buckets_scanned;
+
+    CHECK(legacy_cached_scan_result.num_results >= 0 &&
+          legacy_cached_scan_result.num_results <= MAX_AP_CACHE_PER_SCAN);
+    std::vector<StaScanResult> hidl_scan_results;
+    for (int32_t result_idx = 0;
+         result_idx < legacy_cached_scan_result.num_results; result_idx++) {
+        StaScanResult hidl_scan_result;
+        if (!convertLegacyGscanResultToHidl(
+                legacy_cached_scan_result.results[result_idx], false,
+                &hidl_scan_result)) {
+            return false;
+        }
+        hidl_scan_results.push_back(hidl_scan_result);
+    }
+    hidl_scan_data->results = std::move(hidl_scan_results);
+    return true;
+}
+
+bool convertLegacyVectorOfCachedGscanResultsToHidl(
+    const std::vector<legacy_hal::wifi_cached_scan_results>&
+        legacy_cached_scan_results,
+    std::vector<StaScanData>* hidl_scan_datas) {
+    if (!hidl_scan_datas) {
+        return false;
+    }
+    *hidl_scan_datas = {};
+    for (const auto& legacy_cached_scan_result : legacy_cached_scan_results) {
+        StaScanData hidl_scan_data;
+        if (!convertLegacyCachedGscanResultsToHidl(legacy_cached_scan_result,
+                                                   &hidl_scan_data)) {
+            return false;
+        }
+        hidl_scan_datas->push_back(hidl_scan_data);
+    }
+    return true;
+}
+
+WifiDebugTxPacketFate convertLegacyDebugTxPacketFateToHidl(
+    legacy_hal::wifi_tx_packet_fate fate) {
+    switch (fate) {
+        case legacy_hal::TX_PKT_FATE_ACKED:
+            return WifiDebugTxPacketFate::ACKED;
+        case legacy_hal::TX_PKT_FATE_SENT:
+            return WifiDebugTxPacketFate::SENT;
+        case legacy_hal::TX_PKT_FATE_FW_QUEUED:
+            return WifiDebugTxPacketFate::FW_QUEUED;
+        case legacy_hal::TX_PKT_FATE_FW_DROP_INVALID:
+            return WifiDebugTxPacketFate::FW_DROP_INVALID;
+        case legacy_hal::TX_PKT_FATE_FW_DROP_NOBUFS:
+            return WifiDebugTxPacketFate::FW_DROP_NOBUFS;
+        case legacy_hal::TX_PKT_FATE_FW_DROP_OTHER:
+            return WifiDebugTxPacketFate::FW_DROP_OTHER;
+        case legacy_hal::TX_PKT_FATE_DRV_QUEUED:
+            return WifiDebugTxPacketFate::DRV_QUEUED;
+        case legacy_hal::TX_PKT_FATE_DRV_DROP_INVALID:
+            return WifiDebugTxPacketFate::DRV_DROP_INVALID;
+        case legacy_hal::TX_PKT_FATE_DRV_DROP_NOBUFS:
+            return WifiDebugTxPacketFate::DRV_DROP_NOBUFS;
+        case legacy_hal::TX_PKT_FATE_DRV_DROP_OTHER:
+            return WifiDebugTxPacketFate::DRV_DROP_OTHER;
+    };
+    CHECK(false) << "Unknown legacy fate type: " << fate;
+}
+
+WifiDebugRxPacketFate convertLegacyDebugRxPacketFateToHidl(
+    legacy_hal::wifi_rx_packet_fate fate) {
+    switch (fate) {
+        case legacy_hal::RX_PKT_FATE_SUCCESS:
+            return WifiDebugRxPacketFate::SUCCESS;
+        case legacy_hal::RX_PKT_FATE_FW_QUEUED:
+            return WifiDebugRxPacketFate::FW_QUEUED;
+        case legacy_hal::RX_PKT_FATE_FW_DROP_FILTER:
+            return WifiDebugRxPacketFate::FW_DROP_FILTER;
+        case legacy_hal::RX_PKT_FATE_FW_DROP_INVALID:
+            return WifiDebugRxPacketFate::FW_DROP_INVALID;
+        case legacy_hal::RX_PKT_FATE_FW_DROP_NOBUFS:
+            return WifiDebugRxPacketFate::FW_DROP_NOBUFS;
+        case legacy_hal::RX_PKT_FATE_FW_DROP_OTHER:
+            return WifiDebugRxPacketFate::FW_DROP_OTHER;
+        case legacy_hal::RX_PKT_FATE_DRV_QUEUED:
+            return WifiDebugRxPacketFate::DRV_QUEUED;
+        case legacy_hal::RX_PKT_FATE_DRV_DROP_FILTER:
+            return WifiDebugRxPacketFate::DRV_DROP_FILTER;
+        case legacy_hal::RX_PKT_FATE_DRV_DROP_INVALID:
+            return WifiDebugRxPacketFate::DRV_DROP_INVALID;
+        case legacy_hal::RX_PKT_FATE_DRV_DROP_NOBUFS:
+            return WifiDebugRxPacketFate::DRV_DROP_NOBUFS;
+        case legacy_hal::RX_PKT_FATE_DRV_DROP_OTHER:
+            return WifiDebugRxPacketFate::DRV_DROP_OTHER;
+    };
+    CHECK(false) << "Unknown legacy fate type: " << fate;
+}
+
+WifiDebugPacketFateFrameType convertLegacyDebugPacketFateFrameTypeToHidl(
+    legacy_hal::frame_type type) {
+    switch (type) {
+        case legacy_hal::FRAME_TYPE_UNKNOWN:
+            return WifiDebugPacketFateFrameType::UNKNOWN;
+        case legacy_hal::FRAME_TYPE_ETHERNET_II:
+            return WifiDebugPacketFateFrameType::ETHERNET_II;
+        case legacy_hal::FRAME_TYPE_80211_MGMT:
+            return WifiDebugPacketFateFrameType::MGMT_80211;
+    };
+    CHECK(false) << "Unknown legacy frame type: " << type;
+}
+
+bool convertLegacyDebugPacketFateFrameToHidl(
+    const legacy_hal::frame_info& legacy_frame,
+    WifiDebugPacketFateFrameInfo* hidl_frame) {
+    if (!hidl_frame) {
+        return false;
+    }
+    *hidl_frame = {};
+    hidl_frame->frameType =
+        convertLegacyDebugPacketFateFrameTypeToHidl(legacy_frame.payload_type);
+    hidl_frame->frameLen = legacy_frame.frame_len;
+    hidl_frame->driverTimestampUsec = legacy_frame.driver_timestamp_usec;
+    hidl_frame->firmwareTimestampUsec = legacy_frame.firmware_timestamp_usec;
+    const uint8_t* frame_begin = reinterpret_cast<const uint8_t*>(
+        legacy_frame.frame_content.ethernet_ii_bytes);
+    hidl_frame->frameContent =
+        std::vector<uint8_t>(frame_begin, frame_begin + legacy_frame.frame_len);
+    return true;
+}
+
+bool convertLegacyDebugTxPacketFateToHidl(
+    const legacy_hal::wifi_tx_report& legacy_fate,
+    WifiDebugTxPacketFateReport* hidl_fate) {
+    if (!hidl_fate) {
+        return false;
+    }
+    *hidl_fate = {};
+    hidl_fate->fate = convertLegacyDebugTxPacketFateToHidl(legacy_fate.fate);
+    return convertLegacyDebugPacketFateFrameToHidl(legacy_fate.frame_inf,
+                                                   &hidl_fate->frameInfo);
+}
+
+bool convertLegacyVectorOfDebugTxPacketFateToHidl(
+    const std::vector<legacy_hal::wifi_tx_report>& legacy_fates,
+    std::vector<WifiDebugTxPacketFateReport>* hidl_fates) {
+    if (!hidl_fates) {
+        return false;
+    }
+    *hidl_fates = {};
+    for (const auto& legacy_fate : legacy_fates) {
+        WifiDebugTxPacketFateReport hidl_fate;
+        if (!convertLegacyDebugTxPacketFateToHidl(legacy_fate, &hidl_fate)) {
+            return false;
+        }
+        hidl_fates->push_back(hidl_fate);
+    }
+    return true;
+}
+
+bool convertLegacyDebugRxPacketFateToHidl(
+    const legacy_hal::wifi_rx_report& legacy_fate,
+    WifiDebugRxPacketFateReport* hidl_fate) {
+    if (!hidl_fate) {
+        return false;
+    }
+    *hidl_fate = {};
+    hidl_fate->fate = convertLegacyDebugRxPacketFateToHidl(legacy_fate.fate);
+    return convertLegacyDebugPacketFateFrameToHidl(legacy_fate.frame_inf,
+                                                   &hidl_fate->frameInfo);
+}
+
+bool convertLegacyVectorOfDebugRxPacketFateToHidl(
+    const std::vector<legacy_hal::wifi_rx_report>& legacy_fates,
+    std::vector<WifiDebugRxPacketFateReport>* hidl_fates) {
+    if (!hidl_fates) {
+        return false;
+    }
+    *hidl_fates = {};
+    for (const auto& legacy_fate : legacy_fates) {
+        WifiDebugRxPacketFateReport hidl_fate;
+        if (!convertLegacyDebugRxPacketFateToHidl(legacy_fate, &hidl_fate)) {
+            return false;
+        }
+        hidl_fates->push_back(hidl_fate);
+    }
+    return true;
+}
+
+bool convertLegacyLinkLayerStatsToHidl(
+    const legacy_hal::LinkLayerStats& legacy_stats,
+    StaLinkLayerStats* hidl_stats) {
+    if (!hidl_stats) {
+        return false;
+    }
+    *hidl_stats = {};
+    // iface legacy_stats conversion.
+    hidl_stats->iface.beaconRx = legacy_stats.iface.beacon_rx;
+    hidl_stats->iface.avgRssiMgmt = legacy_stats.iface.rssi_mgmt;
+    hidl_stats->iface.wmeBePktStats.rxMpdu =
+        legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].rx_mpdu;
+    hidl_stats->iface.wmeBePktStats.txMpdu =
+        legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].tx_mpdu;
+    hidl_stats->iface.wmeBePktStats.lostMpdu =
+        legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].mpdu_lost;
+    hidl_stats->iface.wmeBePktStats.retries =
+        legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].retries;
+    hidl_stats->iface.wmeBkPktStats.rxMpdu =
+        legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].rx_mpdu;
+    hidl_stats->iface.wmeBkPktStats.txMpdu =
+        legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].tx_mpdu;
+    hidl_stats->iface.wmeBkPktStats.lostMpdu =
+        legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].mpdu_lost;
+    hidl_stats->iface.wmeBkPktStats.retries =
+        legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].retries;
+    hidl_stats->iface.wmeViPktStats.rxMpdu =
+        legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].rx_mpdu;
+    hidl_stats->iface.wmeViPktStats.txMpdu =
+        legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].tx_mpdu;
+    hidl_stats->iface.wmeViPktStats.lostMpdu =
+        legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].mpdu_lost;
+    hidl_stats->iface.wmeViPktStats.retries =
+        legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].retries;
+    hidl_stats->iface.wmeVoPktStats.rxMpdu =
+        legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].rx_mpdu;
+    hidl_stats->iface.wmeVoPktStats.txMpdu =
+        legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].tx_mpdu;
+    hidl_stats->iface.wmeVoPktStats.lostMpdu =
+        legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].mpdu_lost;
+    hidl_stats->iface.wmeVoPktStats.retries =
+        legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].retries;
+    // radio legacy_stats conversion.
+    std::vector<StaLinkLayerRadioStats> hidl_radios_stats;
+    for (const auto& legacy_radio_stats : legacy_stats.radios) {
+        StaLinkLayerRadioStats hidl_radio_stats;
+        hidl_radio_stats.onTimeInMs = legacy_radio_stats.stats.on_time;
+        hidl_radio_stats.txTimeInMs = legacy_radio_stats.stats.tx_time;
+        hidl_radio_stats.rxTimeInMs = legacy_radio_stats.stats.rx_time;
+        hidl_radio_stats.onTimeInMsForScan =
+            legacy_radio_stats.stats.on_time_scan;
+        hidl_radio_stats.txTimeInMsPerLevel =
+            legacy_radio_stats.tx_time_per_levels;
+        hidl_radios_stats.push_back(hidl_radio_stats);
+    }
+    hidl_stats->radios = hidl_radios_stats;
+    // Timestamp in the HAL wrapper here since it's not provided in the legacy
+    // HAL API.
+    hidl_stats->timeStampInMs = uptimeMillis();
+    return true;
+}
+
+bool convertLegacyRoamingCapabilitiesToHidl(
+    const legacy_hal::wifi_roaming_capabilities& legacy_caps,
+    StaRoamingCapabilities* hidl_caps) {
+    if (!hidl_caps) {
+        return false;
+    }
+    *hidl_caps = {};
+    hidl_caps->maxBlacklistSize = legacy_caps.max_blacklist_size;
+    hidl_caps->maxWhitelistSize = legacy_caps.max_whitelist_size;
+    return true;
+}
+
+bool convertHidlRoamingConfigToLegacy(
+    const StaRoamingConfig& hidl_config,
+    legacy_hal::wifi_roaming_config* legacy_config) {
+    if (!legacy_config) {
+        return false;
+    }
+    *legacy_config = {};
+    if (hidl_config.bssidBlacklist.size() > MAX_BLACKLIST_BSSID ||
+        hidl_config.ssidWhitelist.size() > MAX_WHITELIST_SSID) {
+        return false;
+    }
+    legacy_config->num_blacklist_bssid = hidl_config.bssidBlacklist.size();
+    uint32_t i = 0;
+    for (const auto& bssid : hidl_config.bssidBlacklist) {
+        CHECK(bssid.size() == sizeof(legacy_hal::mac_addr));
+        memcpy(legacy_config->blacklist_bssid[i++], bssid.data(), bssid.size());
+    }
+    legacy_config->num_whitelist_ssid = hidl_config.ssidWhitelist.size();
+    i = 0;
+    for (const auto& ssid : hidl_config.ssidWhitelist) {
+        CHECK(ssid.size() <= sizeof(legacy_hal::ssid_t::ssid_str));
+        legacy_config->whitelist_ssid[i].length = ssid.size();
+        memcpy(legacy_config->whitelist_ssid[i].ssid_str, ssid.data(),
+               ssid.size());
+        i++;
+    }
+    return true;
+}
+
+legacy_hal::fw_roaming_state_t convertHidlRoamingStateToLegacy(
+    StaRoamingState state) {
+    switch (state) {
+        case StaRoamingState::ENABLED:
+            return legacy_hal::ROAMING_ENABLE;
+        case StaRoamingState::DISABLED:
+            return legacy_hal::ROAMING_DISABLE;
+    };
+    CHECK(false);
+}
+
+legacy_hal::NanMatchAlg convertHidlNanMatchAlgToLegacy(NanMatchAlg type) {
+    switch (type) {
+        case NanMatchAlg::MATCH_ONCE:
+            return legacy_hal::NAN_MATCH_ALG_MATCH_ONCE;
+        case NanMatchAlg::MATCH_CONTINUOUS:
+            return legacy_hal::NAN_MATCH_ALG_MATCH_CONTINUOUS;
+        case NanMatchAlg::MATCH_NEVER:
+            return legacy_hal::NAN_MATCH_ALG_MATCH_NEVER;
+    }
+    CHECK(false);
+}
+
+legacy_hal::NanPublishType convertHidlNanPublishTypeToLegacy(
+    NanPublishType type) {
+    switch (type) {
+        case NanPublishType::UNSOLICITED:
+            return legacy_hal::NAN_PUBLISH_TYPE_UNSOLICITED;
+        case NanPublishType::SOLICITED:
+            return legacy_hal::NAN_PUBLISH_TYPE_SOLICITED;
+        case NanPublishType::UNSOLICITED_SOLICITED:
+            return legacy_hal::NAN_PUBLISH_TYPE_UNSOLICITED_SOLICITED;
+    }
+    CHECK(false);
+}
+
+legacy_hal::NanTxType convertHidlNanTxTypeToLegacy(NanTxType type) {
+    switch (type) {
+        case NanTxType::BROADCAST:
+            return legacy_hal::NAN_TX_TYPE_BROADCAST;
+        case NanTxType::UNICAST:
+            return legacy_hal::NAN_TX_TYPE_UNICAST;
+    }
+    CHECK(false);
+}
+
+legacy_hal::NanSubscribeType convertHidlNanSubscribeTypeToLegacy(
+    NanSubscribeType type) {
+    switch (type) {
+        case NanSubscribeType::PASSIVE:
+            return legacy_hal::NAN_SUBSCRIBE_TYPE_PASSIVE;
+        case NanSubscribeType::ACTIVE:
+            return legacy_hal::NAN_SUBSCRIBE_TYPE_ACTIVE;
+    }
+    CHECK(false);
+}
+
+legacy_hal::NanSRFType convertHidlNanSrfTypeToLegacy(NanSrfType type) {
+    switch (type) {
+        case NanSrfType::BLOOM_FILTER:
+            return legacy_hal::NAN_SRF_ATTR_BLOOM_FILTER;
+        case NanSrfType::PARTIAL_MAC_ADDR:
+            return legacy_hal::NAN_SRF_ATTR_PARTIAL_MAC_ADDR;
+    }
+    CHECK(false);
+}
+
+legacy_hal::NanDataPathChannelCfg convertHidlNanDataPathChannelCfgToLegacy(
+    NanDataPathChannelCfg type) {
+    switch (type) {
+        case NanDataPathChannelCfg::CHANNEL_NOT_REQUESTED:
+            return legacy_hal::NAN_DP_CHANNEL_NOT_REQUESTED;
+        case NanDataPathChannelCfg::REQUEST_CHANNEL_SETUP:
+            return legacy_hal::NAN_DP_REQUEST_CHANNEL_SETUP;
+        case NanDataPathChannelCfg::FORCE_CHANNEL_SETUP:
+            return legacy_hal::NAN_DP_FORCE_CHANNEL_SETUP;
+    }
+    CHECK(false);
+}
+
+NanStatusType convertLegacyNanStatusTypeToHidl(legacy_hal::NanStatusType type) {
+    switch (type) {
+        case legacy_hal::NAN_STATUS_SUCCESS:
+            return NanStatusType::SUCCESS;
+        case legacy_hal::NAN_STATUS_INTERNAL_FAILURE:
+            return NanStatusType::INTERNAL_FAILURE;
+        case legacy_hal::NAN_STATUS_PROTOCOL_FAILURE:
+            return NanStatusType::PROTOCOL_FAILURE;
+        case legacy_hal::NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID:
+            return NanStatusType::INVALID_SESSION_ID;
+        case legacy_hal::NAN_STATUS_NO_RESOURCE_AVAILABLE:
+            return NanStatusType::NO_RESOURCES_AVAILABLE;
+        case legacy_hal::NAN_STATUS_INVALID_PARAM:
+            return NanStatusType::INVALID_ARGS;
+        case legacy_hal::NAN_STATUS_INVALID_REQUESTOR_INSTANCE_ID:
+            return NanStatusType::INVALID_PEER_ID;
+        case legacy_hal::NAN_STATUS_INVALID_NDP_ID:
+            return NanStatusType::INVALID_NDP_ID;
+        case legacy_hal::NAN_STATUS_NAN_NOT_ALLOWED:
+            return NanStatusType::NAN_NOT_ALLOWED;
+        case legacy_hal::NAN_STATUS_NO_OTA_ACK:
+            return NanStatusType::NO_OTA_ACK;
+        case legacy_hal::NAN_STATUS_ALREADY_ENABLED:
+            return NanStatusType::ALREADY_ENABLED;
+        case legacy_hal::NAN_STATUS_FOLLOWUP_QUEUE_FULL:
+            return NanStatusType::FOLLOWUP_TX_QUEUE_FULL;
+        case legacy_hal::NAN_STATUS_UNSUPPORTED_CONCURRENCY_NAN_DISABLED:
+            return NanStatusType::UNSUPPORTED_CONCURRENCY_NAN_DISABLED;
+    }
+    CHECK(false);
+}
+
+void convertToWifiNanStatus(legacy_hal::NanStatusType type, const char* str,
+                            size_t max_len, WifiNanStatus* wifiNanStatus) {
+    wifiNanStatus->status = convertLegacyNanStatusTypeToHidl(type);
+    wifiNanStatus->description = safeConvertChar(str, max_len);
+}
+
+bool convertHidlNanEnableRequestToLegacy(
+    const NanEnableRequest& hidl_request,
+    legacy_hal::NanEnableRequest* legacy_request) {
+    if (!legacy_request) {
+        LOG(ERROR)
+            << "convertHidlNanEnableRequestToLegacy: null legacy_request";
+        return false;
+    }
+    *legacy_request = {};
+
+    legacy_request->config_2dot4g_support = 1;
+    legacy_request->support_2dot4g_val =
+        hidl_request.operateInBand[(size_t)NanBandIndex::NAN_BAND_24GHZ];
+    legacy_request->config_support_5g = 1;
+    legacy_request->support_5g_val =
+        hidl_request.operateInBand[(size_t)NanBandIndex::NAN_BAND_5GHZ];
+    legacy_request->config_hop_count_limit = 1;
+    legacy_request->hop_count_limit_val = hidl_request.hopCountMax;
+    legacy_request->master_pref = hidl_request.configParams.masterPref;
+    legacy_request->discovery_indication_cfg = 0;
+    legacy_request->discovery_indication_cfg |=
+        hidl_request.configParams.disableDiscoveryAddressChangeIndication ? 0x1
+                                                                          : 0x0;
+    legacy_request->discovery_indication_cfg |=
+        hidl_request.configParams.disableStartedClusterIndication ? 0x2 : 0x0;
+    legacy_request->discovery_indication_cfg |=
+        hidl_request.configParams.disableJoinedClusterIndication ? 0x4 : 0x0;
+    legacy_request->config_sid_beacon = 1;
+    if (hidl_request.configParams.numberOfPublishServiceIdsInBeacon > 127) {
+        LOG(ERROR) << "convertHidlNanEnableRequestToLegacy: "
+                      "numberOfPublishServiceIdsInBeacon > 127";
+        return false;
+    }
+    legacy_request->sid_beacon_val =
+        (hidl_request.configParams.includePublishServiceIdsInBeacon ? 0x1
+                                                                    : 0x0) |
+        (hidl_request.configParams.numberOfPublishServiceIdsInBeacon << 1);
+    legacy_request->config_subscribe_sid_beacon = 1;
+    if (hidl_request.configParams.numberOfSubscribeServiceIdsInBeacon > 127) {
+        LOG(ERROR) << "convertHidlNanEnableRequestToLegacy: "
+                      "numberOfSubscribeServiceIdsInBeacon > 127";
+        return false;
+    }
+    legacy_request->subscribe_sid_beacon_val =
+        (hidl_request.configParams.includeSubscribeServiceIdsInBeacon ? 0x1
+                                                                      : 0x0) |
+        (hidl_request.configParams.numberOfSubscribeServiceIdsInBeacon << 1);
+    legacy_request->config_rssi_window_size = 1;
+    legacy_request->rssi_window_size_val =
+        hidl_request.configParams.rssiWindowSize;
+    legacy_request->config_disc_mac_addr_randomization = 1;
+    legacy_request->disc_mac_addr_rand_interval_sec =
+        hidl_request.configParams.macAddressRandomizationIntervalSec;
+    legacy_request->config_2dot4g_rssi_close = 1;
+    if (hidl_request.configParams.bandSpecificConfig.size() != 2) {
+        LOG(ERROR) << "convertHidlNanEnableRequestToLegacy: "
+                      "bandSpecificConfig.size() != 2";
+        return false;
+    }
+    legacy_request->rssi_close_2dot4g_val =
+        hidl_request.configParams
+            .bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ]
+            .rssiClose;
+    legacy_request->config_2dot4g_rssi_middle = 1;
+    legacy_request->rssi_middle_2dot4g_val =
+        hidl_request.configParams
+            .bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ]
+            .rssiMiddle;
+    legacy_request->config_2dot4g_rssi_proximity = 1;
+    legacy_request->rssi_proximity_2dot4g_val =
+        hidl_request.configParams
+            .bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ]
+            .rssiCloseProximity;
+    legacy_request->config_scan_params = 1;
+    legacy_request->scan_params_val
+        .dwell_time[legacy_hal::NAN_CHANNEL_24G_BAND] =
+        hidl_request.configParams
+            .bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ]
+            .dwellTimeMs;
+    legacy_request->scan_params_val
+        .scan_period[legacy_hal::NAN_CHANNEL_24G_BAND] =
+        hidl_request.configParams
+            .bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ]
+            .scanPeriodSec;
+    legacy_request->config_dw.config_2dot4g_dw_band =
+        hidl_request.configParams
+            .bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ]
+            .validDiscoveryWindowIntervalVal;
+    legacy_request->config_dw.dw_2dot4g_interval_val =
+        hidl_request.configParams
+            .bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ]
+            .discoveryWindowIntervalVal;
+    legacy_request->config_5g_rssi_close = 1;
+    legacy_request->rssi_close_5g_val =
+        hidl_request.configParams
+            .bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
+            .rssiClose;
+    legacy_request->config_5g_rssi_middle = 1;
+    legacy_request->rssi_middle_5g_val =
+        hidl_request.configParams
+            .bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
+            .rssiMiddle;
+    legacy_request->config_5g_rssi_close_proximity = 1;
+    legacy_request->rssi_close_proximity_5g_val =
+        hidl_request.configParams
+            .bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
+            .rssiCloseProximity;
+    legacy_request->scan_params_val
+        .dwell_time[legacy_hal::NAN_CHANNEL_5G_BAND_LOW] =
+        hidl_request.configParams
+            .bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
+            .dwellTimeMs;
+    legacy_request->scan_params_val
+        .scan_period[legacy_hal::NAN_CHANNEL_5G_BAND_LOW] =
+        hidl_request.configParams
+            .bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
+            .scanPeriodSec;
+    legacy_request->scan_params_val
+        .dwell_time[legacy_hal::NAN_CHANNEL_5G_BAND_HIGH] =
+        hidl_request.configParams
+            .bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
+            .dwellTimeMs;
+    legacy_request->scan_params_val
+        .scan_period[legacy_hal::NAN_CHANNEL_5G_BAND_HIGH] =
+        hidl_request.configParams
+            .bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
+            .scanPeriodSec;
+    legacy_request->config_dw.config_5g_dw_band =
+        hidl_request.configParams
+            .bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
+            .validDiscoveryWindowIntervalVal;
+    legacy_request->config_dw.dw_5g_interval_val =
+        hidl_request.configParams
+            .bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
+            .discoveryWindowIntervalVal;
+    if (hidl_request.debugConfigs.validClusterIdVals) {
+        legacy_request->cluster_low =
+            hidl_request.debugConfigs.clusterIdBottomRangeVal;
+        legacy_request->cluster_high =
+            hidl_request.debugConfigs.clusterIdTopRangeVal;
+    } else {  // need 'else' since not configurable in legacy HAL
+        legacy_request->cluster_low = 0x0000;
+        legacy_request->cluster_high = 0xFFFF;
+    }
+    legacy_request->config_intf_addr =
+        hidl_request.debugConfigs.validIntfAddrVal;
+    memcpy(legacy_request->intf_addr_val,
+           hidl_request.debugConfigs.intfAddrVal.data(), 6);
+    legacy_request->config_oui = hidl_request.debugConfigs.validOuiVal;
+    legacy_request->oui_val = hidl_request.debugConfigs.ouiVal;
+    legacy_request->config_random_factor_force =
+        hidl_request.debugConfigs.validRandomFactorForceVal;
+    legacy_request->random_factor_force_val =
+        hidl_request.debugConfigs.randomFactorForceVal;
+    legacy_request->config_hop_count_force =
+        hidl_request.debugConfigs.validHopCountForceVal;
+    legacy_request->hop_count_force_val =
+        hidl_request.debugConfigs.hopCountForceVal;
+    legacy_request->config_24g_channel =
+        hidl_request.debugConfigs.validDiscoveryChannelVal;
+    legacy_request->channel_24g_val =
+        hidl_request.debugConfigs
+            .discoveryChannelMhzVal[(size_t)NanBandIndex::NAN_BAND_24GHZ];
+    legacy_request->config_5g_channel =
+        hidl_request.debugConfigs.validDiscoveryChannelVal;
+    legacy_request->channel_5g_val =
+        hidl_request.debugConfigs
+            .discoveryChannelMhzVal[(size_t)NanBandIndex::NAN_BAND_5GHZ];
+    legacy_request->config_2dot4g_beacons =
+        hidl_request.debugConfigs.validUseBeaconsInBandVal;
+    legacy_request->beacon_2dot4g_val =
+        hidl_request.debugConfigs
+            .useBeaconsInBandVal[(size_t)NanBandIndex::NAN_BAND_24GHZ];
+    legacy_request->config_5g_beacons =
+        hidl_request.debugConfigs.validUseBeaconsInBandVal;
+    legacy_request->beacon_5g_val =
+        hidl_request.debugConfigs
+            .useBeaconsInBandVal[(size_t)NanBandIndex::NAN_BAND_5GHZ];
+    legacy_request->config_2dot4g_sdf =
+        hidl_request.debugConfigs.validUseSdfInBandVal;
+    legacy_request->sdf_2dot4g_val =
+        hidl_request.debugConfigs
+            .useSdfInBandVal[(size_t)NanBandIndex::NAN_BAND_24GHZ];
+    legacy_request->config_5g_sdf =
+        hidl_request.debugConfigs.validUseSdfInBandVal;
+    legacy_request->sdf_5g_val =
+        hidl_request.debugConfigs
+            .useSdfInBandVal[(size_t)NanBandIndex::NAN_BAND_5GHZ];
+
+    return true;
+}
+
+bool convertHidlNanPublishRequestToLegacy(
+    const NanPublishRequest& hidl_request,
+    legacy_hal::NanPublishRequest* legacy_request) {
+    if (!legacy_request) {
+        LOG(ERROR)
+            << "convertHidlNanPublishRequestToLegacy: null legacy_request";
+        return false;
+    }
+    *legacy_request = {};
+
+    legacy_request->publish_id = hidl_request.baseConfigs.sessionId;
+    legacy_request->ttl = hidl_request.baseConfigs.ttlSec;
+    legacy_request->period = hidl_request.baseConfigs.discoveryWindowPeriod;
+    legacy_request->publish_count = hidl_request.baseConfigs.discoveryCount;
+    legacy_request->service_name_len =
+        hidl_request.baseConfigs.serviceName.size();
+    if (legacy_request->service_name_len > NAN_MAX_SERVICE_NAME_LEN) {
+        LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: service_name_len "
+                      "too large";
+        return false;
+    }
+    memcpy(legacy_request->service_name,
+           hidl_request.baseConfigs.serviceName.data(),
+           legacy_request->service_name_len);
+    legacy_request->publish_match_indicator = convertHidlNanMatchAlgToLegacy(
+        hidl_request.baseConfigs.discoveryMatchIndicator);
+    legacy_request->service_specific_info_len =
+        hidl_request.baseConfigs.serviceSpecificInfo.size();
+    if (legacy_request->service_specific_info_len >
+        NAN_MAX_SERVICE_SPECIFIC_INFO_LEN) {
+        LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: "
+                      "service_specific_info_len too large";
+        return false;
+    }
+    memcpy(legacy_request->service_specific_info,
+           hidl_request.baseConfigs.serviceSpecificInfo.data(),
+           legacy_request->service_specific_info_len);
+    legacy_request->sdea_service_specific_info_len =
+        hidl_request.baseConfigs.extendedServiceSpecificInfo.size();
+    if (legacy_request->sdea_service_specific_info_len >
+        NAN_MAX_SDEA_SERVICE_SPECIFIC_INFO_LEN) {
+        LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: "
+                      "sdea_service_specific_info_len too large";
+        return false;
+    }
+    memcpy(legacy_request->sdea_service_specific_info,
+           hidl_request.baseConfigs.extendedServiceSpecificInfo.data(),
+           legacy_request->sdea_service_specific_info_len);
+    legacy_request->rx_match_filter_len =
+        hidl_request.baseConfigs.rxMatchFilter.size();
+    if (legacy_request->rx_match_filter_len > NAN_MAX_MATCH_FILTER_LEN) {
+        LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: "
+                      "rx_match_filter_len too large";
+        return false;
+    }
+    memcpy(legacy_request->rx_match_filter,
+           hidl_request.baseConfigs.rxMatchFilter.data(),
+           legacy_request->rx_match_filter_len);
+    legacy_request->tx_match_filter_len =
+        hidl_request.baseConfigs.txMatchFilter.size();
+    if (legacy_request->tx_match_filter_len > NAN_MAX_MATCH_FILTER_LEN) {
+        LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: "
+                      "tx_match_filter_len too large";
+        return false;
+    }
+    memcpy(legacy_request->tx_match_filter,
+           hidl_request.baseConfigs.txMatchFilter.data(),
+           legacy_request->tx_match_filter_len);
+    legacy_request->rssi_threshold_flag =
+        hidl_request.baseConfigs.useRssiThreshold;
+    legacy_request->recv_indication_cfg = 0;
+    legacy_request->recv_indication_cfg |=
+        hidl_request.baseConfigs.disableDiscoveryTerminationIndication ? 0x1
+                                                                       : 0x0;
+    legacy_request->recv_indication_cfg |=
+        hidl_request.baseConfigs.disableMatchExpirationIndication ? 0x2 : 0x0;
+    legacy_request->recv_indication_cfg |=
+        hidl_request.baseConfigs.disableFollowupReceivedIndication ? 0x4 : 0x0;
+    legacy_request->recv_indication_cfg |= 0x8;
+    legacy_request->cipher_type =
+        (unsigned int)hidl_request.baseConfigs.securityConfig.cipherType;
+    if (hidl_request.baseConfigs.securityConfig.securityType ==
+        NanDataPathSecurityType::PMK) {
+        legacy_request->key_info.key_type =
+            legacy_hal::NAN_SECURITY_KEY_INPUT_PMK;
+        legacy_request->key_info.body.pmk_info.pmk_len =
+            hidl_request.baseConfigs.securityConfig.pmk.size();
+        if (legacy_request->key_info.body.pmk_info.pmk_len !=
+            NAN_PMK_INFO_LEN) {
+            LOG(ERROR)
+                << "convertHidlNanPublishRequestToLegacy: invalid pmk_len";
+            return false;
+        }
+        memcpy(legacy_request->key_info.body.pmk_info.pmk,
+               hidl_request.baseConfigs.securityConfig.pmk.data(),
+               legacy_request->key_info.body.pmk_info.pmk_len);
+    }
+    if (hidl_request.baseConfigs.securityConfig.securityType ==
+        NanDataPathSecurityType::PASSPHRASE) {
+        legacy_request->key_info.key_type =
+            legacy_hal::NAN_SECURITY_KEY_INPUT_PASSPHRASE;
+        legacy_request->key_info.body.passphrase_info.passphrase_len =
+            hidl_request.baseConfigs.securityConfig.passphrase.size();
+        if (legacy_request->key_info.body.passphrase_info.passphrase_len <
+            NAN_SECURITY_MIN_PASSPHRASE_LEN) {
+            LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: "
+                          "passphrase_len too small";
+            return false;
+        }
+        if (legacy_request->key_info.body.passphrase_info.passphrase_len >
+            NAN_SECURITY_MAX_PASSPHRASE_LEN) {
+            LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: "
+                          "passphrase_len too large";
+            return false;
+        }
+        memcpy(legacy_request->key_info.body.passphrase_info.passphrase,
+               hidl_request.baseConfigs.securityConfig.passphrase.data(),
+               legacy_request->key_info.body.passphrase_info.passphrase_len);
+    }
+    legacy_request->sdea_params.security_cfg =
+        (hidl_request.baseConfigs.securityConfig.securityType !=
+         NanDataPathSecurityType::OPEN)
+            ? legacy_hal::NAN_DP_CONFIG_SECURITY
+            : legacy_hal::NAN_DP_CONFIG_NO_SECURITY;
+    legacy_request->sdea_params.ranging_state =
+        hidl_request.baseConfigs.rangingRequired
+            ? legacy_hal::NAN_RANGING_ENABLE
+            : legacy_hal::NAN_RANGING_DISABLE;
+    legacy_request->ranging_cfg.ranging_interval_msec =
+        hidl_request.baseConfigs.rangingIntervalMsec;
+    legacy_request->ranging_cfg.config_ranging_indications =
+        hidl_request.baseConfigs.configRangingIndications;
+    legacy_request->ranging_cfg.distance_ingress_mm =
+        hidl_request.baseConfigs.distanceIngressCm * 10;
+    legacy_request->ranging_cfg.distance_egress_mm =
+        hidl_request.baseConfigs.distanceEgressCm * 10;
+    legacy_request->ranging_auto_response =
+        hidl_request.baseConfigs.rangingRequired
+            ? legacy_hal::NAN_RANGING_AUTO_RESPONSE_ENABLE
+            : legacy_hal::NAN_RANGING_AUTO_RESPONSE_DISABLE;
+    legacy_request->sdea_params.range_report =
+        legacy_hal::NAN_DISABLE_RANGE_REPORT;
+    legacy_request->publish_type =
+        convertHidlNanPublishTypeToLegacy(hidl_request.publishType);
+    legacy_request->tx_type = convertHidlNanTxTypeToLegacy(hidl_request.txType);
+    legacy_request->service_responder_policy =
+        hidl_request.autoAcceptDataPathRequests
+            ? legacy_hal::NAN_SERVICE_ACCEPT_POLICY_ALL
+            : legacy_hal::NAN_SERVICE_ACCEPT_POLICY_NONE;
+
+    return true;
+}
+
+bool convertHidlNanSubscribeRequestToLegacy(
+    const NanSubscribeRequest& hidl_request,
+    legacy_hal::NanSubscribeRequest* legacy_request) {
+    if (!legacy_request) {
+        LOG(ERROR)
+            << "convertHidlNanSubscribeRequestToLegacy: legacy_request is null";
+        return false;
+    }
+    *legacy_request = {};
+
+    legacy_request->subscribe_id = hidl_request.baseConfigs.sessionId;
+    legacy_request->ttl = hidl_request.baseConfigs.ttlSec;
+    legacy_request->period = hidl_request.baseConfigs.discoveryWindowPeriod;
+    legacy_request->subscribe_count = hidl_request.baseConfigs.discoveryCount;
+    legacy_request->service_name_len =
+        hidl_request.baseConfigs.serviceName.size();
+    if (legacy_request->service_name_len > NAN_MAX_SERVICE_NAME_LEN) {
+        LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: "
+                      "service_name_len too large";
+        return false;
+    }
+    memcpy(legacy_request->service_name,
+           hidl_request.baseConfigs.serviceName.data(),
+           legacy_request->service_name_len);
+    legacy_request->subscribe_match_indicator = convertHidlNanMatchAlgToLegacy(
+        hidl_request.baseConfigs.discoveryMatchIndicator);
+    legacy_request->service_specific_info_len =
+        hidl_request.baseConfigs.serviceSpecificInfo.size();
+    if (legacy_request->service_specific_info_len >
+        NAN_MAX_SERVICE_SPECIFIC_INFO_LEN) {
+        LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: "
+                      "service_specific_info_len too large";
+        return false;
+    }
+    memcpy(legacy_request->service_specific_info,
+           hidl_request.baseConfigs.serviceSpecificInfo.data(),
+           legacy_request->service_specific_info_len);
+    legacy_request->sdea_service_specific_info_len =
+        hidl_request.baseConfigs.extendedServiceSpecificInfo.size();
+    if (legacy_request->sdea_service_specific_info_len >
+        NAN_MAX_SDEA_SERVICE_SPECIFIC_INFO_LEN) {
+        LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: "
+                      "sdea_service_specific_info_len too large";
+        return false;
+    }
+    memcpy(legacy_request->sdea_service_specific_info,
+           hidl_request.baseConfigs.extendedServiceSpecificInfo.data(),
+           legacy_request->sdea_service_specific_info_len);
+    legacy_request->rx_match_filter_len =
+        hidl_request.baseConfigs.rxMatchFilter.size();
+    if (legacy_request->rx_match_filter_len > NAN_MAX_MATCH_FILTER_LEN) {
+        LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: "
+                      "rx_match_filter_len too large";
+        return false;
+    }
+    memcpy(legacy_request->rx_match_filter,
+           hidl_request.baseConfigs.rxMatchFilter.data(),
+           legacy_request->rx_match_filter_len);
+    legacy_request->tx_match_filter_len =
+        hidl_request.baseConfigs.txMatchFilter.size();
+    if (legacy_request->tx_match_filter_len > NAN_MAX_MATCH_FILTER_LEN) {
+        LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: "
+                      "tx_match_filter_len too large";
+        return false;
+    }
+    memcpy(legacy_request->tx_match_filter,
+           hidl_request.baseConfigs.txMatchFilter.data(),
+           legacy_request->tx_match_filter_len);
+    legacy_request->rssi_threshold_flag =
+        hidl_request.baseConfigs.useRssiThreshold;
+    legacy_request->recv_indication_cfg = 0;
+    legacy_request->recv_indication_cfg |=
+        hidl_request.baseConfigs.disableDiscoveryTerminationIndication ? 0x1
+                                                                       : 0x0;
+    legacy_request->recv_indication_cfg |=
+        hidl_request.baseConfigs.disableMatchExpirationIndication ? 0x2 : 0x0;
+    legacy_request->recv_indication_cfg |=
+        hidl_request.baseConfigs.disableFollowupReceivedIndication ? 0x4 : 0x0;
+    legacy_request->cipher_type =
+        (unsigned int)hidl_request.baseConfigs.securityConfig.cipherType;
+    if (hidl_request.baseConfigs.securityConfig.securityType ==
+        NanDataPathSecurityType::PMK) {
+        legacy_request->key_info.key_type =
+            legacy_hal::NAN_SECURITY_KEY_INPUT_PMK;
+        legacy_request->key_info.body.pmk_info.pmk_len =
+            hidl_request.baseConfigs.securityConfig.pmk.size();
+        if (legacy_request->key_info.body.pmk_info.pmk_len !=
+            NAN_PMK_INFO_LEN) {
+            LOG(ERROR)
+                << "convertHidlNanSubscribeRequestToLegacy: invalid pmk_len";
+            return false;
+        }
+        memcpy(legacy_request->key_info.body.pmk_info.pmk,
+               hidl_request.baseConfigs.securityConfig.pmk.data(),
+               legacy_request->key_info.body.pmk_info.pmk_len);
+    }
+    if (hidl_request.baseConfigs.securityConfig.securityType ==
+        NanDataPathSecurityType::PASSPHRASE) {
+        legacy_request->key_info.key_type =
+            legacy_hal::NAN_SECURITY_KEY_INPUT_PASSPHRASE;
+        legacy_request->key_info.body.passphrase_info.passphrase_len =
+            hidl_request.baseConfigs.securityConfig.passphrase.size();
+        if (legacy_request->key_info.body.passphrase_info.passphrase_len <
+            NAN_SECURITY_MIN_PASSPHRASE_LEN) {
+            LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: "
+                          "passphrase_len too small";
+            return false;
+        }
+        if (legacy_request->key_info.body.passphrase_info.passphrase_len >
+            NAN_SECURITY_MAX_PASSPHRASE_LEN) {
+            LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: "
+                          "passphrase_len too large";
+            return false;
+        }
+        memcpy(legacy_request->key_info.body.passphrase_info.passphrase,
+               hidl_request.baseConfigs.securityConfig.passphrase.data(),
+               legacy_request->key_info.body.passphrase_info.passphrase_len);
+    }
+    legacy_request->sdea_params.security_cfg =
+        (hidl_request.baseConfigs.securityConfig.securityType !=
+         NanDataPathSecurityType::OPEN)
+            ? legacy_hal::NAN_DP_CONFIG_SECURITY
+            : legacy_hal::NAN_DP_CONFIG_NO_SECURITY;
+    legacy_request->sdea_params.ranging_state =
+        hidl_request.baseConfigs.rangingRequired
+            ? legacy_hal::NAN_RANGING_ENABLE
+            : legacy_hal::NAN_RANGING_DISABLE;
+    legacy_request->ranging_cfg.ranging_interval_msec =
+        hidl_request.baseConfigs.rangingIntervalMsec;
+    legacy_request->ranging_cfg.config_ranging_indications =
+        hidl_request.baseConfigs.configRangingIndications;
+    legacy_request->ranging_cfg.distance_ingress_mm =
+        hidl_request.baseConfigs.distanceIngressCm * 10;
+    legacy_request->ranging_cfg.distance_egress_mm =
+        hidl_request.baseConfigs.distanceEgressCm * 10;
+    legacy_request->ranging_auto_response =
+        hidl_request.baseConfigs.rangingRequired
+            ? legacy_hal::NAN_RANGING_AUTO_RESPONSE_ENABLE
+            : legacy_hal::NAN_RANGING_AUTO_RESPONSE_DISABLE;
+    legacy_request->sdea_params.range_report =
+        legacy_hal::NAN_DISABLE_RANGE_REPORT;
+    legacy_request->subscribe_type =
+        convertHidlNanSubscribeTypeToLegacy(hidl_request.subscribeType);
+    legacy_request->serviceResponseFilter =
+        convertHidlNanSrfTypeToLegacy(hidl_request.srfType);
+    legacy_request->serviceResponseInclude =
+        hidl_request.srfRespondIfInAddressSet
+            ? legacy_hal::NAN_SRF_INCLUDE_RESPOND
+            : legacy_hal::NAN_SRF_INCLUDE_DO_NOT_RESPOND;
+    legacy_request->useServiceResponseFilter =
+        hidl_request.shouldUseSrf ? legacy_hal::NAN_USE_SRF
+                                  : legacy_hal::NAN_DO_NOT_USE_SRF;
+    legacy_request->ssiRequiredForMatchIndication =
+        hidl_request.isSsiRequiredForMatch
+            ? legacy_hal::NAN_SSI_REQUIRED_IN_MATCH_IND
+            : legacy_hal::NAN_SSI_NOT_REQUIRED_IN_MATCH_IND;
+    legacy_request->num_intf_addr_present = hidl_request.intfAddr.size();
+    if (legacy_request->num_intf_addr_present > NAN_MAX_SUBSCRIBE_MAX_ADDRESS) {
+        LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: "
+                      "num_intf_addr_present - too many";
+        return false;
+    }
+    for (int i = 0; i < legacy_request->num_intf_addr_present; i++) {
+        memcpy(legacy_request->intf_addr[i], hidl_request.intfAddr[i].data(),
+               6);
+    }
+
+    return true;
+}
+
+bool convertHidlNanTransmitFollowupRequestToLegacy(
+    const NanTransmitFollowupRequest& hidl_request,
+    legacy_hal::NanTransmitFollowupRequest* legacy_request) {
+    if (!legacy_request) {
+        LOG(ERROR) << "convertHidlNanTransmitFollowupRequestToLegacy: "
+                      "legacy_request is null";
+        return false;
+    }
+    *legacy_request = {};
+
+    legacy_request->publish_subscribe_id = hidl_request.discoverySessionId;
+    legacy_request->requestor_instance_id = hidl_request.peerId;
+    memcpy(legacy_request->addr, hidl_request.addr.data(), 6);
+    legacy_request->priority = hidl_request.isHighPriority
+                                   ? legacy_hal::NAN_TX_PRIORITY_HIGH
+                                   : legacy_hal::NAN_TX_PRIORITY_NORMAL;
+    legacy_request->dw_or_faw = hidl_request.shouldUseDiscoveryWindow
+                                    ? legacy_hal::NAN_TRANSMIT_IN_DW
+                                    : legacy_hal::NAN_TRANSMIT_IN_FAW;
+    legacy_request->service_specific_info_len =
+        hidl_request.serviceSpecificInfo.size();
+    if (legacy_request->service_specific_info_len >
+        NAN_MAX_SERVICE_SPECIFIC_INFO_LEN) {
+        LOG(ERROR) << "convertHidlNanTransmitFollowupRequestToLegacy: "
+                      "service_specific_info_len too large";
+        return false;
+    }
+    memcpy(legacy_request->service_specific_info,
+           hidl_request.serviceSpecificInfo.data(),
+           legacy_request->service_specific_info_len);
+    legacy_request->sdea_service_specific_info_len =
+        hidl_request.extendedServiceSpecificInfo.size();
+    if (legacy_request->sdea_service_specific_info_len >
+        NAN_MAX_SDEA_SERVICE_SPECIFIC_INFO_LEN) {
+        LOG(ERROR) << "convertHidlNanTransmitFollowupRequestToLegacy: "
+                      "sdea_service_specific_info_len too large";
+        return false;
+    }
+    memcpy(legacy_request->sdea_service_specific_info,
+           hidl_request.extendedServiceSpecificInfo.data(),
+           legacy_request->sdea_service_specific_info_len);
+    legacy_request->recv_indication_cfg =
+        hidl_request.disableFollowupResultIndication ? 0x1 : 0x0;
+
+    return true;
+}
+
+bool convertHidlNanConfigRequestToLegacy(
+    const NanConfigRequest& hidl_request,
+    legacy_hal::NanConfigRequest* legacy_request) {
+    if (!legacy_request) {
+        LOG(ERROR)
+            << "convertHidlNanConfigRequestToLegacy: legacy_request is null";
+        return false;
+    }
+    *legacy_request = {};
+
+    // TODO: b/34059183 tracks missing configurations in legacy HAL or uknown
+    // defaults
+    legacy_request->master_pref = hidl_request.masterPref;
+    legacy_request->discovery_indication_cfg = 0;
+    legacy_request->discovery_indication_cfg |=
+        hidl_request.disableDiscoveryAddressChangeIndication ? 0x1 : 0x0;
+    legacy_request->discovery_indication_cfg |=
+        hidl_request.disableStartedClusterIndication ? 0x2 : 0x0;
+    legacy_request->discovery_indication_cfg |=
+        hidl_request.disableJoinedClusterIndication ? 0x4 : 0x0;
+    legacy_request->config_sid_beacon = 1;
+    if (hidl_request.numberOfPublishServiceIdsInBeacon > 127) {
+        LOG(ERROR) << "convertHidlNanConfigRequestToLegacy: "
+                      "numberOfPublishServiceIdsInBeacon > 127";
+        return false;
+    }
+    legacy_request->sid_beacon =
+        (hidl_request.includePublishServiceIdsInBeacon ? 0x1 : 0x0) |
+        (hidl_request.numberOfPublishServiceIdsInBeacon << 1);
+    legacy_request->config_subscribe_sid_beacon = 1;
+    if (hidl_request.numberOfSubscribeServiceIdsInBeacon > 127) {
+        LOG(ERROR) << "convertHidlNanConfigRequestToLegacy: "
+                      "numberOfSubscribeServiceIdsInBeacon > 127";
+        return false;
+    }
+    legacy_request->subscribe_sid_beacon_val =
+        (hidl_request.includeSubscribeServiceIdsInBeacon ? 0x1 : 0x0) |
+        (hidl_request.numberOfSubscribeServiceIdsInBeacon << 1);
+    legacy_request->config_rssi_window_size = 1;
+    legacy_request->rssi_window_size_val = hidl_request.rssiWindowSize;
+    legacy_request->config_disc_mac_addr_randomization = 1;
+    legacy_request->disc_mac_addr_rand_interval_sec =
+        hidl_request.macAddressRandomizationIntervalSec;
+    /* TODO : missing
+    legacy_request->config_2dot4g_rssi_close = 1;
+    legacy_request->rssi_close_2dot4g_val =
+          hidl_request.bandSpecificConfig[
+              (size_t) NanBandIndex::NAN_BAND_24GHZ].rssiClose;
+    legacy_request->config_2dot4g_rssi_middle = 1;
+    legacy_request->rssi_middle_2dot4g_val =
+          hidl_request.bandSpecificConfig[
+              (size_t) NanBandIndex::NAN_BAND_24GHZ].rssiMiddle;
+    legacy_request->config_2dot4g_rssi_proximity = 1;
+    legacy_request->rssi_proximity_2dot4g_val =
+          hidl_request.bandSpecificConfig[
+              (size_t) NanBandIndex::NAN_BAND_24GHZ].rssiCloseProximity;
+    */
+    legacy_request->config_scan_params = 1;
+    legacy_request->scan_params_val
+        .dwell_time[legacy_hal::NAN_CHANNEL_24G_BAND] =
+        hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ]
+            .dwellTimeMs;
+    legacy_request->scan_params_val
+        .scan_period[legacy_hal::NAN_CHANNEL_24G_BAND] =
+        hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ]
+            .scanPeriodSec;
+    legacy_request->config_dw.config_2dot4g_dw_band =
+        hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ]
+            .validDiscoveryWindowIntervalVal;
+    legacy_request->config_dw.dw_2dot4g_interval_val =
+        hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ]
+            .discoveryWindowIntervalVal;
+    /* TODO: missing
+    legacy_request->config_5g_rssi_close = 1;
+    legacy_request->rssi_close_5g_val =
+          hidl_request.bandSpecificConfig[
+              (size_t) NanBandIndex::NAN_BAND_5GHZ].rssiClose;
+    legacy_request->config_5g_rssi_middle = 1;
+    legacy_request->rssi_middle_5g_val =
+          hidl_request.bandSpecificConfig[
+              (size_t) NanBandIndex::NAN_BAND_5GHZ].rssiMiddle;
+    */
+    legacy_request->config_5g_rssi_close_proximity = 1;
+    legacy_request->rssi_close_proximity_5g_val =
+        hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
+            .rssiCloseProximity;
+    legacy_request->scan_params_val
+        .dwell_time[legacy_hal::NAN_CHANNEL_5G_BAND_LOW] =
+        hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
+            .dwellTimeMs;
+    legacy_request->scan_params_val
+        .scan_period[legacy_hal::NAN_CHANNEL_5G_BAND_LOW] =
+        hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
+            .scanPeriodSec;
+    legacy_request->scan_params_val
+        .dwell_time[legacy_hal::NAN_CHANNEL_5G_BAND_HIGH] =
+        hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
+            .dwellTimeMs;
+    legacy_request->scan_params_val
+        .scan_period[legacy_hal::NAN_CHANNEL_5G_BAND_HIGH] =
+        hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
+            .scanPeriodSec;
+    legacy_request->config_dw.config_5g_dw_band =
+        hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
+            .validDiscoveryWindowIntervalVal;
+    legacy_request->config_dw.dw_5g_interval_val =
+        hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
+            .discoveryWindowIntervalVal;
+
+    return true;
+}
+
+bool convertHidlNanDataPathInitiatorRequestToLegacy(
+    const NanInitiateDataPathRequest& hidl_request,
+    legacy_hal::NanDataPathInitiatorRequest* legacy_request) {
+    if (!legacy_request) {
+        LOG(ERROR) << "convertHidlNanDataPathInitiatorRequestToLegacy: "
+                      "legacy_request is null";
+        return false;
+    }
+    *legacy_request = {};
+
+    legacy_request->requestor_instance_id = hidl_request.peerId;
+    memcpy(legacy_request->peer_disc_mac_addr,
+           hidl_request.peerDiscMacAddr.data(), 6);
+    legacy_request->channel_request_type =
+        convertHidlNanDataPathChannelCfgToLegacy(
+            hidl_request.channelRequestType);
+    legacy_request->channel = hidl_request.channel;
+    strcpy(legacy_request->ndp_iface, hidl_request.ifaceName.c_str());
+    legacy_request->ndp_cfg.security_cfg =
+        (hidl_request.securityConfig.securityType !=
+         NanDataPathSecurityType::OPEN)
+            ? legacy_hal::NAN_DP_CONFIG_SECURITY
+            : legacy_hal::NAN_DP_CONFIG_NO_SECURITY;
+    legacy_request->app_info.ndp_app_info_len = hidl_request.appInfo.size();
+    if (legacy_request->app_info.ndp_app_info_len > NAN_DP_MAX_APP_INFO_LEN) {
+        LOG(ERROR) << "convertHidlNanDataPathInitiatorRequestToLegacy: "
+                      "ndp_app_info_len too large";
+        return false;
+    }
+    memcpy(legacy_request->app_info.ndp_app_info, hidl_request.appInfo.data(),
+           legacy_request->app_info.ndp_app_info_len);
+    legacy_request->cipher_type =
+        (unsigned int)hidl_request.securityConfig.cipherType;
+    if (hidl_request.securityConfig.securityType ==
+        NanDataPathSecurityType::PMK) {
+        legacy_request->key_info.key_type =
+            legacy_hal::NAN_SECURITY_KEY_INPUT_PMK;
+        legacy_request->key_info.body.pmk_info.pmk_len =
+            hidl_request.securityConfig.pmk.size();
+        if (legacy_request->key_info.body.pmk_info.pmk_len !=
+            NAN_PMK_INFO_LEN) {
+            LOG(ERROR) << "convertHidlNanDataPathInitiatorRequestToLegacy: "
+                          "invalid pmk_len";
+            return false;
+        }
+        memcpy(legacy_request->key_info.body.pmk_info.pmk,
+               hidl_request.securityConfig.pmk.data(),
+               legacy_request->key_info.body.pmk_info.pmk_len);
+    }
+    if (hidl_request.securityConfig.securityType ==
+        NanDataPathSecurityType::PASSPHRASE) {
+        legacy_request->key_info.key_type =
+            legacy_hal::NAN_SECURITY_KEY_INPUT_PASSPHRASE;
+        legacy_request->key_info.body.passphrase_info.passphrase_len =
+            hidl_request.securityConfig.passphrase.size();
+        if (legacy_request->key_info.body.passphrase_info.passphrase_len <
+            NAN_SECURITY_MIN_PASSPHRASE_LEN) {
+            LOG(ERROR) << "convertHidlNanDataPathInitiatorRequestToLegacy: "
+                          "passphrase_len too small";
+            return false;
+        }
+        if (legacy_request->key_info.body.passphrase_info.passphrase_len >
+            NAN_SECURITY_MAX_PASSPHRASE_LEN) {
+            LOG(ERROR) << "convertHidlNanDataPathInitiatorRequestToLegacy: "
+                          "passphrase_len too large";
+            return false;
+        }
+        memcpy(legacy_request->key_info.body.passphrase_info.passphrase,
+               hidl_request.securityConfig.passphrase.data(),
+               legacy_request->key_info.body.passphrase_info.passphrase_len);
+    }
+    legacy_request->service_name_len = hidl_request.serviceNameOutOfBand.size();
+    if (legacy_request->service_name_len > NAN_MAX_SERVICE_NAME_LEN) {
+        LOG(ERROR) << "convertHidlNanDataPathInitiatorRequestToLegacy: "
+                      "service_name_len too large";
+        return false;
+    }
+    memcpy(legacy_request->service_name,
+           hidl_request.serviceNameOutOfBand.data(),
+           legacy_request->service_name_len);
+
+    return true;
+}
+
+bool convertHidlNanDataPathIndicationResponseToLegacy(
+    const NanRespondToDataPathIndicationRequest& hidl_request,
+    legacy_hal::NanDataPathIndicationResponse* legacy_request) {
+    if (!legacy_request) {
+        LOG(ERROR) << "convertHidlNanDataPathIndicationResponseToLegacy: "
+                      "legacy_request is null";
+        return false;
+    }
+    *legacy_request = {};
+
+    legacy_request->rsp_code = hidl_request.acceptRequest
+                                   ? legacy_hal::NAN_DP_REQUEST_ACCEPT
+                                   : legacy_hal::NAN_DP_REQUEST_REJECT;
+    legacy_request->ndp_instance_id = hidl_request.ndpInstanceId;
+    strcpy(legacy_request->ndp_iface, hidl_request.ifaceName.c_str());
+    legacy_request->ndp_cfg.security_cfg =
+        (hidl_request.securityConfig.securityType !=
+         NanDataPathSecurityType::OPEN)
+            ? legacy_hal::NAN_DP_CONFIG_SECURITY
+            : legacy_hal::NAN_DP_CONFIG_NO_SECURITY;
+    legacy_request->app_info.ndp_app_info_len = hidl_request.appInfo.size();
+    if (legacy_request->app_info.ndp_app_info_len > NAN_DP_MAX_APP_INFO_LEN) {
+        LOG(ERROR) << "convertHidlNanDataPathIndicationResponseToLegacy: "
+                      "ndp_app_info_len too large";
+        return false;
+    }
+    memcpy(legacy_request->app_info.ndp_app_info, hidl_request.appInfo.data(),
+           legacy_request->app_info.ndp_app_info_len);
+    legacy_request->cipher_type =
+        (unsigned int)hidl_request.securityConfig.cipherType;
+    if (hidl_request.securityConfig.securityType ==
+        NanDataPathSecurityType::PMK) {
+        legacy_request->key_info.key_type =
+            legacy_hal::NAN_SECURITY_KEY_INPUT_PMK;
+        legacy_request->key_info.body.pmk_info.pmk_len =
+            hidl_request.securityConfig.pmk.size();
+        if (legacy_request->key_info.body.pmk_info.pmk_len !=
+            NAN_PMK_INFO_LEN) {
+            LOG(ERROR) << "convertHidlNanDataPathIndicationResponseToLegacy: "
+                          "invalid pmk_len";
+            return false;
+        }
+        memcpy(legacy_request->key_info.body.pmk_info.pmk,
+               hidl_request.securityConfig.pmk.data(),
+               legacy_request->key_info.body.pmk_info.pmk_len);
+    }
+    if (hidl_request.securityConfig.securityType ==
+        NanDataPathSecurityType::PASSPHRASE) {
+        legacy_request->key_info.key_type =
+            legacy_hal::NAN_SECURITY_KEY_INPUT_PASSPHRASE;
+        legacy_request->key_info.body.passphrase_info.passphrase_len =
+            hidl_request.securityConfig.passphrase.size();
+        if (legacy_request->key_info.body.passphrase_info.passphrase_len <
+            NAN_SECURITY_MIN_PASSPHRASE_LEN) {
+            LOG(ERROR) << "convertHidlNanDataPathIndicationResponseToLegacy: "
+                          "passphrase_len too small";
+            return false;
+        }
+        if (legacy_request->key_info.body.passphrase_info.passphrase_len >
+            NAN_SECURITY_MAX_PASSPHRASE_LEN) {
+            LOG(ERROR) << "convertHidlNanDataPathIndicationResponseToLegacy: "
+                          "passphrase_len too large";
+            return false;
+        }
+        memcpy(legacy_request->key_info.body.passphrase_info.passphrase,
+               hidl_request.securityConfig.passphrase.data(),
+               legacy_request->key_info.body.passphrase_info.passphrase_len);
+    }
+    legacy_request->service_name_len = hidl_request.serviceNameOutOfBand.size();
+    if (legacy_request->service_name_len > NAN_MAX_SERVICE_NAME_LEN) {
+        LOG(ERROR) << "convertHidlNanDataPathIndicationResponseToLegacy: "
+                      "service_name_len too large";
+        return false;
+    }
+    memcpy(legacy_request->service_name,
+           hidl_request.serviceNameOutOfBand.data(),
+           legacy_request->service_name_len);
+
+    return true;
+}
+
+bool convertLegacyNanResponseHeaderToHidl(
+    const legacy_hal::NanResponseMsg& legacy_response,
+    WifiNanStatus* wifiNanStatus) {
+    if (!wifiNanStatus) {
+        LOG(ERROR)
+            << "convertLegacyNanResponseHeaderToHidl: wifiNanStatus is null";
+        return false;
+    }
+    *wifiNanStatus = {};
+
+    convertToWifiNanStatus(legacy_response.status, legacy_response.nan_error,
+                           sizeof(legacy_response.nan_error), wifiNanStatus);
+    return true;
+}
+
+bool convertLegacyNanCapabilitiesResponseToHidl(
+    const legacy_hal::NanCapabilities& legacy_response,
+    NanCapabilities* hidl_response) {
+    if (!hidl_response) {
+        LOG(ERROR) << "convertLegacyNanCapabilitiesResponseToHidl: "
+                      "hidl_response is null";
+        return false;
+    }
+    *hidl_response = {};
+
+    hidl_response->maxConcurrentClusters =
+        legacy_response.max_concurrent_nan_clusters;
+    hidl_response->maxPublishes = legacy_response.max_publishes;
+    hidl_response->maxSubscribes = legacy_response.max_subscribes;
+    hidl_response->maxServiceNameLen = legacy_response.max_service_name_len;
+    hidl_response->maxMatchFilterLen = legacy_response.max_match_filter_len;
+    hidl_response->maxTotalMatchFilterLen =
+        legacy_response.max_total_match_filter_len;
+    hidl_response->maxServiceSpecificInfoLen =
+        legacy_response.max_service_specific_info_len;
+    hidl_response->maxExtendedServiceSpecificInfoLen =
+        legacy_response.max_sdea_service_specific_info_len;
+    hidl_response->maxNdiInterfaces = legacy_response.max_ndi_interfaces;
+    hidl_response->maxNdpSessions = legacy_response.max_ndp_sessions;
+    hidl_response->maxAppInfoLen = legacy_response.max_app_info_len;
+    hidl_response->maxQueuedTransmitFollowupMsgs =
+        legacy_response.max_queued_transmit_followup_msgs;
+    hidl_response->maxSubscribeInterfaceAddresses =
+        legacy_response.max_subscribe_address;
+    hidl_response->supportedCipherSuites =
+        legacy_response.cipher_suites_supported;
+
+    return true;
+}
+
+bool convertLegacyNanMatchIndToHidl(const legacy_hal::NanMatchInd& legacy_ind,
+                                    NanMatchInd* hidl_ind) {
+    if (!hidl_ind) {
+        LOG(ERROR) << "convertLegacyNanMatchIndToHidl: hidl_ind is null";
+        return false;
+    }
+    *hidl_ind = {};
+
+    hidl_ind->discoverySessionId = legacy_ind.publish_subscribe_id;
+    hidl_ind->peerId = legacy_ind.requestor_instance_id;
+    hidl_ind->addr = hidl_array<uint8_t, 6>(legacy_ind.addr);
+    hidl_ind->serviceSpecificInfo =
+        std::vector<uint8_t>(legacy_ind.service_specific_info,
+                             legacy_ind.service_specific_info +
+                                 legacy_ind.service_specific_info_len);
+    hidl_ind->extendedServiceSpecificInfo =
+        std::vector<uint8_t>(legacy_ind.sdea_service_specific_info,
+                             legacy_ind.sdea_service_specific_info +
+                                 legacy_ind.sdea_service_specific_info_len);
+    hidl_ind->matchFilter = std::vector<uint8_t>(
+        legacy_ind.sdf_match_filter,
+        legacy_ind.sdf_match_filter + legacy_ind.sdf_match_filter_len);
+    hidl_ind->matchOccuredInBeaconFlag = legacy_ind.match_occured_flag == 1;
+    hidl_ind->outOfResourceFlag = legacy_ind.out_of_resource_flag == 1;
+    hidl_ind->rssiValue = legacy_ind.rssi_value;
+    hidl_ind->peerCipherType = (NanCipherSuiteType)legacy_ind.peer_cipher_type;
+    hidl_ind->peerRequiresSecurityEnabledInNdp =
+        legacy_ind.peer_sdea_params.security_cfg ==
+        legacy_hal::NAN_DP_CONFIG_SECURITY;
+    hidl_ind->peerRequiresRanging = legacy_ind.peer_sdea_params.ranging_state ==
+                                    legacy_hal::NAN_RANGING_ENABLE;
+    hidl_ind->rangingMeasurementInCm =
+        legacy_ind.range_info.range_measurement_mm / 10;
+    hidl_ind->rangingIndicationType = legacy_ind.range_info.ranging_event_type;
+
+    return true;
+}
+
+bool convertLegacyNanFollowupIndToHidl(
+    const legacy_hal::NanFollowupInd& legacy_ind,
+    NanFollowupReceivedInd* hidl_ind) {
+    if (!hidl_ind) {
+        LOG(ERROR) << "convertLegacyNanFollowupIndToHidl: hidl_ind is null";
+        return false;
+    }
+    *hidl_ind = {};
+
+    hidl_ind->discoverySessionId = legacy_ind.publish_subscribe_id;
+    hidl_ind->peerId = legacy_ind.requestor_instance_id;
+    hidl_ind->addr = hidl_array<uint8_t, 6>(legacy_ind.addr);
+    hidl_ind->receivedInFaw = legacy_ind.dw_or_faw == 1;
+    hidl_ind->serviceSpecificInfo =
+        std::vector<uint8_t>(legacy_ind.service_specific_info,
+                             legacy_ind.service_specific_info +
+                                 legacy_ind.service_specific_info_len);
+    hidl_ind->extendedServiceSpecificInfo =
+        std::vector<uint8_t>(legacy_ind.sdea_service_specific_info,
+                             legacy_ind.sdea_service_specific_info +
+                                 legacy_ind.sdea_service_specific_info_len);
+
+    return true;
+}
+
+bool convertLegacyNanDataPathRequestIndToHidl(
+    const legacy_hal::NanDataPathRequestInd& legacy_ind,
+    NanDataPathRequestInd* hidl_ind) {
+    if (!hidl_ind) {
+        LOG(ERROR)
+            << "convertLegacyNanDataPathRequestIndToHidl: hidl_ind is null";
+        return false;
+    }
+    *hidl_ind = {};
+
+    hidl_ind->discoverySessionId = legacy_ind.service_instance_id;
+    hidl_ind->peerDiscMacAddr =
+        hidl_array<uint8_t, 6>(legacy_ind.peer_disc_mac_addr);
+    hidl_ind->ndpInstanceId = legacy_ind.ndp_instance_id;
+    hidl_ind->securityRequired =
+        legacy_ind.ndp_cfg.security_cfg == legacy_hal::NAN_DP_CONFIG_SECURITY;
+    hidl_ind->appInfo =
+        std::vector<uint8_t>(legacy_ind.app_info.ndp_app_info,
+                             legacy_ind.app_info.ndp_app_info +
+                                 legacy_ind.app_info.ndp_app_info_len);
+
+    return true;
+}
+
+bool convertLegacyNanDataPathConfirmIndToHidl(
+    const legacy_hal::NanDataPathConfirmInd& legacy_ind,
+    NanDataPathConfirmInd* hidl_ind) {
+    if (!hidl_ind) {
+        LOG(ERROR)
+            << "convertLegacyNanDataPathConfirmIndToHidl: hidl_ind is null";
+        return false;
+    }
+    *hidl_ind = {};
+
+    hidl_ind->ndpInstanceId = legacy_ind.ndp_instance_id;
+    hidl_ind->dataPathSetupSuccess =
+        legacy_ind.rsp_code == legacy_hal::NAN_DP_REQUEST_ACCEPT;
+    hidl_ind->peerNdiMacAddr =
+        hidl_array<uint8_t, 6>(legacy_ind.peer_ndi_mac_addr);
+    hidl_ind->appInfo =
+        std::vector<uint8_t>(legacy_ind.app_info.ndp_app_info,
+                             legacy_ind.app_info.ndp_app_info +
+                                 legacy_ind.app_info.ndp_app_info_len);
+    hidl_ind->status.status =
+        convertLegacyNanStatusTypeToHidl(legacy_ind.reason_code);
+    hidl_ind->status.description = "";  // TODO: b/34059183
+
+    return true;
+}
+
+legacy_hal::wifi_rtt_type convertHidlRttTypeToLegacy(RttType type) {
+    switch (type) {
+        case RttType::ONE_SIDED:
+            return legacy_hal::RTT_TYPE_1_SIDED;
+        case RttType::TWO_SIDED:
+            return legacy_hal::RTT_TYPE_2_SIDED;
+    };
+    CHECK(false);
+}
+
+RttType convertLegacyRttTypeToHidl(legacy_hal::wifi_rtt_type type) {
+    switch (type) {
+        case legacy_hal::RTT_TYPE_1_SIDED:
+            return RttType::ONE_SIDED;
+        case legacy_hal::RTT_TYPE_2_SIDED:
+            return RttType::TWO_SIDED;
+    };
+    CHECK(false) << "Unknown legacy type: " << type;
+}
+
+legacy_hal::rtt_peer_type convertHidlRttPeerTypeToLegacy(RttPeerType type) {
+    switch (type) {
+        case RttPeerType::AP:
+            return legacy_hal::RTT_PEER_AP;
+        case RttPeerType::STA:
+            return legacy_hal::RTT_PEER_STA;
+        case RttPeerType::P2P_GO:
+            return legacy_hal::RTT_PEER_P2P_GO;
+        case RttPeerType::P2P_CLIENT:
+            return legacy_hal::RTT_PEER_P2P_CLIENT;
+        case RttPeerType::NAN:
+            return legacy_hal::RTT_PEER_NAN;
+    };
+    CHECK(false);
+}
+
+legacy_hal::wifi_channel_width convertHidlWifiChannelWidthToLegacy(
+    WifiChannelWidthInMhz type) {
+    switch (type) {
+        case WifiChannelWidthInMhz::WIDTH_20:
+            return legacy_hal::WIFI_CHAN_WIDTH_20;
+        case WifiChannelWidthInMhz::WIDTH_40:
+            return legacy_hal::WIFI_CHAN_WIDTH_40;
+        case WifiChannelWidthInMhz::WIDTH_80:
+            return legacy_hal::WIFI_CHAN_WIDTH_80;
+        case WifiChannelWidthInMhz::WIDTH_160:
+            return legacy_hal::WIFI_CHAN_WIDTH_160;
+        case WifiChannelWidthInMhz::WIDTH_80P80:
+            return legacy_hal::WIFI_CHAN_WIDTH_80P80;
+        case WifiChannelWidthInMhz::WIDTH_5:
+            return legacy_hal::WIFI_CHAN_WIDTH_5;
+        case WifiChannelWidthInMhz::WIDTH_10:
+            return legacy_hal::WIFI_CHAN_WIDTH_10;
+        case WifiChannelWidthInMhz::WIDTH_INVALID:
+            return legacy_hal::WIFI_CHAN_WIDTH_INVALID;
+    };
+    CHECK(false);
+}
+
+WifiChannelWidthInMhz convertLegacyWifiChannelWidthToHidl(
+    legacy_hal::wifi_channel_width type) {
+    switch (type) {
+        case legacy_hal::WIFI_CHAN_WIDTH_20:
+            return WifiChannelWidthInMhz::WIDTH_20;
+        case legacy_hal::WIFI_CHAN_WIDTH_40:
+            return WifiChannelWidthInMhz::WIDTH_40;
+        case legacy_hal::WIFI_CHAN_WIDTH_80:
+            return WifiChannelWidthInMhz::WIDTH_80;
+        case legacy_hal::WIFI_CHAN_WIDTH_160:
+            return WifiChannelWidthInMhz::WIDTH_160;
+        case legacy_hal::WIFI_CHAN_WIDTH_80P80:
+            return WifiChannelWidthInMhz::WIDTH_80P80;
+        case legacy_hal::WIFI_CHAN_WIDTH_5:
+            return WifiChannelWidthInMhz::WIDTH_5;
+        case legacy_hal::WIFI_CHAN_WIDTH_10:
+            return WifiChannelWidthInMhz::WIDTH_10;
+        case legacy_hal::WIFI_CHAN_WIDTH_INVALID:
+            return WifiChannelWidthInMhz::WIDTH_INVALID;
+    };
+    CHECK(false) << "Unknown legacy type: " << type;
+}
+
+legacy_hal::wifi_rtt_preamble convertHidlRttPreambleToLegacy(RttPreamble type) {
+    switch (type) {
+        case RttPreamble::LEGACY:
+            return legacy_hal::WIFI_RTT_PREAMBLE_LEGACY;
+        case RttPreamble::HT:
+            return legacy_hal::WIFI_RTT_PREAMBLE_HT;
+        case RttPreamble::VHT:
+            return legacy_hal::WIFI_RTT_PREAMBLE_VHT;
+    };
+    CHECK(false);
+}
+
+RttPreamble convertLegacyRttPreambleToHidl(legacy_hal::wifi_rtt_preamble type) {
+    switch (type) {
+        case legacy_hal::WIFI_RTT_PREAMBLE_LEGACY:
+            return RttPreamble::LEGACY;
+        case legacy_hal::WIFI_RTT_PREAMBLE_HT:
+            return RttPreamble::HT;
+        case legacy_hal::WIFI_RTT_PREAMBLE_VHT:
+            return RttPreamble::VHT;
+    };
+    CHECK(false) << "Unknown legacy type: " << type;
+}
+
+legacy_hal::wifi_rtt_bw convertHidlRttBwToLegacy(RttBw type) {
+    switch (type) {
+        case RttBw::BW_5MHZ:
+            return legacy_hal::WIFI_RTT_BW_5;
+        case RttBw::BW_10MHZ:
+            return legacy_hal::WIFI_RTT_BW_10;
+        case RttBw::BW_20MHZ:
+            return legacy_hal::WIFI_RTT_BW_20;
+        case RttBw::BW_40MHZ:
+            return legacy_hal::WIFI_RTT_BW_40;
+        case RttBw::BW_80MHZ:
+            return legacy_hal::WIFI_RTT_BW_80;
+        case RttBw::BW_160MHZ:
+            return legacy_hal::WIFI_RTT_BW_160;
+    };
+    CHECK(false);
+}
+
+RttBw convertLegacyRttBwToHidl(legacy_hal::wifi_rtt_bw type) {
+    switch (type) {
+        case legacy_hal::WIFI_RTT_BW_5:
+            return RttBw::BW_5MHZ;
+        case legacy_hal::WIFI_RTT_BW_10:
+            return RttBw::BW_10MHZ;
+        case legacy_hal::WIFI_RTT_BW_20:
+            return RttBw::BW_20MHZ;
+        case legacy_hal::WIFI_RTT_BW_40:
+            return RttBw::BW_40MHZ;
+        case legacy_hal::WIFI_RTT_BW_80:
+            return RttBw::BW_80MHZ;
+        case legacy_hal::WIFI_RTT_BW_160:
+            return RttBw::BW_160MHZ;
+    };
+    CHECK(false) << "Unknown legacy type: " << type;
+}
+
+legacy_hal::wifi_motion_pattern convertHidlRttMotionPatternToLegacy(
+    RttMotionPattern type) {
+    switch (type) {
+        case RttMotionPattern::NOT_EXPECTED:
+            return legacy_hal::WIFI_MOTION_NOT_EXPECTED;
+        case RttMotionPattern::EXPECTED:
+            return legacy_hal::WIFI_MOTION_EXPECTED;
+        case RttMotionPattern::UNKNOWN:
+            return legacy_hal::WIFI_MOTION_UNKNOWN;
+    };
+    CHECK(false);
+}
+
+WifiRatePreamble convertLegacyWifiRatePreambleToHidl(uint8_t preamble) {
+    switch (preamble) {
+        case 0:
+            return WifiRatePreamble::OFDM;
+        case 1:
+            return WifiRatePreamble::CCK;
+        case 2:
+            return WifiRatePreamble::HT;
+        case 3:
+            return WifiRatePreamble::VHT;
+        default:
+            return WifiRatePreamble::RESERVED;
+    };
+    CHECK(false) << "Unknown legacy preamble: " << preamble;
+}
+
+WifiRateNss convertLegacyWifiRateNssToHidl(uint8_t nss) {
+    switch (nss) {
+        case 0:
+            return WifiRateNss::NSS_1x1;
+        case 1:
+            return WifiRateNss::NSS_2x2;
+        case 2:
+            return WifiRateNss::NSS_3x3;
+        case 3:
+            return WifiRateNss::NSS_4x4;
+    };
+    CHECK(false) << "Unknown legacy nss: " << nss;
+    return {};
+}
+
+RttStatus convertLegacyRttStatusToHidl(legacy_hal::wifi_rtt_status status) {
+    switch (status) {
+        case legacy_hal::RTT_STATUS_SUCCESS:
+            return RttStatus::SUCCESS;
+        case legacy_hal::RTT_STATUS_FAILURE:
+            return RttStatus::FAILURE;
+        case legacy_hal::RTT_STATUS_FAIL_NO_RSP:
+            return RttStatus::FAIL_NO_RSP;
+        case legacy_hal::RTT_STATUS_FAIL_REJECTED:
+            return RttStatus::FAIL_REJECTED;
+        case legacy_hal::RTT_STATUS_FAIL_NOT_SCHEDULED_YET:
+            return RttStatus::FAIL_NOT_SCHEDULED_YET;
+        case legacy_hal::RTT_STATUS_FAIL_TM_TIMEOUT:
+            return RttStatus::FAIL_TM_TIMEOUT;
+        case legacy_hal::RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL:
+            return RttStatus::FAIL_AP_ON_DIFF_CHANNEL;
+        case legacy_hal::RTT_STATUS_FAIL_NO_CAPABILITY:
+            return RttStatus::FAIL_NO_CAPABILITY;
+        case legacy_hal::RTT_STATUS_ABORTED:
+            return RttStatus::ABORTED;
+        case legacy_hal::RTT_STATUS_FAIL_INVALID_TS:
+            return RttStatus::FAIL_INVALID_TS;
+        case legacy_hal::RTT_STATUS_FAIL_PROTOCOL:
+            return RttStatus::FAIL_PROTOCOL;
+        case legacy_hal::RTT_STATUS_FAIL_SCHEDULE:
+            return RttStatus::FAIL_SCHEDULE;
+        case legacy_hal::RTT_STATUS_FAIL_BUSY_TRY_LATER:
+            return RttStatus::FAIL_BUSY_TRY_LATER;
+        case legacy_hal::RTT_STATUS_INVALID_REQ:
+            return RttStatus::INVALID_REQ;
+        case legacy_hal::RTT_STATUS_NO_WIFI:
+            return RttStatus::NO_WIFI;
+        case legacy_hal::RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE:
+            return RttStatus::FAIL_FTM_PARAM_OVERRIDE;
+    };
+    CHECK(false) << "Unknown legacy status: " << status;
+}
+
+bool convertHidlWifiChannelInfoToLegacy(
+    const WifiChannelInfo& hidl_info,
+    legacy_hal::wifi_channel_info* legacy_info) {
+    if (!legacy_info) {
+        return false;
+    }
+    *legacy_info = {};
+    legacy_info->width = convertHidlWifiChannelWidthToLegacy(hidl_info.width);
+    legacy_info->center_freq = hidl_info.centerFreq;
+    legacy_info->center_freq0 = hidl_info.centerFreq0;
+    legacy_info->center_freq1 = hidl_info.centerFreq1;
+    return true;
+}
+
+bool convertLegacyWifiChannelInfoToHidl(
+    const legacy_hal::wifi_channel_info& legacy_info,
+    WifiChannelInfo* hidl_info) {
+    if (!hidl_info) {
+        return false;
+    }
+    *hidl_info = {};
+    hidl_info->width = convertLegacyWifiChannelWidthToHidl(legacy_info.width);
+    hidl_info->centerFreq = legacy_info.center_freq;
+    hidl_info->centerFreq0 = legacy_info.center_freq0;
+    hidl_info->centerFreq1 = legacy_info.center_freq1;
+    return true;
+}
+
+bool convertHidlRttConfigToLegacy(const RttConfig& hidl_config,
+                                  legacy_hal::wifi_rtt_config* legacy_config) {
+    if (!legacy_config) {
+        return false;
+    }
+    *legacy_config = {};
+    CHECK(hidl_config.addr.size() == sizeof(legacy_config->addr));
+    memcpy(legacy_config->addr, hidl_config.addr.data(),
+           hidl_config.addr.size());
+    legacy_config->type = convertHidlRttTypeToLegacy(hidl_config.type);
+    legacy_config->peer = convertHidlRttPeerTypeToLegacy(hidl_config.peer);
+    if (!convertHidlWifiChannelInfoToLegacy(hidl_config.channel,
+                                            &legacy_config->channel)) {
+        return false;
+    }
+    legacy_config->burst_period = hidl_config.burstPeriod;
+    legacy_config->num_burst = hidl_config.numBurst;
+    legacy_config->num_frames_per_burst = hidl_config.numFramesPerBurst;
+    legacy_config->num_retries_per_rtt_frame =
+        hidl_config.numRetriesPerRttFrame;
+    legacy_config->num_retries_per_ftmr = hidl_config.numRetriesPerFtmr;
+    legacy_config->LCI_request = hidl_config.mustRequestLci;
+    legacy_config->LCR_request = hidl_config.mustRequestLcr;
+    legacy_config->burst_duration = hidl_config.burstDuration;
+    legacy_config->preamble =
+        convertHidlRttPreambleToLegacy(hidl_config.preamble);
+    legacy_config->bw = convertHidlRttBwToLegacy(hidl_config.bw);
+    return true;
+}
+
+bool convertHidlVectorOfRttConfigToLegacy(
+    const std::vector<RttConfig>& hidl_configs,
+    std::vector<legacy_hal::wifi_rtt_config>* legacy_configs) {
+    if (!legacy_configs) {
+        return false;
+    }
+    *legacy_configs = {};
+    for (const auto& hidl_config : hidl_configs) {
+        legacy_hal::wifi_rtt_config legacy_config;
+        if (!convertHidlRttConfigToLegacy(hidl_config, &legacy_config)) {
+            return false;
+        }
+        legacy_configs->push_back(legacy_config);
+    }
+    return true;
+}
+
+bool convertHidlRttLciInformationToLegacy(
+    const RttLciInformation& hidl_info,
+    legacy_hal::wifi_lci_information* legacy_info) {
+    if (!legacy_info) {
+        return false;
+    }
+    *legacy_info = {};
+    legacy_info->latitude = hidl_info.latitude;
+    legacy_info->longitude = hidl_info.longitude;
+    legacy_info->altitude = hidl_info.altitude;
+    legacy_info->latitude_unc = hidl_info.latitudeUnc;
+    legacy_info->longitude_unc = hidl_info.longitudeUnc;
+    legacy_info->altitude_unc = hidl_info.altitudeUnc;
+    legacy_info->motion_pattern =
+        convertHidlRttMotionPatternToLegacy(hidl_info.motionPattern);
+    legacy_info->floor = hidl_info.floor;
+    legacy_info->height_above_floor = hidl_info.heightAboveFloor;
+    legacy_info->height_unc = hidl_info.heightUnc;
+    return true;
+}
+
+bool convertHidlRttLcrInformationToLegacy(
+    const RttLcrInformation& hidl_info,
+    legacy_hal::wifi_lcr_information* legacy_info) {
+    if (!legacy_info) {
+        return false;
+    }
+    *legacy_info = {};
+    CHECK(hidl_info.countryCode.size() == sizeof(legacy_info->country_code));
+    memcpy(legacy_info->country_code, hidl_info.countryCode.data(),
+           hidl_info.countryCode.size());
+    if (hidl_info.civicInfo.size() > sizeof(legacy_info->civic_info)) {
+        return false;
+    }
+    legacy_info->length = hidl_info.civicInfo.size();
+    memcpy(legacy_info->civic_info, hidl_info.civicInfo.c_str(),
+           hidl_info.civicInfo.size());
+    return true;
+}
+
+bool convertHidlRttResponderToLegacy(
+    const RttResponder& hidl_responder,
+    legacy_hal::wifi_rtt_responder* legacy_responder) {
+    if (!legacy_responder) {
+        return false;
+    }
+    *legacy_responder = {};
+    if (!convertHidlWifiChannelInfoToLegacy(hidl_responder.channel,
+                                            &legacy_responder->channel)) {
+        return false;
+    }
+    legacy_responder->preamble =
+        convertHidlRttPreambleToLegacy(hidl_responder.preamble);
+    return true;
+}
+
+bool convertLegacyRttResponderToHidl(
+    const legacy_hal::wifi_rtt_responder& legacy_responder,
+    RttResponder* hidl_responder) {
+    if (!hidl_responder) {
+        return false;
+    }
+    *hidl_responder = {};
+    if (!convertLegacyWifiChannelInfoToHidl(legacy_responder.channel,
+                                            &hidl_responder->channel)) {
+        return false;
+    }
+    hidl_responder->preamble =
+        convertLegacyRttPreambleToHidl(legacy_responder.preamble);
+    return true;
+}
+
+bool convertLegacyRttCapabilitiesToHidl(
+    const legacy_hal::wifi_rtt_capabilities& legacy_capabilities,
+    RttCapabilities* hidl_capabilities) {
+    if (!hidl_capabilities) {
+        return false;
+    }
+    *hidl_capabilities = {};
+    hidl_capabilities->rttOneSidedSupported =
+        legacy_capabilities.rtt_one_sided_supported;
+    hidl_capabilities->rttFtmSupported = legacy_capabilities.rtt_ftm_supported;
+    hidl_capabilities->lciSupported = legacy_capabilities.lci_support;
+    hidl_capabilities->lcrSupported = legacy_capabilities.lcr_support;
+    hidl_capabilities->responderSupported =
+        legacy_capabilities.responder_supported;
+    hidl_capabilities->preambleSupport = 0;
+    for (const auto flag : {legacy_hal::WIFI_RTT_PREAMBLE_LEGACY,
+                            legacy_hal::WIFI_RTT_PREAMBLE_HT,
+                            legacy_hal::WIFI_RTT_PREAMBLE_VHT}) {
+        if (legacy_capabilities.preamble_support & flag) {
+            hidl_capabilities->preambleSupport |=
+                static_cast<std::underlying_type<RttPreamble>::type>(
+                    convertLegacyRttPreambleToHidl(flag));
+        }
+    }
+    hidl_capabilities->bwSupport = 0;
+    for (const auto flag :
+         {legacy_hal::WIFI_RTT_BW_5, legacy_hal::WIFI_RTT_BW_10,
+          legacy_hal::WIFI_RTT_BW_20, legacy_hal::WIFI_RTT_BW_40,
+          legacy_hal::WIFI_RTT_BW_80, legacy_hal::WIFI_RTT_BW_160}) {
+        if (legacy_capabilities.bw_support & flag) {
+            hidl_capabilities->bwSupport |=
+                static_cast<std::underlying_type<RttBw>::type>(
+                    convertLegacyRttBwToHidl(flag));
+        }
+    }
+    hidl_capabilities->mcVersion = legacy_capabilities.mc_version;
+    return true;
+}
+
+bool convertLegacyWifiRateInfoToHidl(const legacy_hal::wifi_rate& legacy_rate,
+                                     WifiRateInfo* hidl_rate) {
+    if (!hidl_rate) {
+        return false;
+    }
+    *hidl_rate = {};
+    hidl_rate->preamble =
+        convertLegacyWifiRatePreambleToHidl(legacy_rate.preamble);
+    hidl_rate->nss = convertLegacyWifiRateNssToHidl(legacy_rate.nss);
+    hidl_rate->bw = convertLegacyWifiChannelWidthToHidl(
+        static_cast<legacy_hal::wifi_channel_width>(legacy_rate.bw));
+    hidl_rate->rateMcsIdx = legacy_rate.rateMcsIdx;
+    hidl_rate->bitRateInKbps = legacy_rate.bitrate;
+    return true;
+}
+
+bool convertLegacyRttResultToHidl(
+    const legacy_hal::wifi_rtt_result& legacy_result, RttResult* hidl_result) {
+    if (!hidl_result) {
+        return false;
+    }
+    *hidl_result = {};
+    CHECK(sizeof(legacy_result.addr) == hidl_result->addr.size());
+    memcpy(hidl_result->addr.data(), legacy_result.addr,
+           sizeof(legacy_result.addr));
+    hidl_result->burstNum = legacy_result.burst_num;
+    hidl_result->measurementNumber = legacy_result.measurement_number;
+    hidl_result->successNumber = legacy_result.success_number;
+    hidl_result->numberPerBurstPeer = legacy_result.number_per_burst_peer;
+    hidl_result->status = convertLegacyRttStatusToHidl(legacy_result.status);
+    hidl_result->retryAfterDuration = legacy_result.retry_after_duration;
+    hidl_result->type = convertLegacyRttTypeToHidl(legacy_result.type);
+    hidl_result->rssi = legacy_result.rssi;
+    hidl_result->rssiSpread = legacy_result.rssi_spread;
+    if (!convertLegacyWifiRateInfoToHidl(legacy_result.tx_rate,
+                                         &hidl_result->txRate)) {
+        return false;
+    }
+    if (!convertLegacyWifiRateInfoToHidl(legacy_result.rx_rate,
+                                         &hidl_result->rxRate)) {
+        return false;
+    }
+    hidl_result->rtt = legacy_result.rtt;
+    hidl_result->rttSd = legacy_result.rtt_sd;
+    hidl_result->rttSpread = legacy_result.rtt_spread;
+    hidl_result->distanceInMm = legacy_result.distance_mm;
+    hidl_result->distanceSdInMm = legacy_result.distance_sd_mm;
+    hidl_result->distanceSpreadInMm = legacy_result.distance_spread_mm;
+    hidl_result->timeStampInUs = legacy_result.ts;
+    hidl_result->burstDurationInMs = legacy_result.burst_duration;
+    hidl_result->negotiatedBurstNum = legacy_result.negotiated_burst_num;
+    if (legacy_result.LCI &&
+        !convertLegacyIeToHidl(*legacy_result.LCI, &hidl_result->lci)) {
+        return false;
+    }
+    if (legacy_result.LCR &&
+        !convertLegacyIeToHidl(*legacy_result.LCR, &hidl_result->lcr)) {
+        return false;
+    }
+    return true;
+}
+
+bool convertLegacyVectorOfRttResultToHidl(
+    const std::vector<const legacy_hal::wifi_rtt_result*>& legacy_results,
+    std::vector<RttResult>* hidl_results) {
+    if (!hidl_results) {
+        return false;
+    }
+    *hidl_results = {};
+    for (const auto legacy_result : legacy_results) {
+        RttResult hidl_result;
+        if (!convertLegacyRttResultToHidl(*legacy_result, &hidl_result)) {
+            return false;
+        }
+        hidl_results->push_back(hidl_result);
+    }
+    return true;
+}
+}  // namespace hidl_struct_util
+}  // namespace implementation
+}  // namespace V1_2
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
diff --git a/wifi/1.1/default/hidl_struct_util.h b/wifi/1.2/default/hidl_struct_util.h
similarity index 94%
rename from wifi/1.1/default/hidl_struct_util.h
rename to wifi/1.2/default/hidl_struct_util.h
index 747fd2f..6766b0f 100644
--- a/wifi/1.1/default/hidl_struct_util.h
+++ b/wifi/1.2/default/hidl_struct_util.h
@@ -19,8 +19,8 @@
 
 #include <vector>
 
-#include <android/hardware/wifi/1.0/types.h>
 #include <android/hardware/wifi/1.0/IWifiChip.h>
+#include <android/hardware/wifi/1.0/types.h>
 #include <android/hardware/wifi/1.1/IWifiChip.h>
 
 #include "wifi_legacy_hal.h"
@@ -34,15 +34,14 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_1 {
+namespace V1_2 {
 namespace implementation {
 namespace hidl_struct_util {
 using namespace android::hardware::wifi::V1_0;
 
 // Chip conversion methods.
 bool convertLegacyFeaturesToHidlChipCapabilities(
-    uint32_t legacy_feature_set,
-    uint32_t legacy_logger_feature_set,
+    uint32_t legacy_feature_set, uint32_t legacy_logger_feature_set,
     uint32_t* hidl_caps);
 bool convertLegacyDebugRingBufferStatusToHidl(
     const legacy_hal::wifi_ring_buffer_status& legacy_status,
@@ -58,8 +57,7 @@
 
 // STA iface conversion methods.
 bool convertLegacyFeaturesToHidlStaCapabilities(
-    uint32_t legacy_feature_set,
-    uint32_t legacy_logger_feature_set,
+    uint32_t legacy_feature_set, uint32_t legacy_logger_feature_set,
     uint32_t* hidl_caps);
 bool convertLegacyApfCapabilitiesToHidl(
     const legacy_hal::PacketFilterCapabilities& legacy_caps,
@@ -74,8 +72,7 @@
 // |has_ie_data| indicates whether or not the wifi_scan_result includes 802.11
 // Information Elements (IEs)
 bool convertLegacyGscanResultToHidl(
-    const legacy_hal::wifi_scan_result& legacy_scan_result,
-    bool has_ie_data,
+    const legacy_hal::wifi_scan_result& legacy_scan_result, bool has_ie_data,
     StaScanResult* hidl_scan_result);
 // |cached_results| is assumed to not include IEs.
 bool convertLegacyVectorOfCachedGscanResultsToHidl(
@@ -101,8 +98,8 @@
     std::vector<WifiDebugRxPacketFateReport>* hidl_fates);
 
 // NAN iface conversion methods.
-void convertToWifiNanStatus(legacy_hal::NanStatusType type, const char* str, size_t max_len,
-    WifiNanStatus* wifiNanStatus);
+void convertToWifiNanStatus(legacy_hal::NanStatusType type, const char* str,
+                            size_t max_len, WifiNanStatus* wifiNanStatus);
 bool convertHidlNanEnableRequestToLegacy(
     const NanEnableRequest& hidl_request,
     legacy_hal::NanEnableRequest* legacy_request);
@@ -133,7 +130,8 @@
 bool convertLegacyNanMatchIndToHidl(const legacy_hal::NanMatchInd& legacy_ind,
                                     NanMatchInd* hidl_ind);
 bool convertLegacyNanFollowupIndToHidl(
-    const legacy_hal::NanFollowupInd& legacy_ind, NanFollowupReceivedInd* hidl_ind);
+    const legacy_hal::NanFollowupInd& legacy_ind,
+    NanFollowupReceivedInd* hidl_ind);
 bool convertLegacyNanDataPathRequestIndToHidl(
     const legacy_hal::NanDataPathRequestInd& legacy_ind,
     NanDataPathRequestInd* hidl_ind);
@@ -168,7 +166,7 @@
     std::vector<RttResult>* hidl_results);
 }  // namespace hidl_struct_util
 }  // namespace implementation
-}  // namespace V1_1
+}  // namespace V1_2
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.1/default/hidl_sync_util.cpp b/wifi/1.2/default/hidl_sync_util.cpp
similarity index 91%
rename from wifi/1.1/default/hidl_sync_util.cpp
rename to wifi/1.2/default/hidl_sync_util.cpp
index ba18e34..ad8448a 100644
--- a/wifi/1.1/default/hidl_sync_util.cpp
+++ b/wifi/1.2/default/hidl_sync_util.cpp
@@ -23,17 +23,17 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_1 {
+namespace V1_2 {
 namespace implementation {
 namespace hidl_sync_util {
 
 std::unique_lock<std::recursive_mutex> acquireGlobalLock() {
-  return std::unique_lock<std::recursive_mutex>{g_mutex};
+    return std::unique_lock<std::recursive_mutex>{g_mutex};
 }
 
 }  // namespace hidl_sync_util
 }  // namespace implementation
-}  // namespace V1_1
+}  // namespace V1_2
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.1/default/hidl_sync_util.h b/wifi/1.2/default/hidl_sync_util.h
similarity index 96%
rename from wifi/1.1/default/hidl_sync_util.h
rename to wifi/1.2/default/hidl_sync_util.h
index 0e882df..8381862 100644
--- a/wifi/1.1/default/hidl_sync_util.h
+++ b/wifi/1.2/default/hidl_sync_util.h
@@ -24,13 +24,13 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_1 {
+namespace V1_2 {
 namespace implementation {
 namespace hidl_sync_util {
 std::unique_lock<std::recursive_mutex> acquireGlobalLock();
 }  // namespace hidl_sync_util
 }  // namespace implementation
-}  // namespace V1_1
+}  // namespace V1_2
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.2/default/service.cpp b/wifi/1.2/default/service.cpp
new file mode 100644
index 0000000..01d22bd
--- /dev/null
+++ b/wifi/1.2/default/service.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+#include <hidl/HidlTransportSupport.h>
+#include <utils/Looper.h>
+#include <utils/StrongPointer.h>
+
+#include "wifi.h"
+#include "wifi_feature_flags.h"
+#include "wifi_legacy_hal.h"
+#include "wifi_mode_controller.h"
+
+using android::hardware::configureRpcThreadpool;
+using android::hardware::joinRpcThreadpool;
+using android::hardware::wifi::V1_2::implementation::feature_flags::
+    WifiFeatureFlags;
+using android::hardware::wifi::V1_2::implementation::legacy_hal::WifiLegacyHal;
+using android::hardware::wifi::V1_2::implementation::mode_controller::
+    WifiModeController;
+
+int main(int /*argc*/, char** argv) {
+    android::base::InitLogging(
+        argv, android::base::LogdLogger(android::base::SYSTEM));
+    LOG(INFO) << "Wifi Hal is booting up...";
+
+    configureRpcThreadpool(1, true /* callerWillJoin */);
+
+    // Setup hwbinder service
+    android::sp<android::hardware::wifi::V1_2::IWifi> service =
+        new android::hardware::wifi::V1_2::implementation::Wifi(
+            std::make_shared<WifiLegacyHal>(),
+            std::make_shared<WifiModeController>(),
+            std::make_shared<WifiFeatureFlags>());
+    CHECK_EQ(service->registerAsService(), android::NO_ERROR)
+        << "Failed to register wifi HAL";
+
+    joinRpcThreadpool();
+
+    LOG(INFO) << "Wifi Hal is terminating...";
+    return 0;
+}
diff --git a/wifi/1.2/default/tests/main.cpp b/wifi/1.2/default/tests/main.cpp
new file mode 100644
index 0000000..9aac837
--- /dev/null
+++ b/wifi/1.2/default/tests/main.cpp
@@ -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.
+ */
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include <android-base/logging.h>
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    ::testing::InitGoogleMock(&argc, argv);
+    // Force ourselves to always log to stderr
+    android::base::InitLogging(argv, android::base::StderrLogger);
+    return RUN_ALL_TESTS();
+}
diff --git a/wifi/1.1/default/wifi_legacy_hal_stubs.h b/wifi/1.2/default/tests/mock_wifi_feature_flags.cpp
similarity index 68%
copy from wifi/1.1/default/wifi_legacy_hal_stubs.h
copy to wifi/1.2/default/tests/mock_wifi_feature_flags.cpp
index bfc4c9b..8d0b192 100644
--- a/wifi/1.1/default/wifi_legacy_hal_stubs.h
+++ b/wifi/1.2/default/tests/mock_wifi_feature_flags.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * 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.
@@ -14,23 +14,22 @@
  * limitations under the License.
  */
 
-#ifndef WIFI_LEGACY_HAL_STUBS_H_
-#define WIFI_LEGACY_HAL_STUBS_H_
+#include <gmock/gmock.h>
+
+#include "mock_wifi_feature_flags.h"
 
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_1 {
+namespace V1_2 {
 namespace implementation {
-namespace legacy_hal {
-#include <hardware_legacy/wifi_hal.h>
+namespace feature_flags {
 
-bool initHalFuncTableWithStubs(wifi_hal_fn* hal_fn);
-}  // namespace legacy_hal
+MockWifiFeatureFlags::MockWifiFeatureFlags() {}
+
+}  // namespace feature_flags
 }  // namespace implementation
-}  // namespace V1_1
+}  // namespace V1_2
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
-
-#endif  // WIFI_LEGACY_HAL_STUBS_H_
diff --git a/wifi/1.2/default/tests/mock_wifi_feature_flags.h b/wifi/1.2/default/tests/mock_wifi_feature_flags.h
new file mode 100644
index 0000000..8cf1d4b
--- /dev/null
+++ b/wifi/1.2/default/tests/mock_wifi_feature_flags.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 MOCK_WIFI_FEATURE_FLAGS_H_
+#define MOCK_WIFI_FEATURE_FLAGS_H_
+
+#include <gmock/gmock.h>
+
+#include "wifi_feature_flags.h"
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace V1_2 {
+namespace implementation {
+namespace feature_flags {
+
+class MockWifiFeatureFlags : public WifiFeatureFlags {
+   public:
+    MockWifiFeatureFlags();
+
+    MOCK_METHOD0(isAwareSupported, bool());
+    MOCK_METHOD0(isDualInterfaceSupported, bool());
+};
+
+}  // namespace feature_flags
+}  // namespace implementation
+}  // namespace V1_2
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
+
+#endif  // MOCK_WIFI_FEATURE_FLAGS_H_
diff --git a/wifi/1.1/default/wifi_legacy_hal_stubs.h b/wifi/1.2/default/tests/mock_wifi_legacy_hal.cpp
similarity index 68%
copy from wifi/1.1/default/wifi_legacy_hal_stubs.h
copy to wifi/1.2/default/tests/mock_wifi_legacy_hal.cpp
index bfc4c9b..8381dde 100644
--- a/wifi/1.1/default/wifi_legacy_hal_stubs.h
+++ b/wifi/1.2/default/tests/mock_wifi_legacy_hal.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * 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.
@@ -14,23 +14,24 @@
  * limitations under the License.
  */
 
-#ifndef WIFI_LEGACY_HAL_STUBS_H_
-#define WIFI_LEGACY_HAL_STUBS_H_
+#include <android-base/logging.h>
+#include <android-base/macros.h>
+#include <gmock/gmock.h>
+
+#undef NAN  // This is weird, NAN is defined in bionic/libc/include/math.h:38
+#include "mock_wifi_legacy_hal.h"
 
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_1 {
+namespace V1_2 {
 namespace implementation {
 namespace legacy_hal {
-#include <hardware_legacy/wifi_hal.h>
 
-bool initHalFuncTableWithStubs(wifi_hal_fn* hal_fn);
+MockWifiLegacyHal::MockWifiLegacyHal() : WifiLegacyHal() {}
 }  // namespace legacy_hal
 }  // namespace implementation
-}  // namespace V1_1
+}  // namespace V1_2
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
-
-#endif  // WIFI_LEGACY_HAL_STUBS_H_
diff --git a/wifi/1.2/default/tests/mock_wifi_legacy_hal.h b/wifi/1.2/default/tests/mock_wifi_legacy_hal.h
new file mode 100644
index 0000000..8e1696e
--- /dev/null
+++ b/wifi/1.2/default/tests/mock_wifi_legacy_hal.h
@@ -0,0 +1,54 @@
+/*
+ * 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 MOCK_WIFI_LEGACY_HAL_H_
+#define MOCK_WIFI_LEGACY_HAL_H_
+
+#include <gmock/gmock.h>
+
+#include "wifi_legacy_hal.h"
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace V1_2 {
+namespace implementation {
+namespace legacy_hal {
+
+class MockWifiLegacyHal : public WifiLegacyHal {
+   public:
+    MockWifiLegacyHal();
+    MOCK_METHOD0(initialize, wifi_error());
+    MOCK_METHOD0(start, wifi_error());
+    MOCK_METHOD2(stop, wifi_error(std::unique_lock<std::recursive_mutex>*,
+                                  const std::function<void()>&));
+    MOCK_METHOD2(setDfsFlag, wifi_error(const std::string&, bool));
+    MOCK_METHOD2(nanRegisterCallbackHandlers,
+                 wifi_error(const std::string&, const NanCallbackHandlers&));
+    MOCK_METHOD2(nanDisableRequest,
+                 wifi_error(const std::string&, transaction_id));
+    MOCK_METHOD3(nanDataInterfaceDelete,
+                 wifi_error(const std::string&, transaction_id,
+                            const std::string&));
+};
+}  // namespace legacy_hal
+}  // namespace implementation
+}  // namespace V1_2
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
+
+#endif  // MOCK_WIFI_LEGACY_HAL_H_
diff --git a/wifi/1.1/default/wifi_feature_flags.h b/wifi/1.2/default/tests/mock_wifi_mode_controller.cpp
similarity index 62%
copy from wifi/1.1/default/wifi_feature_flags.h
copy to wifi/1.2/default/tests/mock_wifi_mode_controller.cpp
index 5939ffb..461a581 100644
--- a/wifi/1.1/default/wifi_feature_flags.h
+++ b/wifi/1.2/default/tests/mock_wifi_mode_controller.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * 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.
@@ -14,28 +14,24 @@
  * limitations under the License.
  */
 
-#ifndef WIFI_FEATURE_FLAGS_H_
-#define WIFI_FEATURE_FLAGS_H_
+#include <android-base/logging.h>
+#include <android-base/macros.h>
+#include <gmock/gmock.h>
+
+#undef NAN  // This is weird, NAN is defined in bionic/libc/include/math.h:38
+#include "mock_wifi_mode_controller.h"
 
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_1 {
+namespace V1_2 {
 namespace implementation {
+namespace mode_controller {
 
-class WifiFeatureFlags {
- public:
-#ifdef WIFI_HIDL_FEATURE_AWARE
-  static const bool wifiHidlFeatureAware = true;
-#else
-  static const bool wifiHidlFeatureAware = false;
-#endif // WIFI_HIDL_FEATURE_AWARE
-};
-
+MockWifiModeController::MockWifiModeController() : WifiModeController() {}
+}  // namespace mode_controller
 }  // namespace implementation
-}  // namespace V1_1
+}  // namespace V1_2
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
-
-#endif  // WIFI_FEATURE_FLAGS_H_
diff --git a/wifi/1.2/default/tests/mock_wifi_mode_controller.h b/wifi/1.2/default/tests/mock_wifi_mode_controller.h
new file mode 100644
index 0000000..50c3e35
--- /dev/null
+++ b/wifi/1.2/default/tests/mock_wifi_mode_controller.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 MOCK_WIFI_MODE_CONTROLLER_H_
+#define MOCK_WIFI_MODE_CONTROLLER_H_
+
+#include <gmock/gmock.h>
+
+#include "wifi_mode_controller.h"
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace V1_2 {
+namespace implementation {
+namespace mode_controller {
+
+class MockWifiModeController : public WifiModeController {
+   public:
+    MockWifiModeController();
+    MOCK_METHOD0(initialize, bool());
+    MOCK_METHOD1(changeFirmwareMode, bool(IfaceType));
+    MOCK_METHOD1(isFirmwareModeChangeNeeded, bool(IfaceType));
+    MOCK_METHOD0(deinitialize, bool());
+};
+}  // namespace mode_controller
+}  // namespace implementation
+}  // namespace V1_2
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
+
+#endif  // MOCK_WIFI_MODE_CONTROLLER_H_
diff --git a/wifi/1.2/default/tests/runtests.sh b/wifi/1.2/default/tests/runtests.sh
new file mode 100755
index 0000000..966a6a7
--- /dev/null
+++ b/wifi/1.2/default/tests/runtests.sh
@@ -0,0 +1,50 @@
+#!/usr/bin/env bash
+
+# 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.
+
+if [ -z $ANDROID_BUILD_TOP ]; then
+  echo "You need to source and lunch before you can use this script"
+  exit 1
+fi
+
+echo "Running tests"
+set -e # fail early
+
+#NOTE We can't actually run these commands, since they rely on functions added by
+#build / envsetup.sh to the bash shell environment.
+echo "+ mmma -j32 $ANDROID_BUILD_TOP/"
+make -j32 -C $ANDROID_BUILD_TOP -f build/core/main.mk \
+    MODULES-IN-hardware-interfaces-wifi-1.2-default
+
+set -x # print commands
+
+adb wait-for-device
+adb root
+adb wait-for-device
+
+#'disable-verity' will appear in 'adb remount' output if
+#dm - verity is enabled and needs to be disabled.
+if adb remount | grep 'disable-verity'; then
+  adb disable-verity
+  adb reboot
+  adb wait-for-device
+  adb root
+  adb wait-for-device
+  adb remount
+fi
+
+adb sync
+
+adb shell /data/nativetest/vendor/android.hardware.wifi@1.0-service-tests/android.hardware.wifi@1.0-service-tests
diff --git a/wifi/1.2/default/tests/wifi_chip_unit_tests.cpp b/wifi/1.2/default/tests/wifi_chip_unit_tests.cpp
new file mode 100644
index 0000000..f73869b
--- /dev/null
+++ b/wifi/1.2/default/tests/wifi_chip_unit_tests.cpp
@@ -0,0 +1,547 @@
+/*
+ * 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 <android-base/macros.h>
+#include <gmock/gmock.h>
+
+#undef NAN  // This is weird, NAN is defined in bionic/libc/include/math.h:38
+#include "wifi_chip.h"
+
+#include "mock_wifi_feature_flags.h"
+#include "mock_wifi_legacy_hal.h"
+#include "mock_wifi_mode_controller.h"
+
+using testing::NiceMock;
+using testing::Return;
+using testing::Test;
+
+namespace {
+using android::hardware::wifi::V1_0::ChipId;
+
+constexpr ChipId kFakeChipId = 5;
+}  // namespace
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace V1_2 {
+namespace implementation {
+
+class WifiChipTest : public Test {
+   protected:
+    void setupV1IfaceCombination() {
+        EXPECT_CALL(*feature_flags_, isAwareSupported())
+            .WillRepeatedly(testing::Return(false));
+        EXPECT_CALL(*feature_flags_, isDualInterfaceSupported())
+            .WillRepeatedly(testing::Return(false));
+    }
+
+    void setupV1_AwareIfaceCombination() {
+        EXPECT_CALL(*feature_flags_, isAwareSupported())
+            .WillRepeatedly(testing::Return(true));
+        EXPECT_CALL(*feature_flags_, isDualInterfaceSupported())
+            .WillRepeatedly(testing::Return(false));
+    }
+
+    void setupV2_AwareIfaceCombination() {
+        EXPECT_CALL(*feature_flags_, isAwareSupported())
+            .WillRepeatedly(testing::Return(true));
+        EXPECT_CALL(*feature_flags_, isDualInterfaceSupported())
+            .WillRepeatedly(testing::Return(true));
+    }
+
+    void assertNumberOfModes(uint32_t num_modes) {
+        chip_->getAvailableModes(
+            [num_modes](const WifiStatus& status,
+                        const std::vector<WifiChip::ChipMode>& modes) {
+                ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
+                // V2_Aware has 1 mode of operation.
+                ASSERT_EQ(num_modes, modes.size());
+            });
+    }
+
+    void findModeAndConfigureForIfaceType(const IfaceType& type) {
+        // This should be aligned with kInvalidModeId in wifi_chip.cpp.
+        ChipModeId mode_id = UINT32_MAX;
+        chip_->getAvailableModes(
+            [&mode_id, &type](const WifiStatus& status,
+                              const std::vector<WifiChip::ChipMode>& modes) {
+                ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
+                for (const auto& mode : modes) {
+                    for (const auto& combination : mode.availableCombinations) {
+                        for (const auto& limit : combination.limits) {
+                            if (limit.types.end() !=
+                                std::find(limit.types.begin(),
+                                          limit.types.end(), type)) {
+                                mode_id = mode.id;
+                            }
+                        }
+                    }
+                }
+            });
+        ASSERT_NE(UINT32_MAX, mode_id);
+
+        chip_->configureChip(mode_id, [](const WifiStatus& status) {
+            ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
+        });
+    }
+
+    // Returns an empty string on error.
+    std::string createIface(const IfaceType& type) {
+        std::string iface_name;
+        if (type == IfaceType::AP) {
+            chip_->createApIface([&iface_name](const WifiStatus& status,
+                                               const sp<IWifiApIface>& iface) {
+                if (WifiStatusCode::SUCCESS == status.code) {
+                    ASSERT_NE(iface.get(), nullptr);
+                    iface->getName([&iface_name](const WifiStatus& status,
+                                                 const hidl_string& name) {
+                        ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
+                        iface_name = name.c_str();
+                    });
+                }
+            });
+        } else if (type == IfaceType::NAN) {
+            chip_->createNanIface(
+                [&iface_name](const WifiStatus& status,
+                              const sp<IWifiNanIface>& iface) {
+                    if (WifiStatusCode::SUCCESS == status.code) {
+                        ASSERT_NE(iface.get(), nullptr);
+                        iface->getName([&iface_name](const WifiStatus& status,
+                                                     const hidl_string& name) {
+                            ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
+                            iface_name = name.c_str();
+                        });
+                    }
+                });
+        } else if (type == IfaceType::P2P) {
+            chip_->createP2pIface(
+                [&iface_name](const WifiStatus& status,
+                              const sp<IWifiP2pIface>& iface) {
+                    if (WifiStatusCode::SUCCESS == status.code) {
+                        ASSERT_NE(iface.get(), nullptr);
+                        iface->getName([&iface_name](const WifiStatus& status,
+                                                     const hidl_string& name) {
+                            ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
+                            iface_name = name.c_str();
+                        });
+                    }
+                });
+        } else if (type == IfaceType::STA) {
+            chip_->createStaIface(
+                [&iface_name](const WifiStatus& status,
+                              const sp<IWifiStaIface>& iface) {
+                    if (WifiStatusCode::SUCCESS == status.code) {
+                        ASSERT_NE(iface.get(), nullptr);
+                        iface->getName([&iface_name](const WifiStatus& status,
+                                                     const hidl_string& name) {
+                            ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
+                            iface_name = name.c_str();
+                        });
+                    }
+                });
+        }
+        return iface_name;
+    }
+
+    void removeIface(const IfaceType& type, const std::string& iface_name) {
+        if (type == IfaceType::AP) {
+            chip_->removeApIface(iface_name, [](const WifiStatus& status) {
+                ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
+            });
+        } else if (type == IfaceType::NAN) {
+            chip_->removeNanIface(iface_name, [](const WifiStatus& status) {
+                ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
+            });
+        } else if (type == IfaceType::P2P) {
+            chip_->removeP2pIface(iface_name, [](const WifiStatus& status) {
+                ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
+            });
+        } else if (type == IfaceType::STA) {
+            chip_->removeStaIface(iface_name, [](const WifiStatus& status) {
+                ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
+            });
+        }
+    }
+
+   public:
+    void SetUp() override {
+        chip_ = new WifiChip(chip_id_, legacy_hal_, mode_controller_,
+                             feature_flags_);
+
+        EXPECT_CALL(*mode_controller_, changeFirmwareMode(testing::_))
+            .WillRepeatedly(testing::Return(true));
+        EXPECT_CALL(*legacy_hal_, start())
+            .WillRepeatedly(testing::Return(legacy_hal::WIFI_SUCCESS));
+    }
+
+   private:
+    sp<WifiChip> chip_;
+    ChipId chip_id_ = kFakeChipId;
+    std::shared_ptr<NiceMock<legacy_hal::MockWifiLegacyHal>> legacy_hal_{
+        new NiceMock<legacy_hal::MockWifiLegacyHal>};
+    std::shared_ptr<NiceMock<mode_controller::MockWifiModeController>>
+        mode_controller_{new NiceMock<mode_controller::MockWifiModeController>};
+    std::shared_ptr<NiceMock<feature_flags::MockWifiFeatureFlags>>
+        feature_flags_{new NiceMock<feature_flags::MockWifiFeatureFlags>};
+};
+
+////////// V1 Iface Combinations ////////////
+// Mode 1 - STA + P2P
+// Mode 2 - AP
+class WifiChipV1IfaceCombinationTest : public WifiChipTest {
+   public:
+    void SetUp() override {
+        setupV1IfaceCombination();
+        WifiChipTest::SetUp();
+        // V1 has 2 modes of operation.
+        assertNumberOfModes(2u);
+    }
+};
+
+TEST_F(WifiChipV1IfaceCombinationTest, StaMode_CreateSta_ShouldSucceed) {
+    findModeAndConfigureForIfaceType(IfaceType::STA);
+    ASSERT_FALSE(createIface(IfaceType::STA).empty());
+}
+
+TEST_F(WifiChipV1IfaceCombinationTest, StaMode_CreateP2p_ShouldSucceed) {
+    findModeAndConfigureForIfaceType(IfaceType::STA);
+    ASSERT_FALSE(createIface(IfaceType::P2P).empty());
+}
+
+TEST_F(WifiChipV1IfaceCombinationTest, StaMode_CreateNan_ShouldFail) {
+    findModeAndConfigureForIfaceType(IfaceType::STA);
+    ASSERT_TRUE(createIface(IfaceType::NAN).empty());
+}
+
+TEST_F(WifiChipV1IfaceCombinationTest, StaMode_CreateAp_ShouldFail) {
+    findModeAndConfigureForIfaceType(IfaceType::STA);
+    ASSERT_TRUE(createIface(IfaceType::AP).empty());
+}
+
+TEST_F(WifiChipV1IfaceCombinationTest, StaMode_CreateStaP2p_ShouldSucceed) {
+    findModeAndConfigureForIfaceType(IfaceType::STA);
+    ASSERT_FALSE(createIface(IfaceType::STA).empty());
+    ASSERT_FALSE(createIface(IfaceType::P2P).empty());
+}
+
+TEST_F(WifiChipV1IfaceCombinationTest, ApMode_CreateAp_ShouldSucceed) {
+    findModeAndConfigureForIfaceType(IfaceType::AP);
+    ASSERT_FALSE(createIface(IfaceType::AP).empty());
+}
+
+TEST_F(WifiChipV1IfaceCombinationTest, ApMode_CreateSta_ShouldFail) {
+    findModeAndConfigureForIfaceType(IfaceType::AP);
+    ASSERT_TRUE(createIface(IfaceType::STA).empty());
+}
+
+TEST_F(WifiChipV1IfaceCombinationTest, ApMode_CreateP2p_ShouldFail) {
+    findModeAndConfigureForIfaceType(IfaceType::AP);
+    ASSERT_TRUE(createIface(IfaceType::STA).empty());
+}
+
+TEST_F(WifiChipV1IfaceCombinationTest, ApMode_CreateNan_ShouldFail) {
+    findModeAndConfigureForIfaceType(IfaceType::AP);
+    ASSERT_TRUE(createIface(IfaceType::NAN).empty());
+}
+
+////////// V1 + Aware Iface Combinations ////////////
+// Mode 1 - STA + P2P/NAN
+// Mode 2 - AP
+class WifiChipV1_AwareIfaceCombinationTest : public WifiChipTest {
+   public:
+    void SetUp() override {
+        setupV1_AwareIfaceCombination();
+        WifiChipTest::SetUp();
+        // V1_Aware has 2 modes of operation.
+        assertNumberOfModes(2u);
+    }
+};
+
+TEST_F(WifiChipV1_AwareIfaceCombinationTest, StaMode_CreateSta_ShouldSucceed) {
+    findModeAndConfigureForIfaceType(IfaceType::STA);
+    ASSERT_FALSE(createIface(IfaceType::STA).empty());
+}
+
+TEST_F(WifiChipV1_AwareIfaceCombinationTest, StaMode_CreateP2p_ShouldSucceed) {
+    findModeAndConfigureForIfaceType(IfaceType::STA);
+    ASSERT_FALSE(createIface(IfaceType::P2P).empty());
+}
+
+TEST_F(WifiChipV1_AwareIfaceCombinationTest, StaMode_CreateNan_ShouldSucceed) {
+    findModeAndConfigureForIfaceType(IfaceType::STA);
+    ASSERT_FALSE(createIface(IfaceType::NAN).empty());
+}
+
+TEST_F(WifiChipV1_AwareIfaceCombinationTest, StaMode_CreateAp_ShouldFail) {
+    findModeAndConfigureForIfaceType(IfaceType::STA);
+    ASSERT_TRUE(createIface(IfaceType::AP).empty());
+}
+
+TEST_F(WifiChipV1_AwareIfaceCombinationTest,
+       StaMode_CreateStaP2p_ShouldSucceed) {
+    findModeAndConfigureForIfaceType(IfaceType::STA);
+    ASSERT_FALSE(createIface(IfaceType::STA).empty());
+    ASSERT_FALSE(createIface(IfaceType::P2P).empty());
+}
+
+TEST_F(WifiChipV1_AwareIfaceCombinationTest,
+       StaMode_CreateStaNan_ShouldSucceed) {
+    findModeAndConfigureForIfaceType(IfaceType::STA);
+    ASSERT_FALSE(createIface(IfaceType::STA).empty());
+    ASSERT_FALSE(createIface(IfaceType::NAN).empty());
+}
+
+TEST_F(WifiChipV1_AwareIfaceCombinationTest,
+       StaMode_CreateStaP2PNan_ShouldFail) {
+    findModeAndConfigureForIfaceType(IfaceType::STA);
+    ASSERT_FALSE(createIface(IfaceType::STA).empty());
+    ASSERT_FALSE(createIface(IfaceType::P2P).empty());
+    ASSERT_TRUE(createIface(IfaceType::NAN).empty());
+}
+
+TEST_F(WifiChipV1_AwareIfaceCombinationTest,
+       StaMode_CreateStaNan_AfterP2pRemove_ShouldSucceed) {
+    findModeAndConfigureForIfaceType(IfaceType::STA);
+    ASSERT_FALSE(createIface(IfaceType::STA).empty());
+    const auto p2p_iface_name = createIface(IfaceType::P2P);
+    ASSERT_FALSE(p2p_iface_name.empty());
+    ASSERT_TRUE(createIface(IfaceType::NAN).empty());
+
+    // After removing P2P iface, NAN iface creation should succeed.
+    removeIface(IfaceType::P2P, p2p_iface_name);
+    ASSERT_FALSE(createIface(IfaceType::NAN).empty());
+}
+
+TEST_F(WifiChipV1_AwareIfaceCombinationTest,
+       StaMode_CreateStaP2p_AfterNanRemove_ShouldSucceed) {
+    findModeAndConfigureForIfaceType(IfaceType::STA);
+    ASSERT_FALSE(createIface(IfaceType::STA).empty());
+    const auto nan_iface_name = createIface(IfaceType::NAN);
+    ASSERT_FALSE(nan_iface_name.empty());
+    ASSERT_TRUE(createIface(IfaceType::P2P).empty());
+
+    // After removing NAN iface, P2P iface creation should succeed.
+    removeIface(IfaceType::NAN, nan_iface_name);
+    ASSERT_FALSE(createIface(IfaceType::P2P).empty());
+}
+
+TEST_F(WifiChipV1_AwareIfaceCombinationTest, ApMode_CreateAp_ShouldSucceed) {
+    findModeAndConfigureForIfaceType(IfaceType::AP);
+    ASSERT_FALSE(createIface(IfaceType::AP).empty());
+}
+
+TEST_F(WifiChipV1_AwareIfaceCombinationTest, ApMode_CreateSta_ShouldFail) {
+    findModeAndConfigureForIfaceType(IfaceType::AP);
+    ASSERT_TRUE(createIface(IfaceType::STA).empty());
+}
+
+TEST_F(WifiChipV1_AwareIfaceCombinationTest, ApMode_CreateP2p_ShouldFail) {
+    findModeAndConfigureForIfaceType(IfaceType::AP);
+    ASSERT_TRUE(createIface(IfaceType::STA).empty());
+}
+
+TEST_F(WifiChipV1_AwareIfaceCombinationTest, ApMode_CreateNan_ShouldFail) {
+    findModeAndConfigureForIfaceType(IfaceType::AP);
+    ASSERT_TRUE(createIface(IfaceType::NAN).empty());
+}
+
+////////// V2 + Aware Iface Combinations ////////////
+// Mode 1 - STA + STA/AP
+//        - STA + P2P/NAN
+class WifiChipV2_AwareIfaceCombinationTest : public WifiChipTest {
+   public:
+    void SetUp() override {
+        setupV2_AwareIfaceCombination();
+        WifiChipTest::SetUp();
+        // V2_Aware has 1 mode of operation.
+        assertNumberOfModes(1u);
+    }
+};
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateSta_ShouldSucceed) {
+    findModeAndConfigureForIfaceType(IfaceType::STA);
+    ASSERT_FALSE(createIface(IfaceType::STA).empty());
+}
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateP2p_ShouldSucceed) {
+    findModeAndConfigureForIfaceType(IfaceType::STA);
+    ASSERT_FALSE(createIface(IfaceType::P2P).empty());
+}
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateNan_ShouldSucceed) {
+    findModeAndConfigureForIfaceType(IfaceType::STA);
+    ASSERT_FALSE(createIface(IfaceType::NAN).empty());
+}
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateAp_ShouldSucceed) {
+    findModeAndConfigureForIfaceType(IfaceType::STA);
+    ASSERT_FALSE(createIface(IfaceType::AP).empty());
+}
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateStaSta_ShouldSucceed) {
+    findModeAndConfigureForIfaceType(IfaceType::AP);
+    ASSERT_FALSE(createIface(IfaceType::STA).empty());
+    ASSERT_FALSE(createIface(IfaceType::STA).empty());
+}
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateStaAp_ShouldSucceed) {
+    findModeAndConfigureForIfaceType(IfaceType::AP);
+    ASSERT_FALSE(createIface(IfaceType::AP).empty());
+    ASSERT_FALSE(createIface(IfaceType::STA).empty());
+}
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateStaStaAp_ShouldFail) {
+    findModeAndConfigureForIfaceType(IfaceType::AP);
+    ASSERT_FALSE(createIface(IfaceType::STA).empty());
+    ASSERT_FALSE(createIface(IfaceType::STA).empty());
+    ASSERT_TRUE(createIface(IfaceType::AP).empty());
+}
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest,
+       CreateStaAp_AfterStaRemove_ShouldSucceed) {
+    findModeAndConfigureForIfaceType(IfaceType::STA);
+    ASSERT_FALSE(createIface(IfaceType::STA).empty());
+    const auto sta_iface_name = createIface(IfaceType::STA);
+    ASSERT_FALSE(sta_iface_name.empty());
+    ASSERT_TRUE(createIface(IfaceType::AP).empty());
+
+    // After removing STA iface, AP iface creation should succeed.
+    removeIface(IfaceType::STA, sta_iface_name);
+    ASSERT_FALSE(createIface(IfaceType::AP).empty());
+}
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest,
+       CreateStaSta_AfterApRemove_ShouldSucceed) {
+    findModeAndConfigureForIfaceType(IfaceType::STA);
+    ASSERT_FALSE(createIface(IfaceType::STA).empty());
+    const auto ap_iface_name = createIface(IfaceType::AP);
+    ASSERT_FALSE(ap_iface_name.empty());
+    ASSERT_TRUE(createIface(IfaceType::STA).empty());
+
+    // After removing AP  iface, STA iface creation should succeed.
+    removeIface(IfaceType::AP, ap_iface_name);
+    ASSERT_FALSE(createIface(IfaceType::STA).empty());
+}
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateStaP2p_ShouldSucceed) {
+    findModeAndConfigureForIfaceType(IfaceType::STA);
+    ASSERT_FALSE(createIface(IfaceType::STA).empty());
+    ASSERT_FALSE(createIface(IfaceType::P2P).empty());
+}
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateStaNan_ShouldSucceed) {
+    findModeAndConfigureForIfaceType(IfaceType::STA);
+    ASSERT_FALSE(createIface(IfaceType::STA).empty());
+    ASSERT_FALSE(createIface(IfaceType::NAN).empty());
+}
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateStaP2PNan_ShouldFail) {
+    findModeAndConfigureForIfaceType(IfaceType::STA);
+    ASSERT_FALSE(createIface(IfaceType::STA).empty());
+    ASSERT_FALSE(createIface(IfaceType::P2P).empty());
+    ASSERT_TRUE(createIface(IfaceType::NAN).empty());
+}
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest,
+       CreateStaNan_AfterP2pRemove_ShouldSucceed) {
+    findModeAndConfigureForIfaceType(IfaceType::STA);
+    ASSERT_FALSE(createIface(IfaceType::STA).empty());
+    const auto p2p_iface_name = createIface(IfaceType::P2P);
+    ASSERT_FALSE(p2p_iface_name.empty());
+    ASSERT_TRUE(createIface(IfaceType::NAN).empty());
+
+    // After removing P2P iface, NAN iface creation should succeed.
+    removeIface(IfaceType::P2P, p2p_iface_name);
+    ASSERT_FALSE(createIface(IfaceType::NAN).empty());
+}
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest,
+       CreateStaP2p_AfterNanRemove_ShouldSucceed) {
+    findModeAndConfigureForIfaceType(IfaceType::STA);
+    ASSERT_FALSE(createIface(IfaceType::STA).empty());
+    const auto nan_iface_name = createIface(IfaceType::NAN);
+    ASSERT_FALSE(nan_iface_name.empty());
+    ASSERT_TRUE(createIface(IfaceType::P2P).empty());
+
+    // After removing NAN iface, P2P iface creation should succeed.
+    removeIface(IfaceType::NAN, nan_iface_name);
+    ASSERT_FALSE(createIface(IfaceType::P2P).empty());
+}
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateApNan_ShouldFail) {
+    findModeAndConfigureForIfaceType(IfaceType::AP);
+    ASSERT_FALSE(createIface(IfaceType::AP).empty());
+    ASSERT_TRUE(createIface(IfaceType::NAN).empty());
+}
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateApP2p_ShouldFail) {
+    findModeAndConfigureForIfaceType(IfaceType::AP);
+    ASSERT_FALSE(createIface(IfaceType::AP).empty());
+    ASSERT_TRUE(createIface(IfaceType::P2P).empty());
+}
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest,
+       StaMode_CreateStaNan_AfterP2pRemove_ShouldSucceed) {
+    findModeAndConfigureForIfaceType(IfaceType::STA);
+    ASSERT_FALSE(createIface(IfaceType::STA).empty());
+    const auto p2p_iface_name = createIface(IfaceType::P2P);
+    ASSERT_FALSE(p2p_iface_name.empty());
+    ASSERT_TRUE(createIface(IfaceType::NAN).empty());
+
+    // After removing P2P iface, NAN iface creation should succeed.
+    removeIface(IfaceType::P2P, p2p_iface_name);
+    ASSERT_FALSE(createIface(IfaceType::NAN).empty());
+}
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest,
+       StaMode_CreateStaP2p_AfterNanRemove_ShouldSucceed) {
+    findModeAndConfigureForIfaceType(IfaceType::STA);
+    ASSERT_FALSE(createIface(IfaceType::STA).empty());
+    const auto nan_iface_name = createIface(IfaceType::NAN);
+    ASSERT_FALSE(nan_iface_name.empty());
+    ASSERT_TRUE(createIface(IfaceType::P2P).empty());
+
+    // After removing NAN iface, P2P iface creation should succeed.
+    removeIface(IfaceType::NAN, nan_iface_name);
+    ASSERT_FALSE(createIface(IfaceType::P2P).empty());
+}
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest,
+       CreateStaSta_EnsureDifferentIfaceNames) {
+    findModeAndConfigureForIfaceType(IfaceType::AP);
+    const auto sta1_iface_name = createIface(IfaceType::STA);
+    const auto sta2_iface_name = createIface(IfaceType::STA);
+    ASSERT_FALSE(sta1_iface_name.empty());
+    ASSERT_FALSE(sta2_iface_name.empty());
+    ASSERT_NE(sta1_iface_name, sta2_iface_name);
+}
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest,
+       CreateStaAp_EnsureDifferentIfaceNames) {
+    findModeAndConfigureForIfaceType(IfaceType::AP);
+    const auto sta_iface_name = createIface(IfaceType::STA);
+    const auto ap_iface_name = createIface(IfaceType::AP);
+    ASSERT_FALSE(sta_iface_name.empty());
+    ASSERT_FALSE(ap_iface_name.empty());
+    ASSERT_NE(sta_iface_name, ap_iface_name);
+}
+}  // namespace implementation
+}  // namespace V1_2
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
diff --git a/wifi/1.2/default/wifi.cpp b/wifi/1.2/default/wifi.cpp
new file mode 100644
index 0000000..06f5058
--- /dev/null
+++ b/wifi/1.2/default/wifi.cpp
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+
+#include "hidl_return_util.h"
+#include "wifi.h"
+#include "wifi_status_util.h"
+
+namespace {
+// Chip ID to use for the only supported chip.
+static constexpr android::hardware::wifi::V1_0::ChipId kChipId = 0;
+}  // namespace
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace V1_2 {
+namespace implementation {
+using hidl_return_util::validateAndCall;
+using hidl_return_util::validateAndCallWithLock;
+
+Wifi::Wifi(
+    const std::shared_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
+    const std::shared_ptr<mode_controller::WifiModeController> mode_controller,
+    const std::shared_ptr<feature_flags::WifiFeatureFlags> feature_flags)
+    : legacy_hal_(legacy_hal),
+      mode_controller_(mode_controller),
+      feature_flags_(feature_flags),
+      run_state_(RunState::STOPPED) {}
+
+bool Wifi::isValid() {
+    // This object is always valid.
+    return true;
+}
+
+Return<void> Wifi::registerEventCallback(
+    const sp<IWifiEventCallback>& event_callback,
+    registerEventCallback_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN,
+                           &Wifi::registerEventCallbackInternal, hidl_status_cb,
+                           event_callback);
+}
+
+Return<bool> Wifi::isStarted() { return run_state_ != RunState::STOPPED; }
+
+Return<void> Wifi::start(start_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN,
+                           &Wifi::startInternal, hidl_status_cb);
+}
+
+Return<void> Wifi::stop(stop_cb hidl_status_cb) {
+    return validateAndCallWithLock(this, WifiStatusCode::ERROR_UNKNOWN,
+                                   &Wifi::stopInternal, hidl_status_cb);
+}
+
+Return<void> Wifi::getChipIds(getChipIds_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN,
+                           &Wifi::getChipIdsInternal, hidl_status_cb);
+}
+
+Return<void> Wifi::getChip(ChipId chip_id, getChip_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN,
+                           &Wifi::getChipInternal, hidl_status_cb, chip_id);
+}
+
+WifiStatus Wifi::registerEventCallbackInternal(
+    const sp<IWifiEventCallback>& event_callback) {
+    if (!event_cb_handler_.addCallback(event_callback)) {
+        return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
+    }
+    return createWifiStatus(WifiStatusCode::SUCCESS);
+}
+
+WifiStatus Wifi::startInternal() {
+    if (run_state_ == RunState::STARTED) {
+        return createWifiStatus(WifiStatusCode::SUCCESS);
+    } else if (run_state_ == RunState::STOPPING) {
+        return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE,
+                                "HAL is stopping");
+    }
+    WifiStatus wifi_status = initializeModeControllerAndLegacyHal();
+    if (wifi_status.code == WifiStatusCode::SUCCESS) {
+        // Create the chip instance once the HAL is started.
+        chip_ = new WifiChip(kChipId, legacy_hal_, mode_controller_,
+                             feature_flags_);
+        run_state_ = RunState::STARTED;
+        for (const auto& callback : event_cb_handler_.getCallbacks()) {
+            if (!callback->onStart().isOk()) {
+                LOG(ERROR) << "Failed to invoke onStart callback";
+            };
+        }
+        LOG(INFO) << "Wifi HAL started";
+    } else {
+        for (const auto& callback : event_cb_handler_.getCallbacks()) {
+            if (!callback->onFailure(wifi_status).isOk()) {
+                LOG(ERROR) << "Failed to invoke onFailure callback";
+            }
+        }
+        LOG(ERROR) << "Wifi HAL start failed";
+    }
+    return wifi_status;
+}
+
+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) {
+        return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE,
+                                "HAL is stopping");
+    }
+    // Clear the chip object and its child objects since the HAL is now
+    // stopped.
+    if (chip_.get()) {
+        chip_->invalidate();
+        chip_.clear();
+    }
+    WifiStatus wifi_status = stopLegacyHalAndDeinitializeModeController(lock);
+    if (wifi_status.code == WifiStatusCode::SUCCESS) {
+        for (const auto& callback : event_cb_handler_.getCallbacks()) {
+            if (!callback->onStop().isOk()) {
+                LOG(ERROR) << "Failed to invoke onStop callback";
+            };
+        }
+        LOG(INFO) << "Wifi HAL stopped";
+    } else {
+        for (const auto& callback : event_cb_handler_.getCallbacks()) {
+            if (!callback->onFailure(wifi_status).isOk()) {
+                LOG(ERROR) << "Failed to invoke onFailure callback";
+            }
+        }
+        LOG(ERROR) << "Wifi HAL stop failed";
+    }
+    return wifi_status;
+}
+
+std::pair<WifiStatus, std::vector<ChipId>> Wifi::getChipIdsInternal() {
+    std::vector<ChipId> chip_ids;
+    if (chip_.get()) {
+        chip_ids.emplace_back(kChipId);
+    }
+    return {createWifiStatus(WifiStatusCode::SUCCESS), std::move(chip_ids)};
+}
+
+std::pair<WifiStatus, sp<IWifiChip>> Wifi::getChipInternal(ChipId chip_id) {
+    if (!chip_.get()) {
+        return {createWifiStatus(WifiStatusCode::ERROR_NOT_STARTED), nullptr};
+    }
+    if (chip_id != kChipId) {
+        return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr};
+    }
+    return {createWifiStatus(WifiStatusCode::SUCCESS), chip_};
+}
+
+WifiStatus Wifi::initializeModeControllerAndLegacyHal() {
+    if (!mode_controller_->initialize()) {
+        LOG(ERROR) << "Failed to initialize firmware mode controller";
+        return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
+    }
+    legacy_hal::wifi_error legacy_status = legacy_hal_->initialize();
+    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+        LOG(ERROR) << "Failed to initialize legacy HAL: "
+                   << legacyErrorToString(legacy_status);
+        return createWifiStatusFromLegacyError(legacy_status);
+    }
+    return createWifiStatus(WifiStatusCode::SUCCESS);
+}
+
+WifiStatus Wifi::stopLegacyHalAndDeinitializeModeController(
+    /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock) {
+    run_state_ = RunState::STOPPING;
+    legacy_hal::wifi_error legacy_status =
+        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);
+        return createWifiStatusFromLegacyError(legacy_status);
+    }
+    if (!mode_controller_->deinitialize()) {
+        LOG(ERROR) << "Failed to deinitialize firmware mode controller";
+        return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
+    }
+    return createWifiStatus(WifiStatusCode::SUCCESS);
+}
+}  // namespace implementation
+}  // namespace V1_2
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
diff --git a/wifi/1.2/default/wifi.h b/wifi/1.2/default/wifi.h
new file mode 100644
index 0000000..440c3c7
--- /dev/null
+++ b/wifi/1.2/default/wifi.h
@@ -0,0 +1,94 @@
+/*
+ * 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 WIFI_H_
+#define WIFI_H_
+
+#include <functional>
+
+#include <android-base/macros.h>
+#include <android/hardware/wifi/1.2/IWifi.h>
+#include <utils/Looper.h>
+
+#include "hidl_callback_util.h"
+#include "wifi_chip.h"
+#include "wifi_feature_flags.h"
+#include "wifi_legacy_hal.h"
+#include "wifi_mode_controller.h"
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace V1_2 {
+namespace implementation {
+
+/**
+ * Root HIDL interface object used to control the Wifi HAL.
+ */
+class Wifi : public V1_2::IWifi {
+   public:
+    Wifi(const std::shared_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
+         const std::shared_ptr<mode_controller::WifiModeController>
+             mode_controller,
+         const std::shared_ptr<feature_flags::WifiFeatureFlags> feature_flags);
+
+    bool isValid();
+
+    // HIDL methods exposed.
+    Return<void> registerEventCallback(
+        const sp<IWifiEventCallback>& event_callback,
+        registerEventCallback_cb hidl_status_cb) override;
+    Return<bool> isStarted() override;
+    Return<void> start(start_cb hidl_status_cb) override;
+    Return<void> stop(stop_cb hidl_status_cb) override;
+    Return<void> getChipIds(getChipIds_cb hidl_status_cb) override;
+    Return<void> getChip(ChipId chip_id, getChip_cb hidl_status_cb) override;
+
+   private:
+    enum class RunState { STOPPED, STARTED, STOPPING };
+
+    // Corresponding worker functions for the HIDL methods.
+    WifiStatus registerEventCallbackInternal(
+        const sp<IWifiEventCallback>& event_callback);
+    WifiStatus startInternal();
+    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 initializeModeControllerAndLegacyHal();
+    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.
+    std::shared_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
+    std::shared_ptr<mode_controller::WifiModeController> mode_controller_;
+    std::shared_ptr<feature_flags::WifiFeatureFlags> feature_flags_;
+    RunState run_state_;
+    sp<WifiChip> chip_;
+    hidl_callback_util::HidlCallbackHandler<IWifiEventCallback>
+        event_cb_handler_;
+
+    DISALLOW_COPY_AND_ASSIGN(Wifi);
+};
+
+}  // namespace implementation
+}  // namespace V1_2
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
+
+#endif  // WIFI_H_
diff --git a/wifi/1.2/default/wifi_ap_iface.cpp b/wifi/1.2/default/wifi_ap_iface.cpp
new file mode 100644
index 0000000..92b7b48
--- /dev/null
+++ b/wifi/1.2/default/wifi_ap_iface.cpp
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+
+#include "hidl_return_util.h"
+#include "hidl_struct_util.h"
+#include "wifi_ap_iface.h"
+#include "wifi_status_util.h"
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace V1_2 {
+namespace implementation {
+using hidl_return_util::validateAndCall;
+
+WifiApIface::WifiApIface(
+    const std::string& ifname,
+    const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal)
+    : ifname_(ifname), legacy_hal_(legacy_hal), is_valid_(true) {}
+
+void WifiApIface::invalidate() {
+    legacy_hal_.reset();
+    is_valid_ = false;
+}
+
+bool WifiApIface::isValid() { return is_valid_; }
+
+std::string WifiApIface::getName() { return ifname_; }
+
+Return<void> WifiApIface::getName(getName_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiApIface::getNameInternal, hidl_status_cb);
+}
+
+Return<void> WifiApIface::getType(getType_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiApIface::getTypeInternal, hidl_status_cb);
+}
+
+Return<void> WifiApIface::setCountryCode(const hidl_array<int8_t, 2>& code,
+                                         setCountryCode_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiApIface::setCountryCodeInternal, hidl_status_cb,
+                           code);
+}
+
+Return<void> WifiApIface::getValidFrequenciesForBand(
+    WifiBand band, getValidFrequenciesForBand_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiApIface::getValidFrequenciesForBandInternal,
+                           hidl_status_cb, band);
+}
+
+std::pair<WifiStatus, std::string> WifiApIface::getNameInternal() {
+    return {createWifiStatus(WifiStatusCode::SUCCESS), ifname_};
+}
+
+std::pair<WifiStatus, IfaceType> WifiApIface::getTypeInternal() {
+    return {createWifiStatus(WifiStatusCode::SUCCESS), IfaceType::AP};
+}
+
+WifiStatus WifiApIface::setCountryCodeInternal(
+    const std::array<int8_t, 2>& code) {
+    legacy_hal::wifi_error legacy_status =
+        legacy_hal_.lock()->setCountryCode(ifname_, code);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+std::pair<WifiStatus, std::vector<WifiChannelInMhz>>
+WifiApIface::getValidFrequenciesForBandInternal(WifiBand band) {
+    static_assert(sizeof(WifiChannelInMhz) == sizeof(uint32_t),
+                  "Size mismatch");
+    legacy_hal::wifi_error legacy_status;
+    std::vector<uint32_t> valid_frequencies;
+    std::tie(legacy_status, valid_frequencies) =
+        legacy_hal_.lock()->getValidFrequenciesForBand(
+            ifname_, hidl_struct_util::convertHidlWifiBandToLegacy(band));
+    return {createWifiStatusFromLegacyError(legacy_status), valid_frequencies};
+}
+}  // namespace implementation
+}  // namespace V1_2
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
diff --git a/wifi/1.2/default/wifi_ap_iface.h b/wifi/1.2/default/wifi_ap_iface.h
new file mode 100644
index 0000000..5363ec2
--- /dev/null
+++ b/wifi/1.2/default/wifi_ap_iface.h
@@ -0,0 +1,73 @@
+/*
+ * 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 WIFI_AP_IFACE_H_
+#define WIFI_AP_IFACE_H_
+
+#include <android-base/macros.h>
+#include <android/hardware/wifi/1.0/IWifiApIface.h>
+
+#include "wifi_legacy_hal.h"
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace V1_2 {
+namespace implementation {
+using namespace android::hardware::wifi::V1_0;
+
+/**
+ * HIDL interface object used to control a AP Iface instance.
+ */
+class WifiApIface : public V1_0::IWifiApIface {
+   public:
+    WifiApIface(const std::string& ifname,
+                const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal);
+    // Refer to |WifiChip::invalidate()|.
+    void invalidate();
+    bool isValid();
+    std::string getName();
+
+    // HIDL methods exposed.
+    Return<void> getName(getName_cb hidl_status_cb) override;
+    Return<void> getType(getType_cb hidl_status_cb) override;
+    Return<void> setCountryCode(const hidl_array<int8_t, 2>& code,
+                                setCountryCode_cb hidl_status_cb) override;
+    Return<void> getValidFrequenciesForBand(
+        WifiBand band, getValidFrequenciesForBand_cb hidl_status_cb) override;
+
+   private:
+    // Corresponding worker functions for the HIDL methods.
+    std::pair<WifiStatus, std::string> getNameInternal();
+    std::pair<WifiStatus, IfaceType> getTypeInternal();
+    WifiStatus setCountryCodeInternal(const std::array<int8_t, 2>& code);
+    std::pair<WifiStatus, std::vector<WifiChannelInMhz>>
+    getValidFrequenciesForBandInternal(WifiBand band);
+
+    std::string ifname_;
+    std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
+    bool is_valid_;
+
+    DISALLOW_COPY_AND_ASSIGN(WifiApIface);
+};
+
+}  // namespace implementation
+}  // namespace V1_2
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
+
+#endif  // WIFI_AP_IFACE_H_
diff --git a/wifi/1.2/default/wifi_chip.cpp b/wifi/1.2/default/wifi_chip.cpp
new file mode 100644
index 0000000..adba054
--- /dev/null
+++ b/wifi/1.2/default/wifi_chip.cpp
@@ -0,0 +1,1086 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+#include <cutils/properties.h>
+
+#include "hidl_return_util.h"
+#include "hidl_struct_util.h"
+#include "wifi_chip.h"
+#include "wifi_status_util.h"
+
+namespace {
+using android::hardware::hidl_string;
+using android::hardware::hidl_vec;
+using android::hardware::wifi::V1_0::ChipModeId;
+using android::hardware::wifi::V1_0::IfaceType;
+using android::hardware::wifi::V1_0::IWifiChip;
+using android::sp;
+
+constexpr ChipModeId kInvalidModeId = UINT32_MAX;
+// These mode ID's should be unique (even across combo versions). Refer to
+// handleChipConfiguration() for it's usage.
+// Mode ID's for V1
+constexpr ChipModeId kV1StaChipModeId = 0;
+constexpr ChipModeId kV1ApChipModeId = 1;
+// Mode ID for V2
+constexpr ChipModeId kV2ChipModeId = 2;
+
+template <typename Iface>
+void invalidateAndClear(std::vector<sp<Iface>>& ifaces, sp<Iface> iface) {
+    iface->invalidate();
+    ifaces.erase(std::remove(ifaces.begin(), ifaces.end(), iface),
+                 ifaces.end());
+}
+
+template <typename Iface>
+void invalidateAndClearAll(std::vector<sp<Iface>>& ifaces) {
+    for (const auto& iface : ifaces) {
+        iface->invalidate();
+    }
+    ifaces.clear();
+}
+
+template <typename Iface>
+std::vector<hidl_string> getNames(std::vector<sp<Iface>>& ifaces) {
+    std::vector<hidl_string> names;
+    for (const auto& iface : ifaces) {
+        names.emplace_back(iface->getName());
+    }
+    return names;
+}
+
+template <typename Iface>
+sp<Iface> findUsingName(std::vector<sp<Iface>>& ifaces,
+                        const std::string& name) {
+    std::vector<hidl_string> names;
+    for (const auto& iface : ifaces) {
+        if (name == iface->getName()) {
+            return iface;
+        }
+    }
+    return nullptr;
+}
+
+std::string getWlan0IfaceName() {
+    std::array<char, PROPERTY_VALUE_MAX> buffer;
+    property_get("wifi.interface", buffer.data(), "wlan0");
+    return buffer.data();
+}
+
+std::string getWlan1IfaceName() {
+    std::array<char, PROPERTY_VALUE_MAX> buffer;
+    property_get("wifi.concurrent.interface", buffer.data(), "wlan1");
+    return buffer.data();
+}
+
+std::string getP2pIfaceName() {
+    std::array<char, PROPERTY_VALUE_MAX> buffer;
+    property_get("wifi.direct.interface", buffer.data(), "p2p0");
+    return buffer.data();
+}
+
+}  // namespace
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace V1_2 {
+namespace implementation {
+using hidl_return_util::validateAndCall;
+using hidl_return_util::validateAndCallWithLock;
+
+WifiChip::WifiChip(
+    ChipId chip_id, const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
+    const std::weak_ptr<mode_controller::WifiModeController> mode_controller,
+    const std::weak_ptr<feature_flags::WifiFeatureFlags> feature_flags)
+    : chip_id_(chip_id),
+      legacy_hal_(legacy_hal),
+      mode_controller_(mode_controller),
+      feature_flags_(feature_flags),
+      is_valid_(true),
+      current_mode_id_(kInvalidModeId),
+      debug_ring_buffer_cb_registered_(false) {
+    populateModes();
+}
+
+void WifiChip::invalidate() {
+    invalidateAndRemoveAllIfaces();
+    legacy_hal_.reset();
+    event_cb_handler_.invalidate();
+    is_valid_ = false;
+}
+
+bool WifiChip::isValid() { return is_valid_; }
+
+std::set<sp<IWifiChipEventCallback>> WifiChip::getEventCallbacks() {
+    return event_cb_handler_.getCallbacks();
+}
+
+Return<void> WifiChip::getId(getId_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+                           &WifiChip::getIdInternal, hidl_status_cb);
+}
+
+Return<void> WifiChip::registerEventCallback(
+    const sp<IWifiChipEventCallback>& event_callback,
+    registerEventCallback_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+                           &WifiChip::registerEventCallbackInternal,
+                           hidl_status_cb, event_callback);
+}
+
+Return<void> WifiChip::getCapabilities(getCapabilities_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+                           &WifiChip::getCapabilitiesInternal, hidl_status_cb);
+}
+
+Return<void> WifiChip::getAvailableModes(getAvailableModes_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+                           &WifiChip::getAvailableModesInternal,
+                           hidl_status_cb);
+}
+
+Return<void> WifiChip::configureChip(ChipModeId mode_id,
+                                     configureChip_cb hidl_status_cb) {
+    return validateAndCallWithLock(
+        this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+        &WifiChip::configureChipInternal, hidl_status_cb, mode_id);
+}
+
+Return<void> WifiChip::getMode(getMode_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+                           &WifiChip::getModeInternal, hidl_status_cb);
+}
+
+Return<void> WifiChip::requestChipDebugInfo(
+    requestChipDebugInfo_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+                           &WifiChip::requestChipDebugInfoInternal,
+                           hidl_status_cb);
+}
+
+Return<void> WifiChip::requestDriverDebugDump(
+    requestDriverDebugDump_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+                           &WifiChip::requestDriverDebugDumpInternal,
+                           hidl_status_cb);
+}
+
+Return<void> WifiChip::requestFirmwareDebugDump(
+    requestFirmwareDebugDump_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+                           &WifiChip::requestFirmwareDebugDumpInternal,
+                           hidl_status_cb);
+}
+
+Return<void> WifiChip::createApIface(createApIface_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+                           &WifiChip::createApIfaceInternal, hidl_status_cb);
+}
+
+Return<void> WifiChip::getApIfaceNames(getApIfaceNames_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+                           &WifiChip::getApIfaceNamesInternal, hidl_status_cb);
+}
+
+Return<void> WifiChip::getApIface(const hidl_string& ifname,
+                                  getApIface_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+                           &WifiChip::getApIfaceInternal, hidl_status_cb,
+                           ifname);
+}
+
+Return<void> WifiChip::removeApIface(const hidl_string& ifname,
+                                     removeApIface_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+                           &WifiChip::removeApIfaceInternal, hidl_status_cb,
+                           ifname);
+}
+
+Return<void> WifiChip::createNanIface(createNanIface_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+                           &WifiChip::createNanIfaceInternal, hidl_status_cb);
+}
+
+Return<void> WifiChip::getNanIfaceNames(getNanIfaceNames_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+                           &WifiChip::getNanIfaceNamesInternal, hidl_status_cb);
+}
+
+Return<void> WifiChip::getNanIface(const hidl_string& ifname,
+                                   getNanIface_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+                           &WifiChip::getNanIfaceInternal, hidl_status_cb,
+                           ifname);
+}
+
+Return<void> WifiChip::removeNanIface(const hidl_string& ifname,
+                                      removeNanIface_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+                           &WifiChip::removeNanIfaceInternal, hidl_status_cb,
+                           ifname);
+}
+
+Return<void> WifiChip::createP2pIface(createP2pIface_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+                           &WifiChip::createP2pIfaceInternal, hidl_status_cb);
+}
+
+Return<void> WifiChip::getP2pIfaceNames(getP2pIfaceNames_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+                           &WifiChip::getP2pIfaceNamesInternal, hidl_status_cb);
+}
+
+Return<void> WifiChip::getP2pIface(const hidl_string& ifname,
+                                   getP2pIface_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+                           &WifiChip::getP2pIfaceInternal, hidl_status_cb,
+                           ifname);
+}
+
+Return<void> WifiChip::removeP2pIface(const hidl_string& ifname,
+                                      removeP2pIface_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+                           &WifiChip::removeP2pIfaceInternal, hidl_status_cb,
+                           ifname);
+}
+
+Return<void> WifiChip::createStaIface(createStaIface_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+                           &WifiChip::createStaIfaceInternal, hidl_status_cb);
+}
+
+Return<void> WifiChip::getStaIfaceNames(getStaIfaceNames_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+                           &WifiChip::getStaIfaceNamesInternal, hidl_status_cb);
+}
+
+Return<void> WifiChip::getStaIface(const hidl_string& ifname,
+                                   getStaIface_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+                           &WifiChip::getStaIfaceInternal, hidl_status_cb,
+                           ifname);
+}
+
+Return<void> WifiChip::removeStaIface(const hidl_string& ifname,
+                                      removeStaIface_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+                           &WifiChip::removeStaIfaceInternal, hidl_status_cb,
+                           ifname);
+}
+
+Return<void> WifiChip::createRttController(
+    const sp<IWifiIface>& bound_iface, createRttController_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+                           &WifiChip::createRttControllerInternal,
+                           hidl_status_cb, bound_iface);
+}
+
+Return<void> WifiChip::getDebugRingBuffersStatus(
+    getDebugRingBuffersStatus_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+                           &WifiChip::getDebugRingBuffersStatusInternal,
+                           hidl_status_cb);
+}
+
+Return<void> WifiChip::startLoggingToDebugRingBuffer(
+    const hidl_string& ring_name, WifiDebugRingBufferVerboseLevel verbose_level,
+    uint32_t max_interval_in_sec, uint32_t min_data_size_in_bytes,
+    startLoggingToDebugRingBuffer_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+                           &WifiChip::startLoggingToDebugRingBufferInternal,
+                           hidl_status_cb, ring_name, verbose_level,
+                           max_interval_in_sec, min_data_size_in_bytes);
+}
+
+Return<void> WifiChip::forceDumpToDebugRingBuffer(
+    const hidl_string& ring_name,
+    forceDumpToDebugRingBuffer_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+                           &WifiChip::forceDumpToDebugRingBufferInternal,
+                           hidl_status_cb, ring_name);
+}
+
+Return<void> WifiChip::stopLoggingToDebugRingBuffer(
+    stopLoggingToDebugRingBuffer_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+                           &WifiChip::stopLoggingToDebugRingBufferInternal,
+                           hidl_status_cb);
+}
+
+Return<void> WifiChip::getDebugHostWakeReasonStats(
+    getDebugHostWakeReasonStats_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+                           &WifiChip::getDebugHostWakeReasonStatsInternal,
+                           hidl_status_cb);
+}
+
+Return<void> WifiChip::enableDebugErrorAlerts(
+    bool enable, enableDebugErrorAlerts_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+                           &WifiChip::enableDebugErrorAlertsInternal,
+                           hidl_status_cb, enable);
+}
+
+Return<void> WifiChip::selectTxPowerScenario(
+    TxPowerScenario scenario, selectTxPowerScenario_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+                           &WifiChip::selectTxPowerScenarioInternal,
+                           hidl_status_cb, scenario);
+}
+
+Return<void> WifiChip::resetTxPowerScenario(
+    resetTxPowerScenario_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+                           &WifiChip::resetTxPowerScenarioInternal,
+                           hidl_status_cb);
+}
+
+void WifiChip::invalidateAndRemoveAllIfaces() {
+    invalidateAndClearAll(ap_ifaces_);
+    invalidateAndClearAll(nan_ifaces_);
+    invalidateAndClearAll(p2p_ifaces_);
+    invalidateAndClearAll(sta_ifaces_);
+    // Since all the ifaces are invalid now, all RTT controller objects
+    // using those ifaces also need to be invalidated.
+    for (const auto& rtt : rtt_controllers_) {
+        rtt->invalidate();
+    }
+    rtt_controllers_.clear();
+}
+
+std::pair<WifiStatus, ChipId> WifiChip::getIdInternal() {
+    return {createWifiStatus(WifiStatusCode::SUCCESS), chip_id_};
+}
+
+WifiStatus WifiChip::registerEventCallbackInternal(
+    const sp<IWifiChipEventCallback>& event_callback) {
+    if (!event_cb_handler_.addCallback(event_callback)) {
+        return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
+    }
+    return createWifiStatus(WifiStatusCode::SUCCESS);
+}
+
+std::pair<WifiStatus, uint32_t> WifiChip::getCapabilitiesInternal() {
+    legacy_hal::wifi_error legacy_status;
+    uint32_t legacy_feature_set;
+    uint32_t legacy_logger_feature_set;
+    std::tie(legacy_status, legacy_feature_set) =
+        legacy_hal_.lock()->getSupportedFeatureSet(getWlan0IfaceName());
+    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+        return {createWifiStatusFromLegacyError(legacy_status), 0};
+    }
+    std::tie(legacy_status, legacy_logger_feature_set) =
+        legacy_hal_.lock()->getLoggerSupportedFeatureSet(getWlan0IfaceName());
+    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+        return {createWifiStatusFromLegacyError(legacy_status), 0};
+    }
+    uint32_t hidl_caps;
+    if (!hidl_struct_util::convertLegacyFeaturesToHidlChipCapabilities(
+            legacy_feature_set, legacy_logger_feature_set, &hidl_caps)) {
+        return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), 0};
+    }
+    return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps};
+}
+
+std::pair<WifiStatus, std::vector<IWifiChip::ChipMode>>
+WifiChip::getAvailableModesInternal() {
+    return {createWifiStatus(WifiStatusCode::SUCCESS), modes_};
+}
+
+WifiStatus WifiChip::configureChipInternal(
+    /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock,
+    ChipModeId mode_id) {
+    if (!isValidModeId(mode_id)) {
+        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+    }
+    if (mode_id == current_mode_id_) {
+        LOG(DEBUG) << "Already in the specified mode " << mode_id;
+        return createWifiStatus(WifiStatusCode::SUCCESS);
+    }
+    WifiStatus status = handleChipConfiguration(lock, mode_id);
+    if (status.code != WifiStatusCode::SUCCESS) {
+        for (const auto& callback : event_cb_handler_.getCallbacks()) {
+            if (!callback->onChipReconfigureFailure(status).isOk()) {
+                LOG(ERROR)
+                    << "Failed to invoke onChipReconfigureFailure callback";
+            }
+        }
+        return status;
+    }
+    for (const auto& callback : event_cb_handler_.getCallbacks()) {
+        if (!callback->onChipReconfigured(mode_id).isOk()) {
+            LOG(ERROR) << "Failed to invoke onChipReconfigured callback";
+        }
+    }
+    current_mode_id_ = mode_id;
+    LOG(INFO) << "Configured chip in mode " << mode_id;
+    return status;
+}
+
+std::pair<WifiStatus, uint32_t> WifiChip::getModeInternal() {
+    if (!isValidModeId(current_mode_id_)) {
+        return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE),
+                current_mode_id_};
+    }
+    return {createWifiStatus(WifiStatusCode::SUCCESS), current_mode_id_};
+}
+
+std::pair<WifiStatus, IWifiChip::ChipDebugInfo>
+WifiChip::requestChipDebugInfoInternal() {
+    IWifiChip::ChipDebugInfo result;
+    legacy_hal::wifi_error legacy_status;
+    std::string driver_desc;
+    std::tie(legacy_status, driver_desc) =
+        legacy_hal_.lock()->getDriverVersion(getWlan0IfaceName());
+    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+        LOG(ERROR) << "Failed to get driver version: "
+                   << legacyErrorToString(legacy_status);
+        WifiStatus status = createWifiStatusFromLegacyError(
+            legacy_status, "failed to get driver version");
+        return {status, result};
+    }
+    result.driverDescription = driver_desc.c_str();
+
+    std::string firmware_desc;
+    std::tie(legacy_status, firmware_desc) =
+        legacy_hal_.lock()->getFirmwareVersion(getWlan0IfaceName());
+    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+        LOG(ERROR) << "Failed to get firmware version: "
+                   << legacyErrorToString(legacy_status);
+        WifiStatus status = createWifiStatusFromLegacyError(
+            legacy_status, "failed to get firmware version");
+        return {status, result};
+    }
+    result.firmwareDescription = firmware_desc.c_str();
+
+    return {createWifiStatus(WifiStatusCode::SUCCESS), result};
+}
+
+std::pair<WifiStatus, std::vector<uint8_t>>
+WifiChip::requestDriverDebugDumpInternal() {
+    legacy_hal::wifi_error legacy_status;
+    std::vector<uint8_t> driver_dump;
+    std::tie(legacy_status, driver_dump) =
+        legacy_hal_.lock()->requestDriverMemoryDump(getWlan0IfaceName());
+    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+        LOG(ERROR) << "Failed to get driver debug dump: "
+                   << legacyErrorToString(legacy_status);
+        return {createWifiStatusFromLegacyError(legacy_status),
+                std::vector<uint8_t>()};
+    }
+    return {createWifiStatus(WifiStatusCode::SUCCESS), driver_dump};
+}
+
+std::pair<WifiStatus, std::vector<uint8_t>>
+WifiChip::requestFirmwareDebugDumpInternal() {
+    legacy_hal::wifi_error legacy_status;
+    std::vector<uint8_t> firmware_dump;
+    std::tie(legacy_status, firmware_dump) =
+        legacy_hal_.lock()->requestFirmwareMemoryDump(getWlan0IfaceName());
+    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+        LOG(ERROR) << "Failed to get firmware debug dump: "
+                   << legacyErrorToString(legacy_status);
+        return {createWifiStatusFromLegacyError(legacy_status), {}};
+    }
+    return {createWifiStatus(WifiStatusCode::SUCCESS), firmware_dump};
+}
+
+std::pair<WifiStatus, sp<IWifiApIface>> WifiChip::createApIfaceInternal() {
+    if (!canCurrentModeSupportIfaceOfType(IfaceType::AP)) {
+        return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
+    }
+    std::string ifname = allocateApOrStaIfaceName();
+    sp<WifiApIface> iface = new WifiApIface(ifname, legacy_hal_);
+    ap_ifaces_.push_back(iface);
+    for (const auto& callback : event_cb_handler_.getCallbacks()) {
+        if (!callback->onIfaceAdded(IfaceType::AP, ifname).isOk()) {
+            LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
+        }
+    }
+    return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
+}
+
+std::pair<WifiStatus, std::vector<hidl_string>>
+WifiChip::getApIfaceNamesInternal() {
+    if (ap_ifaces_.empty()) {
+        return {createWifiStatus(WifiStatusCode::SUCCESS), {}};
+    }
+    return {createWifiStatus(WifiStatusCode::SUCCESS), getNames(ap_ifaces_)};
+}
+
+std::pair<WifiStatus, sp<IWifiApIface>> WifiChip::getApIfaceInternal(
+    const std::string& ifname) {
+    const auto iface = findUsingName(ap_ifaces_, ifname);
+    if (!iface.get()) {
+        return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr};
+    }
+    return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
+}
+
+WifiStatus WifiChip::removeApIfaceInternal(const std::string& ifname) {
+    const auto iface = findUsingName(ap_ifaces_, ifname);
+    if (!iface.get()) {
+        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+    }
+    invalidateAndClear(ap_ifaces_, iface);
+    for (const auto& callback : event_cb_handler_.getCallbacks()) {
+        if (!callback->onIfaceRemoved(IfaceType::AP, ifname).isOk()) {
+            LOG(ERROR) << "Failed to invoke onIfaceRemoved callback";
+        }
+    }
+    return createWifiStatus(WifiStatusCode::SUCCESS);
+}
+
+std::pair<WifiStatus, sp<IWifiNanIface>> WifiChip::createNanIfaceInternal() {
+    if (!canCurrentModeSupportIfaceOfType(IfaceType::NAN)) {
+        return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
+    }
+    // These are still assumed to be based on wlan0.
+    std::string ifname = getWlan0IfaceName();
+    sp<WifiNanIface> iface = new WifiNanIface(ifname, legacy_hal_);
+    nan_ifaces_.push_back(iface);
+    for (const auto& callback : event_cb_handler_.getCallbacks()) {
+        if (!callback->onIfaceAdded(IfaceType::NAN, ifname).isOk()) {
+            LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
+        }
+    }
+    return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
+}
+
+std::pair<WifiStatus, std::vector<hidl_string>>
+WifiChip::getNanIfaceNamesInternal() {
+    if (nan_ifaces_.empty()) {
+        return {createWifiStatus(WifiStatusCode::SUCCESS), {}};
+    }
+    return {createWifiStatus(WifiStatusCode::SUCCESS), getNames(nan_ifaces_)};
+}
+
+std::pair<WifiStatus, sp<IWifiNanIface>> WifiChip::getNanIfaceInternal(
+    const std::string& ifname) {
+    const auto iface = findUsingName(nan_ifaces_, ifname);
+    if (!iface.get()) {
+        return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr};
+    }
+    return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
+}
+
+WifiStatus WifiChip::removeNanIfaceInternal(const std::string& ifname) {
+    const auto iface = findUsingName(nan_ifaces_, ifname);
+    if (!iface.get()) {
+        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+    }
+    invalidateAndClear(nan_ifaces_, iface);
+    for (const auto& callback : event_cb_handler_.getCallbacks()) {
+        if (!callback->onIfaceRemoved(IfaceType::NAN, ifname).isOk()) {
+            LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
+        }
+    }
+    return createWifiStatus(WifiStatusCode::SUCCESS);
+}
+
+std::pair<WifiStatus, sp<IWifiP2pIface>> WifiChip::createP2pIfaceInternal() {
+    if (!canCurrentModeSupportIfaceOfType(IfaceType::P2P)) {
+        return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
+    }
+    std::string ifname = getP2pIfaceName();
+    sp<WifiP2pIface> iface = new WifiP2pIface(ifname, legacy_hal_);
+    p2p_ifaces_.push_back(iface);
+    for (const auto& callback : event_cb_handler_.getCallbacks()) {
+        if (!callback->onIfaceAdded(IfaceType::P2P, ifname).isOk()) {
+            LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
+        }
+    }
+    return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
+}
+
+std::pair<WifiStatus, std::vector<hidl_string>>
+WifiChip::getP2pIfaceNamesInternal() {
+    if (p2p_ifaces_.empty()) {
+        return {createWifiStatus(WifiStatusCode::SUCCESS), {}};
+    }
+    return {createWifiStatus(WifiStatusCode::SUCCESS), getNames(p2p_ifaces_)};
+}
+
+std::pair<WifiStatus, sp<IWifiP2pIface>> WifiChip::getP2pIfaceInternal(
+    const std::string& ifname) {
+    const auto iface = findUsingName(p2p_ifaces_, ifname);
+    if (!iface.get()) {
+        return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr};
+    }
+    return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
+}
+
+WifiStatus WifiChip::removeP2pIfaceInternal(const std::string& ifname) {
+    const auto iface = findUsingName(p2p_ifaces_, ifname);
+    if (!iface.get()) {
+        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+    }
+    invalidateAndClear(p2p_ifaces_, iface);
+    for (const auto& callback : event_cb_handler_.getCallbacks()) {
+        if (!callback->onIfaceRemoved(IfaceType::P2P, ifname).isOk()) {
+            LOG(ERROR) << "Failed to invoke onIfaceRemoved callback";
+        }
+    }
+    return createWifiStatus(WifiStatusCode::SUCCESS);
+}
+
+std::pair<WifiStatus, sp<IWifiStaIface>> WifiChip::createStaIfaceInternal() {
+    if (!canCurrentModeSupportIfaceOfType(IfaceType::STA)) {
+        return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
+    }
+    std::string ifname = allocateApOrStaIfaceName();
+    sp<WifiStaIface> iface = new WifiStaIface(ifname, legacy_hal_);
+    sta_ifaces_.push_back(iface);
+    for (const auto& callback : event_cb_handler_.getCallbacks()) {
+        if (!callback->onIfaceAdded(IfaceType::STA, ifname).isOk()) {
+            LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
+        }
+    }
+    return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
+}
+
+std::pair<WifiStatus, std::vector<hidl_string>>
+WifiChip::getStaIfaceNamesInternal() {
+    if (sta_ifaces_.empty()) {
+        return {createWifiStatus(WifiStatusCode::SUCCESS), {}};
+    }
+    return {createWifiStatus(WifiStatusCode::SUCCESS), getNames(sta_ifaces_)};
+}
+
+std::pair<WifiStatus, sp<IWifiStaIface>> WifiChip::getStaIfaceInternal(
+    const std::string& ifname) {
+    const auto iface = findUsingName(sta_ifaces_, ifname);
+    if (!iface.get()) {
+        return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr};
+    }
+    return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
+}
+
+WifiStatus WifiChip::removeStaIfaceInternal(const std::string& ifname) {
+    const auto iface = findUsingName(sta_ifaces_, ifname);
+    if (!iface.get()) {
+        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+    }
+    invalidateAndClear(sta_ifaces_, iface);
+    for (const auto& callback : event_cb_handler_.getCallbacks()) {
+        if (!callback->onIfaceRemoved(IfaceType::STA, ifname).isOk()) {
+            LOG(ERROR) << "Failed to invoke onIfaceRemoved callback";
+        }
+    }
+    return createWifiStatus(WifiStatusCode::SUCCESS);
+}
+
+std::pair<WifiStatus, sp<IWifiRttController>>
+WifiChip::createRttControllerInternal(const sp<IWifiIface>& bound_iface) {
+    sp<WifiRttController> rtt =
+        new WifiRttController(getWlan0IfaceName(), bound_iface, legacy_hal_);
+    rtt_controllers_.emplace_back(rtt);
+    return {createWifiStatus(WifiStatusCode::SUCCESS), rtt};
+}
+
+std::pair<WifiStatus, std::vector<WifiDebugRingBufferStatus>>
+WifiChip::getDebugRingBuffersStatusInternal() {
+    legacy_hal::wifi_error legacy_status;
+    std::vector<legacy_hal::wifi_ring_buffer_status>
+        legacy_ring_buffer_status_vec;
+    std::tie(legacy_status, legacy_ring_buffer_status_vec) =
+        legacy_hal_.lock()->getRingBuffersStatus(getWlan0IfaceName());
+    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+        return {createWifiStatusFromLegacyError(legacy_status), {}};
+    }
+    std::vector<WifiDebugRingBufferStatus> hidl_ring_buffer_status_vec;
+    if (!hidl_struct_util::convertLegacyVectorOfDebugRingBufferStatusToHidl(
+            legacy_ring_buffer_status_vec, &hidl_ring_buffer_status_vec)) {
+        return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
+    }
+    return {createWifiStatus(WifiStatusCode::SUCCESS),
+            hidl_ring_buffer_status_vec};
+}
+
+WifiStatus WifiChip::startLoggingToDebugRingBufferInternal(
+    const hidl_string& ring_name, WifiDebugRingBufferVerboseLevel verbose_level,
+    uint32_t max_interval_in_sec, uint32_t min_data_size_in_bytes) {
+    WifiStatus status = registerDebugRingBufferCallback();
+    if (status.code != WifiStatusCode::SUCCESS) {
+        return status;
+    }
+    legacy_hal::wifi_error legacy_status =
+        legacy_hal_.lock()->startRingBufferLogging(
+            getWlan0IfaceName(), ring_name,
+            static_cast<
+                std::underlying_type<WifiDebugRingBufferVerboseLevel>::type>(
+                verbose_level),
+            max_interval_in_sec, min_data_size_in_bytes);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+WifiStatus WifiChip::forceDumpToDebugRingBufferInternal(
+    const hidl_string& ring_name) {
+    WifiStatus status = registerDebugRingBufferCallback();
+    if (status.code != WifiStatusCode::SUCCESS) {
+        return status;
+    }
+    legacy_hal::wifi_error legacy_status =
+        legacy_hal_.lock()->getRingBufferData(getWlan0IfaceName(), ring_name);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+WifiStatus WifiChip::stopLoggingToDebugRingBufferInternal() {
+    legacy_hal::wifi_error legacy_status =
+        legacy_hal_.lock()->deregisterRingBufferCallbackHandler(
+            getWlan0IfaceName());
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+std::pair<WifiStatus, WifiDebugHostWakeReasonStats>
+WifiChip::getDebugHostWakeReasonStatsInternal() {
+    legacy_hal::wifi_error legacy_status;
+    legacy_hal::WakeReasonStats legacy_stats;
+    std::tie(legacy_status, legacy_stats) =
+        legacy_hal_.lock()->getWakeReasonStats(getWlan0IfaceName());
+    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+        return {createWifiStatusFromLegacyError(legacy_status), {}};
+    }
+    WifiDebugHostWakeReasonStats hidl_stats;
+    if (!hidl_struct_util::convertLegacyWakeReasonStatsToHidl(legacy_stats,
+                                                              &hidl_stats)) {
+        return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
+    }
+    return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_stats};
+}
+
+WifiStatus WifiChip::enableDebugErrorAlertsInternal(bool enable) {
+    legacy_hal::wifi_error legacy_status;
+    if (enable) {
+        android::wp<WifiChip> weak_ptr_this(this);
+        const auto& on_alert_callback = [weak_ptr_this](
+                                            int32_t error_code,
+                                            std::vector<uint8_t> debug_data) {
+            const auto shared_ptr_this = weak_ptr_this.promote();
+            if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+                LOG(ERROR) << "Callback invoked on an invalid object";
+                return;
+            }
+            for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+                if (!callback->onDebugErrorAlert(error_code, debug_data)
+                         .isOk()) {
+                    LOG(ERROR) << "Failed to invoke onDebugErrorAlert callback";
+                }
+            }
+        };
+        legacy_status = legacy_hal_.lock()->registerErrorAlertCallbackHandler(
+            getWlan0IfaceName(), on_alert_callback);
+    } else {
+        legacy_status = legacy_hal_.lock()->deregisterErrorAlertCallbackHandler(
+            getWlan0IfaceName());
+    }
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+WifiStatus WifiChip::selectTxPowerScenarioInternal(TxPowerScenario scenario) {
+    auto legacy_status = legacy_hal_.lock()->selectTxPowerScenario(
+        getWlan0IfaceName(),
+        hidl_struct_util::convertHidlTxPowerScenarioToLegacy(scenario));
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+WifiStatus WifiChip::resetTxPowerScenarioInternal() {
+    auto legacy_status =
+        legacy_hal_.lock()->resetTxPowerScenario(getWlan0IfaceName());
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+WifiStatus WifiChip::handleChipConfiguration(
+    /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock,
+    ChipModeId mode_id) {
+    // If the chip is already configured in a different mode, stop
+    // the legacy HAL and then start it after firmware mode change.
+    if (isValidModeId(current_mode_id_)) {
+        LOG(INFO) << "Reconfiguring chip from mode " << current_mode_id_
+                  << " to mode " << mode_id;
+        invalidateAndRemoveAllIfaces();
+        legacy_hal::wifi_error legacy_status =
+            legacy_hal_.lock()->stop(lock, []() {});
+        if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+            LOG(ERROR) << "Failed to stop legacy HAL: "
+                       << legacyErrorToString(legacy_status);
+            return createWifiStatusFromLegacyError(legacy_status);
+        }
+    }
+    // Firmware mode change not needed for V2 devices.
+    bool success = true;
+    if (mode_id == kV1StaChipModeId) {
+        success = mode_controller_.lock()->changeFirmwareMode(IfaceType::STA);
+    } else if (mode_id == kV1ApChipModeId) {
+        success = mode_controller_.lock()->changeFirmwareMode(IfaceType::AP);
+    }
+    if (!success) {
+        return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
+    }
+    legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->start();
+    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+        LOG(ERROR) << "Failed to start legacy HAL: "
+                   << legacyErrorToString(legacy_status);
+        return createWifiStatusFromLegacyError(legacy_status);
+    }
+    return createWifiStatus(WifiStatusCode::SUCCESS);
+}
+
+WifiStatus WifiChip::registerDebugRingBufferCallback() {
+    if (debug_ring_buffer_cb_registered_) {
+        return createWifiStatus(WifiStatusCode::SUCCESS);
+    }
+
+    android::wp<WifiChip> weak_ptr_this(this);
+    const auto& on_ring_buffer_data_callback =
+        [weak_ptr_this](const std::string& /* name */,
+                        const std::vector<uint8_t>& data,
+                        const legacy_hal::wifi_ring_buffer_status& status) {
+            const auto shared_ptr_this = weak_ptr_this.promote();
+            if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+                LOG(ERROR) << "Callback invoked on an invalid object";
+                return;
+            }
+            WifiDebugRingBufferStatus hidl_status;
+            if (!hidl_struct_util::convertLegacyDebugRingBufferStatusToHidl(
+                    status, &hidl_status)) {
+                LOG(ERROR) << "Error converting ring buffer status";
+                return;
+            }
+            for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+                if (!callback->onDebugRingBufferDataAvailable(hidl_status, data)
+                         .isOk()) {
+                    LOG(ERROR)
+                        << "Failed to invoke onDebugRingBufferDataAvailable"
+                        << " callback on: " << toString(callback);
+                }
+            }
+        };
+    legacy_hal::wifi_error legacy_status =
+        legacy_hal_.lock()->registerRingBufferCallbackHandler(
+            getWlan0IfaceName(), on_ring_buffer_data_callback);
+
+    if (legacy_status == legacy_hal::WIFI_SUCCESS) {
+        debug_ring_buffer_cb_registered_ = true;
+    }
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+void WifiChip::populateModes() {
+    // The chip combination supported for current devices is fixed.
+    // They can be one of the following based on device features:
+    // a) 2 separate modes of operation with 1 interface combination each:
+    //    Mode 1 (STA mode): Will support 1 STA and 1 P2P or NAN(optional)
+    //                       concurrent iface operations.
+    //    Mode 2 (AP mode): Will support 1 AP iface operation.
+    //
+    // b) 1 mode of operation with 2 interface combinations
+    // (conditional on isDualInterfaceSupported()):
+    //    Interface Combination 1: Will support 1 STA and 1 P2P or NAN(optional)
+    //                             concurrent iface operations.
+    //    Interface Combination 2: Will support 1 STA and 1 STA or AP concurrent
+    //                             iface operations.
+    // If Aware is enabled (conditional on isAwareSupported()), the iface
+    // combination will be modified to support either P2P or NAN in place of
+    // just P2P.
+    if (feature_flags_.lock()->isDualInterfaceSupported()) {
+        // V2 Iface combinations for Mode Id = 2.
+        const IWifiChip::ChipIfaceCombinationLimit
+            chip_iface_combination_limit_1 = {{IfaceType::STA}, 1};
+        const IWifiChip::ChipIfaceCombinationLimit
+            chip_iface_combination_limit_2 = {{IfaceType::STA, IfaceType::AP},
+                                              1};
+        IWifiChip::ChipIfaceCombinationLimit chip_iface_combination_limit_3;
+        if (feature_flags_.lock()->isAwareSupported()) {
+            chip_iface_combination_limit_3 = {{IfaceType::P2P, IfaceType::NAN},
+                                              1};
+        } else {
+            chip_iface_combination_limit_3 = {{IfaceType::P2P}, 1};
+        }
+        const IWifiChip::ChipIfaceCombination chip_iface_combination_1 = {
+            {chip_iface_combination_limit_1, chip_iface_combination_limit_2}};
+        const IWifiChip::ChipIfaceCombination chip_iface_combination_2 = {
+            {chip_iface_combination_limit_1, chip_iface_combination_limit_3}};
+        const IWifiChip::ChipMode chip_mode = {
+            kV2ChipModeId,
+            {chip_iface_combination_1, chip_iface_combination_2}};
+        modes_ = {chip_mode};
+    } else {
+        // V1 Iface combinations for Mode Id = 0. (STA Mode)
+        const IWifiChip::ChipIfaceCombinationLimit
+            sta_chip_iface_combination_limit_1 = {{IfaceType::STA}, 1};
+        IWifiChip::ChipIfaceCombinationLimit sta_chip_iface_combination_limit_2;
+        if (feature_flags_.lock()->isAwareSupported()) {
+            sta_chip_iface_combination_limit_2 = {
+                {IfaceType::P2P, IfaceType::NAN}, 1};
+        } else {
+            sta_chip_iface_combination_limit_2 = {{IfaceType::P2P}, 1};
+        }
+        const IWifiChip::ChipIfaceCombination sta_chip_iface_combination = {
+            {sta_chip_iface_combination_limit_1,
+             sta_chip_iface_combination_limit_2}};
+        const IWifiChip::ChipMode sta_chip_mode = {
+            kV1StaChipModeId, {sta_chip_iface_combination}};
+        // Iface combinations for Mode Id = 1. (AP Mode)
+        const IWifiChip::ChipIfaceCombinationLimit
+            ap_chip_iface_combination_limit = {{IfaceType::AP}, 1};
+        const IWifiChip::ChipIfaceCombination ap_chip_iface_combination = {
+            {ap_chip_iface_combination_limit}};
+        const IWifiChip::ChipMode ap_chip_mode = {kV1ApChipModeId,
+                                                  {ap_chip_iface_combination}};
+        modes_ = {sta_chip_mode, ap_chip_mode};
+    }
+}
+
+std::vector<IWifiChip::ChipIfaceCombination>
+WifiChip::getCurrentModeIfaceCombinations() {
+    if (!isValidModeId(current_mode_id_)) {
+        LOG(ERROR) << "Chip not configured in a mode yet";
+        return {};
+    }
+    for (const auto& mode : modes_) {
+        if (mode.id == current_mode_id_) {
+            return mode.availableCombinations;
+        }
+    }
+    CHECK(0) << "Expected to find iface combinations for current mode!";
+    return {};
+}
+
+// Returns a map indexed by IfaceType with the number of ifaces currently
+// created of the corresponding type.
+std::map<IfaceType, size_t> WifiChip::getCurrentIfaceCombination() {
+    std::map<IfaceType, size_t> iface_counts;
+    iface_counts[IfaceType::AP] = ap_ifaces_.size();
+    iface_counts[IfaceType::NAN] = nan_ifaces_.size();
+    iface_counts[IfaceType::P2P] = p2p_ifaces_.size();
+    iface_counts[IfaceType::STA] = sta_ifaces_.size();
+    return iface_counts;
+}
+
+// This expands the provided iface combinations to a more parseable
+// form. Returns a vector of available combinations possible with the number
+// of ifaces of each type in the combination.
+// This method is a port of HalDeviceManager.expandIfaceCombos() from framework.
+std::vector<std::map<IfaceType, size_t>> WifiChip::expandIfaceCombinations(
+    const IWifiChip::ChipIfaceCombination& combination) {
+    uint32_t num_expanded_combos = 1;
+    for (const auto& limit : combination.limits) {
+        for (uint32_t i = 0; i < limit.maxIfaces; i++) {
+            num_expanded_combos *= limit.types.size();
+        }
+    }
+
+    // Allocate the vector of expanded combos and reset all iface counts to 0
+    // in each combo.
+    std::vector<std::map<IfaceType, size_t>> expanded_combos;
+    expanded_combos.resize(num_expanded_combos);
+    for (auto& expanded_combo : expanded_combos) {
+        for (const auto type :
+             {IfaceType::AP, IfaceType::NAN, IfaceType::P2P, IfaceType::STA}) {
+            expanded_combo[type] = 0;
+        }
+    }
+    uint32_t span = num_expanded_combos;
+    for (const auto& limit : combination.limits) {
+        for (uint32_t i = 0; i < limit.maxIfaces; i++) {
+            span /= limit.types.size();
+            for (uint32_t k = 0; k < num_expanded_combos; ++k) {
+                const auto iface_type =
+                    limit.types[(k / span) % limit.types.size()];
+                expanded_combos[k][iface_type]++;
+            }
+        }
+    }
+    return expanded_combos;
+}
+
+bool WifiChip::canExpandedIfaceCombinationSupportIfaceOfType(
+    const std::map<IfaceType, size_t>& combo, IfaceType requested_type) {
+    const auto current_combo = getCurrentIfaceCombination();
+
+    // Check if we have space for 1 more iface of |type| in this combo
+    for (const auto type :
+         {IfaceType::AP, IfaceType::NAN, IfaceType::P2P, IfaceType::STA}) {
+        size_t num_ifaces_needed = current_combo.at(type);
+        if (type == requested_type) {
+            num_ifaces_needed++;
+        }
+        size_t num_ifaces_allowed = combo.at(type);
+        if (num_ifaces_needed > num_ifaces_allowed) {
+            return false;
+        }
+    }
+    return true;
+}
+
+// This method does the following:
+// a) Enumerate all possible iface combos by expanding the current
+//    ChipIfaceCombination.
+// b) Check if the requested iface type can be added to the current mode.
+bool WifiChip::canCurrentModeSupportIfaceOfType(IfaceType type) {
+    if (!isValidModeId(current_mode_id_)) {
+        LOG(ERROR) << "Chip not configured in a mode yet";
+        return false;
+    }
+    const auto combinations = getCurrentModeIfaceCombinations();
+    for (const auto& combination : combinations) {
+        const auto expanded_combos = expandIfaceCombinations(combination);
+        for (const auto& expanded_combo : expanded_combos) {
+            if (canExpandedIfaceCombinationSupportIfaceOfType(expanded_combo,
+                                                              type)) {
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+bool WifiChip::isValidModeId(ChipModeId mode_id) {
+    for (const auto& mode : modes_) {
+        if (mode.id == mode_id) {
+            return true;
+        }
+    }
+    return false;
+}
+
+// Return "wlan0", if "wlan0" is not already in use, else return "wlan1".
+// This is based on the assumption that we'll have a max of 2 concurrent
+// AP/STA ifaces.
+std::string WifiChip::allocateApOrStaIfaceName() {
+    auto ap_iface = findUsingName(ap_ifaces_, getWlan0IfaceName());
+    auto sta_iface = findUsingName(sta_ifaces_, getWlan0IfaceName());
+    if (!ap_iface.get() && !sta_iface.get()) {
+        return getWlan0IfaceName();
+    }
+    ap_iface = findUsingName(ap_ifaces_, getWlan1IfaceName());
+    sta_iface = findUsingName(sta_ifaces_, getWlan1IfaceName());
+    if (!ap_iface.get() && !sta_iface.get()) {
+        return getWlan1IfaceName();
+    }
+    // This should never happen. We screwed up somewhere if it did.
+    CHECK(0) << "wlan0 and wlan1 in use already!";
+    return {};
+}
+
+}  // namespace implementation
+}  // namespace V1_2
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
diff --git a/wifi/1.2/default/wifi_chip.h b/wifi/1.2/default/wifi_chip.h
new file mode 100644
index 0000000..97c434e
--- /dev/null
+++ b/wifi/1.2/default/wifi_chip.h
@@ -0,0 +1,237 @@
+/*
+ * 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 WIFI_CHIP_H_
+#define WIFI_CHIP_H_
+
+#include <map>
+
+#include <android-base/macros.h>
+#include <android/hardware/wifi/1.1/IWifiChip.h>
+
+#include "hidl_callback_util.h"
+#include "wifi_ap_iface.h"
+#include "wifi_feature_flags.h"
+#include "wifi_legacy_hal.h"
+#include "wifi_mode_controller.h"
+#include "wifi_nan_iface.h"
+#include "wifi_p2p_iface.h"
+#include "wifi_rtt_controller.h"
+#include "wifi_sta_iface.h"
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace V1_2 {
+namespace implementation {
+using namespace android::hardware::wifi::V1_0;
+
+/**
+ * HIDL interface object used to control a Wifi HAL chip instance.
+ * Since there is only a single chip instance used today, there is no
+ * identifying handle information stored here.
+ */
+class WifiChip : public V1_1::IWifiChip {
+   public:
+    WifiChip(
+        ChipId chip_id,
+        const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
+        const std::weak_ptr<mode_controller::WifiModeController>
+            mode_controller,
+        const std::weak_ptr<feature_flags::WifiFeatureFlags> feature_flags);
+    // HIDL does not provide a built-in mechanism to let the server invalidate
+    // a HIDL interface object after creation. If any client process holds onto
+    // a reference to the object in their context, any method calls on that
+    // reference will continue to be directed to the server.
+    //
+    // However Wifi HAL needs to control the lifetime of these objects. So, add
+    // a public |invalidate| method to |WifiChip| and it's child objects. This
+    // will be used to mark an object invalid when either:
+    // a) Wifi HAL is stopped, or
+    // b) Wifi Chip is reconfigured.
+    //
+    // All HIDL method implementations should check if the object is still
+    // marked valid before processing them.
+    void invalidate();
+    bool isValid();
+    std::set<sp<IWifiChipEventCallback>> getEventCallbacks();
+
+    // HIDL methods exposed.
+    Return<void> getId(getId_cb hidl_status_cb) override;
+    Return<void> registerEventCallback(
+        const sp<IWifiChipEventCallback>& event_callback,
+        registerEventCallback_cb hidl_status_cb) override;
+    Return<void> getCapabilities(getCapabilities_cb hidl_status_cb) override;
+    Return<void> getAvailableModes(
+        getAvailableModes_cb hidl_status_cb) override;
+    Return<void> configureChip(ChipModeId mode_id,
+                               configureChip_cb hidl_status_cb) override;
+    Return<void> getMode(getMode_cb hidl_status_cb) override;
+    Return<void> requestChipDebugInfo(
+        requestChipDebugInfo_cb hidl_status_cb) override;
+    Return<void> requestDriverDebugDump(
+        requestDriverDebugDump_cb hidl_status_cb) override;
+    Return<void> requestFirmwareDebugDump(
+        requestFirmwareDebugDump_cb hidl_status_cb) override;
+    Return<void> createApIface(createApIface_cb hidl_status_cb) override;
+    Return<void> getApIfaceNames(getApIfaceNames_cb hidl_status_cb) override;
+    Return<void> getApIface(const hidl_string& ifname,
+                            getApIface_cb hidl_status_cb) override;
+    Return<void> removeApIface(const hidl_string& ifname,
+                               removeApIface_cb hidl_status_cb) override;
+    Return<void> createNanIface(createNanIface_cb hidl_status_cb) override;
+    Return<void> getNanIfaceNames(getNanIfaceNames_cb hidl_status_cb) override;
+    Return<void> getNanIface(const hidl_string& ifname,
+                             getNanIface_cb hidl_status_cb) override;
+    Return<void> removeNanIface(const hidl_string& ifname,
+                                removeNanIface_cb hidl_status_cb) override;
+    Return<void> createP2pIface(createP2pIface_cb hidl_status_cb) override;
+    Return<void> getP2pIfaceNames(getP2pIfaceNames_cb hidl_status_cb) override;
+    Return<void> getP2pIface(const hidl_string& ifname,
+                             getP2pIface_cb hidl_status_cb) override;
+    Return<void> removeP2pIface(const hidl_string& ifname,
+                                removeP2pIface_cb hidl_status_cb) override;
+    Return<void> createStaIface(createStaIface_cb hidl_status_cb) override;
+    Return<void> getStaIfaceNames(getStaIfaceNames_cb hidl_status_cb) override;
+    Return<void> getStaIface(const hidl_string& ifname,
+                             getStaIface_cb hidl_status_cb) override;
+    Return<void> removeStaIface(const hidl_string& ifname,
+                                removeStaIface_cb hidl_status_cb) override;
+    Return<void> createRttController(
+        const sp<IWifiIface>& bound_iface,
+        createRttController_cb hidl_status_cb) override;
+    Return<void> getDebugRingBuffersStatus(
+        getDebugRingBuffersStatus_cb hidl_status_cb) override;
+    Return<void> startLoggingToDebugRingBuffer(
+        const hidl_string& ring_name,
+        WifiDebugRingBufferVerboseLevel verbose_level,
+        uint32_t max_interval_in_sec, uint32_t min_data_size_in_bytes,
+        startLoggingToDebugRingBuffer_cb hidl_status_cb) override;
+    Return<void> forceDumpToDebugRingBuffer(
+        const hidl_string& ring_name,
+        forceDumpToDebugRingBuffer_cb hidl_status_cb) override;
+    Return<void> stopLoggingToDebugRingBuffer(
+        stopLoggingToDebugRingBuffer_cb hidl_status_cb) override;
+    Return<void> getDebugHostWakeReasonStats(
+        getDebugHostWakeReasonStats_cb hidl_status_cb) override;
+    Return<void> enableDebugErrorAlerts(
+        bool enable, enableDebugErrorAlerts_cb hidl_status_cb) override;
+    Return<void> selectTxPowerScenario(
+        TxPowerScenario scenario,
+        selectTxPowerScenario_cb hidl_status_cb) override;
+    Return<void> resetTxPowerScenario(
+        resetTxPowerScenario_cb hidl_status_cb) override;
+
+   private:
+    void invalidateAndRemoveAllIfaces();
+
+    // Corresponding worker functions for the HIDL methods.
+    std::pair<WifiStatus, ChipId> getIdInternal();
+    WifiStatus registerEventCallbackInternal(
+        const sp<IWifiChipEventCallback>& event_callback);
+    std::pair<WifiStatus, uint32_t> getCapabilitiesInternal();
+    std::pair<WifiStatus, std::vector<ChipMode>> getAvailableModesInternal();
+    WifiStatus configureChipInternal(
+        std::unique_lock<std::recursive_mutex>* lock, ChipModeId mode_id);
+    std::pair<WifiStatus, uint32_t> getModeInternal();
+    std::pair<WifiStatus, IWifiChip::ChipDebugInfo>
+    requestChipDebugInfoInternal();
+    std::pair<WifiStatus, std::vector<uint8_t>>
+    requestDriverDebugDumpInternal();
+    std::pair<WifiStatus, std::vector<uint8_t>>
+    requestFirmwareDebugDumpInternal();
+    std::pair<WifiStatus, sp<IWifiApIface>> createApIfaceInternal();
+    std::pair<WifiStatus, std::vector<hidl_string>> getApIfaceNamesInternal();
+    std::pair<WifiStatus, sp<IWifiApIface>> getApIfaceInternal(
+        const std::string& ifname);
+    WifiStatus removeApIfaceInternal(const std::string& ifname);
+    std::pair<WifiStatus, sp<IWifiNanIface>> createNanIfaceInternal();
+    std::pair<WifiStatus, std::vector<hidl_string>> getNanIfaceNamesInternal();
+    std::pair<WifiStatus, sp<IWifiNanIface>> getNanIfaceInternal(
+        const std::string& ifname);
+    WifiStatus removeNanIfaceInternal(const std::string& ifname);
+    std::pair<WifiStatus, sp<IWifiP2pIface>> createP2pIfaceInternal();
+    std::pair<WifiStatus, std::vector<hidl_string>> getP2pIfaceNamesInternal();
+    std::pair<WifiStatus, sp<IWifiP2pIface>> getP2pIfaceInternal(
+        const std::string& ifname);
+    WifiStatus removeP2pIfaceInternal(const std::string& ifname);
+    std::pair<WifiStatus, sp<IWifiStaIface>> createStaIfaceInternal();
+    std::pair<WifiStatus, std::vector<hidl_string>> getStaIfaceNamesInternal();
+    std::pair<WifiStatus, sp<IWifiStaIface>> getStaIfaceInternal(
+        const std::string& ifname);
+    WifiStatus removeStaIfaceInternal(const std::string& ifname);
+    std::pair<WifiStatus, sp<IWifiRttController>> createRttControllerInternal(
+        const sp<IWifiIface>& bound_iface);
+    std::pair<WifiStatus, std::vector<WifiDebugRingBufferStatus>>
+    getDebugRingBuffersStatusInternal();
+    WifiStatus startLoggingToDebugRingBufferInternal(
+        const hidl_string& ring_name,
+        WifiDebugRingBufferVerboseLevel verbose_level,
+        uint32_t max_interval_in_sec, uint32_t min_data_size_in_bytes);
+    WifiStatus forceDumpToDebugRingBufferInternal(const hidl_string& ring_name);
+    WifiStatus stopLoggingToDebugRingBufferInternal();
+    std::pair<WifiStatus, WifiDebugHostWakeReasonStats>
+    getDebugHostWakeReasonStatsInternal();
+    WifiStatus enableDebugErrorAlertsInternal(bool enable);
+    WifiStatus selectTxPowerScenarioInternal(TxPowerScenario scenario);
+    WifiStatus resetTxPowerScenarioInternal();
+
+    WifiStatus handleChipConfiguration(
+        std::unique_lock<std::recursive_mutex>* lock, ChipModeId mode_id);
+    WifiStatus registerDebugRingBufferCallback();
+
+    void populateModes();
+    std::vector<IWifiChip::ChipIfaceCombination>
+    getCurrentModeIfaceCombinations();
+    std::map<IfaceType, size_t> getCurrentIfaceCombination();
+    std::vector<std::map<IfaceType, size_t>> expandIfaceCombinations(
+        const IWifiChip::ChipIfaceCombination& combination);
+    bool canExpandedIfaceCombinationSupportIfaceOfType(
+        const std::map<IfaceType, size_t>& combo, IfaceType type);
+    bool canCurrentModeSupportIfaceOfType(IfaceType type);
+    bool isValidModeId(ChipModeId mode_id);
+    std::string allocateApOrStaIfaceName();
+
+    ChipId chip_id_;
+    std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
+    std::weak_ptr<mode_controller::WifiModeController> mode_controller_;
+    std::weak_ptr<feature_flags::WifiFeatureFlags> feature_flags_;
+    std::vector<sp<WifiApIface>> ap_ifaces_;
+    std::vector<sp<WifiNanIface>> nan_ifaces_;
+    std::vector<sp<WifiP2pIface>> p2p_ifaces_;
+    std::vector<sp<WifiStaIface>> sta_ifaces_;
+    std::vector<sp<WifiRttController>> rtt_controllers_;
+    bool is_valid_;
+    // Members pertaining to chip configuration.
+    uint32_t current_mode_id_;
+    std::vector<IWifiChip::ChipMode> modes_;
+    // The legacy ring buffer callback API has only a global callback
+    // registration mechanism. Use this to check if we have already
+    // registered a callback.
+    bool debug_ring_buffer_cb_registered_;
+    hidl_callback_util::HidlCallbackHandler<IWifiChipEventCallback>
+        event_cb_handler_;
+
+    DISALLOW_COPY_AND_ASSIGN(WifiChip);
+};
+
+}  // namespace implementation
+}  // namespace V1_2
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
+
+#endif  // WIFI_CHIP_H_
diff --git a/wifi/1.2/default/wifi_feature_flags.cpp b/wifi/1.2/default/wifi_feature_flags.cpp
new file mode 100644
index 0000000..554d4d5
--- /dev/null
+++ b/wifi/1.2/default/wifi_feature_flags.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "wifi_feature_flags.h"
+
+namespace {
+#ifdef WIFI_HIDL_FEATURE_AWARE
+static const bool wifiHidlFeatureAware = true;
+#else
+static const bool wifiHidlFeatureAware = false;
+#endif  // WIFI_HIDL_FEATURE_AWARE
+#ifdef WIFI_HIDL_FEATURE_DUAL_INTERFACE
+static const bool wifiHidlFeatureDualInterface = true;
+#else
+static const bool wifiHidlFeatureDualInterface = false;
+#endif  // WIFI_HIDL_FEATURE_DUAL_INTERFACE
+}  // namespace
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace V1_2 {
+namespace implementation {
+namespace feature_flags {
+
+WifiFeatureFlags::WifiFeatureFlags() {}
+bool WifiFeatureFlags::isAwareSupported() { return wifiHidlFeatureAware; }
+bool WifiFeatureFlags::isDualInterfaceSupported() {
+    return wifiHidlFeatureDualInterface;
+}
+
+}  // namespace feature_flags
+}  // namespace implementation
+}  // namespace V1_2
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
diff --git a/wifi/1.1/default/wifi_feature_flags.h b/wifi/1.2/default/wifi_feature_flags.h
similarity index 78%
rename from wifi/1.1/default/wifi_feature_flags.h
rename to wifi/1.2/default/wifi_feature_flags.h
index 5939ffb..dc0c1ff 100644
--- a/wifi/1.1/default/wifi_feature_flags.h
+++ b/wifi/1.2/default/wifi_feature_flags.h
@@ -20,20 +20,22 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_1 {
+namespace V1_2 {
 namespace implementation {
+namespace feature_flags {
 
 class WifiFeatureFlags {
- public:
-#ifdef WIFI_HIDL_FEATURE_AWARE
-  static const bool wifiHidlFeatureAware = true;
-#else
-  static const bool wifiHidlFeatureAware = false;
-#endif // WIFI_HIDL_FEATURE_AWARE
+   public:
+    WifiFeatureFlags();
+    virtual ~WifiFeatureFlags() = default;
+
+    virtual bool isAwareSupported();
+    virtual bool isDualInterfaceSupported();
 };
 
+}  // namespace feature_flags
 }  // namespace implementation
-}  // namespace V1_1
+}  // namespace V1_2
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.2/default/wifi_legacy_hal.cpp b/wifi/1.2/default/wifi_legacy_hal.cpp
new file mode 100644
index 0000000..9abe514
--- /dev/null
+++ b/wifi/1.2/default/wifi_legacy_hal.cpp
@@ -0,0 +1,1352 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <array>
+#include <chrono>
+
+#include <android-base/logging.h>
+
+#include "hidl_sync_util.h"
+#include "wifi_legacy_hal.h"
+#include "wifi_legacy_hal_stubs.h"
+
+namespace {
+// Constants ported over from the legacy HAL calling code
+// (com_android_server_wifi_WifiNative.cpp). This will all be thrown
+// away when this shim layer is replaced by the real vendor
+// implementation.
+static constexpr uint32_t kMaxVersionStringLength = 256;
+static constexpr uint32_t kMaxCachedGscanResults = 64;
+static constexpr uint32_t kMaxGscanFrequenciesForBand = 64;
+static constexpr uint32_t kLinkLayerStatsDataMpduSizeThreshold = 128;
+static constexpr uint32_t kMaxWakeReasonStatsArraySize = 32;
+static constexpr uint32_t kMaxRingBuffers = 10;
+static constexpr uint32_t kMaxStopCompleteWaitMs = 100;
+
+// Helper function to create a non-const char* for legacy Hal API's.
+std::vector<char> makeCharVec(const std::string& str) {
+    std::vector<char> vec(str.size() + 1);
+    vec.assign(str.begin(), str.end());
+    vec.push_back('\0');
+    return vec;
+}
+}  // namespace
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace V1_2 {
+namespace implementation {
+namespace legacy_hal {
+// 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
+std::function<void(wifi_handle handle)> on_stop_complete_internal_callback;
+void onAsyncStopComplete(wifi_handle handle) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_stop_complete_internal_callback) {
+        on_stop_complete_internal_callback(handle);
+        // Invalidate this callback since we don't want this firing again.
+        on_stop_complete_internal_callback = nullptr;
+    }
+}
+
+// Callback to be invoked for driver dump.
+std::function<void(char*, int)> on_driver_memory_dump_internal_callback;
+void onSyncDriverMemoryDump(char* buffer, int buffer_size) {
+    if (on_driver_memory_dump_internal_callback) {
+        on_driver_memory_dump_internal_callback(buffer, buffer_size);
+    }
+}
+
+// Callback to be invoked for firmware dump.
+std::function<void(char*, int)> on_firmware_memory_dump_internal_callback;
+void onSyncFirmwareMemoryDump(char* buffer, int buffer_size) {
+    if (on_firmware_memory_dump_internal_callback) {
+        on_firmware_memory_dump_internal_callback(buffer, buffer_size);
+    }
+}
+
+// Callback to be invoked for Gscan events.
+std::function<void(wifi_request_id, wifi_scan_event)>
+    on_gscan_event_internal_callback;
+void onAsyncGscanEvent(wifi_request_id id, wifi_scan_event event) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_gscan_event_internal_callback) {
+        on_gscan_event_internal_callback(id, event);
+    }
+}
+
+// Callback to be invoked for Gscan full results.
+std::function<void(wifi_request_id, wifi_scan_result*, uint32_t)>
+    on_gscan_full_result_internal_callback;
+void onAsyncGscanFullResult(wifi_request_id id, wifi_scan_result* result,
+                            uint32_t buckets_scanned) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_gscan_full_result_internal_callback) {
+        on_gscan_full_result_internal_callback(id, result, buckets_scanned);
+    }
+}
+
+// Callback to be invoked for link layer stats results.
+std::function<void((wifi_request_id, wifi_iface_stat*, int, wifi_radio_stat*))>
+    on_link_layer_stats_result_internal_callback;
+void onSyncLinkLayerStatsResult(wifi_request_id id, wifi_iface_stat* iface_stat,
+                                int num_radios, wifi_radio_stat* radio_stat) {
+    if (on_link_layer_stats_result_internal_callback) {
+        on_link_layer_stats_result_internal_callback(id, iface_stat, num_radios,
+                                                     radio_stat);
+    }
+}
+
+// Callback to be invoked for rssi threshold breach.
+std::function<void((wifi_request_id, uint8_t*, int8_t))>
+    on_rssi_threshold_breached_internal_callback;
+void onAsyncRssiThresholdBreached(wifi_request_id id, uint8_t* bssid,
+                                  int8_t rssi) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_rssi_threshold_breached_internal_callback) {
+        on_rssi_threshold_breached_internal_callback(id, bssid, rssi);
+    }
+}
+
+// Callback to be invoked for ring buffer data indication.
+std::function<void(char*, char*, int, wifi_ring_buffer_status*)>
+    on_ring_buffer_data_internal_callback;
+void onAsyncRingBufferData(char* ring_name, char* buffer, int buffer_size,
+                           wifi_ring_buffer_status* status) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_ring_buffer_data_internal_callback) {
+        on_ring_buffer_data_internal_callback(ring_name, buffer, buffer_size,
+                                              status);
+    }
+}
+
+// Callback to be invoked for error alert indication.
+std::function<void(wifi_request_id, char*, int, int)>
+    on_error_alert_internal_callback;
+void onAsyncErrorAlert(wifi_request_id id, char* buffer, int buffer_size,
+                       int err_code) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_error_alert_internal_callback) {
+        on_error_alert_internal_callback(id, buffer, buffer_size, err_code);
+    }
+}
+
+// Callback to be invoked for rtt results results.
+std::function<void(wifi_request_id, unsigned num_results,
+                   wifi_rtt_result* rtt_results[])>
+    on_rtt_results_internal_callback;
+void onAsyncRttResults(wifi_request_id id, unsigned num_results,
+                       wifi_rtt_result* rtt_results[]) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_rtt_results_internal_callback) {
+        on_rtt_results_internal_callback(id, num_results, rtt_results);
+        on_rtt_results_internal_callback = nullptr;
+    }
+}
+
+// Callbacks for the various NAN operations.
+// NOTE: These have very little conversions to perform before invoking the user
+// callbacks.
+// So, handle all of them here directly to avoid adding an unnecessary layer.
+std::function<void(transaction_id, const NanResponseMsg&)>
+    on_nan_notify_response_user_callback;
+void onAysncNanNotifyResponse(transaction_id id, NanResponseMsg* msg) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_nan_notify_response_user_callback && msg) {
+        on_nan_notify_response_user_callback(id, *msg);
+    }
+}
+
+std::function<void(const NanPublishRepliedInd&)>
+    on_nan_event_publish_replied_user_callback;
+void onAysncNanEventPublishReplied(NanPublishRepliedInd* /* event */) {
+    LOG(ERROR) << "onAysncNanEventPublishReplied triggered";
+}
+
+std::function<void(const NanPublishTerminatedInd&)>
+    on_nan_event_publish_terminated_user_callback;
+void onAysncNanEventPublishTerminated(NanPublishTerminatedInd* event) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_nan_event_publish_terminated_user_callback && event) {
+        on_nan_event_publish_terminated_user_callback(*event);
+    }
+}
+
+std::function<void(const NanMatchInd&)> on_nan_event_match_user_callback;
+void onAysncNanEventMatch(NanMatchInd* event) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_nan_event_match_user_callback && event) {
+        on_nan_event_match_user_callback(*event);
+    }
+}
+
+std::function<void(const NanMatchExpiredInd&)>
+    on_nan_event_match_expired_user_callback;
+void onAysncNanEventMatchExpired(NanMatchExpiredInd* event) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_nan_event_match_expired_user_callback && event) {
+        on_nan_event_match_expired_user_callback(*event);
+    }
+}
+
+std::function<void(const NanSubscribeTerminatedInd&)>
+    on_nan_event_subscribe_terminated_user_callback;
+void onAysncNanEventSubscribeTerminated(NanSubscribeTerminatedInd* event) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_nan_event_subscribe_terminated_user_callback && event) {
+        on_nan_event_subscribe_terminated_user_callback(*event);
+    }
+}
+
+std::function<void(const NanFollowupInd&)> on_nan_event_followup_user_callback;
+void onAysncNanEventFollowup(NanFollowupInd* event) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_nan_event_followup_user_callback && event) {
+        on_nan_event_followup_user_callback(*event);
+    }
+}
+
+std::function<void(const NanDiscEngEventInd&)>
+    on_nan_event_disc_eng_event_user_callback;
+void onAysncNanEventDiscEngEvent(NanDiscEngEventInd* event) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_nan_event_disc_eng_event_user_callback && event) {
+        on_nan_event_disc_eng_event_user_callback(*event);
+    }
+}
+
+std::function<void(const NanDisabledInd&)> on_nan_event_disabled_user_callback;
+void onAysncNanEventDisabled(NanDisabledInd* event) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_nan_event_disabled_user_callback && event) {
+        on_nan_event_disabled_user_callback(*event);
+    }
+}
+
+std::function<void(const NanTCAInd&)> on_nan_event_tca_user_callback;
+void onAysncNanEventTca(NanTCAInd* event) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_nan_event_tca_user_callback && event) {
+        on_nan_event_tca_user_callback(*event);
+    }
+}
+
+std::function<void(const NanBeaconSdfPayloadInd&)>
+    on_nan_event_beacon_sdf_payload_user_callback;
+void onAysncNanEventBeaconSdfPayload(NanBeaconSdfPayloadInd* event) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_nan_event_beacon_sdf_payload_user_callback && event) {
+        on_nan_event_beacon_sdf_payload_user_callback(*event);
+    }
+}
+
+std::function<void(const NanDataPathRequestInd&)>
+    on_nan_event_data_path_request_user_callback;
+void onAysncNanEventDataPathRequest(NanDataPathRequestInd* event) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_nan_event_data_path_request_user_callback && event) {
+        on_nan_event_data_path_request_user_callback(*event);
+    }
+}
+std::function<void(const NanDataPathConfirmInd&)>
+    on_nan_event_data_path_confirm_user_callback;
+void onAysncNanEventDataPathConfirm(NanDataPathConfirmInd* event) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_nan_event_data_path_confirm_user_callback && event) {
+        on_nan_event_data_path_confirm_user_callback(*event);
+    }
+}
+
+std::function<void(const NanDataPathEndInd&)>
+    on_nan_event_data_path_end_user_callback;
+void onAysncNanEventDataPathEnd(NanDataPathEndInd* event) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_nan_event_data_path_end_user_callback && event) {
+        on_nan_event_data_path_end_user_callback(*event);
+    }
+}
+
+std::function<void(const NanTransmitFollowupInd&)>
+    on_nan_event_transmit_follow_up_user_callback;
+void onAysncNanEventTransmitFollowUp(NanTransmitFollowupInd* event) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_nan_event_transmit_follow_up_user_callback && event) {
+        on_nan_event_transmit_follow_up_user_callback(*event);
+    }
+}
+
+std::function<void(const NanRangeRequestInd&)>
+    on_nan_event_range_request_user_callback;
+void onAysncNanEventRangeRequest(NanRangeRequestInd* event) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_nan_event_range_request_user_callback && event) {
+        on_nan_event_range_request_user_callback(*event);
+    }
+}
+
+std::function<void(const NanRangeReportInd&)>
+    on_nan_event_range_report_user_callback;
+void onAysncNanEventRangeReport(NanRangeReportInd* event) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_nan_event_range_report_user_callback && event) {
+        on_nan_event_range_report_user_callback(*event);
+    }
+}
+
+std::function<void(const NanDataPathScheduleUpdateInd&)>
+    on_nan_event_schedule_update_user_callback;
+void onAsyncNanEventScheduleUpdate(NanDataPathScheduleUpdateInd* event) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_nan_event_schedule_update_user_callback && event) {
+        on_nan_event_schedule_update_user_callback(*event);
+    }
+}
+// End of the free-standing "C" style callbacks.
+
+WifiLegacyHal::WifiLegacyHal()
+    : global_handle_(nullptr),
+      awaiting_event_loop_termination_(false),
+      is_started_(false) {}
+
+wifi_error WifiLegacyHal::initialize() {
+    LOG(DEBUG) << "Initialize legacy HAL";
+    // TODO: Add back the HAL Tool if we need to. All we need from the HAL tool
+    // for now is this function call which we can directly call.
+    if (!initHalFuncTableWithStubs(&global_func_table_)) {
+        LOG(ERROR)
+            << "Failed to initialize legacy hal function table with stubs";
+        return WIFI_ERROR_UNKNOWN;
+    }
+    wifi_error status = init_wifi_vendor_hal_func_table(&global_func_table_);
+    if (status != WIFI_SUCCESS) {
+        LOG(ERROR) << "Failed to initialize legacy hal function table";
+    }
+    return status;
+}
+
+wifi_error WifiLegacyHal::start() {
+    // Ensure that we're starting in a good state.
+    CHECK(global_func_table_.wifi_initialize && !global_handle_ &&
+          iface_name_to_handle_.empty() && !awaiting_event_loop_termination_);
+    if (is_started_) {
+        LOG(DEBUG) << "Legacy HAL already started";
+        return WIFI_SUCCESS;
+    }
+    LOG(DEBUG) << "Starting legacy HAL";
+    if (!iface_tool_.SetWifiUpState(true)) {
+        LOG(ERROR) << "Failed to set WiFi interface up";
+        return WIFI_ERROR_UNKNOWN;
+    }
+    wifi_error status = global_func_table_.wifi_initialize(&global_handle_);
+    if (status != WIFI_SUCCESS || !global_handle_) {
+        LOG(ERROR) << "Failed to retrieve global handle";
+        return status;
+    }
+    std::thread(&WifiLegacyHal::runEventLoop, this).detach();
+    status = retrieveIfaceHandles();
+    if (status != WIFI_SUCCESS || iface_name_to_handle_.empty()) {
+        LOG(ERROR) << "Failed to retrieve wlan interface handle";
+        return status;
+    }
+    LOG(DEBUG) << "Legacy HAL start complete";
+    is_started_ = true;
+    return WIFI_SUCCESS;
+}
+
+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";
+        on_stop_complete_user_callback();
+        return WIFI_SUCCESS;
+    }
+    LOG(DEBUG) << "Stopping legacy HAL";
+    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";
+    return WIFI_SUCCESS;
+}
+
+std::pair<wifi_error, std::string> WifiLegacyHal::getDriverVersion(
+    const std::string& iface_name) {
+    std::array<char, kMaxVersionStringLength> buffer;
+    buffer.fill(0);
+    wifi_error status = global_func_table_.wifi_get_driver_version(
+        getIfaceHandle(iface_name), buffer.data(), buffer.size());
+    return {status, buffer.data()};
+}
+
+std::pair<wifi_error, std::string> WifiLegacyHal::getFirmwareVersion(
+    const std::string& iface_name) {
+    std::array<char, kMaxVersionStringLength> buffer;
+    buffer.fill(0);
+    wifi_error status = global_func_table_.wifi_get_firmware_version(
+        getIfaceHandle(iface_name), buffer.data(), buffer.size());
+    return {status, buffer.data()};
+}
+
+std::pair<wifi_error, std::vector<uint8_t>>
+WifiLegacyHal::requestDriverMemoryDump(const std::string& iface_name) {
+    std::vector<uint8_t> driver_dump;
+    on_driver_memory_dump_internal_callback = [&driver_dump](char* buffer,
+                                                             int buffer_size) {
+        driver_dump.insert(driver_dump.end(),
+                           reinterpret_cast<uint8_t*>(buffer),
+                           reinterpret_cast<uint8_t*>(buffer) + buffer_size);
+    };
+    wifi_error status = global_func_table_.wifi_get_driver_memory_dump(
+        getIfaceHandle(iface_name), {onSyncDriverMemoryDump});
+    on_driver_memory_dump_internal_callback = nullptr;
+    return {status, std::move(driver_dump)};
+}
+
+std::pair<wifi_error, std::vector<uint8_t>>
+WifiLegacyHal::requestFirmwareMemoryDump(const std::string& iface_name) {
+    std::vector<uint8_t> firmware_dump;
+    on_firmware_memory_dump_internal_callback =
+        [&firmware_dump](char* buffer, int buffer_size) {
+            firmware_dump.insert(
+                firmware_dump.end(), reinterpret_cast<uint8_t*>(buffer),
+                reinterpret_cast<uint8_t*>(buffer) + buffer_size);
+        };
+    wifi_error status = global_func_table_.wifi_get_firmware_memory_dump(
+        getIfaceHandle(iface_name), {onSyncFirmwareMemoryDump});
+    on_firmware_memory_dump_internal_callback = nullptr;
+    return {status, std::move(firmware_dump)};
+}
+
+std::pair<wifi_error, uint32_t> WifiLegacyHal::getSupportedFeatureSet(
+    const std::string& iface_name) {
+    feature_set set;
+    static_assert(sizeof(set) == sizeof(uint32_t),
+                  "Some feature_flags can not be represented in output");
+    wifi_error status = global_func_table_.wifi_get_supported_feature_set(
+        getIfaceHandle(iface_name), &set);
+    return {status, static_cast<uint32_t>(set)};
+}
+
+std::pair<wifi_error, PacketFilterCapabilities>
+WifiLegacyHal::getPacketFilterCapabilities(const std::string& iface_name) {
+    PacketFilterCapabilities caps;
+    wifi_error status = global_func_table_.wifi_get_packet_filter_capabilities(
+        getIfaceHandle(iface_name), &caps.version, &caps.max_len);
+    return {status, caps};
+}
+
+wifi_error WifiLegacyHal::setPacketFilter(const std::string& iface_name,
+                                          const std::vector<uint8_t>& program) {
+    return global_func_table_.wifi_set_packet_filter(
+        getIfaceHandle(iface_name), program.data(), program.size());
+}
+
+std::pair<wifi_error, wifi_gscan_capabilities>
+WifiLegacyHal::getGscanCapabilities(const std::string& iface_name) {
+    wifi_gscan_capabilities caps;
+    wifi_error status = global_func_table_.wifi_get_gscan_capabilities(
+        getIfaceHandle(iface_name), &caps);
+    return {status, caps};
+}
+
+wifi_error WifiLegacyHal::startGscan(
+    const std::string& iface_name, wifi_request_id id,
+    const wifi_scan_cmd_params& params,
+    const std::function<void(wifi_request_id)>& on_failure_user_callback,
+    const on_gscan_results_callback& on_results_user_callback,
+    const on_gscan_full_result_callback& on_full_result_user_callback) {
+    // If there is already an ongoing background scan, reject new scan requests.
+    if (on_gscan_event_internal_callback ||
+        on_gscan_full_result_internal_callback) {
+        return WIFI_ERROR_NOT_AVAILABLE;
+    }
+
+    // This callback will be used to either trigger |on_results_user_callback|
+    // or |on_failure_user_callback|.
+    on_gscan_event_internal_callback =
+        [iface_name, on_failure_user_callback, on_results_user_callback, this](
+            wifi_request_id id, wifi_scan_event event) {
+            switch (event) {
+                case WIFI_SCAN_RESULTS_AVAILABLE:
+                case WIFI_SCAN_THRESHOLD_NUM_SCANS:
+                case WIFI_SCAN_THRESHOLD_PERCENT: {
+                    wifi_error status;
+                    std::vector<wifi_cached_scan_results> cached_scan_results;
+                    std::tie(status, cached_scan_results) =
+                        getGscanCachedResults(iface_name);
+                    if (status == WIFI_SUCCESS) {
+                        on_results_user_callback(id, cached_scan_results);
+                        return;
+                    }
+                }
+                // Fall through if failed. Failure to retrieve cached scan
+                // results should trigger a background scan failure.
+                case WIFI_SCAN_FAILED:
+                    on_failure_user_callback(id);
+                    on_gscan_event_internal_callback = nullptr;
+                    on_gscan_full_result_internal_callback = nullptr;
+                    return;
+            }
+            LOG(FATAL) << "Unexpected gscan event received: " << event;
+        };
+
+    on_gscan_full_result_internal_callback = [on_full_result_user_callback](
+                                                 wifi_request_id id,
+                                                 wifi_scan_result* result,
+                                                 uint32_t buckets_scanned) {
+        if (result) {
+            on_full_result_user_callback(id, result, buckets_scanned);
+        }
+    };
+
+    wifi_scan_result_handler handler = {onAsyncGscanFullResult,
+                                        onAsyncGscanEvent};
+    wifi_error status = global_func_table_.wifi_start_gscan(
+        id, getIfaceHandle(iface_name), params, handler);
+    if (status != WIFI_SUCCESS) {
+        on_gscan_event_internal_callback = nullptr;
+        on_gscan_full_result_internal_callback = nullptr;
+    }
+    return status;
+}
+
+wifi_error WifiLegacyHal::stopGscan(const std::string& iface_name,
+                                    wifi_request_id id) {
+    // If there is no an ongoing background scan, reject stop requests.
+    // TODO(b/32337212): This needs to be handled by the HIDL object because we
+    // need to return the NOT_STARTED error code.
+    if (!on_gscan_event_internal_callback &&
+        !on_gscan_full_result_internal_callback) {
+        return WIFI_ERROR_NOT_AVAILABLE;
+    }
+    wifi_error status =
+        global_func_table_.wifi_stop_gscan(id, getIfaceHandle(iface_name));
+    // If the request Id is wrong, don't stop the ongoing background scan. Any
+    // other error should be treated as the end of background scan.
+    if (status != WIFI_ERROR_INVALID_REQUEST_ID) {
+        on_gscan_event_internal_callback = nullptr;
+        on_gscan_full_result_internal_callback = nullptr;
+    }
+    return status;
+}
+
+std::pair<wifi_error, std::vector<uint32_t>>
+WifiLegacyHal::getValidFrequenciesForBand(const std::string& iface_name,
+                                          wifi_band band) {
+    static_assert(sizeof(uint32_t) >= sizeof(wifi_channel),
+                  "Wifi Channel cannot be represented in output");
+    std::vector<uint32_t> freqs;
+    freqs.resize(kMaxGscanFrequenciesForBand);
+    int32_t num_freqs = 0;
+    wifi_error status = global_func_table_.wifi_get_valid_channels(
+        getIfaceHandle(iface_name), band, freqs.size(),
+        reinterpret_cast<wifi_channel*>(freqs.data()), &num_freqs);
+    CHECK(num_freqs >= 0 &&
+          static_cast<uint32_t>(num_freqs) <= kMaxGscanFrequenciesForBand);
+    freqs.resize(num_freqs);
+    return {status, std::move(freqs)};
+}
+
+wifi_error WifiLegacyHal::setDfsFlag(const std::string& iface_name,
+                                     bool dfs_on) {
+    return global_func_table_.wifi_set_nodfs_flag(getIfaceHandle(iface_name),
+                                                  dfs_on ? 0 : 1);
+}
+
+wifi_error WifiLegacyHal::enableLinkLayerStats(const std::string& iface_name,
+                                               bool debug) {
+    wifi_link_layer_params params;
+    params.mpdu_size_threshold = kLinkLayerStatsDataMpduSizeThreshold;
+    params.aggressive_statistics_gathering = debug;
+    return global_func_table_.wifi_set_link_stats(getIfaceHandle(iface_name),
+                                                  params);
+}
+
+wifi_error WifiLegacyHal::disableLinkLayerStats(const std::string& iface_name) {
+    // TODO: Do we care about these responses?
+    uint32_t clear_mask_rsp;
+    uint8_t stop_rsp;
+    return global_func_table_.wifi_clear_link_stats(
+        getIfaceHandle(iface_name), 0xFFFFFFFF, &clear_mask_rsp, 1, &stop_rsp);
+}
+
+std::pair<wifi_error, LinkLayerStats> WifiLegacyHal::getLinkLayerStats(
+    const std::string& iface_name) {
+    LinkLayerStats link_stats{};
+    LinkLayerStats* link_stats_ptr = &link_stats;
+
+    on_link_layer_stats_result_internal_callback =
+        [&link_stats_ptr](wifi_request_id /* id */,
+                          wifi_iface_stat* iface_stats_ptr, int num_radios,
+                          wifi_radio_stat* radio_stats_ptr) {
+            if (iface_stats_ptr != nullptr) {
+                link_stats_ptr->iface = *iface_stats_ptr;
+                link_stats_ptr->iface.num_peers = 0;
+            } else {
+                LOG(ERROR) << "Invalid iface stats in link layer stats";
+            }
+            if (num_radios <= 0 || radio_stats_ptr == nullptr) {
+                LOG(ERROR) << "Invalid radio stats in link layer stats";
+                return;
+            }
+            for (int i = 0; i < num_radios; i++) {
+                LinkLayerRadioStats radio;
+                radio.stats = radio_stats_ptr[i];
+                // Copy over the tx level array to the separate vector.
+                if (radio_stats_ptr[i].num_tx_levels > 0 &&
+                    radio_stats_ptr[i].tx_time_per_levels != nullptr) {
+                    radio.tx_time_per_levels.assign(
+                        radio_stats_ptr[i].tx_time_per_levels,
+                        radio_stats_ptr[i].tx_time_per_levels +
+                            radio_stats_ptr[i].num_tx_levels);
+                }
+                radio.stats.num_tx_levels = 0;
+                radio.stats.tx_time_per_levels = nullptr;
+                link_stats_ptr->radios.push_back(radio);
+            }
+        };
+
+    wifi_error status = global_func_table_.wifi_get_link_stats(
+        0, getIfaceHandle(iface_name), {onSyncLinkLayerStatsResult});
+    on_link_layer_stats_result_internal_callback = nullptr;
+    return {status, link_stats};
+}
+
+wifi_error WifiLegacyHal::startRssiMonitoring(
+    const std::string& iface_name, wifi_request_id id, int8_t max_rssi,
+    int8_t min_rssi,
+    const on_rssi_threshold_breached_callback&
+        on_threshold_breached_user_callback) {
+    if (on_rssi_threshold_breached_internal_callback) {
+        return WIFI_ERROR_NOT_AVAILABLE;
+    }
+    on_rssi_threshold_breached_internal_callback =
+        [on_threshold_breached_user_callback](wifi_request_id id,
+                                              uint8_t* bssid_ptr, int8_t rssi) {
+            if (!bssid_ptr) {
+                return;
+            }
+            std::array<uint8_t, 6> bssid_arr;
+            // |bssid_ptr| pointer is assumed to have 6 bytes for the mac
+            // address.
+            std::copy(bssid_ptr, bssid_ptr + 6, std::begin(bssid_arr));
+            on_threshold_breached_user_callback(id, bssid_arr, rssi);
+        };
+    wifi_error status = global_func_table_.wifi_start_rssi_monitoring(
+        id, getIfaceHandle(iface_name), max_rssi, min_rssi,
+        {onAsyncRssiThresholdBreached});
+    if (status != WIFI_SUCCESS) {
+        on_rssi_threshold_breached_internal_callback = nullptr;
+    }
+    return status;
+}
+
+wifi_error WifiLegacyHal::stopRssiMonitoring(const std::string& iface_name,
+                                             wifi_request_id id) {
+    if (!on_rssi_threshold_breached_internal_callback) {
+        return WIFI_ERROR_NOT_AVAILABLE;
+    }
+    wifi_error status = global_func_table_.wifi_stop_rssi_monitoring(
+        id, getIfaceHandle(iface_name));
+    // If the request Id is wrong, don't stop the ongoing rssi monitoring. Any
+    // other error should be treated as the end of background scan.
+    if (status != WIFI_ERROR_INVALID_REQUEST_ID) {
+        on_rssi_threshold_breached_internal_callback = nullptr;
+    }
+    return status;
+}
+
+std::pair<wifi_error, wifi_roaming_capabilities>
+WifiLegacyHal::getRoamingCapabilities(const std::string& iface_name) {
+    wifi_roaming_capabilities caps;
+    wifi_error status = global_func_table_.wifi_get_roaming_capabilities(
+        getIfaceHandle(iface_name), &caps);
+    return {status, caps};
+}
+
+wifi_error WifiLegacyHal::configureRoaming(const std::string& iface_name,
+                                           const wifi_roaming_config& config) {
+    wifi_roaming_config config_internal = config;
+    return global_func_table_.wifi_configure_roaming(getIfaceHandle(iface_name),
+                                                     &config_internal);
+}
+
+wifi_error WifiLegacyHal::enableFirmwareRoaming(const std::string& iface_name,
+                                                fw_roaming_state_t state) {
+    return global_func_table_.wifi_enable_firmware_roaming(
+        getIfaceHandle(iface_name), state);
+}
+
+wifi_error WifiLegacyHal::configureNdOffload(const std::string& iface_name,
+                                             bool enable) {
+    return global_func_table_.wifi_configure_nd_offload(
+        getIfaceHandle(iface_name), enable);
+}
+
+wifi_error WifiLegacyHal::startSendingOffloadedPacket(
+    const std::string& iface_name, uint32_t cmd_id,
+    const std::vector<uint8_t>& ip_packet_data,
+    const std::array<uint8_t, 6>& src_address,
+    const std::array<uint8_t, 6>& dst_address, uint32_t period_in_ms) {
+    std::vector<uint8_t> ip_packet_data_internal(ip_packet_data);
+    std::vector<uint8_t> src_address_internal(
+        src_address.data(), src_address.data() + src_address.size());
+    std::vector<uint8_t> dst_address_internal(
+        dst_address.data(), dst_address.data() + dst_address.size());
+    return global_func_table_.wifi_start_sending_offloaded_packet(
+        cmd_id, getIfaceHandle(iface_name), ip_packet_data_internal.data(),
+        ip_packet_data_internal.size(), src_address_internal.data(),
+        dst_address_internal.data(), period_in_ms);
+}
+
+wifi_error WifiLegacyHal::stopSendingOffloadedPacket(
+    const std::string& iface_name, uint32_t cmd_id) {
+    return global_func_table_.wifi_stop_sending_offloaded_packet(
+        cmd_id, getIfaceHandle(iface_name));
+}
+
+wifi_error WifiLegacyHal::setScanningMacOui(const std::string& iface_name,
+                                            const std::array<uint8_t, 3>& oui) {
+    std::vector<uint8_t> oui_internal(oui.data(), oui.data() + oui.size());
+    return global_func_table_.wifi_set_scanning_mac_oui(
+        getIfaceHandle(iface_name), oui_internal.data());
+}
+
+wifi_error WifiLegacyHal::selectTxPowerScenario(const std::string& iface_name,
+                                                wifi_power_scenario scenario) {
+    return global_func_table_.wifi_select_tx_power_scenario(
+        getIfaceHandle(iface_name), scenario);
+}
+
+wifi_error WifiLegacyHal::resetTxPowerScenario(const std::string& iface_name) {
+    return global_func_table_.wifi_reset_tx_power_scenario(
+        getIfaceHandle(iface_name));
+}
+
+std::pair<wifi_error, uint32_t> WifiLegacyHal::getLoggerSupportedFeatureSet(
+    const std::string& iface_name) {
+    uint32_t supported_feature_flags;
+    wifi_error status =
+        global_func_table_.wifi_get_logger_supported_feature_set(
+            getIfaceHandle(iface_name), &supported_feature_flags);
+    return {status, supported_feature_flags};
+}
+
+wifi_error WifiLegacyHal::startPktFateMonitoring(
+    const std::string& iface_name) {
+    return global_func_table_.wifi_start_pkt_fate_monitoring(
+        getIfaceHandle(iface_name));
+}
+
+std::pair<wifi_error, std::vector<wifi_tx_report>> WifiLegacyHal::getTxPktFates(
+    const std::string& iface_name) {
+    std::vector<wifi_tx_report> tx_pkt_fates;
+    tx_pkt_fates.resize(MAX_FATE_LOG_LEN);
+    size_t num_fates = 0;
+    wifi_error status = global_func_table_.wifi_get_tx_pkt_fates(
+        getIfaceHandle(iface_name), tx_pkt_fates.data(), tx_pkt_fates.size(),
+        &num_fates);
+    CHECK(num_fates <= MAX_FATE_LOG_LEN);
+    tx_pkt_fates.resize(num_fates);
+    return {status, std::move(tx_pkt_fates)};
+}
+
+std::pair<wifi_error, std::vector<wifi_rx_report>> WifiLegacyHal::getRxPktFates(
+    const std::string& iface_name) {
+    std::vector<wifi_rx_report> rx_pkt_fates;
+    rx_pkt_fates.resize(MAX_FATE_LOG_LEN);
+    size_t num_fates = 0;
+    wifi_error status = global_func_table_.wifi_get_rx_pkt_fates(
+        getIfaceHandle(iface_name), rx_pkt_fates.data(), rx_pkt_fates.size(),
+        &num_fates);
+    CHECK(num_fates <= MAX_FATE_LOG_LEN);
+    rx_pkt_fates.resize(num_fates);
+    return {status, std::move(rx_pkt_fates)};
+}
+
+std::pair<wifi_error, WakeReasonStats> WifiLegacyHal::getWakeReasonStats(
+    const std::string& iface_name) {
+    WakeReasonStats stats;
+    stats.cmd_event_wake_cnt.resize(kMaxWakeReasonStatsArraySize);
+    stats.driver_fw_local_wake_cnt.resize(kMaxWakeReasonStatsArraySize);
+
+    // This legacy struct needs separate memory to store the variable sized wake
+    // reason types.
+    stats.wake_reason_cnt.cmd_event_wake_cnt =
+        reinterpret_cast<int32_t*>(stats.cmd_event_wake_cnt.data());
+    stats.wake_reason_cnt.cmd_event_wake_cnt_sz =
+        stats.cmd_event_wake_cnt.size();
+    stats.wake_reason_cnt.cmd_event_wake_cnt_used = 0;
+    stats.wake_reason_cnt.driver_fw_local_wake_cnt =
+        reinterpret_cast<int32_t*>(stats.driver_fw_local_wake_cnt.data());
+    stats.wake_reason_cnt.driver_fw_local_wake_cnt_sz =
+        stats.driver_fw_local_wake_cnt.size();
+    stats.wake_reason_cnt.driver_fw_local_wake_cnt_used = 0;
+
+    wifi_error status = global_func_table_.wifi_get_wake_reason_stats(
+        getIfaceHandle(iface_name), &stats.wake_reason_cnt);
+
+    CHECK(
+        stats.wake_reason_cnt.cmd_event_wake_cnt_used >= 0 &&
+        static_cast<uint32_t>(stats.wake_reason_cnt.cmd_event_wake_cnt_used) <=
+            kMaxWakeReasonStatsArraySize);
+    stats.cmd_event_wake_cnt.resize(
+        stats.wake_reason_cnt.cmd_event_wake_cnt_used);
+    stats.wake_reason_cnt.cmd_event_wake_cnt = nullptr;
+
+    CHECK(stats.wake_reason_cnt.driver_fw_local_wake_cnt_used >= 0 &&
+          static_cast<uint32_t>(
+              stats.wake_reason_cnt.driver_fw_local_wake_cnt_used) <=
+              kMaxWakeReasonStatsArraySize);
+    stats.driver_fw_local_wake_cnt.resize(
+        stats.wake_reason_cnt.driver_fw_local_wake_cnt_used);
+    stats.wake_reason_cnt.driver_fw_local_wake_cnt = nullptr;
+
+    return {status, stats};
+}
+
+wifi_error WifiLegacyHal::registerRingBufferCallbackHandler(
+    const std::string& iface_name,
+    const on_ring_buffer_data_callback& on_user_data_callback) {
+    if (on_ring_buffer_data_internal_callback) {
+        return WIFI_ERROR_NOT_AVAILABLE;
+    }
+    on_ring_buffer_data_internal_callback =
+        [on_user_data_callback](char* ring_name, char* buffer, int buffer_size,
+                                wifi_ring_buffer_status* status) {
+            if (status && buffer) {
+                std::vector<uint8_t> buffer_vector(
+                    reinterpret_cast<uint8_t*>(buffer),
+                    reinterpret_cast<uint8_t*>(buffer) + buffer_size);
+                on_user_data_callback(ring_name, buffer_vector, *status);
+            }
+        };
+    wifi_error status = global_func_table_.wifi_set_log_handler(
+        0, getIfaceHandle(iface_name), {onAsyncRingBufferData});
+    if (status != WIFI_SUCCESS) {
+        on_ring_buffer_data_internal_callback = nullptr;
+    }
+    return status;
+}
+
+wifi_error WifiLegacyHal::deregisterRingBufferCallbackHandler(
+    const std::string& iface_name) {
+    if (!on_ring_buffer_data_internal_callback) {
+        return WIFI_ERROR_NOT_AVAILABLE;
+    }
+    on_ring_buffer_data_internal_callback = nullptr;
+    return global_func_table_.wifi_reset_log_handler(
+        0, getIfaceHandle(iface_name));
+}
+
+std::pair<wifi_error, std::vector<wifi_ring_buffer_status>>
+WifiLegacyHal::getRingBuffersStatus(const std::string& iface_name) {
+    std::vector<wifi_ring_buffer_status> ring_buffers_status;
+    ring_buffers_status.resize(kMaxRingBuffers);
+    uint32_t num_rings = kMaxRingBuffers;
+    wifi_error status = global_func_table_.wifi_get_ring_buffers_status(
+        getIfaceHandle(iface_name), &num_rings, ring_buffers_status.data());
+    CHECK(num_rings <= kMaxRingBuffers);
+    ring_buffers_status.resize(num_rings);
+    return {status, std::move(ring_buffers_status)};
+}
+
+wifi_error WifiLegacyHal::startRingBufferLogging(const std::string& iface_name,
+                                                 const std::string& ring_name,
+                                                 uint32_t verbose_level,
+                                                 uint32_t max_interval_sec,
+                                                 uint32_t min_data_size) {
+    return global_func_table_.wifi_start_logging(
+        getIfaceHandle(iface_name), verbose_level, 0, max_interval_sec,
+        min_data_size, makeCharVec(ring_name).data());
+}
+
+wifi_error WifiLegacyHal::getRingBufferData(const std::string& iface_name,
+                                            const std::string& ring_name) {
+    return global_func_table_.wifi_get_ring_data(getIfaceHandle(iface_name),
+                                                 makeCharVec(ring_name).data());
+}
+
+wifi_error WifiLegacyHal::registerErrorAlertCallbackHandler(
+    const std::string& iface_name,
+    const on_error_alert_callback& on_user_alert_callback) {
+    if (on_error_alert_internal_callback) {
+        return WIFI_ERROR_NOT_AVAILABLE;
+    }
+    on_error_alert_internal_callback = [on_user_alert_callback](
+                                           wifi_request_id id, char* buffer,
+                                           int buffer_size, int err_code) {
+        if (buffer) {
+            CHECK(id == 0);
+            on_user_alert_callback(
+                err_code,
+                std::vector<uint8_t>(
+                    reinterpret_cast<uint8_t*>(buffer),
+                    reinterpret_cast<uint8_t*>(buffer) + buffer_size));
+        }
+    };
+    wifi_error status = global_func_table_.wifi_set_alert_handler(
+        0, getIfaceHandle(iface_name), {onAsyncErrorAlert});
+    if (status != WIFI_SUCCESS) {
+        on_error_alert_internal_callback = nullptr;
+    }
+    return status;
+}
+
+wifi_error WifiLegacyHal::deregisterErrorAlertCallbackHandler(
+    const std::string& iface_name) {
+    if (!on_error_alert_internal_callback) {
+        return WIFI_ERROR_NOT_AVAILABLE;
+    }
+    on_error_alert_internal_callback = nullptr;
+    return global_func_table_.wifi_reset_alert_handler(
+        0, getIfaceHandle(iface_name));
+}
+
+wifi_error WifiLegacyHal::startRttRangeRequest(
+    const std::string& iface_name, wifi_request_id id,
+    const std::vector<wifi_rtt_config>& rtt_configs,
+    const on_rtt_results_callback& on_results_user_callback) {
+    if (on_rtt_results_internal_callback) {
+        return WIFI_ERROR_NOT_AVAILABLE;
+    }
+
+    on_rtt_results_internal_callback =
+        [on_results_user_callback](wifi_request_id id, unsigned num_results,
+                                   wifi_rtt_result* rtt_results[]) {
+            if (num_results > 0 && !rtt_results) {
+                LOG(ERROR) << "Unexpected nullptr in RTT results";
+                return;
+            }
+            std::vector<const wifi_rtt_result*> rtt_results_vec;
+            std::copy_if(rtt_results, rtt_results + num_results,
+                         back_inserter(rtt_results_vec),
+                         [](wifi_rtt_result* rtt_result) {
+                             return rtt_result != nullptr;
+                         });
+            on_results_user_callback(id, rtt_results_vec);
+        };
+
+    std::vector<wifi_rtt_config> rtt_configs_internal(rtt_configs);
+    wifi_error status = global_func_table_.wifi_rtt_range_request(
+        id, getIfaceHandle(iface_name), rtt_configs.size(),
+        rtt_configs_internal.data(), {onAsyncRttResults});
+    if (status != WIFI_SUCCESS) {
+        on_rtt_results_internal_callback = nullptr;
+    }
+    return status;
+}
+
+wifi_error WifiLegacyHal::cancelRttRangeRequest(
+    const std::string& iface_name, wifi_request_id id,
+    const std::vector<std::array<uint8_t, 6>>& mac_addrs) {
+    if (!on_rtt_results_internal_callback) {
+        return WIFI_ERROR_NOT_AVAILABLE;
+    }
+    static_assert(sizeof(mac_addr) == sizeof(std::array<uint8_t, 6>),
+                  "MAC address size mismatch");
+    // TODO: How do we handle partial cancels (i.e only a subset of enabled mac
+    // addressed are cancelled).
+    std::vector<std::array<uint8_t, 6>> mac_addrs_internal(mac_addrs);
+    wifi_error status = global_func_table_.wifi_rtt_range_cancel(
+        id, getIfaceHandle(iface_name), mac_addrs.size(),
+        reinterpret_cast<mac_addr*>(mac_addrs_internal.data()));
+    // If the request Id is wrong, don't stop the ongoing range request. Any
+    // other error should be treated as the end of rtt ranging.
+    if (status != WIFI_ERROR_INVALID_REQUEST_ID) {
+        on_rtt_results_internal_callback = nullptr;
+    }
+    return status;
+}
+
+std::pair<wifi_error, wifi_rtt_capabilities> WifiLegacyHal::getRttCapabilities(
+    const std::string& iface_name) {
+    wifi_rtt_capabilities rtt_caps;
+    wifi_error status = global_func_table_.wifi_get_rtt_capabilities(
+        getIfaceHandle(iface_name), &rtt_caps);
+    return {status, rtt_caps};
+}
+
+std::pair<wifi_error, wifi_rtt_responder> WifiLegacyHal::getRttResponderInfo(
+    const std::string& iface_name) {
+    wifi_rtt_responder rtt_responder;
+    wifi_error status = global_func_table_.wifi_rtt_get_responder_info(
+        getIfaceHandle(iface_name), &rtt_responder);
+    return {status, rtt_responder};
+}
+
+wifi_error WifiLegacyHal::enableRttResponder(
+    const std::string& iface_name, wifi_request_id id,
+    const wifi_channel_info& channel_hint, uint32_t max_duration_secs,
+    const wifi_rtt_responder& info) {
+    wifi_rtt_responder info_internal(info);
+    return global_func_table_.wifi_enable_responder(
+        id, getIfaceHandle(iface_name), channel_hint, max_duration_secs,
+        &info_internal);
+}
+
+wifi_error WifiLegacyHal::disableRttResponder(const std::string& iface_name,
+                                              wifi_request_id id) {
+    return global_func_table_.wifi_disable_responder(
+        id, getIfaceHandle(iface_name));
+}
+
+wifi_error WifiLegacyHal::setRttLci(const std::string& iface_name,
+                                    wifi_request_id id,
+                                    const wifi_lci_information& info) {
+    wifi_lci_information info_internal(info);
+    return global_func_table_.wifi_set_lci(id, getIfaceHandle(iface_name),
+                                           &info_internal);
+}
+
+wifi_error WifiLegacyHal::setRttLcr(const std::string& iface_name,
+                                    wifi_request_id id,
+                                    const wifi_lcr_information& info) {
+    wifi_lcr_information info_internal(info);
+    return global_func_table_.wifi_set_lcr(id, getIfaceHandle(iface_name),
+                                           &info_internal);
+}
+
+wifi_error WifiLegacyHal::nanRegisterCallbackHandlers(
+    const std::string& iface_name, const NanCallbackHandlers& user_callbacks) {
+    on_nan_notify_response_user_callback = user_callbacks.on_notify_response;
+    on_nan_event_publish_terminated_user_callback =
+        user_callbacks.on_event_publish_terminated;
+    on_nan_event_match_user_callback = user_callbacks.on_event_match;
+    on_nan_event_match_expired_user_callback =
+        user_callbacks.on_event_match_expired;
+    on_nan_event_subscribe_terminated_user_callback =
+        user_callbacks.on_event_subscribe_terminated;
+    on_nan_event_followup_user_callback = user_callbacks.on_event_followup;
+    on_nan_event_disc_eng_event_user_callback =
+        user_callbacks.on_event_disc_eng_event;
+    on_nan_event_disabled_user_callback = user_callbacks.on_event_disabled;
+    on_nan_event_tca_user_callback = user_callbacks.on_event_tca;
+    on_nan_event_beacon_sdf_payload_user_callback =
+        user_callbacks.on_event_beacon_sdf_payload;
+    on_nan_event_data_path_request_user_callback =
+        user_callbacks.on_event_data_path_request;
+    on_nan_event_data_path_confirm_user_callback =
+        user_callbacks.on_event_data_path_confirm;
+    on_nan_event_data_path_end_user_callback =
+        user_callbacks.on_event_data_path_end;
+    on_nan_event_transmit_follow_up_user_callback =
+        user_callbacks.on_event_transmit_follow_up;
+    on_nan_event_range_request_user_callback =
+        user_callbacks.on_event_range_request;
+    on_nan_event_range_report_user_callback =
+        user_callbacks.on_event_range_report;
+    on_nan_event_schedule_update_user_callback =
+        user_callbacks.on_event_schedule_update;
+
+    return global_func_table_.wifi_nan_register_handler(
+        getIfaceHandle(iface_name),
+        {onAysncNanNotifyResponse, onAysncNanEventPublishReplied,
+         onAysncNanEventPublishTerminated, onAysncNanEventMatch,
+         onAysncNanEventMatchExpired, onAysncNanEventSubscribeTerminated,
+         onAysncNanEventFollowup, onAysncNanEventDiscEngEvent,
+         onAysncNanEventDisabled, onAysncNanEventTca,
+         onAysncNanEventBeaconSdfPayload, onAysncNanEventDataPathRequest,
+         onAysncNanEventDataPathConfirm, onAysncNanEventDataPathEnd,
+         onAysncNanEventTransmitFollowUp, onAysncNanEventRangeRequest,
+         onAysncNanEventRangeReport, onAsyncNanEventScheduleUpdate});
+}
+
+wifi_error WifiLegacyHal::nanEnableRequest(const std::string& iface_name,
+                                           transaction_id id,
+                                           const NanEnableRequest& msg) {
+    NanEnableRequest msg_internal(msg);
+    return global_func_table_.wifi_nan_enable_request(
+        id, getIfaceHandle(iface_name), &msg_internal);
+}
+
+wifi_error WifiLegacyHal::nanDisableRequest(const std::string& iface_name,
+                                            transaction_id id) {
+    return global_func_table_.wifi_nan_disable_request(
+        id, getIfaceHandle(iface_name));
+}
+
+wifi_error WifiLegacyHal::nanPublishRequest(const std::string& iface_name,
+                                            transaction_id id,
+                                            const NanPublishRequest& msg) {
+    NanPublishRequest msg_internal(msg);
+    return global_func_table_.wifi_nan_publish_request(
+        id, getIfaceHandle(iface_name), &msg_internal);
+}
+
+wifi_error WifiLegacyHal::nanPublishCancelRequest(
+    const std::string& iface_name, transaction_id id,
+    const NanPublishCancelRequest& msg) {
+    NanPublishCancelRequest msg_internal(msg);
+    return global_func_table_.wifi_nan_publish_cancel_request(
+        id, getIfaceHandle(iface_name), &msg_internal);
+}
+
+wifi_error WifiLegacyHal::nanSubscribeRequest(const std::string& iface_name,
+                                              transaction_id id,
+                                              const NanSubscribeRequest& msg) {
+    NanSubscribeRequest msg_internal(msg);
+    return global_func_table_.wifi_nan_subscribe_request(
+        id, getIfaceHandle(iface_name), &msg_internal);
+}
+
+wifi_error WifiLegacyHal::nanSubscribeCancelRequest(
+    const std::string& iface_name, transaction_id id,
+    const NanSubscribeCancelRequest& msg) {
+    NanSubscribeCancelRequest msg_internal(msg);
+    return global_func_table_.wifi_nan_subscribe_cancel_request(
+        id, getIfaceHandle(iface_name), &msg_internal);
+}
+
+wifi_error WifiLegacyHal::nanTransmitFollowupRequest(
+    const std::string& iface_name, transaction_id id,
+    const NanTransmitFollowupRequest& msg) {
+    NanTransmitFollowupRequest msg_internal(msg);
+    return global_func_table_.wifi_nan_transmit_followup_request(
+        id, getIfaceHandle(iface_name), &msg_internal);
+}
+
+wifi_error WifiLegacyHal::nanStatsRequest(const std::string& iface_name,
+                                          transaction_id id,
+                                          const NanStatsRequest& msg) {
+    NanStatsRequest msg_internal(msg);
+    return global_func_table_.wifi_nan_stats_request(
+        id, getIfaceHandle(iface_name), &msg_internal);
+}
+
+wifi_error WifiLegacyHal::nanConfigRequest(const std::string& iface_name,
+                                           transaction_id id,
+                                           const NanConfigRequest& msg) {
+    NanConfigRequest msg_internal(msg);
+    return global_func_table_.wifi_nan_config_request(
+        id, getIfaceHandle(iface_name), &msg_internal);
+}
+
+wifi_error WifiLegacyHal::nanTcaRequest(const std::string& iface_name,
+                                        transaction_id id,
+                                        const NanTCARequest& msg) {
+    NanTCARequest msg_internal(msg);
+    return global_func_table_.wifi_nan_tca_request(
+        id, getIfaceHandle(iface_name), &msg_internal);
+}
+
+wifi_error WifiLegacyHal::nanBeaconSdfPayloadRequest(
+    const std::string& iface_name, transaction_id id,
+    const NanBeaconSdfPayloadRequest& msg) {
+    NanBeaconSdfPayloadRequest msg_internal(msg);
+    return global_func_table_.wifi_nan_beacon_sdf_payload_request(
+        id, getIfaceHandle(iface_name), &msg_internal);
+}
+
+std::pair<wifi_error, NanVersion> WifiLegacyHal::nanGetVersion() {
+    NanVersion version;
+    wifi_error status =
+        global_func_table_.wifi_nan_get_version(global_handle_, &version);
+    return {status, version};
+}
+
+wifi_error WifiLegacyHal::nanGetCapabilities(const std::string& iface_name,
+                                             transaction_id id) {
+    return global_func_table_.wifi_nan_get_capabilities(
+        id, getIfaceHandle(iface_name));
+}
+
+wifi_error WifiLegacyHal::nanDataInterfaceCreate(
+    const std::string& iface_name, transaction_id id,
+    const std::string& data_iface_name) {
+    return global_func_table_.wifi_nan_data_interface_create(
+        id, getIfaceHandle(iface_name), makeCharVec(data_iface_name).data());
+}
+
+wifi_error WifiLegacyHal::nanDataInterfaceDelete(
+    const std::string& iface_name, transaction_id id,
+    const std::string& data_iface_name) {
+    return global_func_table_.wifi_nan_data_interface_delete(
+        id, getIfaceHandle(iface_name), makeCharVec(data_iface_name).data());
+}
+
+wifi_error WifiLegacyHal::nanDataRequestInitiator(
+    const std::string& iface_name, transaction_id id,
+    const NanDataPathInitiatorRequest& msg) {
+    NanDataPathInitiatorRequest msg_internal(msg);
+    return global_func_table_.wifi_nan_data_request_initiator(
+        id, getIfaceHandle(iface_name), &msg_internal);
+}
+
+wifi_error WifiLegacyHal::nanDataIndicationResponse(
+    const std::string& iface_name, transaction_id id,
+    const NanDataPathIndicationResponse& msg) {
+    NanDataPathIndicationResponse msg_internal(msg);
+    return global_func_table_.wifi_nan_data_indication_response(
+        id, getIfaceHandle(iface_name), &msg_internal);
+}
+
+typedef struct {
+    u8 num_ndp_instances;
+    NanDataPathId ndp_instance_id;
+} NanDataPathEndSingleNdpIdRequest;
+
+wifi_error WifiLegacyHal::nanDataEnd(const std::string& iface_name,
+                                     transaction_id id,
+                                     uint32_t ndpInstanceId) {
+    NanDataPathEndSingleNdpIdRequest msg;
+    msg.num_ndp_instances = 1;
+    msg.ndp_instance_id = ndpInstanceId;
+    wifi_error status = global_func_table_.wifi_nan_data_end(
+        id, getIfaceHandle(iface_name), (NanDataPathEndRequest*)&msg);
+    return status;
+}
+
+wifi_error WifiLegacyHal::setCountryCode(const std::string& iface_name,
+                                         std::array<int8_t, 2> code) {
+    std::string code_str(code.data(), code.data() + code.size());
+    return global_func_table_.wifi_set_country_code(getIfaceHandle(iface_name),
+                                                    code_str.c_str());
+}
+
+wifi_error WifiLegacyHal::retrieveIfaceHandles() {
+    wifi_interface_handle* iface_handles = nullptr;
+    int num_iface_handles = 0;
+    wifi_error status = global_func_table_.wifi_get_ifaces(
+        global_handle_, &num_iface_handles, &iface_handles);
+    if (status != WIFI_SUCCESS) {
+        LOG(ERROR) << "Failed to enumerate interface handles";
+        return status;
+    }
+    for (int i = 0; i < num_iface_handles; ++i) {
+        std::array<char, IFNAMSIZ> iface_name_arr = {};
+        status = global_func_table_.wifi_get_iface_name(
+            iface_handles[i], iface_name_arr.data(), iface_name_arr.size());
+        if (status != WIFI_SUCCESS) {
+            LOG(WARNING) << "Failed to get interface handle name";
+            continue;
+        }
+        // Assuming the interface name is null terminated since the legacy HAL
+        // API does not return a size.
+        std::string iface_name(iface_name_arr.data());
+        LOG(INFO) << "Adding interface handle for " << iface_name;
+        iface_name_to_handle_[iface_name] = iface_handles[i];
+    }
+    return WIFI_SUCCESS;
+}
+
+wifi_interface_handle WifiLegacyHal::getIfaceHandle(
+    const std::string& iface_name) {
+    const auto iface_handle_iter = iface_name_to_handle_.find(iface_name);
+    if (iface_handle_iter == iface_name_to_handle_.end()) {
+        LOG(ERROR) << "Unknown iface name: " << iface_name;
+        return nullptr;
+    }
+    return iface_handle_iter->second;
+}
+
+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>>
+WifiLegacyHal::getGscanCachedResults(const std::string& iface_name) {
+    std::vector<wifi_cached_scan_results> cached_scan_results;
+    cached_scan_results.resize(kMaxCachedGscanResults);
+    int32_t num_results = 0;
+    wifi_error status = global_func_table_.wifi_get_cached_gscan_results(
+        getIfaceHandle(iface_name), true /* always flush */,
+        cached_scan_results.size(), cached_scan_results.data(), &num_results);
+    CHECK(num_results >= 0 &&
+          static_cast<uint32_t>(num_results) <= kMaxCachedGscanResults);
+    cached_scan_results.resize(num_results);
+    // Check for invalid IE lengths in these cached scan results and correct it.
+    for (auto& cached_scan_result : cached_scan_results) {
+        int num_scan_results = cached_scan_result.num_results;
+        for (int i = 0; i < num_scan_results; i++) {
+            auto& scan_result = cached_scan_result.results[i];
+            if (scan_result.ie_length > 0) {
+                LOG(DEBUG) << "Cached scan result has non-zero IE length "
+                           << scan_result.ie_length;
+                scan_result.ie_length = 0;
+            }
+        }
+    }
+    return {status, std::move(cached_scan_results)};
+}
+
+void WifiLegacyHal::invalidate() {
+    global_handle_ = nullptr;
+    iface_name_to_handle_.clear();
+    on_driver_memory_dump_internal_callback = nullptr;
+    on_firmware_memory_dump_internal_callback = nullptr;
+    on_gscan_event_internal_callback = nullptr;
+    on_gscan_full_result_internal_callback = nullptr;
+    on_link_layer_stats_result_internal_callback = nullptr;
+    on_rssi_threshold_breached_internal_callback = nullptr;
+    on_ring_buffer_data_internal_callback = nullptr;
+    on_error_alert_internal_callback = nullptr;
+    on_rtt_results_internal_callback = nullptr;
+    on_nan_notify_response_user_callback = nullptr;
+    on_nan_event_publish_terminated_user_callback = nullptr;
+    on_nan_event_match_user_callback = nullptr;
+    on_nan_event_match_expired_user_callback = nullptr;
+    on_nan_event_subscribe_terminated_user_callback = nullptr;
+    on_nan_event_followup_user_callback = nullptr;
+    on_nan_event_disc_eng_event_user_callback = nullptr;
+    on_nan_event_disabled_user_callback = nullptr;
+    on_nan_event_tca_user_callback = nullptr;
+    on_nan_event_beacon_sdf_payload_user_callback = nullptr;
+    on_nan_event_data_path_request_user_callback = nullptr;
+    on_nan_event_data_path_confirm_user_callback = nullptr;
+    on_nan_event_data_path_end_user_callback = nullptr;
+    on_nan_event_transmit_follow_up_user_callback = nullptr;
+    on_nan_event_range_request_user_callback = nullptr;
+    on_nan_event_range_report_user_callback = nullptr;
+    on_nan_event_schedule_update_user_callback = nullptr;
+}
+
+}  // namespace legacy_hal
+}  // namespace implementation
+}  // namespace V1_2
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
diff --git a/wifi/1.2/default/wifi_legacy_hal.h b/wifi/1.2/default/wifi_legacy_hal.h
new file mode 100644
index 0000000..da88f6b
--- /dev/null
+++ b/wifi/1.2/default/wifi_legacy_hal.h
@@ -0,0 +1,365 @@
+/*
+ * 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 WIFI_LEGACY_HAL_H_
+#define WIFI_LEGACY_HAL_H_
+
+#include <condition_variable>
+#include <functional>
+#include <map>
+#include <thread>
+#include <vector>
+
+#include <wifi_system/interface_tool.h>
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace V1_2 {
+namespace implementation {
+// This is in a separate namespace to prevent typename conflicts between
+// the legacy HAL types and the HIDL interface types.
+namespace legacy_hal {
+// Wrap all the types defined inside the legacy HAL header files inside this
+// namespace.
+#include <hardware_legacy/wifi_hal.h>
+
+// APF capabilities supported by the iface.
+struct PacketFilterCapabilities {
+    uint32_t version;
+    uint32_t max_len;
+};
+
+// WARNING: We don't care about the variable sized members of either
+// |wifi_iface_stat|, |wifi_radio_stat| structures. So, using the pragma
+// to escape the compiler warnings regarding this.
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wgnu-variable-sized-type-not-at-end"
+// The |wifi_radio_stat.tx_time_per_levels| stats is provided as a pointer in
+// |wifi_radio_stat| structure in the legacy HAL API. Separate that out
+// into a separate return element to avoid passing pointers around.
+struct LinkLayerRadioStats {
+    wifi_radio_stat stats;
+    std::vector<uint32_t> tx_time_per_levels;
+};
+
+struct LinkLayerStats {
+    wifi_iface_stat iface;
+    std::vector<LinkLayerRadioStats> radios;
+};
+#pragma GCC diagnostic pop
+
+// The |WLAN_DRIVER_WAKE_REASON_CNT.cmd_event_wake_cnt| and
+// |WLAN_DRIVER_WAKE_REASON_CNT.driver_fw_local_wake_cnt| stats is provided
+// as a pointer in |WLAN_DRIVER_WAKE_REASON_CNT| structure in the legacy HAL
+// API. Separate that out into a separate return elements to avoid passing
+// pointers around.
+struct WakeReasonStats {
+    WLAN_DRIVER_WAKE_REASON_CNT wake_reason_cnt;
+    std::vector<uint32_t> cmd_event_wake_cnt;
+    std::vector<uint32_t> driver_fw_local_wake_cnt;
+};
+
+// NAN response and event callbacks struct.
+struct NanCallbackHandlers {
+    // NotifyResponse invoked to notify the status of the Request.
+    std::function<void(transaction_id, const NanResponseMsg&)>
+        on_notify_response;
+    // Various event callbacks.
+    std::function<void(const NanPublishTerminatedInd&)>
+        on_event_publish_terminated;
+    std::function<void(const NanMatchInd&)> on_event_match;
+    std::function<void(const NanMatchExpiredInd&)> on_event_match_expired;
+    std::function<void(const NanSubscribeTerminatedInd&)>
+        on_event_subscribe_terminated;
+    std::function<void(const NanFollowupInd&)> on_event_followup;
+    std::function<void(const NanDiscEngEventInd&)> on_event_disc_eng_event;
+    std::function<void(const NanDisabledInd&)> on_event_disabled;
+    std::function<void(const NanTCAInd&)> on_event_tca;
+    std::function<void(const NanBeaconSdfPayloadInd&)>
+        on_event_beacon_sdf_payload;
+    std::function<void(const NanDataPathRequestInd&)>
+        on_event_data_path_request;
+    std::function<void(const NanDataPathConfirmInd&)>
+        on_event_data_path_confirm;
+    std::function<void(const NanDataPathEndInd&)> on_event_data_path_end;
+    std::function<void(const NanTransmitFollowupInd&)>
+        on_event_transmit_follow_up;
+    std::function<void(const NanRangeRequestInd&)> on_event_range_request;
+    std::function<void(const NanRangeReportInd&)> on_event_range_report;
+    std::function<void(const NanDataPathScheduleUpdateInd&)> on_event_schedule_update;
+};
+
+// Full scan results contain IE info and are hence passed by reference, to
+// preserve the variable length array member |ie_data|. Callee must not retain
+// the pointer.
+using on_gscan_full_result_callback =
+    std::function<void(wifi_request_id, const wifi_scan_result*, uint32_t)>;
+// These scan results don't contain any IE info, so no need to pass by
+// reference.
+using on_gscan_results_callback = std::function<void(
+    wifi_request_id, const std::vector<wifi_cached_scan_results>&)>;
+
+// Invoked when the rssi value breaches the thresholds set.
+using on_rssi_threshold_breached_callback =
+    std::function<void(wifi_request_id, std::array<uint8_t, 6>, int8_t)>;
+
+// Callback for RTT range request results.
+// Rtt results contain IE info and are hence passed by reference, to
+// preserve the |LCI| and |LCR| pointers. Callee must not retain
+// the pointer.
+using on_rtt_results_callback = std::function<void(
+    wifi_request_id, const std::vector<const wifi_rtt_result*>&)>;
+
+// Callback for ring buffer data.
+using on_ring_buffer_data_callback =
+    std::function<void(const std::string&, const std::vector<uint8_t>&,
+                       const wifi_ring_buffer_status&)>;
+
+// Callback for alerts.
+using on_error_alert_callback =
+    std::function<void(int32_t, const std::vector<uint8_t>&)>;
+/**
+ * Class that encapsulates all legacy HAL interactions.
+ * This class manages the lifetime of the event loop thread used by legacy HAL.
+ *
+ * Note: aThere will only be a single instance of this class created in the Wifi
+ * object and will be valid for the lifetime of the process.
+ */
+class WifiLegacyHal {
+   public:
+    WifiLegacyHal();
+    virtual ~WifiLegacyHal() = default;
+
+    // Initialize the legacy HAL function table.
+    virtual wifi_error initialize();
+    // Start the legacy HAL and the event looper thread.
+    virtual wifi_error start();
+    // Deinitialize the legacy HAL and wait for the event loop thread to exit
+    // using a predefined timeout.
+    virtual 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(
+        const std::string& iface_name);
+    std::pair<wifi_error, std::string> getFirmwareVersion(
+        const std::string& iface_name);
+    std::pair<wifi_error, std::vector<uint8_t>> requestDriverMemoryDump(
+        const std::string& iface_name);
+    std::pair<wifi_error, std::vector<uint8_t>> requestFirmwareMemoryDump(
+        const std::string& iface_name);
+    std::pair<wifi_error, uint32_t> getSupportedFeatureSet(
+        const std::string& iface_name);
+    // APF functions.
+    std::pair<wifi_error, PacketFilterCapabilities> getPacketFilterCapabilities(
+        const std::string& iface_name);
+    wifi_error setPacketFilter(const std::string& iface_name,
+                               const std::vector<uint8_t>& program);
+    // Gscan functions.
+    std::pair<wifi_error, wifi_gscan_capabilities> getGscanCapabilities(
+        const std::string& iface_name);
+    // These API's provides a simplified interface over the legacy Gscan API's:
+    // a) All scan events from the legacy HAL API other than the
+    //    |WIFI_SCAN_FAILED| are treated as notification of results.
+    //    This method then retrieves the cached scan results from the legacy
+    //    HAL API and triggers the externally provided
+    //    |on_results_user_callback| on success.
+    // b) |WIFI_SCAN_FAILED| scan event or failure to retrieve cached scan
+    // results
+    //    triggers the externally provided |on_failure_user_callback|.
+    // c) Full scan result event triggers the externally provided
+    //    |on_full_result_user_callback|.
+    wifi_error startGscan(
+        const std::string& iface_name, wifi_request_id id,
+        const wifi_scan_cmd_params& params,
+        const std::function<void(wifi_request_id)>& on_failure_callback,
+        const on_gscan_results_callback& on_results_callback,
+        const on_gscan_full_result_callback& on_full_result_callback);
+    wifi_error stopGscan(const std::string& iface_name, wifi_request_id id);
+    std::pair<wifi_error, std::vector<uint32_t>> getValidFrequenciesForBand(
+        const std::string& iface_name, wifi_band band);
+    virtual wifi_error setDfsFlag(const std::string& iface_name, bool dfs_on);
+    // Link layer stats functions.
+    wifi_error enableLinkLayerStats(const std::string& iface_name, bool debug);
+    wifi_error disableLinkLayerStats(const std::string& iface_name);
+    std::pair<wifi_error, LinkLayerStats> getLinkLayerStats(
+        const std::string& iface_name);
+    // RSSI monitor functions.
+    wifi_error startRssiMonitoring(const std::string& iface_name,
+                                   wifi_request_id id, int8_t max_rssi,
+                                   int8_t min_rssi,
+                                   const on_rssi_threshold_breached_callback&
+                                       on_threshold_breached_callback);
+    wifi_error stopRssiMonitoring(const std::string& iface_name,
+                                  wifi_request_id id);
+    std::pair<wifi_error, wifi_roaming_capabilities> getRoamingCapabilities(
+        const std::string& iface_name);
+    wifi_error configureRoaming(const std::string& iface_name,
+                                const wifi_roaming_config& config);
+    wifi_error enableFirmwareRoaming(const std::string& iface_name,
+                                     fw_roaming_state_t state);
+    wifi_error configureNdOffload(const std::string& iface_name, bool enable);
+    wifi_error startSendingOffloadedPacket(
+        const std::string& iface_name, uint32_t cmd_id,
+        const std::vector<uint8_t>& ip_packet_data,
+        const std::array<uint8_t, 6>& src_address,
+        const std::array<uint8_t, 6>& dst_address, uint32_t period_in_ms);
+    wifi_error stopSendingOffloadedPacket(const std::string& iface_name,
+                                          uint32_t cmd_id);
+    wifi_error setScanningMacOui(const std::string& iface_name,
+                                 const std::array<uint8_t, 3>& oui);
+    wifi_error selectTxPowerScenario(const std::string& iface_name,
+                                     wifi_power_scenario scenario);
+    wifi_error resetTxPowerScenario(const std::string& iface_name);
+    // Logger/debug functions.
+    std::pair<wifi_error, uint32_t> getLoggerSupportedFeatureSet(
+        const std::string& iface_name);
+    wifi_error startPktFateMonitoring(const std::string& iface_name);
+    std::pair<wifi_error, std::vector<wifi_tx_report>> getTxPktFates(
+        const std::string& iface_name);
+    std::pair<wifi_error, std::vector<wifi_rx_report>> getRxPktFates(
+        const std::string& iface_name);
+    std::pair<wifi_error, WakeReasonStats> getWakeReasonStats(
+        const std::string& iface_name);
+    wifi_error registerRingBufferCallbackHandler(
+        const std::string& iface_name,
+        const on_ring_buffer_data_callback& on_data_callback);
+    wifi_error deregisterRingBufferCallbackHandler(
+        const std::string& iface_name);
+    std::pair<wifi_error, std::vector<wifi_ring_buffer_status>>
+    getRingBuffersStatus(const std::string& iface_name);
+    wifi_error startRingBufferLogging(const std::string& iface_name,
+                                      const std::string& ring_name,
+                                      uint32_t verbose_level,
+                                      uint32_t max_interval_sec,
+                                      uint32_t min_data_size);
+    wifi_error getRingBufferData(const std::string& iface_name,
+                                 const std::string& ring_name);
+    wifi_error registerErrorAlertCallbackHandler(
+        const std::string& iface_name,
+        const on_error_alert_callback& on_alert_callback);
+    wifi_error deregisterErrorAlertCallbackHandler(
+        const std::string& iface_name);
+    // RTT functions.
+    wifi_error startRttRangeRequest(
+        const std::string& iface_name, wifi_request_id id,
+        const std::vector<wifi_rtt_config>& rtt_configs,
+        const on_rtt_results_callback& on_results_callback);
+    wifi_error cancelRttRangeRequest(
+        const std::string& iface_name, wifi_request_id id,
+        const std::vector<std::array<uint8_t, 6>>& mac_addrs);
+    std::pair<wifi_error, wifi_rtt_capabilities> getRttCapabilities(
+        const std::string& iface_name);
+    std::pair<wifi_error, wifi_rtt_responder> getRttResponderInfo(
+        const std::string& iface_name);
+    wifi_error enableRttResponder(const std::string& iface_name,
+                                  wifi_request_id id,
+                                  const wifi_channel_info& channel_hint,
+                                  uint32_t max_duration_secs,
+                                  const wifi_rtt_responder& info);
+    wifi_error disableRttResponder(const std::string& iface_name,
+                                   wifi_request_id id);
+    wifi_error setRttLci(const std::string& iface_name, wifi_request_id id,
+                         const wifi_lci_information& info);
+    wifi_error setRttLcr(const std::string& iface_name, wifi_request_id id,
+                         const wifi_lcr_information& info);
+    // NAN functions.
+    virtual wifi_error nanRegisterCallbackHandlers(
+        const std::string& iface_name, const NanCallbackHandlers& callbacks);
+    wifi_error nanEnableRequest(const std::string& iface_name,
+                                transaction_id id, const NanEnableRequest& msg);
+    virtual wifi_error nanDisableRequest(const std::string& iface_name,
+                                         transaction_id id);
+    wifi_error nanPublishRequest(const std::string& iface_name,
+                                 transaction_id id,
+                                 const NanPublishRequest& msg);
+    wifi_error nanPublishCancelRequest(const std::string& iface_name,
+                                       transaction_id id,
+                                       const NanPublishCancelRequest& msg);
+    wifi_error nanSubscribeRequest(const std::string& iface_name,
+                                   transaction_id id,
+                                   const NanSubscribeRequest& msg);
+    wifi_error nanSubscribeCancelRequest(const std::string& iface_name,
+                                         transaction_id id,
+                                         const NanSubscribeCancelRequest& msg);
+    wifi_error nanTransmitFollowupRequest(
+        const std::string& iface_name, transaction_id id,
+        const NanTransmitFollowupRequest& msg);
+    wifi_error nanStatsRequest(const std::string& iface_name, transaction_id id,
+                               const NanStatsRequest& msg);
+    wifi_error nanConfigRequest(const std::string& iface_name,
+                                transaction_id id, const NanConfigRequest& msg);
+    wifi_error nanTcaRequest(const std::string& iface_name, transaction_id id,
+                             const NanTCARequest& msg);
+    wifi_error nanBeaconSdfPayloadRequest(
+        const std::string& iface_name, transaction_id id,
+        const NanBeaconSdfPayloadRequest& msg);
+    std::pair<wifi_error, NanVersion> nanGetVersion();
+    wifi_error nanGetCapabilities(const std::string& iface_name,
+                                  transaction_id id);
+    wifi_error nanDataInterfaceCreate(const std::string& iface_name,
+                                      transaction_id id,
+                                      const std::string& data_iface_name);
+    virtual wifi_error nanDataInterfaceDelete(
+        const std::string& iface_name, transaction_id id,
+        const std::string& data_iface_name);
+    wifi_error nanDataRequestInitiator(const std::string& iface_name,
+                                       transaction_id id,
+                                       const NanDataPathInitiatorRequest& msg);
+    wifi_error nanDataIndicationResponse(
+        const std::string& iface_name, transaction_id id,
+        const NanDataPathIndicationResponse& msg);
+    wifi_error nanDataEnd(const std::string& iface_name, transaction_id id,
+                          uint32_t ndpInstanceId);
+    // AP functions.
+    wifi_error setCountryCode(const std::string& iface_name,
+                              std::array<int8_t, 2> code);
+
+   private:
+    // Retrieve interface handles for all the available interfaces.
+    wifi_error retrieveIfaceHandles();
+    wifi_interface_handle getIfaceHandle(const std::string& iface_name);
+    // Run the legacy HAL event loop thread.
+    void runEventLoop();
+    // Retrieve the cached gscan results to pass the results back to the
+    // external callbacks.
+    std::pair<wifi_error, std::vector<wifi_cached_scan_results>>
+    getGscanCachedResults(const std::string& iface_name);
+    void invalidate();
+
+    // Global function table of legacy HAL.
+    wifi_hal_fn global_func_table_;
+    // Opaque handle to be used for all global operations.
+    wifi_handle global_handle_;
+    // Map of interface name to handle that is to be used for all interface
+    // specific operations.
+    std::map<std::string, wifi_interface_handle> iface_name_to_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_;
+};
+
+}  // namespace legacy_hal
+}  // namespace implementation
+}  // namespace V1_2
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
+
+#endif  // WIFI_LEGACY_HAL_H_
diff --git a/wifi/1.2/default/wifi_legacy_hal_stubs.cpp b/wifi/1.2/default/wifi_legacy_hal_stubs.cpp
new file mode 100644
index 0000000..28972cb
--- /dev/null
+++ b/wifi/1.2/default/wifi_legacy_hal_stubs.cpp
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "wifi_legacy_hal_stubs.h"
+
+// TODO: Remove these stubs from HalTool in libwifi-system.
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace V1_2 {
+namespace implementation {
+namespace legacy_hal {
+template <typename>
+struct stubFunction;
+
+template <typename R, typename... Args>
+struct stubFunction<R (*)(Args...)> {
+    static constexpr R invoke(Args...) { return WIFI_ERROR_NOT_SUPPORTED; }
+};
+template <typename... Args>
+struct stubFunction<void (*)(Args...)> {
+    static constexpr void invoke(Args...) {}
+};
+
+template <typename T>
+void populateStubFor(T* val) {
+    *val = &stubFunction<T>::invoke;
+}
+
+bool initHalFuncTableWithStubs(wifi_hal_fn* hal_fn) {
+    if (hal_fn == nullptr) {
+        return false;
+    }
+    populateStubFor(&hal_fn->wifi_initialize);
+    populateStubFor(&hal_fn->wifi_cleanup);
+    populateStubFor(&hal_fn->wifi_event_loop);
+    populateStubFor(&hal_fn->wifi_get_error_info);
+    populateStubFor(&hal_fn->wifi_get_supported_feature_set);
+    populateStubFor(&hal_fn->wifi_get_concurrency_matrix);
+    populateStubFor(&hal_fn->wifi_set_scanning_mac_oui);
+    populateStubFor(&hal_fn->wifi_get_supported_channels);
+    populateStubFor(&hal_fn->wifi_is_epr_supported);
+    populateStubFor(&hal_fn->wifi_get_ifaces);
+    populateStubFor(&hal_fn->wifi_get_iface_name);
+    populateStubFor(&hal_fn->wifi_set_iface_event_handler);
+    populateStubFor(&hal_fn->wifi_reset_iface_event_handler);
+    populateStubFor(&hal_fn->wifi_start_gscan);
+    populateStubFor(&hal_fn->wifi_stop_gscan);
+    populateStubFor(&hal_fn->wifi_get_cached_gscan_results);
+    populateStubFor(&hal_fn->wifi_set_bssid_hotlist);
+    populateStubFor(&hal_fn->wifi_reset_bssid_hotlist);
+    populateStubFor(&hal_fn->wifi_set_significant_change_handler);
+    populateStubFor(&hal_fn->wifi_reset_significant_change_handler);
+    populateStubFor(&hal_fn->wifi_get_gscan_capabilities);
+    populateStubFor(&hal_fn->wifi_set_link_stats);
+    populateStubFor(&hal_fn->wifi_get_link_stats);
+    populateStubFor(&hal_fn->wifi_clear_link_stats);
+    populateStubFor(&hal_fn->wifi_get_valid_channels);
+    populateStubFor(&hal_fn->wifi_rtt_range_request);
+    populateStubFor(&hal_fn->wifi_rtt_range_cancel);
+    populateStubFor(&hal_fn->wifi_get_rtt_capabilities);
+    populateStubFor(&hal_fn->wifi_rtt_get_responder_info);
+    populateStubFor(&hal_fn->wifi_enable_responder);
+    populateStubFor(&hal_fn->wifi_disable_responder);
+    populateStubFor(&hal_fn->wifi_set_nodfs_flag);
+    populateStubFor(&hal_fn->wifi_start_logging);
+    populateStubFor(&hal_fn->wifi_set_epno_list);
+    populateStubFor(&hal_fn->wifi_reset_epno_list);
+    populateStubFor(&hal_fn->wifi_set_country_code);
+    populateStubFor(&hal_fn->wifi_get_firmware_memory_dump);
+    populateStubFor(&hal_fn->wifi_set_log_handler);
+    populateStubFor(&hal_fn->wifi_reset_log_handler);
+    populateStubFor(&hal_fn->wifi_set_alert_handler);
+    populateStubFor(&hal_fn->wifi_reset_alert_handler);
+    populateStubFor(&hal_fn->wifi_get_firmware_version);
+    populateStubFor(&hal_fn->wifi_get_ring_buffers_status);
+    populateStubFor(&hal_fn->wifi_get_logger_supported_feature_set);
+    populateStubFor(&hal_fn->wifi_get_ring_data);
+    populateStubFor(&hal_fn->wifi_enable_tdls);
+    populateStubFor(&hal_fn->wifi_disable_tdls);
+    populateStubFor(&hal_fn->wifi_get_tdls_status);
+    populateStubFor(&hal_fn->wifi_get_tdls_capabilities);
+    populateStubFor(&hal_fn->wifi_get_driver_version);
+    populateStubFor(&hal_fn->wifi_set_passpoint_list);
+    populateStubFor(&hal_fn->wifi_reset_passpoint_list);
+    populateStubFor(&hal_fn->wifi_set_lci);
+    populateStubFor(&hal_fn->wifi_set_lcr);
+    populateStubFor(&hal_fn->wifi_start_sending_offloaded_packet);
+    populateStubFor(&hal_fn->wifi_stop_sending_offloaded_packet);
+    populateStubFor(&hal_fn->wifi_start_rssi_monitoring);
+    populateStubFor(&hal_fn->wifi_stop_rssi_monitoring);
+    populateStubFor(&hal_fn->wifi_get_wake_reason_stats);
+    populateStubFor(&hal_fn->wifi_configure_nd_offload);
+    populateStubFor(&hal_fn->wifi_get_driver_memory_dump);
+    populateStubFor(&hal_fn->wifi_start_pkt_fate_monitoring);
+    populateStubFor(&hal_fn->wifi_get_tx_pkt_fates);
+    populateStubFor(&hal_fn->wifi_get_rx_pkt_fates);
+    populateStubFor(&hal_fn->wifi_nan_enable_request);
+    populateStubFor(&hal_fn->wifi_nan_disable_request);
+    populateStubFor(&hal_fn->wifi_nan_publish_request);
+    populateStubFor(&hal_fn->wifi_nan_publish_cancel_request);
+    populateStubFor(&hal_fn->wifi_nan_subscribe_request);
+    populateStubFor(&hal_fn->wifi_nan_subscribe_cancel_request);
+    populateStubFor(&hal_fn->wifi_nan_transmit_followup_request);
+    populateStubFor(&hal_fn->wifi_nan_stats_request);
+    populateStubFor(&hal_fn->wifi_nan_config_request);
+    populateStubFor(&hal_fn->wifi_nan_tca_request);
+    populateStubFor(&hal_fn->wifi_nan_beacon_sdf_payload_request);
+    populateStubFor(&hal_fn->wifi_nan_register_handler);
+    populateStubFor(&hal_fn->wifi_nan_get_version);
+    populateStubFor(&hal_fn->wifi_nan_get_capabilities);
+    populateStubFor(&hal_fn->wifi_nan_data_interface_create);
+    populateStubFor(&hal_fn->wifi_nan_data_interface_delete);
+    populateStubFor(&hal_fn->wifi_nan_data_request_initiator);
+    populateStubFor(&hal_fn->wifi_nan_data_indication_response);
+    populateStubFor(&hal_fn->wifi_nan_data_end);
+    populateStubFor(&hal_fn->wifi_get_packet_filter_capabilities);
+    populateStubFor(&hal_fn->wifi_set_packet_filter);
+    populateStubFor(&hal_fn->wifi_get_roaming_capabilities);
+    populateStubFor(&hal_fn->wifi_enable_firmware_roaming);
+    populateStubFor(&hal_fn->wifi_configure_roaming);
+    populateStubFor(&hal_fn->wifi_select_tx_power_scenario);
+    populateStubFor(&hal_fn->wifi_reset_tx_power_scenario);
+    return true;
+}
+}  // namespace legacy_hal
+}  // namespace implementation
+}  // namespace V1_2
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
diff --git a/wifi/1.1/default/wifi_legacy_hal_stubs.h b/wifi/1.2/default/wifi_legacy_hal_stubs.h
similarity index 96%
rename from wifi/1.1/default/wifi_legacy_hal_stubs.h
rename to wifi/1.2/default/wifi_legacy_hal_stubs.h
index bfc4c9b..d560dd4 100644
--- a/wifi/1.1/default/wifi_legacy_hal_stubs.h
+++ b/wifi/1.2/default/wifi_legacy_hal_stubs.h
@@ -20,7 +20,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_1 {
+namespace V1_2 {
 namespace implementation {
 namespace legacy_hal {
 #include <hardware_legacy/wifi_hal.h>
@@ -28,7 +28,7 @@
 bool initHalFuncTableWithStubs(wifi_hal_fn* hal_fn);
 }  // namespace legacy_hal
 }  // namespace implementation
-}  // namespace V1_1
+}  // namespace V1_2
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.2/default/wifi_mode_controller.cpp b/wifi/1.2/default/wifi_mode_controller.cpp
new file mode 100644
index 0000000..c286d24
--- /dev/null
+++ b/wifi/1.2/default/wifi_mode_controller.cpp
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+#include <android-base/macros.h>
+#include <private/android_filesystem_config.h>
+
+#include "wifi_mode_controller.h"
+
+using android::hardware::wifi::V1_0::IfaceType;
+using android::wifi_hal::DriverTool;
+
+namespace {
+int convertIfaceTypeToFirmwareMode(IfaceType type) {
+    int mode;
+    switch (type) {
+        case IfaceType::AP:
+            mode = DriverTool::kFirmwareModeAp;
+            break;
+        case IfaceType::P2P:
+            mode = DriverTool::kFirmwareModeP2p;
+            break;
+        case IfaceType::NAN:
+            // NAN is exposed in STA mode currently.
+            mode = DriverTool::kFirmwareModeSta;
+            break;
+        case IfaceType::STA:
+            mode = DriverTool::kFirmwareModeSta;
+            break;
+    }
+    return mode;
+}
+}  // namespace
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace V1_2 {
+namespace implementation {
+namespace mode_controller {
+
+WifiModeController::WifiModeController() : driver_tool_(new DriverTool) {}
+
+bool WifiModeController::isFirmwareModeChangeNeeded(IfaceType type) {
+    return driver_tool_->IsFirmwareModeChangeNeeded(
+        convertIfaceTypeToFirmwareMode(type));
+}
+
+bool WifiModeController::initialize() {
+    if (!driver_tool_->LoadDriver()) {
+        LOG(ERROR) << "Failed to load WiFi driver";
+        return false;
+    }
+    return true;
+}
+
+bool WifiModeController::changeFirmwareMode(IfaceType type) {
+    if (!driver_tool_->ChangeFirmwareMode(
+            convertIfaceTypeToFirmwareMode(type))) {
+        LOG(ERROR) << "Failed to change firmware mode";
+        return false;
+    }
+    return true;
+}
+
+bool WifiModeController::deinitialize() {
+    if (!driver_tool_->UnloadDriver()) {
+        LOG(ERROR) << "Failed to unload WiFi driver";
+        return false;
+    }
+    return true;
+}
+}  // namespace mode_controller
+}  // namespace implementation
+}  // namespace V1_2
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
diff --git a/wifi/1.1/default/wifi_mode_controller.h b/wifi/1.2/default/wifi_mode_controller.h
similarity index 67%
rename from wifi/1.1/default/wifi_mode_controller.h
rename to wifi/1.2/default/wifi_mode_controller.h
index 6984509..395aa5d 100644
--- a/wifi/1.1/default/wifi_mode_controller.h
+++ b/wifi/1.2/default/wifi_mode_controller.h
@@ -24,7 +24,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_1 {
+namespace V1_2 {
 namespace implementation {
 namespace mode_controller {
 using namespace android::hardware::wifi::V1_0;
@@ -35,25 +35,27 @@
  * required state (essentially a wrapper over DriverTool).
  */
 class WifiModeController {
- public:
-  WifiModeController();
+   public:
+    WifiModeController();
+    virtual ~WifiModeController() = default;
 
-  // Checks if a firmware mode change is necessary to support the specified
-  // iface type operations.
-  bool isFirmwareModeChangeNeeded(IfaceType type);
-  // Change the firmware mode to support the specified iface type operations.
-  bool changeFirmwareMode(IfaceType type);
-  // Unload the driver. This should be invoked whenever |IWifi.stop()| is
-  // invoked.
-  bool deinitialize();
+    // Checks if a firmware mode change is necessary to support the specified
+    // iface type operations.
+    virtual bool isFirmwareModeChangeNeeded(IfaceType type);
+    virtual bool initialize();
+    // Change the firmware mode to support the specified iface type operations.
+    virtual bool changeFirmwareMode(IfaceType type);
+    // Unload the driver. This should be invoked whenever |IWifi.stop()| is
+    // invoked.
+    virtual bool deinitialize();
 
- private:
-  std::unique_ptr<wifi_hal::DriverTool> driver_tool_;
+   private:
+    std::unique_ptr<wifi_hal::DriverTool> driver_tool_;
 };
 
 }  // namespace mode_controller
 }  // namespace implementation
-}  // namespace V1_1
+}  // namespace V1_2
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.2/default/wifi_nan_iface.cpp b/wifi/1.2/default/wifi_nan_iface.cpp
new file mode 100644
index 0000000..12e4d7b
--- /dev/null
+++ b/wifi/1.2/default/wifi_nan_iface.cpp
@@ -0,0 +1,787 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+
+#include "hidl_return_util.h"
+#include "hidl_struct_util.h"
+#include "wifi_nan_iface.h"
+#include "wifi_status_util.h"
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace V1_2 {
+namespace implementation {
+using hidl_return_util::validateAndCall;
+
+WifiNanIface::WifiNanIface(
+    const std::string& ifname,
+    const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal)
+    : ifname_(ifname), legacy_hal_(legacy_hal), is_valid_(true) {
+    // Register all the callbacks here. these should be valid for the lifetime
+    // of the object. Whenever the mode changes legacy HAL will remove
+    // all of these callbacks.
+    legacy_hal::NanCallbackHandlers callback_handlers;
+    android::wp<WifiNanIface> weak_ptr_this(this);
+
+    // Callback for response.
+    callback_handlers
+        .on_notify_response = [weak_ptr_this](
+                                  legacy_hal::transaction_id id,
+                                  const legacy_hal::NanResponseMsg& msg) {
+        const auto shared_ptr_this = weak_ptr_this.promote();
+        if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+            LOG(ERROR) << "Callback invoked on an invalid object";
+            return;
+        }
+        WifiNanStatus wifiNanStatus;
+        if (!hidl_struct_util::convertLegacyNanResponseHeaderToHidl(
+                msg, &wifiNanStatus)) {
+            LOG(ERROR) << "Failed to convert nan response header";
+            return;
+        }
+
+        switch (msg.response_type) {
+            case legacy_hal::NAN_RESPONSE_ENABLED: {
+                for (const auto& callback :
+                     shared_ptr_this->getEventCallbacks()) {
+                    if (!callback->notifyEnableResponse(id, wifiNanStatus)
+                             .isOk()) {
+                        LOG(ERROR) << "Failed to invoke the callback";
+                    }
+                }
+                break;
+            }
+            case legacy_hal::NAN_RESPONSE_DISABLED: {
+                for (const auto& callback :
+                     shared_ptr_this->getEventCallbacks()) {
+                    if (!callback->notifyDisableResponse(id, wifiNanStatus)
+                             .isOk()) {
+                        LOG(ERROR) << "Failed to invoke the callback";
+                    }
+                }
+                break;
+            }
+            case legacy_hal::NAN_RESPONSE_PUBLISH: {
+                for (const auto& callback :
+                     shared_ptr_this->getEventCallbacks()) {
+                    if (!callback
+                             ->notifyStartPublishResponse(
+                                 id, wifiNanStatus,
+                                 msg.body.publish_response.publish_id)
+                             .isOk()) {
+                        LOG(ERROR) << "Failed to invoke the callback";
+                    }
+                }
+                break;
+            }
+            case legacy_hal::NAN_RESPONSE_PUBLISH_CANCEL: {
+                for (const auto& callback :
+                     shared_ptr_this->getEventCallbacks()) {
+                    if (!callback->notifyStopPublishResponse(id, wifiNanStatus)
+                             .isOk()) {
+                        LOG(ERROR) << "Failed to invoke the callback";
+                    }
+                }
+                break;
+            }
+            case legacy_hal::NAN_RESPONSE_TRANSMIT_FOLLOWUP: {
+                for (const auto& callback :
+                     shared_ptr_this->getEventCallbacks()) {
+                    if (!callback
+                             ->notifyTransmitFollowupResponse(id, wifiNanStatus)
+                             .isOk()) {
+                        LOG(ERROR) << "Failed to invoke the callback";
+                    }
+                }
+                break;
+            }
+            case legacy_hal::NAN_RESPONSE_SUBSCRIBE: {
+                for (const auto& callback :
+                     shared_ptr_this->getEventCallbacks()) {
+                    if (!callback
+                             ->notifyStartSubscribeResponse(
+                                 id, wifiNanStatus,
+                                 msg.body.subscribe_response.subscribe_id)
+                             .isOk()) {
+                        LOG(ERROR) << "Failed to invoke the callback";
+                    }
+                }
+                break;
+            }
+            case legacy_hal::NAN_RESPONSE_SUBSCRIBE_CANCEL: {
+                for (const auto& callback :
+                     shared_ptr_this->getEventCallbacks()) {
+                    if (!callback
+                             ->notifyStopSubscribeResponse(id, wifiNanStatus)
+                             .isOk()) {
+                        LOG(ERROR) << "Failed to invoke the callback";
+                    }
+                }
+                break;
+            }
+            case legacy_hal::NAN_RESPONSE_CONFIG: {
+                for (const auto& callback :
+                     shared_ptr_this->getEventCallbacks()) {
+                    if (!callback->notifyConfigResponse(id, wifiNanStatus)
+                             .isOk()) {
+                        LOG(ERROR) << "Failed to invoke the callback";
+                    }
+                }
+                break;
+            }
+            case legacy_hal::NAN_GET_CAPABILITIES: {
+                NanCapabilities hidl_struct;
+                if (!hidl_struct_util::
+                        convertLegacyNanCapabilitiesResponseToHidl(
+                            msg.body.nan_capabilities, &hidl_struct)) {
+                    LOG(ERROR) << "Failed to convert nan capabilities response";
+                    return;
+                }
+                for (const auto& callback :
+                     shared_ptr_this->getEventCallbacks()) {
+                    if (!callback
+                             ->notifyCapabilitiesResponse(id, wifiNanStatus,
+                                                          hidl_struct)
+                             .isOk()) {
+                        LOG(ERROR) << "Failed to invoke the callback";
+                    }
+                }
+                break;
+            }
+            case legacy_hal::NAN_DP_INTERFACE_CREATE: {
+                for (const auto& callback :
+                     shared_ptr_this->getEventCallbacks()) {
+                    if (!callback
+                             ->notifyCreateDataInterfaceResponse(id,
+                                                                 wifiNanStatus)
+                             .isOk()) {
+                        LOG(ERROR) << "Failed to invoke the callback";
+                    }
+                }
+                break;
+            }
+            case legacy_hal::NAN_DP_INTERFACE_DELETE: {
+                for (const auto& callback :
+                     shared_ptr_this->getEventCallbacks()) {
+                    if (!callback
+                             ->notifyDeleteDataInterfaceResponse(id,
+                                                                 wifiNanStatus)
+                             .isOk()) {
+                        LOG(ERROR) << "Failed to invoke the callback";
+                    }
+                }
+                break;
+            }
+            case legacy_hal::NAN_DP_INITIATOR_RESPONSE: {
+                for (const auto& callback :
+                     shared_ptr_this->getEventCallbacks()) {
+                    if (!callback
+                             ->notifyInitiateDataPathResponse(
+                                 id, wifiNanStatus,
+                                 msg.body.data_request_response.ndp_instance_id)
+                             .isOk()) {
+                        LOG(ERROR) << "Failed to invoke the callback";
+                    }
+                }
+                break;
+            }
+            case legacy_hal::NAN_DP_RESPONDER_RESPONSE: {
+                for (const auto& callback :
+                     shared_ptr_this->getEventCallbacks()) {
+                    if (!callback
+                             ->notifyRespondToDataPathIndicationResponse(
+                                 id, wifiNanStatus)
+                             .isOk()) {
+                        LOG(ERROR) << "Failed to invoke the callback";
+                    }
+                }
+                break;
+            }
+            case legacy_hal::NAN_DP_END: {
+                for (const auto& callback :
+                     shared_ptr_this->getEventCallbacks()) {
+                    if (!callback
+                             ->notifyTerminateDataPathResponse(id,
+                                                               wifiNanStatus)
+                             .isOk()) {
+                        LOG(ERROR) << "Failed to invoke the callback";
+                    }
+                }
+                break;
+            }
+            case legacy_hal::NAN_RESPONSE_BEACON_SDF_PAYLOAD:
+            /* fall through */
+            case legacy_hal::NAN_RESPONSE_TCA:
+            /* fall through */
+            case legacy_hal::NAN_RESPONSE_STATS:
+            /* fall through */
+            case legacy_hal::NAN_RESPONSE_ERROR:
+            /* fall through */
+            default:
+                LOG(ERROR) << "Unknown or unhandled response type: "
+                           << msg.response_type;
+                return;
+        }
+    };
+
+    callback_handlers.on_event_disc_eng_event =
+        [weak_ptr_this](const legacy_hal::NanDiscEngEventInd& msg) {
+            const auto shared_ptr_this = weak_ptr_this.promote();
+            if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+                LOG(ERROR) << "Callback invoked on an invalid object";
+                return;
+            }
+            NanClusterEventInd hidl_struct;
+            // event types defined identically - hence can be cast
+            hidl_struct.eventType = (NanClusterEventType)msg.event_type;
+            hidl_struct.addr = msg.data.mac_addr.addr;
+
+            for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+                if (!callback->eventClusterEvent(hidl_struct).isOk()) {
+                    LOG(ERROR) << "Failed to invoke the callback";
+                }
+            }
+        };
+
+    callback_handlers.on_event_disabled =
+        [weak_ptr_this](const legacy_hal::NanDisabledInd& msg) {
+            const auto shared_ptr_this = weak_ptr_this.promote();
+            if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+                LOG(ERROR) << "Callback invoked on an invalid object";
+                return;
+            }
+            WifiNanStatus status;
+            hidl_struct_util::convertToWifiNanStatus(
+                msg.reason, msg.nan_reason, sizeof(msg.nan_reason), &status);
+
+            for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+                if (!callback->eventDisabled(status).isOk()) {
+                    LOG(ERROR) << "Failed to invoke the callback";
+                }
+            }
+        };
+
+    callback_handlers.on_event_publish_terminated =
+        [weak_ptr_this](const legacy_hal::NanPublishTerminatedInd& msg) {
+            const auto shared_ptr_this = weak_ptr_this.promote();
+            if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+                LOG(ERROR) << "Callback invoked on an invalid object";
+                return;
+            }
+            WifiNanStatus status;
+            hidl_struct_util::convertToWifiNanStatus(
+                msg.reason, msg.nan_reason, sizeof(msg.nan_reason), &status);
+
+            for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+                if (!callback->eventPublishTerminated(msg.publish_id, status)
+                         .isOk()) {
+                    LOG(ERROR) << "Failed to invoke the callback";
+                }
+            }
+        };
+
+    callback_handlers.on_event_subscribe_terminated =
+        [weak_ptr_this](const legacy_hal::NanSubscribeTerminatedInd& msg) {
+            const auto shared_ptr_this = weak_ptr_this.promote();
+            if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+                LOG(ERROR) << "Callback invoked on an invalid object";
+                return;
+            }
+            WifiNanStatus status;
+            hidl_struct_util::convertToWifiNanStatus(
+                msg.reason, msg.nan_reason, sizeof(msg.nan_reason), &status);
+
+            for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+                if (!callback
+                         ->eventSubscribeTerminated(msg.subscribe_id, status)
+                         .isOk()) {
+                    LOG(ERROR) << "Failed to invoke the callback";
+                }
+            }
+        };
+
+    callback_handlers.on_event_match =
+        [weak_ptr_this](const legacy_hal::NanMatchInd& msg) {
+            const auto shared_ptr_this = weak_ptr_this.promote();
+            if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+                LOG(ERROR) << "Callback invoked on an invalid object";
+                return;
+            }
+            NanMatchInd hidl_struct;
+            if (!hidl_struct_util::convertLegacyNanMatchIndToHidl(
+                    msg, &hidl_struct)) {
+                LOG(ERROR) << "Failed to convert nan capabilities response";
+                return;
+            }
+
+            for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+                if (!callback->eventMatch(hidl_struct).isOk()) {
+                    LOG(ERROR) << "Failed to invoke the callback";
+                }
+            }
+        };
+
+    callback_handlers.on_event_match_expired =
+        [weak_ptr_this](const legacy_hal::NanMatchExpiredInd& msg) {
+            const auto shared_ptr_this = weak_ptr_this.promote();
+            if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+                LOG(ERROR) << "Callback invoked on an invalid object";
+                return;
+            }
+            for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+                if (!callback
+                         ->eventMatchExpired(msg.publish_subscribe_id,
+                                             msg.requestor_instance_id)
+                         .isOk()) {
+                    LOG(ERROR) << "Failed to invoke the callback";
+                }
+            }
+        };
+
+    callback_handlers.on_event_followup =
+        [weak_ptr_this](const legacy_hal::NanFollowupInd& msg) {
+            const auto shared_ptr_this = weak_ptr_this.promote();
+            if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+                LOG(ERROR) << "Callback invoked on an invalid object";
+                return;
+            }
+            NanFollowupReceivedInd hidl_struct;
+            if (!hidl_struct_util::convertLegacyNanFollowupIndToHidl(
+                    msg, &hidl_struct)) {
+                LOG(ERROR) << "Failed to convert nan capabilities response";
+                return;
+            }
+
+            for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+                if (!callback->eventFollowupReceived(hidl_struct).isOk()) {
+                    LOG(ERROR) << "Failed to invoke the callback";
+                }
+            }
+        };
+
+    callback_handlers.on_event_transmit_follow_up =
+        [weak_ptr_this](const legacy_hal::NanTransmitFollowupInd& msg) {
+            const auto shared_ptr_this = weak_ptr_this.promote();
+            if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+                LOG(ERROR) << "Callback invoked on an invalid object";
+                return;
+            }
+            WifiNanStatus status;
+            hidl_struct_util::convertToWifiNanStatus(
+                msg.reason, msg.nan_reason, sizeof(msg.nan_reason), &status);
+
+            for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+                if (!callback->eventTransmitFollowup(msg.id, status).isOk()) {
+                    LOG(ERROR) << "Failed to invoke the callback";
+                }
+            }
+        };
+
+    callback_handlers.on_event_data_path_request =
+        [weak_ptr_this](const legacy_hal::NanDataPathRequestInd& msg) {
+            const auto shared_ptr_this = weak_ptr_this.promote();
+            if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+                LOG(ERROR) << "Callback invoked on an invalid object";
+                return;
+            }
+            NanDataPathRequestInd hidl_struct;
+            if (!hidl_struct_util::convertLegacyNanDataPathRequestIndToHidl(
+                    msg, &hidl_struct)) {
+                LOG(ERROR) << "Failed to convert nan capabilities response";
+                return;
+            }
+
+            for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+                if (!callback->eventDataPathRequest(hidl_struct).isOk()) {
+                    LOG(ERROR) << "Failed to invoke the callback";
+                }
+            }
+        };
+
+    callback_handlers.on_event_data_path_confirm =
+        [weak_ptr_this](const legacy_hal::NanDataPathConfirmInd& msg) {
+            const auto shared_ptr_this = weak_ptr_this.promote();
+            if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+                LOG(ERROR) << "Callback invoked on an invalid object";
+                return;
+            }
+            NanDataPathConfirmInd hidl_struct;
+            if (!hidl_struct_util::convertLegacyNanDataPathConfirmIndToHidl(
+                    msg, &hidl_struct)) {
+                LOG(ERROR) << "Failed to convert nan capabilities response";
+                return;
+            }
+
+            for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+                if (!callback->eventDataPathConfirm(hidl_struct).isOk()) {
+                    LOG(ERROR) << "Failed to invoke the callback";
+                }
+            }
+        };
+
+    callback_handlers.on_event_data_path_end =
+        [weak_ptr_this](const legacy_hal::NanDataPathEndInd& msg) {
+            const auto shared_ptr_this = weak_ptr_this.promote();
+            if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+                LOG(ERROR) << "Callback invoked on an invalid object";
+                return;
+            }
+            for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+                for (int i = 0; i < msg.num_ndp_instances; ++i) {
+                    if (!callback
+                             ->eventDataPathTerminated(msg.ndp_instance_id[i])
+                             .isOk()) {
+                        LOG(ERROR) << "Failed to invoke the callback";
+                    }
+                }
+            }
+        };
+
+    callback_handlers.on_event_beacon_sdf_payload =
+        [weak_ptr_this](const legacy_hal::NanBeaconSdfPayloadInd& /* msg */) {
+            LOG(ERROR) << "on_event_beacon_sdf_payload - should not be called";
+        };
+
+    callback_handlers.on_event_range_request =
+        [weak_ptr_this](const legacy_hal::NanRangeRequestInd& /* msg */) {
+            LOG(ERROR) << "on_event_range_request - should not be called";
+        };
+
+    callback_handlers.on_event_range_report =
+        [weak_ptr_this](const legacy_hal::NanRangeReportInd& /* msg */) {
+            LOG(ERROR) << "on_event_range_report - should not be called";
+        };
+
+    callback_handlers.on_event_schedule_update =
+        [weak_ptr_this](const legacy_hal::NanDataPathScheduleUpdateInd& /* msg */) {
+            LOG(ERROR) << "on_event_schedule_update - should not be called";
+        };
+
+    legacy_hal::wifi_error legacy_status =
+        legacy_hal_.lock()->nanRegisterCallbackHandlers(ifname_,
+                                                        callback_handlers);
+    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+        LOG(ERROR) << "Failed to register nan callbacks. Invalidating object";
+        invalidate();
+    }
+}
+
+void WifiNanIface::invalidate() {
+    // send commands to HAL to actually disable and destroy interfaces
+    legacy_hal_.lock()->nanDisableRequest(ifname_, 0xFFFF);
+    legacy_hal_.lock()->nanDataInterfaceDelete(ifname_, 0xFFFE, "aware_data0");
+    legacy_hal_.lock()->nanDataInterfaceDelete(ifname_, 0xFFFD, "aware_data1");
+
+    legacy_hal_.reset();
+    event_cb_handler_.invalidate();
+    is_valid_ = false;
+}
+
+bool WifiNanIface::isValid() { return is_valid_; }
+
+std::string WifiNanIface::getName() { return ifname_; }
+
+std::set<sp<IWifiNanIfaceEventCallback>> WifiNanIface::getEventCallbacks() {
+    return event_cb_handler_.getCallbacks();
+}
+
+Return<void> WifiNanIface::getName(getName_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiNanIface::getNameInternal, hidl_status_cb);
+}
+
+Return<void> WifiNanIface::getType(getType_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiNanIface::getTypeInternal, hidl_status_cb);
+}
+
+Return<void> WifiNanIface::registerEventCallback(
+    const sp<IWifiNanIfaceEventCallback>& callback,
+    registerEventCallback_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiNanIface::registerEventCallbackInternal,
+                           hidl_status_cb, callback);
+}
+
+Return<void> WifiNanIface::getCapabilitiesRequest(
+    uint16_t cmd_id, getCapabilitiesRequest_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiNanIface::getCapabilitiesRequestInternal,
+                           hidl_status_cb, cmd_id);
+}
+
+Return<void> WifiNanIface::enableRequest(uint16_t cmd_id,
+                                         const NanEnableRequest& msg,
+                                         enableRequest_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiNanIface::enableRequestInternal, hidl_status_cb,
+                           cmd_id, msg);
+}
+
+Return<void> WifiNanIface::configRequest(uint16_t cmd_id,
+                                         const NanConfigRequest& msg,
+                                         configRequest_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiNanIface::configRequestInternal, hidl_status_cb,
+                           cmd_id, msg);
+}
+
+Return<void> WifiNanIface::disableRequest(uint16_t cmd_id,
+                                          disableRequest_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiNanIface::disableRequestInternal,
+                           hidl_status_cb, cmd_id);
+}
+
+Return<void> WifiNanIface::startPublishRequest(
+    uint16_t cmd_id, const NanPublishRequest& msg,
+    startPublishRequest_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiNanIface::startPublishRequestInternal,
+                           hidl_status_cb, cmd_id, msg);
+}
+
+Return<void> WifiNanIface::stopPublishRequest(
+    uint16_t cmd_id, uint8_t sessionId, stopPublishRequest_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiNanIface::stopPublishRequestInternal,
+                           hidl_status_cb, cmd_id, sessionId);
+}
+
+Return<void> WifiNanIface::startSubscribeRequest(
+    uint16_t cmd_id, const NanSubscribeRequest& msg,
+    startSubscribeRequest_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiNanIface::startSubscribeRequestInternal,
+                           hidl_status_cb, cmd_id, msg);
+}
+
+Return<void> WifiNanIface::stopSubscribeRequest(
+    uint16_t cmd_id, uint8_t sessionId,
+    stopSubscribeRequest_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiNanIface::stopSubscribeRequestInternal,
+                           hidl_status_cb, cmd_id, sessionId);
+}
+
+Return<void> WifiNanIface::transmitFollowupRequest(
+    uint16_t cmd_id, const NanTransmitFollowupRequest& msg,
+    transmitFollowupRequest_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiNanIface::transmitFollowupRequestInternal,
+                           hidl_status_cb, cmd_id, msg);
+}
+
+Return<void> WifiNanIface::createDataInterfaceRequest(
+    uint16_t cmd_id, const hidl_string& iface_name,
+    createDataInterfaceRequest_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiNanIface::createDataInterfaceRequestInternal,
+                           hidl_status_cb, cmd_id, iface_name);
+}
+
+Return<void> WifiNanIface::deleteDataInterfaceRequest(
+    uint16_t cmd_id, const hidl_string& iface_name,
+    deleteDataInterfaceRequest_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiNanIface::deleteDataInterfaceRequestInternal,
+                           hidl_status_cb, cmd_id, iface_name);
+}
+
+Return<void> WifiNanIface::initiateDataPathRequest(
+    uint16_t cmd_id, const NanInitiateDataPathRequest& msg,
+    initiateDataPathRequest_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiNanIface::initiateDataPathRequestInternal,
+                           hidl_status_cb, cmd_id, msg);
+}
+
+Return<void> WifiNanIface::respondToDataPathIndicationRequest(
+    uint16_t cmd_id, const NanRespondToDataPathIndicationRequest& msg,
+    respondToDataPathIndicationRequest_cb hidl_status_cb) {
+    return validateAndCall(
+        this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+        &WifiNanIface::respondToDataPathIndicationRequestInternal,
+        hidl_status_cb, cmd_id, msg);
+}
+
+Return<void> WifiNanIface::terminateDataPathRequest(
+    uint16_t cmd_id, uint32_t ndpInstanceId,
+    terminateDataPathRequest_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiNanIface::terminateDataPathRequestInternal,
+                           hidl_status_cb, cmd_id, ndpInstanceId);
+}
+
+std::pair<WifiStatus, std::string> WifiNanIface::getNameInternal() {
+    return {createWifiStatus(WifiStatusCode::SUCCESS), ifname_};
+}
+
+std::pair<WifiStatus, IfaceType> WifiNanIface::getTypeInternal() {
+    return {createWifiStatus(WifiStatusCode::SUCCESS), IfaceType::NAN};
+}
+
+WifiStatus WifiNanIface::registerEventCallbackInternal(
+    const sp<IWifiNanIfaceEventCallback>& callback) {
+    if (!event_cb_handler_.addCallback(callback)) {
+        return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
+    }
+    return createWifiStatus(WifiStatusCode::SUCCESS);
+}
+
+WifiStatus WifiNanIface::getCapabilitiesRequestInternal(uint16_t cmd_id) {
+    legacy_hal::wifi_error legacy_status =
+        legacy_hal_.lock()->nanGetCapabilities(ifname_, cmd_id);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+WifiStatus WifiNanIface::enableRequestInternal(uint16_t cmd_id,
+                                               const NanEnableRequest& msg) {
+    legacy_hal::NanEnableRequest legacy_msg;
+    if (!hidl_struct_util::convertHidlNanEnableRequestToLegacy(msg,
+                                                               &legacy_msg)) {
+        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+    }
+    legacy_hal::wifi_error legacy_status =
+        legacy_hal_.lock()->nanEnableRequest(ifname_, cmd_id, legacy_msg);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+WifiStatus WifiNanIface::configRequestInternal(uint16_t cmd_id,
+                                               const NanConfigRequest& msg) {
+    legacy_hal::NanConfigRequest legacy_msg;
+    if (!hidl_struct_util::convertHidlNanConfigRequestToLegacy(msg,
+                                                               &legacy_msg)) {
+        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+    }
+    legacy_hal::wifi_error legacy_status =
+        legacy_hal_.lock()->nanConfigRequest(ifname_, cmd_id, legacy_msg);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+WifiStatus WifiNanIface::disableRequestInternal(uint16_t cmd_id) {
+    legacy_hal::wifi_error legacy_status =
+        legacy_hal_.lock()->nanDisableRequest(ifname_, cmd_id);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+WifiStatus WifiNanIface::startPublishRequestInternal(
+    uint16_t cmd_id, const NanPublishRequest& msg) {
+    legacy_hal::NanPublishRequest legacy_msg;
+    if (!hidl_struct_util::convertHidlNanPublishRequestToLegacy(msg,
+                                                                &legacy_msg)) {
+        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+    }
+    legacy_hal::wifi_error legacy_status =
+        legacy_hal_.lock()->nanPublishRequest(ifname_, cmd_id, legacy_msg);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+WifiStatus WifiNanIface::stopPublishRequestInternal(uint16_t cmd_id,
+                                                    uint8_t sessionId) {
+    legacy_hal::NanPublishCancelRequest legacy_msg;
+    legacy_msg.publish_id = sessionId;
+    legacy_hal::wifi_error legacy_status =
+        legacy_hal_.lock()->nanPublishCancelRequest(ifname_, cmd_id,
+                                                    legacy_msg);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+WifiStatus WifiNanIface::startSubscribeRequestInternal(
+    uint16_t cmd_id, const NanSubscribeRequest& msg) {
+    legacy_hal::NanSubscribeRequest legacy_msg;
+    if (!hidl_struct_util::convertHidlNanSubscribeRequestToLegacy(
+            msg, &legacy_msg)) {
+        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+    }
+    legacy_hal::wifi_error legacy_status =
+        legacy_hal_.lock()->nanSubscribeRequest(ifname_, cmd_id, legacy_msg);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+WifiStatus WifiNanIface::stopSubscribeRequestInternal(uint16_t cmd_id,
+                                                      uint8_t sessionId) {
+    legacy_hal::NanSubscribeCancelRequest legacy_msg;
+    legacy_msg.subscribe_id = sessionId;
+    legacy_hal::wifi_error legacy_status =
+        legacy_hal_.lock()->nanSubscribeCancelRequest(ifname_, cmd_id,
+                                                      legacy_msg);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+WifiStatus WifiNanIface::transmitFollowupRequestInternal(
+    uint16_t cmd_id, const NanTransmitFollowupRequest& msg) {
+    legacy_hal::NanTransmitFollowupRequest legacy_msg;
+    if (!hidl_struct_util::convertHidlNanTransmitFollowupRequestToLegacy(
+            msg, &legacy_msg)) {
+        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+    }
+    legacy_hal::wifi_error legacy_status =
+        legacy_hal_.lock()->nanTransmitFollowupRequest(ifname_, cmd_id,
+                                                       legacy_msg);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+WifiStatus WifiNanIface::createDataInterfaceRequestInternal(
+    uint16_t cmd_id, const std::string& iface_name) {
+    legacy_hal::wifi_error legacy_status =
+        legacy_hal_.lock()->nanDataInterfaceCreate(ifname_, cmd_id, iface_name);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+WifiStatus WifiNanIface::deleteDataInterfaceRequestInternal(
+    uint16_t cmd_id, const std::string& iface_name) {
+    legacy_hal::wifi_error legacy_status =
+        legacy_hal_.lock()->nanDataInterfaceDelete(ifname_, cmd_id, iface_name);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+WifiStatus WifiNanIface::initiateDataPathRequestInternal(
+    uint16_t cmd_id, const NanInitiateDataPathRequest& msg) {
+    legacy_hal::NanDataPathInitiatorRequest legacy_msg;
+    if (!hidl_struct_util::convertHidlNanDataPathInitiatorRequestToLegacy(
+            msg, &legacy_msg)) {
+        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+    }
+    legacy_hal::wifi_error legacy_status =
+        legacy_hal_.lock()->nanDataRequestInitiator(ifname_, cmd_id,
+                                                    legacy_msg);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+WifiStatus WifiNanIface::respondToDataPathIndicationRequestInternal(
+    uint16_t cmd_id, const NanRespondToDataPathIndicationRequest& msg) {
+    legacy_hal::NanDataPathIndicationResponse legacy_msg;
+    if (!hidl_struct_util::convertHidlNanDataPathIndicationResponseToLegacy(
+            msg, &legacy_msg)) {
+        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+    }
+    legacy_hal::wifi_error legacy_status =
+        legacy_hal_.lock()->nanDataIndicationResponse(ifname_, cmd_id,
+                                                      legacy_msg);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+WifiStatus WifiNanIface::terminateDataPathRequestInternal(
+    uint16_t cmd_id, uint32_t ndpInstanceId) {
+    legacy_hal::wifi_error legacy_status =
+        legacy_hal_.lock()->nanDataEnd(ifname_, cmd_id, ndpInstanceId);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+}  // namespace implementation
+}  // namespace V1_2
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
diff --git a/wifi/1.2/default/wifi_nan_iface.h b/wifi/1.2/default/wifi_nan_iface.h
new file mode 100644
index 0000000..6fa7b0c
--- /dev/null
+++ b/wifi/1.2/default/wifi_nan_iface.h
@@ -0,0 +1,139 @@
+/*
+ * 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 WIFI_NAN_IFACE_H_
+#define WIFI_NAN_IFACE_H_
+
+#include <android-base/macros.h>
+#include <android/hardware/wifi/1.0/IWifiNanIface.h>
+#include <android/hardware/wifi/1.0/IWifiNanIfaceEventCallback.h>
+
+#include "hidl_callback_util.h"
+#include "wifi_legacy_hal.h"
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace V1_2 {
+namespace implementation {
+using namespace android::hardware::wifi::V1_0;
+
+/**
+ * HIDL interface object used to control a NAN Iface instance.
+ */
+class WifiNanIface : public V1_0::IWifiNanIface {
+   public:
+    WifiNanIface(const std::string& ifname,
+                 const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal);
+    // Refer to |WifiChip::invalidate()|.
+    void invalidate();
+    bool isValid();
+    std::string getName();
+
+    // HIDL methods exposed.
+    Return<void> getName(getName_cb hidl_status_cb) override;
+    Return<void> getType(getType_cb hidl_status_cb) override;
+    Return<void> registerEventCallback(
+        const sp<IWifiNanIfaceEventCallback>& callback,
+        registerEventCallback_cb hidl_status_cb) override;
+    Return<void> getCapabilitiesRequest(
+        uint16_t cmd_id, getCapabilitiesRequest_cb hidl_status_cb) override;
+    Return<void> enableRequest(uint16_t cmd_id, const NanEnableRequest& msg,
+                               enableRequest_cb hidl_status_cb) override;
+    Return<void> configRequest(uint16_t cmd_id, const NanConfigRequest& msg,
+                               configRequest_cb hidl_status_cb) override;
+    Return<void> disableRequest(uint16_t cmd_id,
+                                disableRequest_cb hidl_status_cb) override;
+    Return<void> startPublishRequest(
+        uint16_t cmd_id, const NanPublishRequest& msg,
+        startPublishRequest_cb hidl_status_cb) override;
+    Return<void> stopPublishRequest(
+        uint16_t cmd_id, uint8_t sessionId,
+        stopPublishRequest_cb hidl_status_cb) override;
+    Return<void> startSubscribeRequest(
+        uint16_t cmd_id, const NanSubscribeRequest& msg,
+        startSubscribeRequest_cb hidl_status_cb) override;
+    Return<void> stopSubscribeRequest(
+        uint16_t cmd_id, uint8_t sessionId,
+        stopSubscribeRequest_cb hidl_status_cb) override;
+    Return<void> transmitFollowupRequest(
+        uint16_t cmd_id, const NanTransmitFollowupRequest& msg,
+        transmitFollowupRequest_cb hidl_status_cb) override;
+    Return<void> createDataInterfaceRequest(
+        uint16_t cmd_id, const hidl_string& iface_name,
+        createDataInterfaceRequest_cb hidl_status_cb) override;
+    Return<void> deleteDataInterfaceRequest(
+        uint16_t cmd_id, const hidl_string& iface_name,
+        deleteDataInterfaceRequest_cb hidl_status_cb) override;
+    Return<void> initiateDataPathRequest(
+        uint16_t cmd_id, const NanInitiateDataPathRequest& msg,
+        initiateDataPathRequest_cb hidl_status_cb) override;
+    Return<void> respondToDataPathIndicationRequest(
+        uint16_t cmd_id, const NanRespondToDataPathIndicationRequest& msg,
+        respondToDataPathIndicationRequest_cb hidl_status_cb) override;
+    Return<void> terminateDataPathRequest(
+        uint16_t cmd_id, uint32_t ndpInstanceId,
+        terminateDataPathRequest_cb hidl_status_cb) override;
+
+   private:
+    // Corresponding worker functions for the HIDL methods.
+    std::pair<WifiStatus, std::string> getNameInternal();
+    std::pair<WifiStatus, IfaceType> getTypeInternal();
+    WifiStatus registerEventCallbackInternal(
+        const sp<IWifiNanIfaceEventCallback>& callback);
+    WifiStatus getCapabilitiesRequestInternal(uint16_t cmd_id);
+    WifiStatus enableRequestInternal(uint16_t cmd_id,
+                                     const NanEnableRequest& msg);
+    WifiStatus configRequestInternal(uint16_t cmd_id,
+                                     const NanConfigRequest& msg);
+    WifiStatus disableRequestInternal(uint16_t cmd_id);
+    WifiStatus startPublishRequestInternal(uint16_t cmd_id,
+                                           const NanPublishRequest& msg);
+    WifiStatus stopPublishRequestInternal(uint16_t cmd_id, uint8_t sessionId);
+    WifiStatus startSubscribeRequestInternal(uint16_t cmd_id,
+                                             const NanSubscribeRequest& msg);
+    WifiStatus stopSubscribeRequestInternal(uint16_t cmd_id, uint8_t sessionId);
+    WifiStatus transmitFollowupRequestInternal(
+        uint16_t cmd_id, const NanTransmitFollowupRequest& msg);
+    WifiStatus createDataInterfaceRequestInternal(
+        uint16_t cmd_id, const std::string& iface_name);
+    WifiStatus deleteDataInterfaceRequestInternal(
+        uint16_t cmd_id, const std::string& iface_name);
+    WifiStatus initiateDataPathRequestInternal(
+        uint16_t cmd_id, const NanInitiateDataPathRequest& msg);
+    WifiStatus respondToDataPathIndicationRequestInternal(
+        uint16_t cmd_id, const NanRespondToDataPathIndicationRequest& msg);
+    WifiStatus terminateDataPathRequestInternal(uint16_t cmd_id,
+                                                uint32_t ndpInstanceId);
+
+    std::set<sp<IWifiNanIfaceEventCallback>> getEventCallbacks();
+
+    std::string ifname_;
+    std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
+    bool is_valid_;
+    hidl_callback_util::HidlCallbackHandler<IWifiNanIfaceEventCallback>
+        event_cb_handler_;
+
+    DISALLOW_COPY_AND_ASSIGN(WifiNanIface);
+};
+
+}  // namespace implementation
+}  // namespace V1_2
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
+
+#endif  // WIFI_NAN_IFACE_H_
diff --git a/wifi/1.1/default/wifi_p2p_iface.cpp b/wifi/1.2/default/wifi_p2p_iface.cpp
similarity index 69%
rename from wifi/1.1/default/wifi_p2p_iface.cpp
rename to wifi/1.2/default/wifi_p2p_iface.cpp
index 78e08db..92bbaee 100644
--- a/wifi/1.1/default/wifi_p2p_iface.cpp
+++ b/wifi/1.2/default/wifi_p2p_iface.cpp
@@ -23,7 +23,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_1 {
+namespace V1_2 {
 namespace implementation {
 using hidl_return_util::validateAndCall;
 
@@ -33,38 +33,34 @@
     : ifname_(ifname), legacy_hal_(legacy_hal), is_valid_(true) {}
 
 void WifiP2pIface::invalidate() {
-  legacy_hal_.reset();
-  is_valid_ = false;
+    legacy_hal_.reset();
+    is_valid_ = false;
 }
 
-bool WifiP2pIface::isValid() {
-  return is_valid_;
-}
+bool WifiP2pIface::isValid() { return is_valid_; }
+
+std::string WifiP2pIface::getName() { return ifname_; }
 
 Return<void> WifiP2pIface::getName(getName_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                         &WifiP2pIface::getNameInternal,
-                         hidl_status_cb);
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiP2pIface::getNameInternal, hidl_status_cb);
 }
 
 Return<void> WifiP2pIface::getType(getType_cb hidl_status_cb) {
-  return validateAndCall(this,
-                         WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
-                         &WifiP2pIface::getTypeInternal,
-                         hidl_status_cb);
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiP2pIface::getTypeInternal, hidl_status_cb);
 }
 
 std::pair<WifiStatus, std::string> WifiP2pIface::getNameInternal() {
-  return {createWifiStatus(WifiStatusCode::SUCCESS), ifname_};
+    return {createWifiStatus(WifiStatusCode::SUCCESS), ifname_};
 }
 
 std::pair<WifiStatus, IfaceType> WifiP2pIface::getTypeInternal() {
-  return {createWifiStatus(WifiStatusCode::SUCCESS), IfaceType::P2P};
+    return {createWifiStatus(WifiStatusCode::SUCCESS), IfaceType::P2P};
 }
 
 }  // namespace implementation
-}  // namespace V1_1
+}  // namespace V1_2
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.1/default/wifi_p2p_iface.h b/wifi/1.2/default/wifi_p2p_iface.h
similarity index 60%
rename from wifi/1.1/default/wifi_p2p_iface.h
rename to wifi/1.2/default/wifi_p2p_iface.h
index f563a3d..76120b1 100644
--- a/wifi/1.1/default/wifi_p2p_iface.h
+++ b/wifi/1.2/default/wifi_p2p_iface.h
@@ -25,7 +25,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_1 {
+namespace V1_2 {
 namespace implementation {
 using namespace android::hardware::wifi::V1_0;
 
@@ -33,31 +33,32 @@
  * HIDL interface object used to control a P2P Iface instance.
  */
 class WifiP2pIface : public V1_0::IWifiP2pIface {
- public:
-  WifiP2pIface(const std::string& ifname,
-               const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal);
-  // Refer to |WifiChip::invalidate()|.
-  void invalidate();
-  bool isValid();
+   public:
+    WifiP2pIface(const std::string& ifname,
+                 const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal);
+    // Refer to |WifiChip::invalidate()|.
+    void invalidate();
+    bool isValid();
+    std::string getName();
 
-  // HIDL methods exposed.
-  Return<void> getName(getName_cb hidl_status_cb) override;
-  Return<void> getType(getType_cb hidl_status_cb) override;
+    // HIDL methods exposed.
+    Return<void> getName(getName_cb hidl_status_cb) override;
+    Return<void> getType(getType_cb hidl_status_cb) override;
 
- private:
-  // Corresponding worker functions for the HIDL methods.
-  std::pair<WifiStatus, std::string> getNameInternal();
-  std::pair<WifiStatus, IfaceType> getTypeInternal();
+   private:
+    // Corresponding worker functions for the HIDL methods.
+    std::pair<WifiStatus, std::string> getNameInternal();
+    std::pair<WifiStatus, IfaceType> getTypeInternal();
 
-  std::string ifname_;
-  std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
-  bool is_valid_;
+    std::string ifname_;
+    std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
+    bool is_valid_;
 
-  DISALLOW_COPY_AND_ASSIGN(WifiP2pIface);
+    DISALLOW_COPY_AND_ASSIGN(WifiP2pIface);
 };
 
 }  // namespace implementation
-}  // namespace V1_1
+}  // namespace V1_2
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.2/default/wifi_rtt_controller.cpp b/wifi/1.2/default/wifi_rtt_controller.cpp
new file mode 100644
index 0000000..b68445b
--- /dev/null
+++ b/wifi/1.2/default/wifi_rtt_controller.cpp
@@ -0,0 +1,275 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+
+#include "hidl_return_util.h"
+#include "hidl_struct_util.h"
+#include "wifi_rtt_controller.h"
+#include "wifi_status_util.h"
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace V1_2 {
+namespace implementation {
+using hidl_return_util::validateAndCall;
+
+WifiRttController::WifiRttController(
+    const std::string& iface_name, const sp<IWifiIface>& bound_iface,
+    const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal)
+    : ifname_(iface_name),
+      bound_iface_(bound_iface),
+      legacy_hal_(legacy_hal),
+      is_valid_(true) {}
+
+void WifiRttController::invalidate() {
+    legacy_hal_.reset();
+    event_callbacks_.clear();
+    is_valid_ = false;
+}
+
+bool WifiRttController::isValid() { return is_valid_; }
+
+std::vector<sp<IWifiRttControllerEventCallback>>
+WifiRttController::getEventCallbacks() {
+    return event_callbacks_;
+}
+
+Return<void> WifiRttController::getBoundIface(getBoundIface_cb hidl_status_cb) {
+    return validateAndCall(
+        this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
+        &WifiRttController::getBoundIfaceInternal, hidl_status_cb);
+}
+
+Return<void> WifiRttController::registerEventCallback(
+    const sp<IWifiRttControllerEventCallback>& callback,
+    registerEventCallback_cb hidl_status_cb) {
+    return validateAndCall(this,
+                           WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
+                           &WifiRttController::registerEventCallbackInternal,
+                           hidl_status_cb, callback);
+}
+
+Return<void> WifiRttController::rangeRequest(
+    uint32_t cmd_id, const hidl_vec<RttConfig>& rtt_configs,
+    rangeRequest_cb hidl_status_cb) {
+    return validateAndCall(this,
+                           WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
+                           &WifiRttController::rangeRequestInternal,
+                           hidl_status_cb, cmd_id, rtt_configs);
+}
+
+Return<void> WifiRttController::rangeCancel(
+    uint32_t cmd_id, const hidl_vec<hidl_array<uint8_t, 6>>& addrs,
+    rangeCancel_cb hidl_status_cb) {
+    return validateAndCall(
+        this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
+        &WifiRttController::rangeCancelInternal, hidl_status_cb, cmd_id, addrs);
+}
+
+Return<void> WifiRttController::getCapabilities(
+    getCapabilities_cb hidl_status_cb) {
+    return validateAndCall(
+        this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
+        &WifiRttController::getCapabilitiesInternal, hidl_status_cb);
+}
+
+Return<void> WifiRttController::setLci(uint32_t cmd_id,
+                                       const RttLciInformation& lci,
+                                       setLci_cb hidl_status_cb) {
+    return validateAndCall(
+        this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
+        &WifiRttController::setLciInternal, hidl_status_cb, cmd_id, lci);
+}
+
+Return<void> WifiRttController::setLcr(uint32_t cmd_id,
+                                       const RttLcrInformation& lcr,
+                                       setLcr_cb hidl_status_cb) {
+    return validateAndCall(
+        this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
+        &WifiRttController::setLcrInternal, hidl_status_cb, cmd_id, lcr);
+}
+
+Return<void> WifiRttController::getResponderInfo(
+    getResponderInfo_cb hidl_status_cb) {
+    return validateAndCall(
+        this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
+        &WifiRttController::getResponderInfoInternal, hidl_status_cb);
+}
+
+Return<void> WifiRttController::enableResponder(
+    uint32_t cmd_id, const WifiChannelInfo& channel_hint,
+    uint32_t max_duration_seconds, const RttResponder& info,
+    enableResponder_cb hidl_status_cb) {
+    return validateAndCall(
+        this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
+        &WifiRttController::enableResponderInternal, hidl_status_cb, cmd_id,
+        channel_hint, max_duration_seconds, info);
+}
+
+Return<void> WifiRttController::disableResponder(
+    uint32_t cmd_id, disableResponder_cb hidl_status_cb) {
+    return validateAndCall(
+        this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
+        &WifiRttController::disableResponderInternal, hidl_status_cb, cmd_id);
+}
+
+std::pair<WifiStatus, sp<IWifiIface>>
+WifiRttController::getBoundIfaceInternal() {
+    return {createWifiStatus(WifiStatusCode::SUCCESS), bound_iface_};
+}
+
+WifiStatus WifiRttController::registerEventCallbackInternal(
+    const sp<IWifiRttControllerEventCallback>& callback) {
+    // TODO(b/31632518): remove the callback when the client is destroyed
+    event_callbacks_.emplace_back(callback);
+    return createWifiStatus(WifiStatusCode::SUCCESS);
+}
+
+WifiStatus WifiRttController::rangeRequestInternal(
+    uint32_t cmd_id, const std::vector<RttConfig>& rtt_configs) {
+    std::vector<legacy_hal::wifi_rtt_config> legacy_configs;
+    if (!hidl_struct_util::convertHidlVectorOfRttConfigToLegacy(
+            rtt_configs, &legacy_configs)) {
+        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+    }
+    android::wp<WifiRttController> weak_ptr_this(this);
+    const auto& on_results_callback =
+        [weak_ptr_this](
+            legacy_hal::wifi_request_id id,
+            const std::vector<const legacy_hal::wifi_rtt_result*>& results) {
+            const auto shared_ptr_this = weak_ptr_this.promote();
+            if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+                LOG(ERROR) << "Callback invoked on an invalid object";
+                return;
+            }
+            std::vector<RttResult> hidl_results;
+            if (!hidl_struct_util::convertLegacyVectorOfRttResultToHidl(
+                    results, &hidl_results)) {
+                LOG(ERROR) << "Failed to convert rtt results to HIDL structs";
+                return;
+            }
+            for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+                callback->onResults(id, hidl_results);
+            }
+        };
+    legacy_hal::wifi_error legacy_status =
+        legacy_hal_.lock()->startRttRangeRequest(
+            ifname_, cmd_id, legacy_configs, on_results_callback);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+WifiStatus WifiRttController::rangeCancelInternal(
+    uint32_t cmd_id, const std::vector<hidl_array<uint8_t, 6>>& addrs) {
+    std::vector<std::array<uint8_t, 6>> legacy_addrs;
+    for (const auto& addr : addrs) {
+        legacy_addrs.push_back(addr);
+    }
+    legacy_hal::wifi_error legacy_status =
+        legacy_hal_.lock()->cancelRttRangeRequest(ifname_, cmd_id,
+                                                  legacy_addrs);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+std::pair<WifiStatus, RttCapabilities>
+WifiRttController::getCapabilitiesInternal() {
+    legacy_hal::wifi_error legacy_status;
+    legacy_hal::wifi_rtt_capabilities legacy_caps;
+    std::tie(legacy_status, legacy_caps) =
+        legacy_hal_.lock()->getRttCapabilities(ifname_);
+    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+        return {createWifiStatusFromLegacyError(legacy_status), {}};
+    }
+    RttCapabilities hidl_caps;
+    if (!hidl_struct_util::convertLegacyRttCapabilitiesToHidl(legacy_caps,
+                                                              &hidl_caps)) {
+        return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
+    }
+    return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps};
+}
+
+WifiStatus WifiRttController::setLciInternal(uint32_t cmd_id,
+                                             const RttLciInformation& lci) {
+    legacy_hal::wifi_lci_information legacy_lci;
+    if (!hidl_struct_util::convertHidlRttLciInformationToLegacy(lci,
+                                                                &legacy_lci)) {
+        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+    }
+    legacy_hal::wifi_error legacy_status =
+        legacy_hal_.lock()->setRttLci(ifname_, cmd_id, legacy_lci);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+WifiStatus WifiRttController::setLcrInternal(uint32_t cmd_id,
+                                             const RttLcrInformation& lcr) {
+    legacy_hal::wifi_lcr_information legacy_lcr;
+    if (!hidl_struct_util::convertHidlRttLcrInformationToLegacy(lcr,
+                                                                &legacy_lcr)) {
+        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+    }
+    legacy_hal::wifi_error legacy_status =
+        legacy_hal_.lock()->setRttLcr(ifname_, cmd_id, legacy_lcr);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+std::pair<WifiStatus, RttResponder>
+WifiRttController::getResponderInfoInternal() {
+    legacy_hal::wifi_error legacy_status;
+    legacy_hal::wifi_rtt_responder legacy_responder;
+    std::tie(legacy_status, legacy_responder) =
+        legacy_hal_.lock()->getRttResponderInfo(ifname_);
+    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+        return {createWifiStatusFromLegacyError(legacy_status), {}};
+    }
+    RttResponder hidl_responder;
+    if (!hidl_struct_util::convertLegacyRttResponderToHidl(legacy_responder,
+                                                           &hidl_responder)) {
+        return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
+    }
+    return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_responder};
+}
+
+WifiStatus WifiRttController::enableResponderInternal(
+    uint32_t cmd_id, const WifiChannelInfo& channel_hint,
+    uint32_t max_duration_seconds, const RttResponder& info) {
+    legacy_hal::wifi_channel_info legacy_channel_info;
+    if (!hidl_struct_util::convertHidlWifiChannelInfoToLegacy(
+            channel_hint, &legacy_channel_info)) {
+        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+    }
+    legacy_hal::wifi_rtt_responder legacy_responder;
+    if (!hidl_struct_util::convertHidlRttResponderToLegacy(info,
+                                                           &legacy_responder)) {
+        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+    }
+    legacy_hal::wifi_error legacy_status =
+        legacy_hal_.lock()->enableRttResponder(
+            ifname_, cmd_id, legacy_channel_info, max_duration_seconds,
+            legacy_responder);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+WifiStatus WifiRttController::disableResponderInternal(uint32_t cmd_id) {
+    legacy_hal::wifi_error legacy_status =
+        legacy_hal_.lock()->disableRttResponder(ifname_, cmd_id);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+}  // namespace implementation
+}  // namespace V1_2
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
diff --git a/wifi/1.2/default/wifi_rtt_controller.h b/wifi/1.2/default/wifi_rtt_controller.h
new file mode 100644
index 0000000..1ab01e1
--- /dev/null
+++ b/wifi/1.2/default/wifi_rtt_controller.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef WIFI_RTT_CONTROLLER_H_
+#define WIFI_RTT_CONTROLLER_H_
+
+#include <android-base/macros.h>
+#include <android/hardware/wifi/1.0/IWifiIface.h>
+#include <android/hardware/wifi/1.0/IWifiRttController.h>
+#include <android/hardware/wifi/1.0/IWifiRttControllerEventCallback.h>
+
+#include "wifi_legacy_hal.h"
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace V1_2 {
+namespace implementation {
+
+/**
+ * HIDL interface object used to control all RTT operations.
+ */
+class WifiRttController : public V1_0::IWifiRttController {
+   public:
+    WifiRttController(
+        const std::string& iface_name, const sp<IWifiIface>& bound_iface,
+        const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal);
+    // Refer to |WifiChip::invalidate()|.
+    void invalidate();
+    bool isValid();
+    std::vector<sp<IWifiRttControllerEventCallback>> getEventCallbacks();
+
+    // HIDL methods exposed.
+    Return<void> getBoundIface(getBoundIface_cb hidl_status_cb) override;
+    Return<void> registerEventCallback(
+        const sp<IWifiRttControllerEventCallback>& callback,
+        registerEventCallback_cb hidl_status_cb) override;
+    Return<void> rangeRequest(uint32_t cmd_id,
+                              const hidl_vec<RttConfig>& rtt_configs,
+                              rangeRequest_cb hidl_status_cb) override;
+    Return<void> rangeCancel(uint32_t cmd_id,
+                             const hidl_vec<hidl_array<uint8_t, 6>>& addrs,
+                             rangeCancel_cb hidl_status_cb) override;
+    Return<void> getCapabilities(getCapabilities_cb hidl_status_cb) override;
+    Return<void> setLci(uint32_t cmd_id, const RttLciInformation& lci,
+                        setLci_cb hidl_status_cb) override;
+    Return<void> setLcr(uint32_t cmd_id, const RttLcrInformation& lcr,
+                        setLcr_cb hidl_status_cb) override;
+    Return<void> getResponderInfo(getResponderInfo_cb hidl_status_cb) override;
+    Return<void> enableResponder(uint32_t cmd_id,
+                                 const WifiChannelInfo& channel_hint,
+                                 uint32_t max_duration_seconds,
+                                 const RttResponder& info,
+                                 enableResponder_cb hidl_status_cb) override;
+    Return<void> disableResponder(uint32_t cmd_id,
+                                  disableResponder_cb hidl_status_cb) override;
+
+   private:
+    // Corresponding worker functions for the HIDL methods.
+    std::pair<WifiStatus, sp<IWifiIface>> getBoundIfaceInternal();
+    WifiStatus registerEventCallbackInternal(
+        const sp<IWifiRttControllerEventCallback>& callback);
+    WifiStatus rangeRequestInternal(uint32_t cmd_id,
+                                    const std::vector<RttConfig>& rtt_configs);
+    WifiStatus rangeCancelInternal(
+        uint32_t cmd_id, const std::vector<hidl_array<uint8_t, 6>>& addrs);
+    std::pair<WifiStatus, RttCapabilities> getCapabilitiesInternal();
+    WifiStatus setLciInternal(uint32_t cmd_id, const RttLciInformation& lci);
+    WifiStatus setLcrInternal(uint32_t cmd_id, const RttLcrInformation& lcr);
+    std::pair<WifiStatus, RttResponder> getResponderInfoInternal();
+    WifiStatus enableResponderInternal(uint32_t cmd_id,
+                                       const WifiChannelInfo& channel_hint,
+                                       uint32_t max_duration_seconds,
+                                       const RttResponder& info);
+    WifiStatus disableResponderInternal(uint32_t cmd_id);
+
+    std::string ifname_;
+    sp<IWifiIface> bound_iface_;
+    std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
+    std::vector<sp<IWifiRttControllerEventCallback>> event_callbacks_;
+    bool is_valid_;
+
+    DISALLOW_COPY_AND_ASSIGN(WifiRttController);
+};
+
+}  // namespace implementation
+}  // namespace V1_2
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
+
+#endif  // WIFI_RTT_CONTROLLER_H_
diff --git a/wifi/1.2/default/wifi_sta_iface.cpp b/wifi/1.2/default/wifi_sta_iface.cpp
new file mode 100644
index 0000000..6faf009
--- /dev/null
+++ b/wifi/1.2/default/wifi_sta_iface.cpp
@@ -0,0 +1,585 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+
+#include "hidl_return_util.h"
+#include "hidl_struct_util.h"
+#include "wifi_sta_iface.h"
+#include "wifi_status_util.h"
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace V1_2 {
+namespace implementation {
+using hidl_return_util::validateAndCall;
+
+WifiStaIface::WifiStaIface(
+    const std::string& ifname,
+    const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal)
+    : ifname_(ifname), legacy_hal_(legacy_hal), is_valid_(true) {
+    // Turn on DFS channel usage for STA iface.
+    legacy_hal::wifi_error legacy_status =
+        legacy_hal_.lock()->setDfsFlag(ifname_, true);
+    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+        LOG(ERROR)
+            << "Failed to set DFS flag; DFS channels may be unavailable.";
+    }
+}
+
+void WifiStaIface::invalidate() {
+    legacy_hal_.reset();
+    event_cb_handler_.invalidate();
+    is_valid_ = false;
+}
+
+bool WifiStaIface::isValid() { return is_valid_; }
+
+std::string WifiStaIface::getName() { return ifname_; }
+
+std::set<sp<IWifiStaIfaceEventCallback>> WifiStaIface::getEventCallbacks() {
+    return event_cb_handler_.getCallbacks();
+}
+
+Return<void> WifiStaIface::getName(getName_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiStaIface::getNameInternal, hidl_status_cb);
+}
+
+Return<void> WifiStaIface::getType(getType_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiStaIface::getTypeInternal, hidl_status_cb);
+}
+
+Return<void> WifiStaIface::registerEventCallback(
+    const sp<IWifiStaIfaceEventCallback>& callback,
+    registerEventCallback_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiStaIface::registerEventCallbackInternal,
+                           hidl_status_cb, callback);
+}
+
+Return<void> WifiStaIface::getCapabilities(getCapabilities_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiStaIface::getCapabilitiesInternal,
+                           hidl_status_cb);
+}
+
+Return<void> WifiStaIface::getApfPacketFilterCapabilities(
+    getApfPacketFilterCapabilities_cb hidl_status_cb) {
+    return validateAndCall(
+        this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+        &WifiStaIface::getApfPacketFilterCapabilitiesInternal, hidl_status_cb);
+}
+
+Return<void> WifiStaIface::installApfPacketFilter(
+    uint32_t cmd_id, const hidl_vec<uint8_t>& program,
+    installApfPacketFilter_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiStaIface::installApfPacketFilterInternal,
+                           hidl_status_cb, cmd_id, program);
+}
+
+Return<void> WifiStaIface::getBackgroundScanCapabilities(
+    getBackgroundScanCapabilities_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiStaIface::getBackgroundScanCapabilitiesInternal,
+                           hidl_status_cb);
+}
+
+Return<void> WifiStaIface::getValidFrequenciesForBand(
+    WifiBand band, getValidFrequenciesForBand_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiStaIface::getValidFrequenciesForBandInternal,
+                           hidl_status_cb, band);
+}
+
+Return<void> WifiStaIface::startBackgroundScan(
+    uint32_t cmd_id, const StaBackgroundScanParameters& params,
+    startBackgroundScan_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiStaIface::startBackgroundScanInternal,
+                           hidl_status_cb, cmd_id, params);
+}
+
+Return<void> WifiStaIface::stopBackgroundScan(
+    uint32_t cmd_id, stopBackgroundScan_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiStaIface::stopBackgroundScanInternal,
+                           hidl_status_cb, cmd_id);
+}
+
+Return<void> WifiStaIface::enableLinkLayerStatsCollection(
+    bool debug, enableLinkLayerStatsCollection_cb hidl_status_cb) {
+    return validateAndCall(
+        this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+        &WifiStaIface::enableLinkLayerStatsCollectionInternal, hidl_status_cb,
+        debug);
+}
+
+Return<void> WifiStaIface::disableLinkLayerStatsCollection(
+    disableLinkLayerStatsCollection_cb hidl_status_cb) {
+    return validateAndCall(
+        this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+        &WifiStaIface::disableLinkLayerStatsCollectionInternal, hidl_status_cb);
+}
+
+Return<void> WifiStaIface::getLinkLayerStats(
+    getLinkLayerStats_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiStaIface::getLinkLayerStatsInternal,
+                           hidl_status_cb);
+}
+
+Return<void> WifiStaIface::startRssiMonitoring(
+    uint32_t cmd_id, int32_t max_rssi, int32_t min_rssi,
+    startRssiMonitoring_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiStaIface::startRssiMonitoringInternal,
+                           hidl_status_cb, cmd_id, max_rssi, min_rssi);
+}
+
+Return<void> WifiStaIface::stopRssiMonitoring(
+    uint32_t cmd_id, stopRssiMonitoring_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiStaIface::stopRssiMonitoringInternal,
+                           hidl_status_cb, cmd_id);
+}
+
+Return<void> WifiStaIface::getRoamingCapabilities(
+    getRoamingCapabilities_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiStaIface::getRoamingCapabilitiesInternal,
+                           hidl_status_cb);
+}
+
+Return<void> WifiStaIface::configureRoaming(
+    const StaRoamingConfig& config, configureRoaming_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiStaIface::configureRoamingInternal,
+                           hidl_status_cb, config);
+}
+
+Return<void> WifiStaIface::setRoamingState(StaRoamingState state,
+                                           setRoamingState_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiStaIface::setRoamingStateInternal,
+                           hidl_status_cb, state);
+}
+
+Return<void> WifiStaIface::enableNdOffload(bool enable,
+                                           enableNdOffload_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiStaIface::enableNdOffloadInternal,
+                           hidl_status_cb, enable);
+}
+
+Return<void> WifiStaIface::startSendingKeepAlivePackets(
+    uint32_t cmd_id, const hidl_vec<uint8_t>& ip_packet_data,
+    uint16_t ether_type, const hidl_array<uint8_t, 6>& src_address,
+    const hidl_array<uint8_t, 6>& dst_address, uint32_t period_in_ms,
+    startSendingKeepAlivePackets_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiStaIface::startSendingKeepAlivePacketsInternal,
+                           hidl_status_cb, cmd_id, ip_packet_data, ether_type,
+                           src_address, dst_address, period_in_ms);
+}
+
+Return<void> WifiStaIface::stopSendingKeepAlivePackets(
+    uint32_t cmd_id, stopSendingKeepAlivePackets_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiStaIface::stopSendingKeepAlivePacketsInternal,
+                           hidl_status_cb, cmd_id);
+}
+
+Return<void> WifiStaIface::setScanningMacOui(
+    const hidl_array<uint8_t, 3>& oui, setScanningMacOui_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiStaIface::setScanningMacOuiInternal,
+                           hidl_status_cb, oui);
+}
+
+Return<void> WifiStaIface::startDebugPacketFateMonitoring(
+    startDebugPacketFateMonitoring_cb hidl_status_cb) {
+    return validateAndCall(
+        this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+        &WifiStaIface::startDebugPacketFateMonitoringInternal, hidl_status_cb);
+}
+
+Return<void> WifiStaIface::getDebugTxPacketFates(
+    getDebugTxPacketFates_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiStaIface::getDebugTxPacketFatesInternal,
+                           hidl_status_cb);
+}
+
+Return<void> WifiStaIface::getDebugRxPacketFates(
+    getDebugRxPacketFates_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiStaIface::getDebugRxPacketFatesInternal,
+                           hidl_status_cb);
+}
+
+std::pair<WifiStatus, std::string> WifiStaIface::getNameInternal() {
+    return {createWifiStatus(WifiStatusCode::SUCCESS), ifname_};
+}
+
+std::pair<WifiStatus, IfaceType> WifiStaIface::getTypeInternal() {
+    return {createWifiStatus(WifiStatusCode::SUCCESS), IfaceType::STA};
+}
+
+WifiStatus WifiStaIface::registerEventCallbackInternal(
+    const sp<IWifiStaIfaceEventCallback>& callback) {
+    if (!event_cb_handler_.addCallback(callback)) {
+        return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
+    }
+    return createWifiStatus(WifiStatusCode::SUCCESS);
+}
+
+std::pair<WifiStatus, uint32_t> WifiStaIface::getCapabilitiesInternal() {
+    legacy_hal::wifi_error legacy_status;
+    uint32_t legacy_feature_set;
+    std::tie(legacy_status, legacy_feature_set) =
+        legacy_hal_.lock()->getSupportedFeatureSet(ifname_);
+    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+        return {createWifiStatusFromLegacyError(legacy_status), 0};
+    }
+    uint32_t legacy_logger_feature_set;
+    std::tie(legacy_status, legacy_logger_feature_set) =
+        legacy_hal_.lock()->getLoggerSupportedFeatureSet(ifname_);
+    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+        // some devices don't support querying logger feature set
+        legacy_logger_feature_set = 0;
+    }
+    uint32_t hidl_caps;
+    if (!hidl_struct_util::convertLegacyFeaturesToHidlStaCapabilities(
+            legacy_feature_set, legacy_logger_feature_set, &hidl_caps)) {
+        return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), 0};
+    }
+    return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps};
+}
+
+std::pair<WifiStatus, StaApfPacketFilterCapabilities>
+WifiStaIface::getApfPacketFilterCapabilitiesInternal() {
+    legacy_hal::wifi_error legacy_status;
+    legacy_hal::PacketFilterCapabilities legacy_caps;
+    std::tie(legacy_status, legacy_caps) =
+        legacy_hal_.lock()->getPacketFilterCapabilities(ifname_);
+    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+        return {createWifiStatusFromLegacyError(legacy_status), {}};
+    }
+    StaApfPacketFilterCapabilities hidl_caps;
+    if (!hidl_struct_util::convertLegacyApfCapabilitiesToHidl(legacy_caps,
+                                                              &hidl_caps)) {
+        return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
+    }
+    return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps};
+}
+
+WifiStatus WifiStaIface::installApfPacketFilterInternal(
+    uint32_t /* cmd_id */, const std::vector<uint8_t>& program) {
+    legacy_hal::wifi_error legacy_status =
+        legacy_hal_.lock()->setPacketFilter(ifname_, program);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+std::pair<WifiStatus, StaBackgroundScanCapabilities>
+WifiStaIface::getBackgroundScanCapabilitiesInternal() {
+    legacy_hal::wifi_error legacy_status;
+    legacy_hal::wifi_gscan_capabilities legacy_caps;
+    std::tie(legacy_status, legacy_caps) =
+        legacy_hal_.lock()->getGscanCapabilities(ifname_);
+    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+        return {createWifiStatusFromLegacyError(legacy_status), {}};
+    }
+    StaBackgroundScanCapabilities hidl_caps;
+    if (!hidl_struct_util::convertLegacyGscanCapabilitiesToHidl(legacy_caps,
+                                                                &hidl_caps)) {
+        return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
+    }
+    return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps};
+}
+
+std::pair<WifiStatus, std::vector<WifiChannelInMhz>>
+WifiStaIface::getValidFrequenciesForBandInternal(WifiBand band) {
+    static_assert(sizeof(WifiChannelInMhz) == sizeof(uint32_t),
+                  "Size mismatch");
+    legacy_hal::wifi_error legacy_status;
+    std::vector<uint32_t> valid_frequencies;
+    std::tie(legacy_status, valid_frequencies) =
+        legacy_hal_.lock()->getValidFrequenciesForBand(
+            ifname_, hidl_struct_util::convertHidlWifiBandToLegacy(band));
+    return {createWifiStatusFromLegacyError(legacy_status), valid_frequencies};
+}
+
+WifiStatus WifiStaIface::startBackgroundScanInternal(
+    uint32_t cmd_id, const StaBackgroundScanParameters& params) {
+    legacy_hal::wifi_scan_cmd_params legacy_params;
+    if (!hidl_struct_util::convertHidlGscanParamsToLegacy(params,
+                                                          &legacy_params)) {
+        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+    }
+    android::wp<WifiStaIface> weak_ptr_this(this);
+    const auto& on_failure_callback =
+        [weak_ptr_this](legacy_hal::wifi_request_id id) {
+            const auto shared_ptr_this = weak_ptr_this.promote();
+            if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+                LOG(ERROR) << "Callback invoked on an invalid object";
+                return;
+            }
+            for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+                if (!callback->onBackgroundScanFailure(id).isOk()) {
+                    LOG(ERROR)
+                        << "Failed to invoke onBackgroundScanFailure callback";
+                }
+            }
+        };
+    const auto& on_results_callback =
+        [weak_ptr_this](
+            legacy_hal::wifi_request_id id,
+            const std::vector<legacy_hal::wifi_cached_scan_results>& results) {
+            const auto shared_ptr_this = weak_ptr_this.promote();
+            if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+                LOG(ERROR) << "Callback invoked on an invalid object";
+                return;
+            }
+            std::vector<StaScanData> hidl_scan_datas;
+            if (!hidl_struct_util::
+                    convertLegacyVectorOfCachedGscanResultsToHidl(
+                        results, &hidl_scan_datas)) {
+                LOG(ERROR) << "Failed to convert scan results to HIDL structs";
+                return;
+            }
+            for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+                if (!callback->onBackgroundScanResults(id, hidl_scan_datas)
+                         .isOk()) {
+                    LOG(ERROR)
+                        << "Failed to invoke onBackgroundScanResults callback";
+                }
+            }
+        };
+    const auto& on_full_result_callback = [weak_ptr_this](
+                                              legacy_hal::wifi_request_id id,
+                                              const legacy_hal::
+                                                  wifi_scan_result* result,
+                                              uint32_t buckets_scanned) {
+        const auto shared_ptr_this = weak_ptr_this.promote();
+        if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+            LOG(ERROR) << "Callback invoked on an invalid object";
+            return;
+        }
+        StaScanResult hidl_scan_result;
+        if (!hidl_struct_util::convertLegacyGscanResultToHidl(
+                *result, true, &hidl_scan_result)) {
+            LOG(ERROR) << "Failed to convert full scan results to HIDL structs";
+            return;
+        }
+        for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+            if (!callback
+                     ->onBackgroundFullScanResult(id, buckets_scanned,
+                                                  hidl_scan_result)
+                     .isOk()) {
+                LOG(ERROR)
+                    << "Failed to invoke onBackgroundFullScanResult callback";
+            }
+        }
+    };
+    legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->startGscan(
+        ifname_, cmd_id, legacy_params, on_failure_callback,
+        on_results_callback, on_full_result_callback);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+WifiStatus WifiStaIface::stopBackgroundScanInternal(uint32_t cmd_id) {
+    legacy_hal::wifi_error legacy_status =
+        legacy_hal_.lock()->stopGscan(ifname_, cmd_id);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+WifiStatus WifiStaIface::enableLinkLayerStatsCollectionInternal(bool debug) {
+    legacy_hal::wifi_error legacy_status =
+        legacy_hal_.lock()->enableLinkLayerStats(ifname_, debug);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+WifiStatus WifiStaIface::disableLinkLayerStatsCollectionInternal() {
+    legacy_hal::wifi_error legacy_status =
+        legacy_hal_.lock()->disableLinkLayerStats(ifname_);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+std::pair<WifiStatus, StaLinkLayerStats>
+WifiStaIface::getLinkLayerStatsInternal() {
+    legacy_hal::wifi_error legacy_status;
+    legacy_hal::LinkLayerStats legacy_stats;
+    std::tie(legacy_status, legacy_stats) =
+        legacy_hal_.lock()->getLinkLayerStats(ifname_);
+    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+        return {createWifiStatusFromLegacyError(legacy_status), {}};
+    }
+    StaLinkLayerStats hidl_stats;
+    if (!hidl_struct_util::convertLegacyLinkLayerStatsToHidl(legacy_stats,
+                                                             &hidl_stats)) {
+        return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
+    }
+    return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_stats};
+}
+
+WifiStatus WifiStaIface::startRssiMonitoringInternal(uint32_t cmd_id,
+                                                     int32_t max_rssi,
+                                                     int32_t min_rssi) {
+    android::wp<WifiStaIface> weak_ptr_this(this);
+    const auto& on_threshold_breached_callback =
+        [weak_ptr_this](legacy_hal::wifi_request_id id,
+                        std::array<uint8_t, 6> bssid, int8_t rssi) {
+            const auto shared_ptr_this = weak_ptr_this.promote();
+            if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+                LOG(ERROR) << "Callback invoked on an invalid object";
+                return;
+            }
+            for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+                if (!callback->onRssiThresholdBreached(id, bssid, rssi)
+                         .isOk()) {
+                    LOG(ERROR)
+                        << "Failed to invoke onRssiThresholdBreached callback";
+                }
+            }
+        };
+    legacy_hal::wifi_error legacy_status =
+        legacy_hal_.lock()->startRssiMonitoring(ifname_, cmd_id, max_rssi,
+                                                min_rssi,
+                                                on_threshold_breached_callback);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+WifiStatus WifiStaIface::stopRssiMonitoringInternal(uint32_t cmd_id) {
+    legacy_hal::wifi_error legacy_status =
+        legacy_hal_.lock()->stopRssiMonitoring(ifname_, cmd_id);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+std::pair<WifiStatus, StaRoamingCapabilities>
+WifiStaIface::getRoamingCapabilitiesInternal() {
+    legacy_hal::wifi_error legacy_status;
+    legacy_hal::wifi_roaming_capabilities legacy_caps;
+    std::tie(legacy_status, legacy_caps) =
+        legacy_hal_.lock()->getRoamingCapabilities(ifname_);
+    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+        return {createWifiStatusFromLegacyError(legacy_status), {}};
+    }
+    StaRoamingCapabilities hidl_caps;
+    if (!hidl_struct_util::convertLegacyRoamingCapabilitiesToHidl(legacy_caps,
+                                                                  &hidl_caps)) {
+        return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
+    }
+    return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps};
+}
+
+WifiStatus WifiStaIface::configureRoamingInternal(
+    const StaRoamingConfig& config) {
+    legacy_hal::wifi_roaming_config legacy_config;
+    if (!hidl_struct_util::convertHidlRoamingConfigToLegacy(config,
+                                                            &legacy_config)) {
+        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+    }
+    legacy_hal::wifi_error legacy_status =
+        legacy_hal_.lock()->configureRoaming(ifname_, legacy_config);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+WifiStatus WifiStaIface::setRoamingStateInternal(StaRoamingState state) {
+    legacy_hal::wifi_error legacy_status =
+        legacy_hal_.lock()->enableFirmwareRoaming(
+            ifname_, hidl_struct_util::convertHidlRoamingStateToLegacy(state));
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+WifiStatus WifiStaIface::enableNdOffloadInternal(bool enable) {
+    legacy_hal::wifi_error legacy_status =
+        legacy_hal_.lock()->configureNdOffload(ifname_, enable);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+WifiStatus WifiStaIface::startSendingKeepAlivePacketsInternal(
+    uint32_t cmd_id, const std::vector<uint8_t>& ip_packet_data,
+    uint16_t /* ether_type */, const std::array<uint8_t, 6>& src_address,
+    const std::array<uint8_t, 6>& dst_address, uint32_t period_in_ms) {
+    legacy_hal::wifi_error legacy_status =
+        legacy_hal_.lock()->startSendingOffloadedPacket(
+            ifname_, cmd_id, ip_packet_data, src_address, dst_address,
+            period_in_ms);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+WifiStatus WifiStaIface::stopSendingKeepAlivePacketsInternal(uint32_t cmd_id) {
+    legacy_hal::wifi_error legacy_status =
+        legacy_hal_.lock()->stopSendingOffloadedPacket(ifname_, cmd_id);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+WifiStatus WifiStaIface::setScanningMacOuiInternal(
+    const std::array<uint8_t, 3>& oui) {
+    legacy_hal::wifi_error legacy_status =
+        legacy_hal_.lock()->setScanningMacOui(ifname_, oui);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+WifiStatus WifiStaIface::startDebugPacketFateMonitoringInternal() {
+    legacy_hal::wifi_error legacy_status =
+        legacy_hal_.lock()->startPktFateMonitoring(ifname_);
+    return createWifiStatusFromLegacyError(legacy_status);
+}
+
+std::pair<WifiStatus, std::vector<WifiDebugTxPacketFateReport>>
+WifiStaIface::getDebugTxPacketFatesInternal() {
+    legacy_hal::wifi_error legacy_status;
+    std::vector<legacy_hal::wifi_tx_report> legacy_fates;
+    std::tie(legacy_status, legacy_fates) =
+        legacy_hal_.lock()->getTxPktFates(ifname_);
+    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+        return {createWifiStatusFromLegacyError(legacy_status), {}};
+    }
+    std::vector<WifiDebugTxPacketFateReport> hidl_fates;
+    if (!hidl_struct_util::convertLegacyVectorOfDebugTxPacketFateToHidl(
+            legacy_fates, &hidl_fates)) {
+        return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
+    }
+    return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_fates};
+}
+
+std::pair<WifiStatus, std::vector<WifiDebugRxPacketFateReport>>
+WifiStaIface::getDebugRxPacketFatesInternal() {
+    legacy_hal::wifi_error legacy_status;
+    std::vector<legacy_hal::wifi_rx_report> legacy_fates;
+    std::tie(legacy_status, legacy_fates) =
+        legacy_hal_.lock()->getRxPktFates(ifname_);
+    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+        return {createWifiStatusFromLegacyError(legacy_status), {}};
+    }
+    std::vector<WifiDebugRxPacketFateReport> hidl_fates;
+    if (!hidl_struct_util::convertLegacyVectorOfDebugRxPacketFateToHidl(
+            legacy_fates, &hidl_fates)) {
+        return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
+    }
+    return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_fates};
+}
+
+}  // namespace implementation
+}  // namespace V1_2
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
diff --git a/wifi/1.2/default/wifi_sta_iface.h b/wifi/1.2/default/wifi_sta_iface.h
new file mode 100644
index 0000000..423365c
--- /dev/null
+++ b/wifi/1.2/default/wifi_sta_iface.h
@@ -0,0 +1,161 @@
+/*
+ * 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 WIFI_STA_IFACE_H_
+#define WIFI_STA_IFACE_H_
+
+#include <android-base/macros.h>
+#include <android/hardware/wifi/1.0/IWifiStaIface.h>
+#include <android/hardware/wifi/1.0/IWifiStaIfaceEventCallback.h>
+
+#include "hidl_callback_util.h"
+#include "wifi_legacy_hal.h"
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace V1_2 {
+namespace implementation {
+using namespace android::hardware::wifi::V1_0;
+
+/**
+ * HIDL interface object used to control a STA Iface instance.
+ */
+class WifiStaIface : public V1_0::IWifiStaIface {
+   public:
+    WifiStaIface(const std::string& ifname,
+                 const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal);
+    // Refer to |WifiChip::invalidate()|.
+    void invalidate();
+    bool isValid();
+    std::set<sp<IWifiStaIfaceEventCallback>> getEventCallbacks();
+    std::string getName();
+
+    // HIDL methods exposed.
+    Return<void> getName(getName_cb hidl_status_cb) override;
+    Return<void> getType(getType_cb hidl_status_cb) override;
+    Return<void> registerEventCallback(
+        const sp<IWifiStaIfaceEventCallback>& callback,
+        registerEventCallback_cb hidl_status_cb) override;
+    Return<void> getCapabilities(getCapabilities_cb hidl_status_cb) override;
+    Return<void> getApfPacketFilterCapabilities(
+        getApfPacketFilterCapabilities_cb hidl_status_cb) override;
+    Return<void> installApfPacketFilter(
+        uint32_t cmd_id, const hidl_vec<uint8_t>& program,
+        installApfPacketFilter_cb hidl_status_cb) override;
+    Return<void> getBackgroundScanCapabilities(
+        getBackgroundScanCapabilities_cb hidl_status_cb) override;
+    Return<void> getValidFrequenciesForBand(
+        WifiBand band, getValidFrequenciesForBand_cb hidl_status_cb) override;
+    Return<void> startBackgroundScan(
+        uint32_t cmd_id, const StaBackgroundScanParameters& params,
+        startBackgroundScan_cb hidl_status_cb) override;
+    Return<void> stopBackgroundScan(
+        uint32_t cmd_id, stopBackgroundScan_cb hidl_status_cb) override;
+    Return<void> enableLinkLayerStatsCollection(
+        bool debug, enableLinkLayerStatsCollection_cb hidl_status_cb) override;
+    Return<void> disableLinkLayerStatsCollection(
+        disableLinkLayerStatsCollection_cb hidl_status_cb) override;
+    Return<void> getLinkLayerStats(
+        getLinkLayerStats_cb hidl_status_cb) override;
+    Return<void> startRssiMonitoring(
+        uint32_t cmd_id, int32_t max_rssi, int32_t min_rssi,
+        startRssiMonitoring_cb hidl_status_cb) override;
+    Return<void> stopRssiMonitoring(
+        uint32_t cmd_id, stopRssiMonitoring_cb hidl_status_cb) override;
+    Return<void> getRoamingCapabilities(
+        getRoamingCapabilities_cb hidl_status_cb) override;
+    Return<void> configureRoaming(const StaRoamingConfig& config,
+                                  configureRoaming_cb hidl_status_cb) override;
+    Return<void> setRoamingState(StaRoamingState state,
+                                 setRoamingState_cb hidl_status_cb) override;
+    Return<void> enableNdOffload(bool enable,
+                                 enableNdOffload_cb hidl_status_cb) override;
+    Return<void> startSendingKeepAlivePackets(
+        uint32_t cmd_id, const hidl_vec<uint8_t>& ip_packet_data,
+        uint16_t ether_type, const hidl_array<uint8_t, 6>& src_address,
+        const hidl_array<uint8_t, 6>& dst_address, uint32_t period_in_ms,
+        startSendingKeepAlivePackets_cb hidl_status_cb) override;
+    Return<void> stopSendingKeepAlivePackets(
+        uint32_t cmd_id,
+        stopSendingKeepAlivePackets_cb hidl_status_cb) override;
+    Return<void> setScanningMacOui(
+        const hidl_array<uint8_t, 3>& oui,
+        setScanningMacOui_cb hidl_status_cb) override;
+    Return<void> startDebugPacketFateMonitoring(
+        startDebugPacketFateMonitoring_cb hidl_status_cb) override;
+    Return<void> getDebugTxPacketFates(
+        getDebugTxPacketFates_cb hidl_status_cb) override;
+    Return<void> getDebugRxPacketFates(
+        getDebugRxPacketFates_cb hidl_status_cb) override;
+
+   private:
+    // Corresponding worker functions for the HIDL methods.
+    std::pair<WifiStatus, std::string> getNameInternal();
+    std::pair<WifiStatus, IfaceType> getTypeInternal();
+    WifiStatus registerEventCallbackInternal(
+        const sp<IWifiStaIfaceEventCallback>& callback);
+    std::pair<WifiStatus, uint32_t> getCapabilitiesInternal();
+    std::pair<WifiStatus, StaApfPacketFilterCapabilities>
+    getApfPacketFilterCapabilitiesInternal();
+    WifiStatus installApfPacketFilterInternal(
+        uint32_t cmd_id, const std::vector<uint8_t>& program);
+    std::pair<WifiStatus, StaBackgroundScanCapabilities>
+    getBackgroundScanCapabilitiesInternal();
+    std::pair<WifiStatus, std::vector<WifiChannelInMhz>>
+    getValidFrequenciesForBandInternal(WifiBand band);
+    WifiStatus startBackgroundScanInternal(
+        uint32_t cmd_id, const StaBackgroundScanParameters& params);
+    WifiStatus stopBackgroundScanInternal(uint32_t cmd_id);
+    WifiStatus enableLinkLayerStatsCollectionInternal(bool debug);
+    WifiStatus disableLinkLayerStatsCollectionInternal();
+    std::pair<WifiStatus, StaLinkLayerStats> getLinkLayerStatsInternal();
+    WifiStatus startRssiMonitoringInternal(uint32_t cmd_id, int32_t max_rssi,
+                                           int32_t min_rssi);
+    WifiStatus stopRssiMonitoringInternal(uint32_t cmd_id);
+    std::pair<WifiStatus, StaRoamingCapabilities>
+    getRoamingCapabilitiesInternal();
+    WifiStatus configureRoamingInternal(const StaRoamingConfig& config);
+    WifiStatus setRoamingStateInternal(StaRoamingState state);
+    WifiStatus enableNdOffloadInternal(bool enable);
+    WifiStatus startSendingKeepAlivePacketsInternal(
+        uint32_t cmd_id, const std::vector<uint8_t>& ip_packet_data,
+        uint16_t ether_type, const std::array<uint8_t, 6>& src_address,
+        const std::array<uint8_t, 6>& dst_address, uint32_t period_in_ms);
+    WifiStatus stopSendingKeepAlivePacketsInternal(uint32_t cmd_id);
+    WifiStatus setScanningMacOuiInternal(const std::array<uint8_t, 3>& oui);
+    WifiStatus startDebugPacketFateMonitoringInternal();
+    std::pair<WifiStatus, std::vector<WifiDebugTxPacketFateReport>>
+    getDebugTxPacketFatesInternal();
+    std::pair<WifiStatus, std::vector<WifiDebugRxPacketFateReport>>
+    getDebugRxPacketFatesInternal();
+
+    std::string ifname_;
+    std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
+    bool is_valid_;
+    hidl_callback_util::HidlCallbackHandler<IWifiStaIfaceEventCallback>
+        event_cb_handler_;
+
+    DISALLOW_COPY_AND_ASSIGN(WifiStaIface);
+};
+
+}  // namespace implementation
+}  // namespace V1_2
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
+
+#endif  // WIFI_STA_IFACE_H_
diff --git a/wifi/1.2/default/wifi_status_util.cpp b/wifi/1.2/default/wifi_status_util.cpp
new file mode 100644
index 0000000..dd37b6b
--- /dev/null
+++ b/wifi/1.2/default/wifi_status_util.cpp
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "wifi_status_util.h"
+
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace V1_2 {
+namespace implementation {
+
+std::string legacyErrorToString(legacy_hal::wifi_error error) {
+    switch (error) {
+        case legacy_hal::WIFI_SUCCESS:
+            return "SUCCESS";
+        case legacy_hal::WIFI_ERROR_UNINITIALIZED:
+            return "UNINITIALIZED";
+        case legacy_hal::WIFI_ERROR_NOT_AVAILABLE:
+            return "NOT_AVAILABLE";
+        case legacy_hal::WIFI_ERROR_NOT_SUPPORTED:
+            return "NOT_SUPPORTED";
+        case legacy_hal::WIFI_ERROR_INVALID_ARGS:
+            return "INVALID_ARGS";
+        case legacy_hal::WIFI_ERROR_INVALID_REQUEST_ID:
+            return "INVALID_REQUEST_ID";
+        case legacy_hal::WIFI_ERROR_TIMED_OUT:
+            return "TIMED_OUT";
+        case legacy_hal::WIFI_ERROR_TOO_MANY_REQUESTS:
+            return "TOO_MANY_REQUESTS";
+        case legacy_hal::WIFI_ERROR_OUT_OF_MEMORY:
+            return "OUT_OF_MEMORY";
+        case legacy_hal::WIFI_ERROR_BUSY:
+            return "BUSY";
+        case legacy_hal::WIFI_ERROR_UNKNOWN:
+            return "UNKNOWN";
+    }
+}
+
+WifiStatus createWifiStatus(WifiStatusCode code,
+                            const std::string& description) {
+    return {code, description};
+}
+
+WifiStatus createWifiStatus(WifiStatusCode code) {
+    return createWifiStatus(code, "");
+}
+
+WifiStatus createWifiStatusFromLegacyError(legacy_hal::wifi_error error,
+                                           const std::string& desc) {
+    switch (error) {
+        case legacy_hal::WIFI_ERROR_UNINITIALIZED:
+        case legacy_hal::WIFI_ERROR_NOT_AVAILABLE:
+            return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE, desc);
+
+        case legacy_hal::WIFI_ERROR_NOT_SUPPORTED:
+            return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED, desc);
+
+        case legacy_hal::WIFI_ERROR_INVALID_ARGS:
+        case legacy_hal::WIFI_ERROR_INVALID_REQUEST_ID:
+            return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS, desc);
+
+        case legacy_hal::WIFI_ERROR_TIMED_OUT:
+            return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN,
+                                    desc + ", timed out");
+
+        case legacy_hal::WIFI_ERROR_TOO_MANY_REQUESTS:
+            return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN,
+                                    desc + ", too many requests");
+
+        case legacy_hal::WIFI_ERROR_OUT_OF_MEMORY:
+            return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN,
+                                    desc + ", out of memory");
+
+        case legacy_hal::WIFI_ERROR_BUSY:
+            return createWifiStatus(WifiStatusCode::ERROR_BUSY);
+
+        case legacy_hal::WIFI_ERROR_NONE:
+            return createWifiStatus(WifiStatusCode::SUCCESS, desc);
+
+        case legacy_hal::WIFI_ERROR_UNKNOWN:
+            return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN, "unknown");
+    }
+}
+
+WifiStatus createWifiStatusFromLegacyError(legacy_hal::wifi_error error) {
+    return createWifiStatusFromLegacyError(error, "");
+}
+
+}  // namespace implementation
+}  // namespace V1_2
+}  // namespace wifi
+}  // namespace hardware
+}  // namespace android
diff --git a/wifi/1.1/default/wifi_status_util.h b/wifi/1.2/default/wifi_status_util.h
similarity index 97%
rename from wifi/1.1/default/wifi_status_util.h
rename to wifi/1.2/default/wifi_status_util.h
index cc93d66..e9136b3 100644
--- a/wifi/1.1/default/wifi_status_util.h
+++ b/wifi/1.2/default/wifi_status_util.h
@@ -24,7 +24,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_1 {
+namespace V1_2 {
 namespace implementation {
 using namespace android::hardware::wifi::V1_0;
 
@@ -37,7 +37,7 @@
 WifiStatus createWifiStatusFromLegacyError(legacy_hal::wifi_error error);
 
 }  // namespace implementation
-}  // namespace V1_1
+}  // namespace V1_2
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/supplicant/1.1/Android.bp b/wifi/supplicant/1.1/Android.bp
new file mode 100644
index 0000000..c8c8a32
--- /dev/null
+++ b/wifi/supplicant/1.1/Android.bp
@@ -0,0 +1,18 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.wifi.supplicant@1.1",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "ISupplicant.hal",
+    ],
+    interfaces: [
+        "android.hardware.wifi.supplicant@1.0",
+        "android.hidl.base@1.0",
+    ],
+    gen_java: true,
+}
+
diff --git a/wifi/supplicant/1.1/ISupplicant.hal b/wifi/supplicant/1.1/ISupplicant.hal
new file mode 100644
index 0000000..5c60b35
--- /dev/null
+++ b/wifi/supplicant/1.1/ISupplicant.hal
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi.supplicant@1.1;
+
+import @1.0::ISupplicant;
+
+/**
+ * Interface exposed by the supplicant HIDL service registered
+ * with the hardware service manager.
+ * This is the root level object for any the supplicant interactions.
+ */
+interface ISupplicant extends @1.0::ISupplicant {
+};