Merge "[ANAPIC Review] Modify radio 1.6 based on ANAPIC comment" into sc-dev
diff --git a/audio/7.0/config/api/current.txt b/audio/7.0/config/api/current.txt
index 7d2706c..e61ddcb 100644
--- a/audio/7.0/config/api/current.txt
+++ b/audio/7.0/config/api/current.txt
@@ -104,6 +104,7 @@
     enum_constant public static final android.audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_IN_FM_TUNER;
     enum_constant public static final android.audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_IN_HDMI;
     enum_constant public static final android.audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_IN_HDMI_ARC;
+    enum_constant public static final android.audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_IN_HDMI_EARC;
     enum_constant public static final android.audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_IN_IP;
     enum_constant public static final android.audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_IN_LINE;
     enum_constant public static final android.audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_IN_LOOPBACK;
@@ -138,6 +139,7 @@
     enum_constant public static final android.audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_OUT_FM;
     enum_constant public static final android.audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_OUT_HDMI;
     enum_constant public static final android.audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_OUT_HDMI_ARC;
+    enum_constant public static final android.audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_OUT_HDMI_EARC;
     enum_constant public static final android.audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_OUT_HEARING_AID;
     enum_constant public static final android.audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_OUT_IP;
     enum_constant public static final android.audio.policy.configuration.V7_0.AudioDevice AUDIO_DEVICE_OUT_LINE;
@@ -209,6 +211,7 @@
     enum_constant public static final android.audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_DSD;
     enum_constant public static final android.audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_DTS;
     enum_constant public static final android.audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_DTS_HD;
+    enum_constant public static final android.audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_DTS_UHD;
     enum_constant public static final android.audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_EVRC;
     enum_constant public static final android.audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_EVRCB;
     enum_constant public static final android.audio.policy.configuration.V7_0.AudioFormat AUDIO_FORMAT_EVRCNW;
diff --git a/audio/7.0/config/audio_policy_configuration.xsd b/audio/7.0/config/audio_policy_configuration.xsd
index 2030921..77cff91 100644
--- a/audio/7.0/config/audio_policy_configuration.xsd
+++ b/audio/7.0/config/audio_policy_configuration.xsd
@@ -253,6 +253,7 @@
             <xs:enumeration value="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES"/>
             <xs:enumeration value="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER"/>
             <xs:enumeration value="AUDIO_DEVICE_OUT_HDMI"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_HDMI_EARC"/>
             <xs:enumeration value="AUDIO_DEVICE_OUT_AUX_DIGITAL"/>
             <xs:enumeration value="AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET"/>
             <xs:enumeration value="AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET"/>
@@ -304,6 +305,7 @@
             <xs:enumeration value="AUDIO_DEVICE_IN_USB_HEADSET"/>
             <xs:enumeration value="AUDIO_DEVICE_IN_BLUETOOTH_BLE"/>
             <xs:enumeration value="AUDIO_DEVICE_IN_HDMI_ARC"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_HDMI_EARC"/>
             <xs:enumeration value="AUDIO_DEVICE_IN_ECHO_REFERENCE"/>
             <xs:enumeration value="AUDIO_DEVICE_IN_BLE_HEADSET"/>
             <xs:enumeration value="AUDIO_DEVICE_IN_DEFAULT"/>
@@ -412,6 +414,7 @@
             <xs:enumeration value="AUDIO_FORMAT_MPEGH_LC_L3"/>
             <xs:enumeration value="AUDIO_FORMAT_MPEGH_LC_L4"/>
             <xs:enumeration value="AUDIO_FORMAT_IEC60958"/>
+            <xs:enumeration value="AUDIO_FORMAT_DTS_UHD"/>
         </xs:restriction>
     </xs:simpleType>
     <xs:simpleType name="extendableAudioFormat">
diff --git a/audio/common/7.0/enums/include/android_audio_policy_configuration_V7_0-enums.h b/audio/common/7.0/enums/include/android_audio_policy_configuration_V7_0-enums.h
index 7d83556..723d7f8 100644
--- a/audio/common/7.0/enums/include/android_audio_policy_configuration_V7_0-enums.h
+++ b/audio/common/7.0/enums/include/android_audio_policy_configuration_V7_0-enums.h
@@ -155,6 +155,7 @@
         case AudioDevice::AUDIO_DEVICE_OUT_TELEPHONY_TX:
         case AudioDevice::AUDIO_DEVICE_OUT_LINE:
         case AudioDevice::AUDIO_DEVICE_OUT_HDMI_ARC:
+        case AudioDevice::AUDIO_DEVICE_OUT_HDMI_EARC:
         case AudioDevice::AUDIO_DEVICE_OUT_SPDIF:
         case AudioDevice::AUDIO_DEVICE_OUT_FM:
         case AudioDevice::AUDIO_DEVICE_OUT_AUX_LINE:
@@ -197,6 +198,7 @@
         case AudioDevice::AUDIO_DEVICE_IN_USB_HEADSET:
         case AudioDevice::AUDIO_DEVICE_IN_BLUETOOTH_BLE:
         case AudioDevice::AUDIO_DEVICE_IN_HDMI_ARC:
+        case AudioDevice::AUDIO_DEVICE_IN_HDMI_EARC:
         case AudioDevice::AUDIO_DEVICE_IN_ECHO_REFERENCE:
         case AudioDevice::AUDIO_DEVICE_IN_BLE_HEADSET:
         case AudioDevice::AUDIO_DEVICE_IN_DEFAULT:
diff --git a/audio/core/all-versions/default/StreamIn.cpp b/audio/core/all-versions/default/StreamIn.cpp
index 599f3c3..2aeee43 100644
--- a/audio/core/all-versions/default/StreamIn.cpp
+++ b/audio/core/all-versions/default/StreamIn.cpp
@@ -413,8 +413,8 @@
 
     // Create and launch the thread.
     auto tempReadThread =
-        std::make_unique<ReadThread>(&mStopReadThread, mStream, tempCommandMQ.get(),
-                                     tempDataMQ.get(), tempStatusMQ.get(), tempElfGroup.get());
+            sp<ReadThread>::make(&mStopReadThread, mStream, tempCommandMQ.get(), tempDataMQ.get(),
+                                 tempStatusMQ.get(), tempElfGroup.get());
     if (!tempReadThread->init()) {
         ALOGW("failed to start reader thread: %s", strerror(-status));
         sendError(Result::INVALID_ARGUMENTS);
@@ -430,7 +430,7 @@
     mCommandMQ = std::move(tempCommandMQ);
     mDataMQ = std::move(tempDataMQ);
     mStatusMQ = std::move(tempStatusMQ);
-    mReadThread = tempReadThread.release();
+    mReadThread = tempReadThread;
     mEfGroup = tempElfGroup.release();
 #if MAJOR_VERSION <= 6
     threadInfo.pid = getpid();
diff --git a/audio/core/all-versions/default/StreamOut.cpp b/audio/core/all-versions/default/StreamOut.cpp
index 5e4dd2a..6eed3da 100644
--- a/audio/core/all-versions/default/StreamOut.cpp
+++ b/audio/core/all-versions/default/StreamOut.cpp
@@ -398,8 +398,8 @@
 
     // Create and launch the thread.
     auto tempWriteThread =
-        std::make_unique<WriteThread>(&mStopWriteThread, mStream, tempCommandMQ.get(),
-                                      tempDataMQ.get(), tempStatusMQ.get(), tempElfGroup.get());
+            sp<WriteThread>::make(&mStopWriteThread, mStream, tempCommandMQ.get(), tempDataMQ.get(),
+                                  tempStatusMQ.get(), tempElfGroup.get());
     if (!tempWriteThread->init()) {
         ALOGW("failed to start writer thread: %s", strerror(-status));
         sendError(Result::INVALID_ARGUMENTS);
@@ -415,7 +415,7 @@
     mCommandMQ = std::move(tempCommandMQ);
     mDataMQ = std::move(tempDataMQ);
     mStatusMQ = std::move(tempStatusMQ);
-    mWriteThread = tempWriteThread.release();
+    mWriteThread = tempWriteThread;
     mEfGroup = tempElfGroup.release();
 #if MAJOR_VERSION <= 6
     threadInfo.pid = getpid();
diff --git a/audio/core/all-versions/default/util/CoreUtils.cpp b/audio/core/all-versions/default/util/CoreUtils.cpp
index 14f76f3..773be21 100644
--- a/audio/core/all-versions/default/util/CoreUtils.cpp
+++ b/audio/core/all-versions/default/util/CoreUtils.cpp
@@ -66,13 +66,13 @@
     CONVERT_CHECKED(
             deviceAddressFromHal(halMicInfo.device, halMicInfo.address, &micInfo->deviceAddress),
             result);
-    size_t chCount;
-    for (chCount = 0; chCount < AUDIO_CHANNEL_COUNT_MAX; ++chCount) {
-        if (halMicInfo.channel_mapping[chCount] == AUDIO_MICROPHONE_CHANNEL_MAPPING_UNUSED) {
+    int chCount;
+    for (chCount = AUDIO_CHANNEL_COUNT_MAX - 1; chCount >= 0; --chCount) {
+        if (halMicInfo.channel_mapping[chCount] != AUDIO_MICROPHONE_CHANNEL_MAPPING_UNUSED) {
             break;
         }
     }
-    micInfo->channelMapping.resize(chCount);
+    micInfo->channelMapping.resize(chCount + 1);
     for (size_t ch = 0; ch < micInfo->channelMapping.size(); ch++) {
         micInfo->channelMapping[ch] = AudioMicrophoneChannelMapping(halMicInfo.channel_mapping[ch]);
     }
diff --git a/automotive/vehicle/2.0/default/Android.bp b/automotive/vehicle/2.0/default/Android.bp
index b2f8bf6..d6f3120 100644
--- a/automotive/vehicle/2.0/default/Android.bp
+++ b/automotive/vehicle/2.0/default/Android.bp
@@ -210,6 +210,7 @@
     vendor: true,
     relative_install_path: "hw",
     srcs: ["VehicleService.cpp"],
+    cflags: ["-DENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING"],
     shared_libs: [
         "libbase",
         "libjsoncpp",
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 19b0a35..2cc956d 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
@@ -115,6 +115,28 @@
  */
 const int32_t kMixedTypePropertyForTest =
         0x1111 | VehiclePropertyGroup::VENDOR | VehicleArea::GLOBAL | VehiclePropertyType::MIXED;
+
+#ifdef ENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING
+/**
+ * Converts the system property to the vendor property.
+ * WARNING: This is only for the end-to-end testing, Should NOT include in the
+ * user build */
+inline constexpr int32_t toVendor(VehicleProperty prop) {
+    return (toInt(prop) & ~toInt(VehiclePropertyGroup::MASK)) | VehiclePropertyGroup::VENDOR;
+}
+
+/**
+ * These properties are used for the end-to-end testing of ClusterHomeService.
+ */
+constexpr int32_t VENDOR_CLUSTER_SWITCH_UI = toVendor(VehicleProperty::CLUSTER_SWITCH_UI);
+constexpr int32_t VENDOR_CLUSTER_DISPLAY_STATE = toVendor(VehicleProperty::CLUSTER_DISPLAY_STATE);
+constexpr int32_t VENDOR_CLUSTER_REPORT_STATE = toVendor(VehicleProperty::CLUSTER_REPORT_STATE);
+constexpr int32_t VENDOR_CLUSTER_REQUEST_DISPLAY =
+        toVendor(VehicleProperty::CLUSTER_REQUEST_DISPLAY);
+constexpr int32_t VENDOR_CLUSTER_NAVIGATION_STATE =
+        toVendor(VehicleProperty::CLUSTER_NAVIGATION_STATE);
+#endif  // ENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING
+
 /**
  * FakeDataCommand enum defines the supported command type for kGenerateFakeDataControllingProperty.
  * All those commands can be send independently with each other. And each will override the one sent
@@ -1064,6 +1086,16 @@
                     .changeMode = VehiclePropertyChangeMode::ON_CHANGE},
          .initialValue = {.stringValue = "Vendor String Property"}},
 
+        {.config = {.prop = toInt(VehicleProperty::ELECTRONIC_TOLL_COLLECTION_CARD_TYPE),
+                    .access = VehiclePropertyAccess::READ,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE},
+         .initialValue = {.int32Values = {0}}},
+
+        {.config = {.prop = toInt(VehicleProperty::ELECTRONIC_TOLL_COLLECTION_CARD_STATUS),
+                    .access = VehiclePropertyAccess::READ,
+                    .changeMode = VehiclePropertyChangeMode::ON_CHANGE},
+         .initialValue = {.int32Values = {0}}},
+
         {.config =
                  {
                          .prop = toInt(VehicleProperty::SUPPORT_CUSTOMIZE_VENDOR_PERMISSION),
@@ -1227,6 +1259,50 @@
                                 .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
                         },
         },
+#ifdef ENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING
+        // Vendor propetry for E2E ClusterHomeService testing.
+        {
+                .config =
+                        {
+                                .prop = VENDOR_CLUSTER_SWITCH_UI,
+                                .access = VehiclePropertyAccess::WRITE,
+                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                        },
+        },
+        {
+                .config =
+                        {
+                                .prop = VENDOR_CLUSTER_DISPLAY_STATE,
+                                .access = VehiclePropertyAccess::WRITE,
+                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                        },
+        },
+        {
+                .config =
+                        {
+                                .prop = VENDOR_CLUSTER_REPORT_STATE,
+                                .access = VehiclePropertyAccess::READ,
+                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                                .configArray = {0, 0, 0, 9, 0, 0, 0, 0, 16},
+                        },
+        },
+        {
+                .config =
+                        {
+                                .prop = VENDOR_CLUSTER_REQUEST_DISPLAY,
+                                .access = VehiclePropertyAccess::READ,
+                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                        },
+        },
+        {
+                .config =
+                        {
+                                .prop = VENDOR_CLUSTER_NAVIGATION_STATE,
+                                .access = VehiclePropertyAccess::READ,
+                                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                        },
+        },
+#endif  // ENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING
 };
 
 }  // impl
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.cpp
index 0ee1835..6b87052 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.cpp
@@ -247,6 +247,28 @@
                     break;
             }
             break;
+
+#ifdef ENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING
+        case toInt(VehicleProperty::CLUSTER_REPORT_STATE):
+        case toInt(VehicleProperty::CLUSTER_REQUEST_DISPLAY):
+        case toInt(VehicleProperty::CLUSTER_NAVIGATION_STATE):
+        case VENDOR_CLUSTER_SWITCH_UI:
+        case VENDOR_CLUSTER_DISPLAY_STATE: {
+            auto updatedPropValue = createVehiclePropValue(getPropType(value.prop), 0);
+            updatedPropValue->prop = value.prop & ~toInt(VehiclePropertyGroup::MASK);
+            if (isSystemProperty(value.prop)) {
+                updatedPropValue->prop |= toInt(VehiclePropertyGroup::VENDOR);
+            } else {
+                updatedPropValue->prop |= toInt(VehiclePropertyGroup::SYSTEM);
+            }
+            updatedPropValue->value = value.value;
+            updatedPropValue->timestamp = elapsedRealtimeNano();
+            updatedPropValue->areaId = value.areaId;
+            onPropertyValueFromCar(*updatedPropValue, updateStatus);
+            return StatusCode::OK;
+        }
+#endif  // ENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING
+
         default:
             break;
     }
diff --git a/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal
index 1fe4bac..1fb7dc7 100644
--- a/automotive/vehicle/2.0/types.hal
+++ b/automotive/vehicle/2.0/types.hal
@@ -3207,6 +3207,66 @@
          | VehiclePropertyType:BYTES
          | VehicleArea:GLOBAL),
 
+    /**
+     * Electronic Toll Collection card type.
+     *
+     * This property indicates the type of ETC card in this vehicle.
+     * If the head unit is aware of an ETC card attached to the vehicle, this property should
+     * return the type of card attached; otherwise, this property should be UNAVAILABLE.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     * @data_enum ElectronicTollCollectionCardType
+     */
+     ELECTRONIC_TOLL_COLLECTION_CARD_TYPE = (
+         0x0F39
+         | VehiclePropertyGroup:SYSTEM
+         | VehiclePropertyType:INT32
+         | VehicleArea:GLOBAL),
+
+    /**
+     * Electronic Toll Collection card status.
+     *
+     * This property indicates the status of ETC card in this vehicle.
+     * If the head unit is aware of an ETC card attached to the vehicle,
+     * ELECTRONIC_TOLL_COLLECTION_CARD_TYPE gives that status of the card; otherwise,
+     * this property should be UNAVAILABLE.
+     *
+     * @change_mode VehiclePropertyChangeMode:ON_CHANGE
+     * @access VehiclePropertyAccess:READ
+     * @data_enum ElectronicTollCollectionCardStatus
+     */
+     ELECTRONIC_TOLL_COLLECTION_CARD_STATUS = (
+         0x0F3A
+         | VehiclePropertyGroup:SYSTEM
+         | VehiclePropertyType:INT32
+         | VehicleArea:GLOBAL),
+};
+
+/**
+ * Used by ELECTRONIC_TOLL_COLLECTION_CARD_TYPE.
+ */
+enum ElectronicTollCollectionCardType : int32_t {
+    // Type is unknown or not in the list below.
+    UNKNOWN = 0,
+    // A Japanese ETC card reader that does not support ETC 2.0.
+    JP_ELECTRONIC_TOLL_COLLECTION_CARD = 1,
+    // A Japanese ETC 2.0 card reader.
+    JP_ELECTRONIC_TOLL_COLLECTION_CARD_V2 = 2,
+};
+
+/**
+ * Used by ELECTRONIC_TOLL_COLLECTION_CARD_STATUS.
+ */
+enum ElectronicTollCollectionCardStatus : int32_t {
+    // Status could not be determined
+    UNKNOWN = 0,
+    // A valid ETC card is present
+    ELECTRONIC_TOLL_COLLECTION_CARD_VALID = 1,
+    // An ETC card is present, but it is expired or otherwise invalid
+    ELECTRONIC_TOLL_COLLECTION_CARD_INVALID = 2,
+    // No ETC card is inserted in the reader.
+    ELECTRONIC_TOLL_COLLECTION_CARD_NOT_INSERTED = 3,
 };
 
 /**
diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/Feature.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/Feature.aidl
index a8faf06..1875b97 100644
--- a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/Feature.aidl
+++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/Feature.aidl
@@ -34,7 +34,7 @@
 package android.hardware.biometrics.face;
 @Backing(type="byte") @VintfStability
 enum Feature {
-  WAVE_ATTENTION_REQUIREMENT = 0,
-  WAVE_DIVERSE_POSES_REQUIREMENT = 1,
+  REQUIRE_ATTENTION = 0,
+  REQUIRE_DIVERSE_POSES = 1,
   DEBUG = 2,
 }
diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/ISession.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/ISession.aidl
index 9033989..1ee3caf 100644
--- a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/ISession.aidl
+++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/ISession.aidl
@@ -41,8 +41,8 @@
   android.hardware.biometrics.common.ICancellationSignal detectInteraction();
   void enumerateEnrollments();
   void removeEnrollments(in int[] enrollmentIds);
-  void getFeatures(in int enrollmentId);
-  void setFeature(in android.hardware.keymaster.HardwareAuthToken hat, in int enrollmentId, in android.hardware.biometrics.face.Feature feature, boolean enabled);
+  void getFeatures();
+  void setFeature(in android.hardware.keymaster.HardwareAuthToken hat, in android.hardware.biometrics.face.Feature feature, boolean enabled);
   void getAuthenticatorId();
   void invalidateAuthenticatorId();
   void resetLockout(in android.hardware.keymaster.HardwareAuthToken hat);
diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/ISessionCallback.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/ISessionCallback.aidl
index 2bb053a..bbace29 100644
--- a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/ISessionCallback.aidl
+++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/ISessionCallback.aidl
@@ -47,8 +47,8 @@
   void onLockoutCleared();
   void onInteractionDetected();
   void onEnrollmentsEnumerated(in int[] enrollmentIds);
-  void onFeaturesRetrieved(in android.hardware.biometrics.face.Feature[] features, in int enrollmentId);
-  void onFeatureSet(in int enrollmentId, android.hardware.biometrics.face.Feature feature);
+  void onFeaturesRetrieved(in android.hardware.biometrics.face.Feature[] features);
+  void onFeatureSet(android.hardware.biometrics.face.Feature feature);
   void onEnrollmentsRemoved(in int[] enrollmentIds);
   void onAuthenticatorIdRetrieved(in long authenticatorId);
   void onAuthenticatorIdInvalidated(in long newAuthenticatorId);
diff --git a/biometrics/face/aidl/android/hardware/biometrics/face/Feature.aidl b/biometrics/face/aidl/android/hardware/biometrics/face/Feature.aidl
index b88050a..bff1a02 100644
--- a/biometrics/face/aidl/android/hardware/biometrics/face/Feature.aidl
+++ b/biometrics/face/aidl/android/hardware/biometrics/face/Feature.aidl
@@ -20,20 +20,19 @@
 @Backing(type="byte")
 enum Feature {
     /**
-     * Do not require the user to look at the device during enrollment and authentication. Note
-     * this is to accommodate people who have limited vision.
+     * Require the user to look at the device during enrollment and authentication. This feature
+     * can be disabled to accommodate people who have limited vision.
      */
-    WAVE_ATTENTION_REQUIREMENT,
+    REQUIRE_ATTENTION,
 
     /**
-     * Do not require a diverse set of poses during enrollment. This is to accommodate people with
-     * limited mobility.
+     * Require a diverse set of poses during enrollment. This feature can be disabled to accommodate
+     * people with limited mobility.
      */
-    WAVE_DIVERSE_POSES_REQUIREMENT,
+    REQUIRE_DIVERSE_POSES,
 
     /**
      * Enable debugging functionality.
      */
     DEBUG,
 }
-
diff --git a/biometrics/face/aidl/android/hardware/biometrics/face/ISession.aidl b/biometrics/face/aidl/android/hardware/biometrics/face/ISession.aidl
index 9734873..12911e3 100644
--- a/biometrics/face/aidl/android/hardware/biometrics/face/ISession.aidl
+++ b/biometrics/face/aidl/android/hardware/biometrics/face/ISession.aidl
@@ -249,38 +249,34 @@
     /**
      * getFeatures:
      *
-     * Returns a list of currently enabled features for the provided enrollmentId.
+     * Returns a list of currently enabled features for this (sensorId, userId) pair.
      *
-     * If the enrollmentId is invalid, the HAL must invoke ISessionCallback#onError with
+     * If the user is not enrolled, the HAL must invoke ISessionCallback#onError with
      * Error::UNABLE_TO_PROCESS.
      *
      * The HAL must notify the framework about the result by calling
      * ISessionCallback#onFeaturesRetrieved.
-     *
-     * @param enrollmentId the ID of the enrollment for which the features are requested.
      */
-    void getFeatures(in int enrollmentId);
+    void getFeatures();
 
     /**
      * setFeature:
      *
-     * Enables or disables a feature for the given enrollmentId. Because certain features may
+     * Enables or disables a feature for this (sensorId, userId) pair. Because certain features may
      * decrease security, the user must enter their password before this method is invoked
      * (see @param hat). The HAL must verify the hat before changing any feature state.
      *
-     * If either the hat or enrollmentId is invalid, the HAL must invoke ISessionCallback#onError
-     * with Error::UNABLE_TO_PROCESS.
+     * If the hat is invalid or if the user is not enrolled, the HAL must invoke
+     * ISessionCallback#onError with Error::UNABLE_TO_PROCESS.
      *
      * After the feature is successfully set, the HAL must notify the framework by calling
      * ISessionCallback#onFeatureSet.
      *
      * @param hat HardwareAuthToken See above documentation.
-     * @param enrollmentId the ID of the enrollment for which the feature update is requested.
      * @param feature The feature to be enabled or disabled.
      * @param enabled Whether the provided features should be enabled or disabled.
      */
-    void setFeature(
-            in HardwareAuthToken hat, in int enrollmentId, in Feature feature, boolean enabled);
+    void setFeature(in HardwareAuthToken hat, in Feature feature, boolean enabled);
 
     /**
      * getAuthenticatorId:
diff --git a/biometrics/face/aidl/android/hardware/biometrics/face/ISessionCallback.aidl b/biometrics/face/aidl/android/hardware/biometrics/face/ISessionCallback.aidl
index a2601e7..23570bd 100644
--- a/biometrics/face/aidl/android/hardware/biometrics/face/ISessionCallback.aidl
+++ b/biometrics/face/aidl/android/hardware/biometrics/face/ISessionCallback.aidl
@@ -172,22 +172,21 @@
     /**
      * This method must only be used to notify the framework during ISession#getFeatures.
      *
-     * Provides a list of features that are currently enabled for the given enrollmentId.
+     * Provides a list of features that are currently enabled for the session's (userId, sensorId)
+     * pair.
      *
      * @param features A list of currently enabled features. See the Feature enum.
-     * @param enrollmentId The enrollment for which the features were requested.
      */
-    void onFeaturesRetrieved(in Feature[] features, in int enrollmentId);
+    void onFeaturesRetrieved(in Feature[] features);
 
     /**
      * This method must only be used to notify the framework during ISession#setFeature.
      *
      * Notifies the framework that ISession#setFeature has completed.
      *
-     * @param enrollmentId The enrollment for which a feature was set.
      * @param feature The feature that was set.
      */
-    void onFeatureSet(in int enrollmentId, Feature feature);
+    void onFeatureSet(Feature feature);
 
     /**
      * This method must only be used to notify the framework during
diff --git a/biometrics/face/aidl/default/Session.cpp b/biometrics/face/aidl/default/Session.cpp
index b5eb717..4438d35 100644
--- a/biometrics/face/aidl/default/Session.cpp
+++ b/biometrics/face/aidl/default/Session.cpp
@@ -92,14 +92,13 @@
     return ndk::ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus Session::getFeatures(int32_t /*enrollmentId*/) {
+ndk::ScopedAStatus Session::getFeatures() {
     LOG(INFO) << "getFeatures";
     return ndk::ScopedAStatus::ok();
 }
 
 ndk::ScopedAStatus Session::setFeature(const keymaster::HardwareAuthToken& /*hat*/,
-                                       int32_t /*enrollmentId*/, Feature /*feature*/,
-                                       bool /*enabled*/) {
+                                       Feature /*feature*/, bool /*enabled*/) {
     LOG(INFO) << "setFeature";
     return ndk::ScopedAStatus::ok();
 }
diff --git a/biometrics/face/aidl/default/Session.h b/biometrics/face/aidl/default/Session.h
index 73cdf08..c89985e 100644
--- a/biometrics/face/aidl/default/Session.h
+++ b/biometrics/face/aidl/default/Session.h
@@ -50,10 +50,10 @@
 
     ndk::ScopedAStatus removeEnrollments(const std::vector<int32_t>& enrollmentIds) override;
 
-    ndk::ScopedAStatus getFeatures(int32_t enrollmentId) override;
+    ndk::ScopedAStatus getFeatures() override;
 
-    ndk::ScopedAStatus setFeature(const keymaster::HardwareAuthToken& hat, int32_t enrollmentId,
-                                  Feature feature, bool enabled) override;
+    ndk::ScopedAStatus setFeature(const keymaster::HardwareAuthToken& hat, Feature feature,
+                                  bool enabled) override;
 
     ndk::ScopedAStatus getAuthenticatorId() override;
 
diff --git a/biometrics/face/aidl/vts/VtsHalBiometricsFaceTargetTest.cpp b/biometrics/face/aidl/vts/VtsHalBiometricsFaceTargetTest.cpp
index 60e0a2a..ada6f73 100644
--- a/biometrics/face/aidl/vts/VtsHalBiometricsFaceTargetTest.cpp
+++ b/biometrics/face/aidl/vts/VtsHalBiometricsFaceTargetTest.cpp
@@ -104,12 +104,11 @@
         return ndk::ScopedAStatus::ok();
     }
 
-    ndk::ScopedAStatus onFeaturesRetrieved(const std::vector<Feature>& /*features*/,
-                                           int32_t /*enrollmentId*/) override {
+    ndk::ScopedAStatus onFeaturesRetrieved(const std::vector<Feature>& /*features*/) override {
         return ndk::ScopedAStatus::ok();
     }
 
-    ndk::ScopedAStatus onFeatureSet(int32_t /*enrollmentId*/, Feature /*feature*/) override {
+    ndk::ScopedAStatus onFeatureSet(Feature /*feature*/) override {
         return ndk::ScopedAStatus::ok();
     }
 
diff --git a/camera/device/3.7/Android.bp b/camera/device/3.7/Android.bp
index 15c1b5c..be08e91 100644
--- a/camera/device/3.7/Android.bp
+++ b/camera/device/3.7/Android.bp
@@ -16,6 +16,7 @@
         "types.hal",
         "ICameraDevice.hal",
         "ICameraDeviceSession.hal",
+        "ICameraInjectionSession.hal",
     ],
     interfaces: [
         "android.hardware.camera.common@1.0",
diff --git a/camera/device/3.7/ICameraInjectionSession.hal b/camera/device/3.7/ICameraInjectionSession.hal
new file mode 100644
index 0000000..f5797c3
--- /dev/null
+++ b/camera/device/3.7/ICameraInjectionSession.hal
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.camera.device@3.7;
+
+import android.hardware.camera.common@1.0::Status;
+import @3.2::BufferCache;
+import @3.2::CameraMetadata;
+import @3.5::StreamConfiguration;
+import @3.6::HalStreamConfiguration;
+import @3.7::ICameraDeviceSession;
+
+/**
+ * Injection Camera device active session interface.
+ *
+ * When an external camera is injected to replace the internal camera session, the
+ * injection session will be established in camera framework, and then
+ * configureInjectionStreams() will be called to ask the external camera to
+ * configure itself to match the stream configuration of the internal camera.
+ *
+ * Camera framework is responsible to close the injection session once the client
+ * switch back to internal camera streaming.
+ *
+ * If the external camera cannot support the configuration ILLEGAL_ARGUMENT will
+ * be returned.
+ */
+interface ICameraInjectionSession extends @3.7::ICameraDeviceSession {
+    /**
+     * configureInjectionStreams:
+     *
+     * Identical to @3.7::ICameraDeviceSession.configureStreams_3_7, except that:
+     *
+     * @param requestedConfiguration
+     *     The current stream configuration of the internal camera session and
+     *     the injection camera must follow the configuration without overriding
+     *     any part of it.
+     * @param characteristics
+     *     The characteristics of internal camera contains a list of keys so that
+     *     the stream continuity can be maintained after the external camera is
+     *     injected.
+     *
+     * @return status Status code for the operation, one of:
+     *     OK:
+     *         On successful stream configuration.
+     *     INTERNAL_ERROR:
+     *         If there has been a fatal error and the device is no longer
+     *         operational. Only close() can be called successfully by the
+     *         framework after this error is returned.
+     *     ILLEGAL_ARGUMENT:
+     *         If the requested stream configuration is invalid. Some examples
+     *         of invalid stream configurations include:
+     *           - Not including any OUTPUT streams
+     *           - Including streams with unsupported formats, or an unsupported
+     *             size for that format.
+     *           - Including too many output streams of a certain format.
+     *           - Unsupported rotation configuration
+     *           - Stream sizes/formats don't satisfy the
+     *             StreamConfigurationMode requirements
+     *             for non-NORMAL mode, or the requested operation_mode is not
+     *             supported by the HAL.
+     *           - Unsupported usage flag
+     *         The camera service cannot filter out all possible illegal stream
+     *         configurations, since some devices may support more simultaneous
+     *         streams or larger stream resolutions than the minimum required
+     *         for a given camera device hardware level. The HAL must return an
+     *         ILLEGAL_ARGUMENT for any unsupported stream set, and then be
+     *         ready to accept a future valid stream configuration in a later
+     *         configureInjectionStreams call.
+     */
+    configureInjectionStreams(StreamConfiguration requestedConfiguration,
+            CameraMetadata characteristics) generates (Status status);
+};
diff --git a/common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/Ashmem.aidl b/common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/Ashmem.aidl
new file mode 100644
index 0000000..a438031
--- /dev/null
+++ b/common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/Ashmem.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.common;
+@VintfStability
+parcelable Ashmem {
+  ParcelFileDescriptor fd;
+  long size;
+}
diff --git a/common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/MappableFile.aidl b/common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/MappableFile.aidl
new file mode 100644
index 0000000..394ea8f
--- /dev/null
+++ b/common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/MappableFile.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.common;
+@VintfStability
+parcelable MappableFile {
+  long length;
+  int prot;
+  ParcelFileDescriptor fd;
+  long offset;
+}
diff --git a/common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/NativeHandle.aidl b/common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/NativeHandle.aidl
index f37b7d5..2ed5c0b 100644
--- a/common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/NativeHandle.aidl
+++ b/common/aidl/aidl_api/android.hardware.common/current/android/hardware/common/NativeHandle.aidl
@@ -1,14 +1,30 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 ///////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
-// This file is a snapshot of an AIDL interface (or parcelable). Do not try to
-// edit this file. It looks like you are doing that because you have modified
-// an AIDL interface in a backward-incompatible way, e.g., deleting a function
-// from an interface or a field from a parcelable and it broke the build. That
-// breakage is intended.
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
 //
-// You must not make a backward incompatible changes to the AIDL files built
+// You must not make a backward incompatible change to any AIDL file built
 // with the aidl_interface module type with versions property set. The module
 // type is used to build AIDL files in a way that they can be used across
 // independently updatable components of the system. If a device is shipped
diff --git a/common/aidl/android/hardware/common/Ashmem.aidl b/common/aidl/android/hardware/common/Ashmem.aidl
new file mode 100644
index 0000000..8e40266
--- /dev/null
+++ b/common/aidl/android/hardware/common/Ashmem.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2021 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.common;
+
+import android.os.ParcelFileDescriptor;
+
+/**
+ * Type that holds same memory as the "ashmem" hidl_memory type from HIDL.
+ */
+@VintfStability
+parcelable Ashmem {
+    /**
+     * A handle to a memory region.
+     */
+    ParcelFileDescriptor fd;
+    /**
+     * Size of the memory region in bytes.
+     */
+    long size;
+}
diff --git a/common/aidl/android/hardware/common/MappableFile.aidl b/common/aidl/android/hardware/common/MappableFile.aidl
new file mode 100644
index 0000000..a7763ea
--- /dev/null
+++ b/common/aidl/android/hardware/common/MappableFile.aidl
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2021 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.common;
+
+import android.os.ParcelFileDescriptor;
+
+/**
+ * A region of a file that can be mapped into memory.
+ *
+ * In Linux, MappableFile may be used with mmap as `MAP_SHARED`.
+ *
+ * MappableFile is compatible with ::android::base::MappedFile.
+ */
+@VintfStability
+parcelable MappableFile {
+    /**
+     * Length of the mapping region in bytes.
+     */
+    long length;
+    /**
+     * The desired memory protection for the mapping.
+     *
+     * In Linux, prot is either `PROT_NONE` (indicating that mapped pages may not be accessed) or
+     * the bitwise OR of one or more of the following flags:
+     * - `PROT_READ` (indicating that the mapped pages may be read)
+     * - `PROT_WRITE` (indicating that the mapped pages may be written)
+     */
+    int prot;
+    /**
+     * A handle to a mappable file.
+     */
+    ParcelFileDescriptor fd;
+    /**
+     * The offset in the file to the beginning of the mapping region in number of bytes.
+     *
+     * Note: Some mapping functions require that the offset is aligned to the page size.
+     */
+    long offset;
+}
diff --git a/common/support/Android.bp b/common/support/Android.bp
index 8aea306..730798d 100644
--- a/common/support/Android.bp
+++ b/common/support/Android.bp
@@ -18,6 +18,11 @@
         "android.hardware.common-V2-ndk_platform",
         "libcutils",
     ],
+    apex_available: [
+        "//apex_available:platform",
+        "com.android.neuralnetworks",
+    ],
+    min_sdk_version: "29",
 }
 
 cc_test {
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index c656af2..bb22974 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -419,7 +419,7 @@
     </hal>
     <hal format="aidl" optional="false">
         <name>android.hardware.power</name>
-        <version>1</version>
+        <version>1-2</version>
         <interface>
             <name>IPower</name>
             <instance>default</instance>
diff --git a/current.txt b/current.txt
index 6c576ca..270880f 100644
--- a/current.txt
+++ b/current.txt
@@ -782,6 +782,8 @@
 f729ee6a5f136b25d79ea6895d24700fce413df555baaecf2c39e4440d15d043 android.hardware.neuralnetworks@1.0::types
 a84f8dac7a9b75de1cc2936a9b429b9b62b32a31ea88ca52c29f98f5ddc0fa95 android.hardware.neuralnetworks@1.2::types
 cd331b92312d16ab89f475c39296abbf539efc4114a8c5c2b136ad99b904ef33 android.hardware.neuralnetworks@1.3::types
+c3fec5bd470984402997f78a74b6511efc4063b270f2bd9ee7b78f48b683a1bb android.hardware.neuralnetworks@1.3::IDevice
+0fdfad62c2ec33b52e6687004e5a1971c02d10b93ee4d26df5ccff7ce032494a android.hardware.neuralnetworks@1.3::IPreparedModel
 e8c86c69c438da8d1549856c1bb3e2d1b8da52722f8235ff49a30f2cce91742c android.hardware.soundtrigger@2.1::ISoundTriggerHwCallback
 b9fbb6e2e061ed0960939d48b785e9700210add1f13ed32ecd688d0f1ca20ef7 android.hardware.renderscript@1.0::types
 0f53d70e1eadf8d987766db4bf6ae2048004682168f4cab118da576787def3fa android.hardware.radio@1.0::types
diff --git a/drm/1.2/vts/functional/drm_hal_test.cpp b/drm/1.2/vts/functional/drm_hal_test.cpp
index 0dfff26..2d1068d 100644
--- a/drm/1.2/vts/functional/drm_hal_test.cpp
+++ b/drm/1.2/vts/functional/drm_hal_test.cpp
@@ -172,6 +172,7 @@
 TEST_P(DrmHalTest, OfflineLicenseTest) {
     auto sessionId = openSession();
     hidl_vec<uint8_t> keySetId = loadKeys(sessionId, KeyType::OFFLINE);
+    closeSession(sessionId);
 
     auto res = drmPlugin->getOfflineLicenseKeySetIds(
             [&](Status status, const hidl_vec<KeySetId>& keySetIds) {
@@ -201,8 +202,6 @@
 
     err = drmPlugin->removeOfflineLicense(keySetId);
     EXPECT_EQ(Status::BAD_VALUE, err);
-
-    closeSession(sessionId);
 }
 
 /**
@@ -212,6 +211,8 @@
     auto sessionId = openSession();
     DrmHalVTSVendorModule_V1::ContentConfiguration content = getContent(KeyType::OFFLINE);
     hidl_vec<uint8_t> keySetId = loadKeys(sessionId, content, KeyType::OFFLINE);
+    closeSession(sessionId);
+
     drmPlugin->getOfflineLicenseState(keySetId, checkKeySetIdState<Status::OK, OfflineLicenseState::USABLE>);
 
     hidl_vec<uint8_t> keyRequest = getKeyRequest(keySetId, content, KeyType::RELEASE);
@@ -226,7 +227,6 @@
 
     provideKeyResponse(keySetId, keyResponse);
     drmPlugin->getOfflineLicenseState(keySetId, checkKeySetIdState<Status::BAD_VALUE, OfflineLicenseState::UNKNOWN>);
-    closeSession(sessionId);
 }
 
 /**
diff --git a/graphics/common/aidl/Android.bp b/graphics/common/aidl/Android.bp
index 2a46f9d..cadd13c 100644
--- a/graphics/common/aidl/Android.bp
+++ b/graphics/common/aidl/Android.bp
@@ -34,6 +34,7 @@
             apex_available: [
                 "//apex_available:platform",
                 "com.android.media.swcodec",
+                "com.android.neuralnetworks",
             ],
             min_sdk_version: "29",
         },
diff --git a/identity/aidl/default/Android.bp b/identity/aidl/default/Android.bp
index 05b3662..a124b1e 100644
--- a/identity/aidl/default/Android.bp
+++ b/identity/aidl/default/Android.bp
@@ -31,7 +31,7 @@
     ],
     static_libs: [
         "libbase",
-        "libcppbor",
+        "libcppbor_external",
         "libutils",
         "libsoft_attestation_cert",
         "libkeymaster_portable",
@@ -91,7 +91,7 @@
     ],
     static_libs: [
         "libbase",
-        "libcppbor",
+        "libcppbor_external",
         "libutils",
         "libsoft_attestation_cert",
         "libkeymaster_portable",
diff --git a/identity/aidl/default/common/IdentityCredential.cpp b/identity/aidl/default/common/IdentityCredential.cpp
index c8ee0dd..95557b5 100644
--- a/identity/aidl/default/common/IdentityCredential.cpp
+++ b/identity/aidl/default/common/IdentityCredential.cpp
@@ -488,7 +488,7 @@
         }
 
         for (size_t n = 0; n < nsMap->size(); n++) {
-            auto [nsKeyItem, nsValueItem] = (*nsMap)[n];
+            auto& [nsKeyItem, nsValueItem] = (*nsMap)[n];
             const cppbor::Tstr* nsKey = nsKeyItem->asTstr();
             const cppbor::Map* nsInnerMap = nsValueItem->asMap();
             if (nsKey == nullptr || nsInnerMap == nullptr) {
diff --git a/identity/aidl/default/common/IdentityCredential.h b/identity/aidl/default/common/IdentityCredential.h
index 9913b86..ef9d133 100644
--- a/identity/aidl/default/common/IdentityCredential.h
+++ b/identity/aidl/default/common/IdentityCredential.h
@@ -27,7 +27,7 @@
 #include <string>
 #include <vector>
 
-#include <cppbor/cppbor.h>
+#include <cppbor.h>
 
 #include "IdentityCredentialStore.h"
 #include "SecureHardwareProxy.h"
diff --git a/identity/aidl/default/common/WritableIdentityCredential.cpp b/identity/aidl/default/common/WritableIdentityCredential.cpp
index 2d897c7..25f129b 100644
--- a/identity/aidl/default/common/WritableIdentityCredential.cpp
+++ b/identity/aidl/default/common/WritableIdentityCredential.cpp
@@ -23,8 +23,8 @@
 #include <android-base/logging.h>
 #include <android-base/stringprintf.h>
 
-#include <cppbor/cppbor.h>
-#include <cppbor/cppbor_parse.h>
+#include <cppbor.h>
+#include <cppbor_parse.h>
 
 #include <utility>
 
diff --git a/identity/aidl/vts/Android.bp b/identity/aidl/vts/Android.bp
index 82c4011..3592d3e 100644
--- a/identity/aidl/vts/Android.bp
+++ b/identity/aidl/vts/Android.bp
@@ -34,7 +34,7 @@
         "libcrypto",
     ],
     static_libs: [
-        "libcppbor",
+        "libcppbor_external",
         "libkeymaster_portable",
         "libpuresoftkeymasterdevice",
         "android.hardware.keymaster@4.0",
diff --git a/identity/aidl/vts/AuthenticationKeyTests.cpp b/identity/aidl/vts/AuthenticationKeyTests.cpp
index bda3e70..25d74d4 100644
--- a/identity/aidl/vts/AuthenticationKeyTests.cpp
+++ b/identity/aidl/vts/AuthenticationKeyTests.cpp
@@ -118,7 +118,7 @@
     optional<vector<uint8_t>> proofOfProvisioning =
             support::coseSignGetPayload(proofOfProvisioningSignature);
     ASSERT_TRUE(proofOfProvisioning);
-    string cborPretty = support::cborPrettyPrint(proofOfProvisioning.value(), 32, {});
+    string cborPretty = cppbor::prettyPrint(proofOfProvisioning.value(), 32, {});
     EXPECT_EQ(
             "[\n"
             "  'ProofOfProvisioning',\n"
diff --git a/identity/aidl/vts/DeleteCredentialTests.cpp b/identity/aidl/vts/DeleteCredentialTests.cpp
index 1d30067..d3addf4 100644
--- a/identity/aidl/vts/DeleteCredentialTests.cpp
+++ b/identity/aidl/vts/DeleteCredentialTests.cpp
@@ -126,7 +126,7 @@
     optional<vector<uint8_t>> proofOfDeletion =
             support::coseSignGetPayload(proofOfDeletionSignature);
     ASSERT_TRUE(proofOfDeletion);
-    string cborPretty = support::cborPrettyPrint(proofOfDeletion.value(), 32, {});
+    string cborPretty = cppbor::prettyPrint(proofOfDeletion.value(), 32, {});
     EXPECT_EQ("['ProofOfDeletion', 'org.iso.18013-5.2019.mdl', true, ]", cborPretty);
     EXPECT_TRUE(support::coseCheckEcDsaSignature(proofOfDeletionSignature, {},  // Additional data
                                                  credentialPubKey_));
@@ -153,7 +153,7 @@
     optional<vector<uint8_t>> proofOfDeletion =
             support::coseSignGetPayload(proofOfDeletionSignature);
     ASSERT_TRUE(proofOfDeletion);
-    string cborPretty = support::cborPrettyPrint(proofOfDeletion.value(), 32, {});
+    string cborPretty = cppbor::prettyPrint(proofOfDeletion.value(), 32, {});
     EXPECT_EQ("['ProofOfDeletion', 'org.iso.18013-5.2019.mdl', {0x41, 0x42, 0x43}, true, ]",
               cborPretty);
     EXPECT_TRUE(support::coseCheckEcDsaSignature(proofOfDeletionSignature, {},  // Additional data
diff --git a/identity/aidl/vts/EndToEndTests.cpp b/identity/aidl/vts/EndToEndTests.cpp
index 5798b4c..67db915 100644
--- a/identity/aidl/vts/EndToEndTests.cpp
+++ b/identity/aidl/vts/EndToEndTests.cpp
@@ -231,7 +231,7 @@
     optional<vector<uint8_t>> proofOfProvisioning =
             support::coseSignGetPayload(proofOfProvisioningSignature);
     ASSERT_TRUE(proofOfProvisioning);
-    cborPretty = support::cborPrettyPrint(proofOfProvisioning.value(), 32, {"readerCertificate"});
+    cborPretty = cppbor::prettyPrint(proofOfProvisioning.value(), 32, {"readerCertificate"});
     EXPECT_EQ(
             "[\n"
             "  'ProofOfProvisioning',\n"
@@ -339,8 +339,8 @@
     vector<uint8_t> deviceEngagementBytes = deviceEngagement.encode();
     vector<uint8_t> eReaderPubBytes = cppbor::Tstr("ignored").encode();
     cppbor::Array sessionTranscript = cppbor::Array()
-                                              .add(cppbor::Semantic(24, deviceEngagementBytes))
-                                              .add(cppbor::Semantic(24, eReaderPubBytes));
+                                              .add(cppbor::SemanticTag(24, deviceEngagementBytes))
+                                              .add(cppbor::SemanticTag(24, eReaderPubBytes));
     vector<uint8_t> sessionTranscriptEncoded = sessionTranscript.encode();
 
     vector<uint8_t> itemsRequestBytes =
@@ -353,7 +353,7 @@
                                                              .add("Home address", true))
                                 .add("Image", cppbor::Map().add("Portrait image", false)))
                     .encode();
-    cborPretty = support::cborPrettyPrint(itemsRequestBytes, 32, {"EphemeralPublicKey"});
+    cborPretty = cppbor::prettyPrint(itemsRequestBytes, 32, {"EphemeralPublicKey"});
     EXPECT_EQ(
             "{\n"
             "  'nameSpaces' : {\n"
@@ -373,10 +373,10 @@
             cppbor::Array()
                     .add("ReaderAuthentication")
                     .add(sessionTranscript.clone())
-                    .add(cppbor::Semantic(24, itemsRequestBytes))
+                    .add(cppbor::SemanticTag(24, itemsRequestBytes))
                     .encode();
     vector<uint8_t> encodedReaderAuthenticationBytes =
-            cppbor::Semantic(24, encodedReaderAuthentication).encode();
+            cppbor::SemanticTag(24, encodedReaderAuthentication).encode();
     optional<vector<uint8_t>> readerSignature =
             support::coseSignEcDsa(readerKey, {},                     // content
                                    encodedReaderAuthenticationBytes,  // detached content
@@ -443,7 +443,7 @@
     vector<uint8_t> mac;
     vector<uint8_t> deviceNameSpacesEncoded;
     ASSERT_TRUE(credential->finishRetrieval(&mac, &deviceNameSpacesEncoded).isOk());
-    cborPretty = support::cborPrettyPrint(deviceNameSpacesEncoded, 32, {});
+    cborPretty = cppbor::prettyPrint(deviceNameSpacesEncoded, 32, {});
     ASSERT_EQ(
             "{\n"
             "  'PersonalData' : {\n"
@@ -462,10 +462,11 @@
     string docType = "org.iso.18013-5.2019.mdl";
     optional<vector<uint8_t>> readerEphemeralPrivateKey =
             support::ecKeyPairGetPrivateKey(readerEphemeralKeyPair.value());
-    optional<vector<uint8_t>> eMacKey = support::calcEMacKey(
-            readerEphemeralPrivateKey.value(),                           // Private Key
-            signingPubKey.value(),                                       // Public Key
-            cppbor::Semantic(24, sessionTranscript.encode()).encode());  // SessionTranscriptBytes
+    optional<vector<uint8_t>> eMacKey =
+            support::calcEMacKey(readerEphemeralPrivateKey.value(),  // Private Key
+                                 signingPubKey.value(),              // Public Key
+                                 cppbor::SemanticTag(24, sessionTranscript.encode())
+                                         .encode());  // SessionTranscriptBytes
     optional<vector<uint8_t>> calculatedMac =
             support::calcMac(sessionTranscript.encode(),  // SessionTranscript
                              docType,                     // DocType
@@ -486,7 +487,7 @@
                                 testEntriesEntryCounts)
                         .isOk());
     ASSERT_TRUE(credential->finishRetrieval(&mac, &deviceNameSpacesEncoded).isOk());
-    cborPretty = support::cborPrettyPrint(deviceNameSpacesEncoded, 32, {});
+    cborPretty = cppbor::prettyPrint(deviceNameSpacesEncoded, 32, {});
     ASSERT_EQ("{}", cborPretty);
     // Calculate DeviceAuthentication and MAC (MACing key hasn't changed)
     calculatedMac = support::calcMac(sessionTranscript.encode(),  // SessionTranscript
@@ -508,7 +509,7 @@
                                 testEntriesEntryCounts)
                         .isOk());
     ASSERT_TRUE(credential->finishRetrieval(&mac, &deviceNameSpacesEncoded).isOk());
-    cborPretty = support::cborPrettyPrint(deviceNameSpacesEncoded, 32, {});
+    cborPretty = cppbor::prettyPrint(deviceNameSpacesEncoded, 32, {});
     ASSERT_EQ("{}", cborPretty);
     // Calculate DeviceAuthentication and MAC (MACing key hasn't changed)
     calculatedMac = support::calcMac(sessionTranscript.encode(),  // SessionTranscript
diff --git a/identity/aidl/vts/ProveOwnershipTests.cpp b/identity/aidl/vts/ProveOwnershipTests.cpp
index d1a3d39..fa0e293 100644
--- a/identity/aidl/vts/ProveOwnershipTests.cpp
+++ b/identity/aidl/vts/ProveOwnershipTests.cpp
@@ -131,7 +131,7 @@
     optional<vector<uint8_t>> proofOfOwnership =
             support::coseSignGetPayload(proofOfOwnershipSignature);
     ASSERT_TRUE(proofOfOwnership);
-    string cborPretty = support::cborPrettyPrint(proofOfOwnership.value(), 32, {});
+    string cborPretty = cppbor::prettyPrint(proofOfOwnership.value(), 32, {});
     EXPECT_EQ("['ProofOfOwnership', 'org.iso.18013-5.2019.mdl', {0x11, 0x12}, true, ]", cborPretty);
     EXPECT_TRUE(support::coseCheckEcDsaSignature(proofOfOwnershipSignature, {},  // Additional data
                                                  credentialPubKey_));
diff --git a/identity/aidl/vts/ReaderAuthTests.cpp b/identity/aidl/vts/ReaderAuthTests.cpp
index 7656c8e..c4a58c3 100644
--- a/identity/aidl/vts/ReaderAuthTests.cpp
+++ b/identity/aidl/vts/ReaderAuthTests.cpp
@@ -262,8 +262,8 @@
     vector<uint8_t> deviceEngagementBytes = deviceEngagement.encode();
     vector<uint8_t> eReaderPubBytes = cppbor::Tstr("ignored").encode();
     cppbor::Array sessionTranscript = cppbor::Array()
-                                              .add(cppbor::Semantic(24, deviceEngagementBytes))
-                                              .add(cppbor::Semantic(24, eReaderPubBytes));
+                                              .add(cppbor::SemanticTag(24, deviceEngagementBytes))
+                                              .add(cppbor::SemanticTag(24, eReaderPubBytes));
     vector<uint8_t> sessionTranscriptBytes = sessionTranscript.encode();
 
     vector<uint8_t> itemsRequestBytes;
@@ -293,10 +293,10 @@
             cppbor::Array()
                     .add("ReaderAuthentication")
                     .add(sessionTranscript.clone())
-                    .add(cppbor::Semantic(24, itemsRequestBytes))
+                    .add(cppbor::SemanticTag(24, itemsRequestBytes))
                     .encode();
     vector<uint8_t> encodedReaderAuthenticationBytes =
-            cppbor::Semantic(24, encodedReaderAuthentication).encode();
+            cppbor::SemanticTag(24, encodedReaderAuthentication).encode();
 
     optional<vector<uint8_t>> readerSignature =
             support::coseSignEcDsa(readerPrivateKey,                  // private key for reader
@@ -517,8 +517,8 @@
     vector<uint8_t> deviceEngagementBytes = deviceEngagement.encode();
     vector<uint8_t> eReaderPubBytes = cppbor::Tstr("ignored").encode();
     cppbor::Array sessionTranscript = cppbor::Array()
-                                              .add(cppbor::Semantic(24, deviceEngagementBytes))
-                                              .add(cppbor::Semantic(24, eReaderPubBytes));
+                                              .add(cppbor::SemanticTag(24, deviceEngagementBytes))
+                                              .add(cppbor::SemanticTag(24, eReaderPubBytes));
     vector<uint8_t> sessionTranscriptBytes = sessionTranscript.encode();
 
     vector<uint8_t> itemsRequestBytes;
@@ -535,10 +535,10 @@
             cppbor::Array()
                     .add("ReaderAuthentication")
                     .add(sessionTranscript.clone())
-                    .add(cppbor::Semantic(24, itemsRequestBytes))
+                    .add(cppbor::SemanticTag(24, itemsRequestBytes))
                     .encode();
     vector<uint8_t> encodedReaderAuthenticationBytes =
-            cppbor::Semantic(24, encodedReaderAuthentication).encode();
+            cppbor::SemanticTag(24, encodedReaderAuthentication).encode();
 
     vector<vector<uint8_t>> readerCertChain = {cert_reader_SelfSigned_};
     optional<vector<uint8_t>> readerSignature =
diff --git a/identity/aidl/vts/TestCredentialTests.cpp b/identity/aidl/vts/TestCredentialTests.cpp
index d53de3b..46c2229 100644
--- a/identity/aidl/vts/TestCredentialTests.cpp
+++ b/identity/aidl/vts/TestCredentialTests.cpp
@@ -114,7 +114,7 @@
     optional<vector<uint8_t>> proofOfProvisioning =
             support::coseSignGetPayload(proofOfProvisioningSignature);
     ASSERT_TRUE(proofOfProvisioning);
-    string cborPretty = support::cborPrettyPrint(proofOfProvisioning.value(), 32, {});
+    string cborPretty = cppbor::prettyPrint(proofOfProvisioning.value(), 32, {});
     EXPECT_EQ(
             "[\n"
             "  'ProofOfProvisioning',\n"
diff --git a/identity/aidl/vts/UpdateCredentialTests.cpp b/identity/aidl/vts/UpdateCredentialTests.cpp
index 9c5ca55..e05bb3b 100644
--- a/identity/aidl/vts/UpdateCredentialTests.cpp
+++ b/identity/aidl/vts/UpdateCredentialTests.cpp
@@ -114,7 +114,7 @@
     optional<vector<uint8_t>> proofOfProvisioning =
             support::coseSignGetPayload(proofOfProvisioningSignature);
     ASSERT_TRUE(proofOfProvisioning);
-    string cborPretty = support::cborPrettyPrint(proofOfProvisioning.value(), 32, {});
+    string cborPretty = cppbor::prettyPrint(proofOfProvisioning.value(), 32, {});
     EXPECT_EQ(
             "[\n"
             "  'ProofOfProvisioning',\n"
@@ -195,7 +195,7 @@
     optional<vector<uint8_t>> proofOfProvisioning =
             support::coseSignGetPayload(proofOfProvisioningSignature);
     ASSERT_TRUE(proofOfProvisioning);
-    string cborPretty = support::cborPrettyPrint(proofOfProvisioning.value(), 32, {});
+    string cborPretty = cppbor::prettyPrint(proofOfProvisioning.value(), 32, {});
     EXPECT_EQ(
             "[\n"
             "  'ProofOfProvisioning',\n"
diff --git a/identity/aidl/vts/UserAuthTests.cpp b/identity/aidl/vts/UserAuthTests.cpp
index ef89d1c..edd1725 100644
--- a/identity/aidl/vts/UserAuthTests.cpp
+++ b/identity/aidl/vts/UserAuthTests.cpp
@@ -160,8 +160,8 @@
     // Let SessionTranscript be a map here (it's an array in EndToEndTest) just
     // to check that the implementation can deal with either.
     cppbor::Map sessionTranscript;
-    sessionTranscript.add(42, cppbor::Semantic(24, deviceEngagementBytes));
-    sessionTranscript.add(43, cppbor::Semantic(24, eReaderPubBytes));
+    sessionTranscript.add(42, cppbor::SemanticTag(24, deviceEngagementBytes));
+    sessionTranscript.add(43, cppbor::SemanticTag(24, eReaderPubBytes));
     return sessionTranscript;
 }
 
@@ -209,7 +209,7 @@
         vector<uint8_t> dataToSign = cppbor::Array()
                                              .add("ReaderAuthentication")
                                              .add(sessionTranscript_.clone())
-                                             .add(cppbor::Semantic(24, itemsRequestBytes))
+                                             .add(cppbor::SemanticTag(24, itemsRequestBytes))
                                              .encode();
     }
 
diff --git a/identity/aidl/vts/VtsIWritableIdentityCredentialTests.cpp b/identity/aidl/vts/VtsIWritableIdentityCredentialTests.cpp
index cc63c48..bc37020 100644
--- a/identity/aidl/vts/VtsIWritableIdentityCredentialTests.cpp
+++ b/identity/aidl/vts/VtsIWritableIdentityCredentialTests.cpp
@@ -338,8 +338,7 @@
     optional<vector<uint8_t>> proofOfProvisioning =
             support::coseSignGetPayload(proofOfProvisioningSignature);
     ASSERT_TRUE(proofOfProvisioning);
-    string cborPretty =
-            support::cborPrettyPrint(proofOfProvisioning.value(), 32, {"readerCertificate"});
+    string cborPretty = cppbor::prettyPrint(proofOfProvisioning.value(), 32, {"readerCertificate"});
     EXPECT_EQ(
             "[\n"
             "  'ProofOfProvisioning',\n"
@@ -449,9 +448,9 @@
     optional<vector<uint8_t>> proofOfProvisioning =
             support::coseSignGetPayload(proofOfProvisioningSignature);
     ASSERT_TRUE(proofOfProvisioning);
-    string cborPretty = support::cborPrettyPrint(proofOfProvisioning.value(),
-                                                 32,  //
-                                                 {"readerCertificate"});
+    string cborPretty = cppbor::prettyPrint(proofOfProvisioning.value(),
+                                            32,  //
+                                            {"readerCertificate"});
     EXPECT_EQ(
             "[\n"
             "  'ProofOfProvisioning',\n"
diff --git a/identity/support/Android.bp b/identity/support/Android.bp
index d00f59a..774bc40 100644
--- a/identity/support/Android.bp
+++ b/identity/support/Android.bp
@@ -42,7 +42,7 @@
         "libpuresoftkeymasterdevice",
     ],
     static_libs: [
-        "libcppbor",
+        "libcppbor_external",
     ],
 }
 
@@ -59,7 +59,7 @@
         "libhardware",
     ],
     static_libs: [
-        "libcppbor",
+        "libcppbor_external",
         "libgmock",
     ],
     test_suites: ["general-tests"],
@@ -89,7 +89,7 @@
         "tests/cppbor_test.cpp",
     ],
     shared_libs: [
-        "libcppbor",
+        "libcppbor_external",
         "libbase",
     ],
     static_libs: [
@@ -104,7 +104,7 @@
         "tests/cppbor_test.cpp",
     ],
     shared_libs: [
-        "libcppbor",
+        "libcppbor_external",
         "libbase",
     ],
     static_libs: [
diff --git a/identity/support/src/IdentityCredentialSupport.cpp b/identity/support/src/IdentityCredentialSupport.cpp
index aba89c1..4547624 100644
--- a/identity/support/src/IdentityCredentialSupport.cpp
+++ b/identity/support/src/IdentityCredentialSupport.cpp
@@ -148,199 +148,6 @@
 }
 
 // ---------------------------------------------------------------------------
-// CBOR utilities.
-// ---------------------------------------------------------------------------
-
-static bool cborAreAllElementsNonCompound(const cppbor::CompoundItem* compoundItem) {
-    if (compoundItem->type() == cppbor::ARRAY) {
-        const cppbor::Array* array = compoundItem->asArray();
-        for (size_t n = 0; n < array->size(); n++) {
-            const cppbor::Item* entry = (*array)[n].get();
-            switch (entry->type()) {
-                case cppbor::ARRAY:
-                case cppbor::MAP:
-                    return false;
-                default:
-                    break;
-            }
-        }
-    } else {
-        const cppbor::Map* map = compoundItem->asMap();
-        for (size_t n = 0; n < map->size(); n++) {
-            auto [keyEntry, valueEntry] = (*map)[n];
-            switch (keyEntry->type()) {
-                case cppbor::ARRAY:
-                case cppbor::MAP:
-                    return false;
-                default:
-                    break;
-            }
-            switch (valueEntry->type()) {
-                case cppbor::ARRAY:
-                case cppbor::MAP:
-                    return false;
-                default:
-                    break;
-            }
-        }
-    }
-    return true;
-}
-
-static bool cborPrettyPrintInternal(const cppbor::Item* item, string& out, size_t indent,
-                                    size_t maxBStrSize, const vector<string>& mapKeysToNotPrint) {
-    char buf[80];
-
-    string indentString(indent, ' ');
-
-    switch (item->type()) {
-        case cppbor::UINT:
-            snprintf(buf, sizeof(buf), "%" PRIu64, item->asUint()->unsignedValue());
-            out.append(buf);
-            break;
-
-        case cppbor::NINT:
-            snprintf(buf, sizeof(buf), "%" PRId64, item->asNint()->value());
-            out.append(buf);
-            break;
-
-        case cppbor::BSTR: {
-            const cppbor::Bstr* bstr = item->asBstr();
-            const vector<uint8_t>& value = bstr->value();
-            if (value.size() > maxBStrSize) {
-                unsigned char digest[SHA_DIGEST_LENGTH];
-                SHA_CTX ctx;
-                SHA1_Init(&ctx);
-                SHA1_Update(&ctx, value.data(), value.size());
-                SHA1_Final(digest, &ctx);
-                char buf2[SHA_DIGEST_LENGTH * 2 + 1];
-                for (size_t n = 0; n < SHA_DIGEST_LENGTH; n++) {
-                    snprintf(buf2 + n * 2, 3, "%02x", digest[n]);
-                }
-                snprintf(buf, sizeof(buf), "<bstr size=%zd sha1=%s>", value.size(), buf2);
-                out.append(buf);
-            } else {
-                out.append("{");
-                for (size_t n = 0; n < value.size(); n++) {
-                    if (n > 0) {
-                        out.append(", ");
-                    }
-                    snprintf(buf, sizeof(buf), "0x%02x", value[n]);
-                    out.append(buf);
-                }
-                out.append("}");
-            }
-        } break;
-
-        case cppbor::TSTR:
-            out.append("'");
-            {
-                // TODO: escape "'" characters
-                out.append(item->asTstr()->value().c_str());
-            }
-            out.append("'");
-            break;
-
-        case cppbor::ARRAY: {
-            const cppbor::Array* array = item->asArray();
-            if (array->size() == 0) {
-                out.append("[]");
-            } else if (cborAreAllElementsNonCompound(array)) {
-                out.append("[");
-                for (size_t n = 0; n < array->size(); n++) {
-                    if (!cborPrettyPrintInternal((*array)[n].get(), out, indent + 2, maxBStrSize,
-                                                 mapKeysToNotPrint)) {
-                        return false;
-                    }
-                    out.append(", ");
-                }
-                out.append("]");
-            } else {
-                out.append("[\n" + indentString);
-                for (size_t n = 0; n < array->size(); n++) {
-                    out.append("  ");
-                    if (!cborPrettyPrintInternal((*array)[n].get(), out, indent + 2, maxBStrSize,
-                                                 mapKeysToNotPrint)) {
-                        return false;
-                    }
-                    out.append(",\n" + indentString);
-                }
-                out.append("]");
-            }
-        } break;
-
-        case cppbor::MAP: {
-            const cppbor::Map* map = item->asMap();
-
-            if (map->size() == 0) {
-                out.append("{}");
-            } else {
-                out.append("{\n" + indentString);
-                for (size_t n = 0; n < map->size(); n++) {
-                    out.append("  ");
-
-                    auto [map_key, map_value] = (*map)[n];
-
-                    if (!cborPrettyPrintInternal(map_key.get(), out, indent + 2, maxBStrSize,
-                                                 mapKeysToNotPrint)) {
-                        return false;
-                    }
-                    out.append(" : ");
-                    if (map_key->type() == cppbor::TSTR &&
-                        std::find(mapKeysToNotPrint.begin(), mapKeysToNotPrint.end(),
-                                  map_key->asTstr()->value()) != mapKeysToNotPrint.end()) {
-                        out.append("<not printed>");
-                    } else {
-                        if (!cborPrettyPrintInternal(map_value.get(), out, indent + 2, maxBStrSize,
-                                                     mapKeysToNotPrint)) {
-                            return false;
-                        }
-                    }
-                    out.append(",\n" + indentString);
-                }
-                out.append("}");
-            }
-        } break;
-
-        case cppbor::SEMANTIC: {
-            const cppbor::Semantic* semantic = item->asSemantic();
-            snprintf(buf, sizeof(buf), "tag %" PRIu64 " ", semantic->value());
-            out.append(buf);
-            cborPrettyPrintInternal(semantic->child().get(), out, indent, maxBStrSize,
-                                    mapKeysToNotPrint);
-        } break;
-
-        case cppbor::SIMPLE:
-            const cppbor::Bool* asBool = item->asSimple()->asBool();
-            const cppbor::Null* asNull = item->asSimple()->asNull();
-            if (asBool != nullptr) {
-                out.append(asBool->value() ? "true" : "false");
-            } else if (asNull != nullptr) {
-                out.append("null");
-            } else {
-                LOG(ERROR) << "Only boolean/null is implemented for SIMPLE";
-                return false;
-            }
-            break;
-    }
-
-    return true;
-}
-
-string cborPrettyPrint(const vector<uint8_t>& encodedCbor, size_t maxBStrSize,
-                       const vector<string>& mapKeysToNotPrint) {
-    auto [item, _, message] = cppbor::parse(encodedCbor);
-    if (item == nullptr) {
-        LOG(ERROR) << "Data to pretty print is not valid CBOR: " << message;
-        return "";
-    }
-
-    string out;
-    cborPrettyPrintInternal(item.get(), out, 0, maxBStrSize, mapKeysToNotPrint);
-    return out;
-}
-
-// ---------------------------------------------------------------------------
 // Crypto functionality / abstraction.
 // ---------------------------------------------------------------------------
 
@@ -2140,7 +1947,7 @@
     }
 
     for (size_t n = 0; n < protectedHeaders->size(); n++) {
-        auto [keyItem, valueItem] = (*protectedHeaders)[n];
+        auto& [keyItem, valueItem] = (*protectedHeaders)[n];
         const cppbor::Int* number = keyItem->asInt();
         if (number == nullptr) {
             LOG(ERROR) << "Key item in top-level map is not a number";
@@ -2183,7 +1990,7 @@
     }
 
     for (size_t n = 0; n < unprotectedHeaders->size(); n++) {
-        auto [keyItem, valueItem] = (*unprotectedHeaders)[n];
+        auto& [keyItem, valueItem] = (*unprotectedHeaders)[n];
         const cppbor::Int* number = keyItem->asInt();
         if (number == nullptr) {
             LOG(ERROR) << "Key item in top-level map is not a number";
@@ -2335,9 +2142,9 @@
                     .add("DeviceAuthentication")
                     .add(std::move(sessionTranscriptItem))
                     .add(docType)
-                    .add(cppbor::Semantic(kSemanticTagEncodedCbor, deviceNameSpacesEncoded));
+                    .add(cppbor::SemanticTag(kSemanticTagEncodedCbor, deviceNameSpacesEncoded));
     vector<uint8_t> deviceAuthenticationBytes =
-            cppbor::Semantic(kSemanticTagEncodedCbor, deviceAuthentication.encode()).encode();
+            cppbor::SemanticTag(kSemanticTagEncodedCbor, deviceAuthentication.encode()).encode();
     optional<vector<uint8_t>> calculatedMac =
             support::coseMac0(eMacKey, {},                 // payload
                               deviceAuthenticationBytes);  // detached content
diff --git a/identity/support/tests/IdentityCredentialSupportTest.cpp b/identity/support/tests/IdentityCredentialSupportTest.cpp
index 509133c..4c9b87a 100644
--- a/identity/support/tests/IdentityCredentialSupportTest.cpp
+++ b/identity/support/tests/IdentityCredentialSupportTest.cpp
@@ -55,99 +55,6 @@
     EXPECT_FALSE(support::decodeHex("012"));
 }
 
-TEST(IdentityCredentialSupport, CborPrettyPrint) {
-    EXPECT_EQ("'Some text'", support::cborPrettyPrint(cppbor::Tstr("Some text").encode()));
-
-    EXPECT_EQ("''", support::cborPrettyPrint(cppbor::Tstr("").encode()));
-
-    EXPECT_EQ("{0x01, 0x00, 0x02, 0xf0, 0xff, 0x40}",
-              support::cborPrettyPrint(
-                      cppbor::Bstr(vector<uint8_t>({1, 0, 2, 240, 255, 64})).encode()));
-
-    EXPECT_EQ("{}", support::cborPrettyPrint(cppbor::Bstr(vector<uint8_t>()).encode()));
-
-    EXPECT_EQ("true", support::cborPrettyPrint(cppbor::Bool(true).encode()));
-
-    EXPECT_EQ("false", support::cborPrettyPrint(cppbor::Bool(false).encode()));
-
-    EXPECT_EQ("42", support::cborPrettyPrint(cppbor::Uint(42).encode()));
-
-    EXPECT_EQ("9223372036854775807",  // 0x7fff ffff ffff ffff
-              support::cborPrettyPrint(cppbor::Uint(std::numeric_limits<int64_t>::max()).encode()));
-
-    EXPECT_EQ("-42", support::cborPrettyPrint(cppbor::Nint(-42).encode()));
-
-    EXPECT_EQ("-9223372036854775808",  // -0x8000 0000 0000 0000
-              support::cborPrettyPrint(cppbor::Nint(std::numeric_limits<int64_t>::min()).encode()));
-}
-
-TEST(IdentityCredentialSupport, CborPrettyPrintCompound) {
-    cppbor::Array array = cppbor::Array("foo", "bar", "baz");
-    EXPECT_EQ("['foo', 'bar', 'baz', ]", support::cborPrettyPrint(array.encode()));
-
-    cppbor::Map map = cppbor::Map().add("foo", 42).add("bar", 43).add("baz", 44);
-    EXPECT_EQ(
-            "{\n"
-            "  'foo' : 42,\n"
-            "  'bar' : 43,\n"
-            "  'baz' : 44,\n"
-            "}",
-            support::cborPrettyPrint(map.encode()));
-
-    cppbor::Array array2 = cppbor::Array(cppbor::Tstr("Some text"), cppbor::Nint(-42));
-    EXPECT_EQ("['Some text', -42, ]", support::cborPrettyPrint(array2.encode()));
-
-    cppbor::Map map2 = cppbor::Map().add(42, "foo").add(43, "bar").add(44, "baz");
-    EXPECT_EQ(
-            "{\n"
-            "  42 : 'foo',\n"
-            "  43 : 'bar',\n"
-            "  44 : 'baz',\n"
-            "}",
-            support::cborPrettyPrint(map2.encode()));
-
-    cppbor::Array deeplyNestedArrays =
-            cppbor::Array(cppbor::Array(cppbor::Array("a", "b", "c")),
-                          cppbor::Array(cppbor::Array("d", "e", cppbor::Array("f", "g"))));
-    EXPECT_EQ(
-            "[\n"
-            "  ['a', 'b', 'c', ],\n"
-            "  [\n    'd',\n"
-            "    'e',\n"
-            "    ['f', 'g', ],\n"
-            "  ],\n"
-            "]",
-            support::cborPrettyPrint(deeplyNestedArrays.encode()));
-
-    EXPECT_EQ(
-            "[\n"
-            "  {0x0a, 0x0b},\n"
-            "  'foo',\n"
-            "  42,\n"
-            "  ['foo', 'bar', 'baz', ],\n"
-            "  {\n"
-            "    'foo' : 42,\n"
-            "    'bar' : 43,\n"
-            "    'baz' : 44,\n"
-            "  },\n"
-            "  {\n"
-            "    'deep1' : ['Some text', -42, ],\n"
-            "    'deep2' : {\n"
-            "      42 : 'foo',\n"
-            "      43 : 'bar',\n"
-            "      44 : 'baz',\n"
-            "    },\n"
-            "  },\n"
-            "]",
-            support::cborPrettyPrint(cppbor::Array(cppbor::Bstr(vector<uint8_t>{10, 11}),
-                                                   cppbor::Tstr("foo"), cppbor::Uint(42),
-                                                   std::move(array), std::move(map),
-                                                   (cppbor::Map()
-                                                            .add("deep1", std::move(array2))
-                                                            .add("deep2", std::move(map2))))
-                                             .encode()));
-}
-
 TEST(IdentityCredentialSupport, Signatures) {
     vector<uint8_t> data = {1, 2, 3};
 
@@ -219,7 +126,7 @@
     ASSERT_EQ(data, payload.value());
 
     // Finally, check that |coseSign1| are the bytes of a valid COSE_Sign1 message
-    string out = support::cborPrettyPrint(coseSign1.value());
+    string out = cppbor::prettyPrint(coseSign1.value());
     out = replaceLine(out, -2, "  [] // Signature Removed");
     EXPECT_EQ(
             "[\n"
@@ -250,7 +157,7 @@
     ASSERT_EQ(0, payload.value().size());
 
     // Finally, check that |coseSign1| are the bytes of a valid COSE_Sign1 message
-    string out = support::cborPrettyPrint(coseSign1.value());
+    string out = cppbor::prettyPrint(coseSign1.value());
     out = replaceLine(out, -2, "  [] // Signature Removed");
     EXPECT_EQ(
             "[\n"
@@ -411,7 +318,7 @@
             "0x86, 0x5c, 0x28, 0x2c, 0xd5, 0xa5, 0x13, 0xff, 0x3b, 0xd1, 0xde, 0x70, 0x5e, 0xbb, "
             "0xe2, 0x2d, 0x42, 0xbe, 0x53},\n"
             "]",
-            support::cborPrettyPrint(mac.value()));
+            cppbor::prettyPrint(mac.value()));
 }
 
 TEST(IdentityCredentialSupport, CoseMac0DetachedContent) {
@@ -433,7 +340,7 @@
             "0x86, 0x5c, 0x28, 0x2c, 0xd5, 0xa5, 0x13, 0xff, 0x3b, 0xd1, 0xde, 0x70, 0x5e, 0xbb, "
             "0xe2, 0x2d, 0x42, 0xbe, 0x53},\n"
             "]",
-            support::cborPrettyPrint(mac.value()));
+            cppbor::prettyPrint(mac.value()));
 }
 
 // Generates a private key in DER format for a small value of 'd'.
@@ -460,8 +367,8 @@
 
 const cppbor::Item* findValueForTstr(const cppbor::Map* map, const string& keyValue) {
     // TODO: Need cast until libcppbor's Map::get() is marked as const
-    auto [item, found] = ((cppbor::Map*)map)->get(keyValue);
-    if (!found) {
+    const auto& item = map->get(keyValue);
+    if (!item) {
         return nullptr;
     }
     return item.get();
@@ -483,12 +390,13 @@
     return item->asMap();
 }
 
-const cppbor::Semantic* findSemanticValueForTstr(const cppbor::Map* map, const string& keyValue) {
+const cppbor::SemanticTag* findSemanticValueForTstr(const cppbor::Map* map,
+                                                    const string& keyValue) {
     const cppbor::Item* item = findValueForTstr(map, keyValue);
     if (item == nullptr) {
         return nullptr;
     }
-    return item->asSemantic();
+    return item->asSemanticTag();
 }
 
 const std::string findStringValueForTstr(const cppbor::Map* map, const string& keyValue) {
@@ -576,11 +484,11 @@
     auto [sessionEstablishmentItem, _se, _se2] = cppbor::parse(sessionEstablishmentEncoded.value());
     const cppbor::Map* sessionEstablishment = sessionEstablishmentItem->asMap();
     ASSERT_NE(sessionEstablishment, nullptr);
-    const cppbor::Semantic* eReaderKeyBytes =
+    const cppbor::SemanticTag* eReaderKeyBytes =
             findSemanticValueForTstr(sessionEstablishment, "eReaderKeyBytes");
     ASSERT_NE(eReaderKeyBytes, nullptr);
-    ASSERT_EQ(eReaderKeyBytes->value(), 24);
-    const cppbor::Bstr* eReaderKeyBstr = eReaderKeyBytes->child()->asBstr();
+    ASSERT_EQ(eReaderKeyBytes->semanticTag(), 24);
+    const cppbor::Bstr* eReaderKeyBstr = eReaderKeyBytes->asBstr();
     ASSERT_NE(eReaderKeyBstr, nullptr);
     vector<uint8_t> eReaderKeyEncoded = eReaderKeyBstr->value();
     // TODO: verify this agrees with ephemeralReaderKeyX and ephemeralReaderKeyY
@@ -605,12 +513,12 @@
     //   SessionTranscriptBytes = #6.24(bstr .cbor SessionTranscript)
     //
     cppbor::Array sessionTranscript;
-    sessionTranscript.add(cppbor::Semantic(24, deviceEngagementEncoded));
-    sessionTranscript.add(cppbor::Semantic(24, eReaderKeyEncoded));
+    sessionTranscript.add(cppbor::SemanticTag(24, deviceEngagementEncoded));
+    sessionTranscript.add(cppbor::SemanticTag(24, eReaderKeyEncoded));
     sessionTranscript.add(cppbor::Null());
     vector<uint8_t> sessionTranscriptEncoded = sessionTranscript.encode();
     vector<uint8_t> sessionTranscriptBytes =
-            cppbor::Semantic(24, sessionTranscriptEncoded).encode();
+            cppbor::SemanticTag(24, sessionTranscriptEncoded).encode();
 
     // The expected EMacKey is 4c1ebb8aacc633465390fa44edfdb49cb57f2e079aaa771d812584699c0b97e2
     //
@@ -696,11 +604,11 @@
 
     // Dig out the encoded form of DeviceNameSpaces
     //
-    const cppbor::Semantic* deviceNameSpacesBytes =
+    const cppbor::SemanticTag* deviceNameSpacesBytes =
             findSemanticValueForTstr(deviceSigned, "nameSpaces");
     ASSERT_NE(deviceNameSpacesBytes, nullptr);
-    ASSERT_EQ(deviceNameSpacesBytes->value(), 24);
-    const cppbor::Bstr* deviceNameSpacesBstr = deviceNameSpacesBytes->child()->asBstr();
+    ASSERT_EQ(deviceNameSpacesBytes->semanticTag(), 24);
+    const cppbor::Bstr* deviceNameSpacesBstr = deviceNameSpacesBytes->asBstr();
     ASSERT_NE(deviceNameSpacesBstr, nullptr);
     vector<uint8_t> deviceNameSpacesEncoded = deviceNameSpacesBstr->value();
 
diff --git a/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h b/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h
index 8d6e74a..ea40971 100644
--- a/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h
+++ b/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h
@@ -117,6 +117,9 @@
 DECLARE_TYPED_TAG(ATTESTATION_ID_PRODUCT);
 DECLARE_TYPED_TAG(ATTESTATION_ID_MANUFACTURER);
 DECLARE_TYPED_TAG(ATTESTATION_ID_MODEL);
+DECLARE_TYPED_TAG(ATTESTATION_ID_SERIAL);
+DECLARE_TYPED_TAG(ATTESTATION_ID_IMEI);
+DECLARE_TYPED_TAG(ATTESTATION_ID_MEID);
 DECLARE_TYPED_TAG(AUTH_TIMEOUT);
 DECLARE_TYPED_TAG(BLOB_USAGE_REQUIREMENTS);
 DECLARE_TYPED_TAG(BLOCK_MODE);
diff --git a/neuralnetworks/1.3/IDevice.hal b/neuralnetworks/1.3/IDevice.hal
index e0b04a8..de889e4 100644
--- a/neuralnetworks/1.3/IDevice.hal
+++ b/neuralnetworks/1.3/IDevice.hal
@@ -131,6 +131,14 @@
      * ErrorStatus::MISSED_DEADLINE_TRANSIENT} or {@link
      * ErrorStatus::MISSED_DEADLINE_PERSISTENT} may be returned. The error due
      * to an abort must be sent the same way as other errors, described above.
+     * The deadline is represented as nanoseconds since the epoch of the steady
+     * clock (as if from std::chrono::steady_clock::time_point), but the service
+     * may convert it to the nanoseconds since boot time (as if from
+     * clock_gettime(CLOCK_BOOTTIME, &ts) or
+     * android::base::boot_clock::time_point) to account for time when the
+     * system is suspended. This conversion can by done by finding the timeout
+     * duration remaining compared to the steady_clock and adding it to the
+     * current boot_clock time.
      *
      * Optionally, the driver may save the prepared model to cache during the
      * asynchronous preparation. Any error that occurs when saving to cache must
@@ -249,7 +257,15 @@
      * ErrorStatus::MISSED_DEADLINE_TRANSIENT}
      * or {@link ErrorStatus::MISSED_DEADLINE_PERSISTENT} may be returned. The
      * error due to an abort must be sent the same way as other errors,
-     * described above.
+     * described above. The deadline is represented as nanoseconds since the
+     * epoch of the steady clock (as if from
+     * std::chrono::steady_clock::time_point), but the service may convert it to
+     * the nanoseconds since boot time (as if from
+     * clock_gettime(CLOCK_BOOTTIME, &ts) or
+     * android::base::boot_clock::time_point) to account for time when the
+     * system is suspended. This conversion can by done by finding the timeout
+     * duration remaining compared to the steady_clock and adding it to the
+     * current boot_clock time.
      *
      * The only information that may be unknown to the model at this stage is
      * the shape of the tensors, which may only be known at execution time. As
diff --git a/neuralnetworks/1.3/IPreparedModel.hal b/neuralnetworks/1.3/IPreparedModel.hal
index e7d63f4..8b86a1a 100644
--- a/neuralnetworks/1.3/IPreparedModel.hal
+++ b/neuralnetworks/1.3/IPreparedModel.hal
@@ -74,6 +74,14 @@
      * ErrorStatus::MISSED_DEADLINE_TRANSIENT} or {@link
      * ErrorStatus::MISSED_DEADLINE_PERSISTENT} may be returned. The error due
      * to an abort must be sent the same way as other errors, described above.
+     * The deadline is represented as nanoseconds since the epoch of the steady
+     * clock (as if from std::chrono::steady_clock::time_point), but the service
+     * may convert it to the nanoseconds since boot time (as if from
+     * clock_gettime(CLOCK_BOOTTIME, &ts) or
+     * android::base::boot_clock::time_point) to account for time when the
+     * system is suspended. This conversion can by done by finding the timeout
+     * duration remaining compared to the steady_clock and adding it to the
+     * current boot_clock time.
      *
      * Any number of calls to the execute* and executeSynchronously* functions,
      * in any combination, may be made concurrently, even on the same
@@ -150,6 +158,14 @@
      * ErrorStatus::MISSED_DEADLINE_TRANSIENT} or {@link
      * ErrorStatus::MISSED_DEADLINE_PERSISTENT} may be returned. The error due
      * to an abort must be sent the same way as other errors, described above.
+     * The deadline is represented as nanoseconds since the epoch of the steady
+     * clock (as if from std::chrono::steady_clock::time_point), but the service
+     * may convert it to the nanoseconds since boot time (as if from
+     * clock_gettime(CLOCK_BOOTTIME, &ts) or
+     * android::base::boot_clock::time_point) to account for time when the
+     * system is suspended. This conversion can by done by finding the timeout
+     * duration remaining compared to the steady_clock and adding it to the
+     * current boot_clock time.
      *
      * Any number of calls to the execute* and executeSynchronously* functions,
      * in any combination, may be made concurrently, even on the same
@@ -231,6 +247,14 @@
      * {@link ErrorStatus::MISSED_DEADLINE_TRANSIENT} or {@link
      * ErrorStatus::MISSED_DEADLINE_PERSISTENT} may be returned. The error due
      * to an abort must be sent the same way as other errors, described above.
+     * The deadline is represented as nanoseconds since the epoch of the steady
+     * clock (as if from std::chrono::steady_clock::time_point), but the service
+     * may convert it to the nanoseconds since boot time (as if from
+     * clock_gettime(CLOCK_BOOTTIME, &ts) or
+     * android::base::boot_clock::time_point) to account for time when the
+     * system is suspended. This conversion can by done by finding the timeout
+     * duration remaining compared to the steady_clock and adding it to the
+     * current boot_clock time.
      *
      * If any of the sync fences in waitFor changes to error status after the executeFenced
      * call succeeds, or the execution is aborted because it cannot finish before the deadline
diff --git a/neuralnetworks/1.3/utils/src/Conversions.cpp b/neuralnetworks/1.3/utils/src/Conversions.cpp
index 8083ae4..e8a4f55 100644
--- a/neuralnetworks/1.3/utils/src/Conversions.cpp
+++ b/neuralnetworks/1.3/utils/src/Conversions.cpp
@@ -42,6 +42,23 @@
 
 namespace {
 
+std::chrono::nanoseconds makeNanosFromUint64(uint64_t nanoseconds) {
+    constexpr auto kMaxCount = std::chrono::nanoseconds::max().count();
+    using CommonType = std::common_type_t<std::chrono::nanoseconds::rep, uint64_t>;
+    const auto count = std::min<CommonType>(kMaxCount, nanoseconds);
+    return std::chrono::nanoseconds{static_cast<std::chrono::nanoseconds::rep>(count)};
+}
+
+uint64_t makeUint64FromNanos(std::chrono::nanoseconds nanoseconds) {
+    if (nanoseconds < std::chrono::nanoseconds::zero()) {
+        return 0;
+    }
+    constexpr auto kMaxCount = std::numeric_limits<uint64_t>::max();
+    using CommonType = std::common_type_t<std::chrono::nanoseconds::rep, uint64_t>;
+    const auto count = std::min<CommonType>(kMaxCount, nanoseconds.count());
+    return static_cast<uint64_t>(count);
+}
+
 template <typename Type>
 constexpr std::underlying_type_t<Type> underlyingType(Type value) {
     return static_cast<std::underlying_type_t<Type>>(value);
@@ -237,8 +254,32 @@
     switch (optionalTimePoint.getDiscriminator()) {
         case Discriminator::none:
             return {};
-        case Discriminator::nanosecondsSinceEpoch:
-            return TimePoint{Duration{optionalTimePoint.nanosecondsSinceEpoch()}};
+        case Discriminator::nanosecondsSinceEpoch: {
+            const auto currentSteadyTime = std::chrono::steady_clock::now();
+            const auto currentBootTime = Clock::now();
+
+            const auto timeSinceEpoch =
+                    makeNanosFromUint64(optionalTimePoint.nanosecondsSinceEpoch());
+            const auto steadyTimePoint = std::chrono::steady_clock::time_point{timeSinceEpoch};
+
+            // Both steadyTimePoint and currentSteadyTime are guaranteed to be non-negative, so this
+            // subtraction will never overflow or underflow.
+            const auto timeRemaining = steadyTimePoint - currentSteadyTime;
+
+            // currentBootTime is guaranteed to be non-negative, so this code only protects against
+            // an overflow.
+            nn::TimePoint bootTimePoint;
+            constexpr auto kZeroNano = std::chrono::nanoseconds::zero();
+            constexpr auto kMaxTime = nn::TimePoint::max();
+            if (timeRemaining > kZeroNano && currentBootTime > kMaxTime - timeRemaining) {
+                bootTimePoint = kMaxTime;
+            } else {
+                bootTimePoint = currentBootTime + timeRemaining;
+            }
+
+            constexpr auto kZeroTime = nn::TimePoint{};
+            return std::max(bootTimePoint, kZeroTime);
+        }
     }
     return NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
            << "Invalid OptionalTimePoint discriminator "
@@ -549,9 +590,33 @@
 
 nn::GeneralResult<OptionalTimePoint> unvalidatedConvert(
         const nn::OptionalTimePoint& optionalTimePoint) {
+    const auto currentSteadyTime = std::chrono::steady_clock::now();
+    const auto currentBootTime = nn::Clock::now();
+
     OptionalTimePoint ret;
     if (optionalTimePoint.has_value()) {
-        const auto count = optionalTimePoint.value().time_since_epoch().count();
+        const auto bootTimePoint = optionalTimePoint.value();
+
+        if (bootTimePoint < nn::TimePoint{}) {
+            return NN_ERROR() << "Trying to cast invalid time point";
+        }
+
+        // Both bootTimePoint and currentBootTime are guaranteed to be non-negative, so this
+        // subtraction will never overflow or underflow.
+        const auto timeRemaining = bootTimePoint - currentBootTime;
+
+        // currentSteadyTime is guaranteed to be non-negative, so this code only protects against an
+        // overflow.
+        std::chrono::steady_clock::time_point steadyTimePoint;
+        constexpr auto kZeroNano = std::chrono::nanoseconds::zero();
+        constexpr auto kMaxTime = std::chrono::steady_clock::time_point::max();
+        if (timeRemaining > kZeroNano && currentSteadyTime > kMaxTime - timeRemaining) {
+            steadyTimePoint = kMaxTime;
+        } else {
+            steadyTimePoint = currentSteadyTime + timeRemaining;
+        }
+
+        const uint64_t count = makeUint64FromNanos(steadyTimePoint.time_since_epoch());
         ret.nanosecondsSinceEpoch(count);
     }
     return ret;
diff --git a/neuralnetworks/aidl/Android.bp b/neuralnetworks/aidl/Android.bp
index b1860e2..ebf4654 100644
--- a/neuralnetworks/aidl/Android.bp
+++ b/neuralnetworks/aidl/Android.bp
@@ -16,6 +16,7 @@
     stability: "vintf",
     imports: [
         "android.hardware.common",
+        "android.hardware.graphics.common",
     ],
     backend: {
         java: {
diff --git a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Memory.aidl b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Memory.aidl
index 8207b25..37fa102 100644
--- a/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Memory.aidl
+++ b/neuralnetworks/aidl/aidl_api/android.hardware.neuralnetworks/current/android/hardware/neuralnetworks/Memory.aidl
@@ -33,8 +33,8 @@
 
 package android.hardware.neuralnetworks;
 @VintfStability
-parcelable Memory {
-  android.hardware.common.NativeHandle handle;
-  long size;
-  String name;
+union Memory {
+  android.hardware.common.Ashmem ashmem;
+  android.hardware.common.MappableFile mappableFile;
+  android.hardware.graphics.common.HardwareBuffer hardwareBuffer;
 }
diff --git a/neuralnetworks/aidl/android/hardware/neuralnetworks/FusedActivationFunc.aidl b/neuralnetworks/aidl/android/hardware/neuralnetworks/FusedActivationFunc.aidl
index 861b6f0..df015ca 100644
--- a/neuralnetworks/aidl/android/hardware/neuralnetworks/FusedActivationFunc.aidl
+++ b/neuralnetworks/aidl/android/hardware/neuralnetworks/FusedActivationFunc.aidl
@@ -22,8 +22,20 @@
 @VintfStability
 @Backing(type="int")
 enum FusedActivationFunc {
+    /**
+     * No activation.
+     */
     NONE,
+    /**
+     * ReLU(x) = max(0, x)
+     */
     RELU,
+    /**
+     * ReLU1(x) = min(1, max(-1, x))
+     */
     RELU1,
+    /**
+     * ReLU6(x) = min(6, max(0, x))
+     */
     RELU6,
 }
diff --git a/neuralnetworks/aidl/android/hardware/neuralnetworks/IDevice.aidl b/neuralnetworks/aidl/android/hardware/neuralnetworks/IDevice.aidl
index e17e0cd..c5b4ab1 100644
--- a/neuralnetworks/aidl/android/hardware/neuralnetworks/IDevice.aidl
+++ b/neuralnetworks/aidl/android/hardware/neuralnetworks/IDevice.aidl
@@ -307,10 +307,10 @@
      * @param priority The priority of the prepared model relative to other prepared models owned by
      *                 the client.
      * @param deadline The time by which the model is expected to be prepared. The time is measured
-     *                 in nanoseconds since epoch of the steady clock (as from
-     *                 std::chrono::steady_clock). If the model cannot be prepared by the deadline,
-     *                 the preparation may be aborted. Passing -1 means the deadline is omitted.
-     *                 Other negative values are invalid.
+     *                 in nanoseconds since boot (as from clock_gettime(CLOCK_BOOTTIME, &ts)
+     *                 or ::android::base::boot_clock). If the model cannot be prepared by the
+     *                 deadline, the preparation may be aborted. Passing -1 means the deadline is
+     *                 omitted. Other negative values are invalid.
      * @param modelCache A vector of file descriptors for the security-sensitive cache. The length
      *                   of the vector must either be 0 indicating that caching information is not
      *                   provided, or match the numModelCache returned from
@@ -396,10 +396,10 @@
      * different shapes of inputs on different (possibly concurrent) executions.
      *
      * @param deadline The time by which the model is expected to be prepared. The time is measured
-     *                 in nanoseconds since epoch of the steady clock (as from
-     *                 std::chrono::steady_clock). If the model cannot be prepared by the deadline,
-     *                 the preparation may be aborted. Passing -1 means the deadline is omitted.
-     *                 Other negative values are invalid.
+     *                 in nanoseconds since boot (as from clock_gettime(CLOCK_BOOTTIME, &ts) or
+     *                 ::android::base::boot_clock). If the model cannot be prepared by the
+     *                 deadline, the preparation may be aborted. Passing -1 means the deadline is
+     *                 omitted. Other negative values are invalid.
      * @param modelCache A vector of file descriptors for the security-sensitive cache. The length
      *                   of the vector must match the numModelCache returned from
      *                   getNumberOfCacheFilesNeeded. The cache file descriptors will be provided in
diff --git a/neuralnetworks/aidl/android/hardware/neuralnetworks/IPreparedModel.aidl b/neuralnetworks/aidl/android/hardware/neuralnetworks/IPreparedModel.aidl
index 2a9757b..bfab906 100644
--- a/neuralnetworks/aidl/android/hardware/neuralnetworks/IPreparedModel.aidl
+++ b/neuralnetworks/aidl/android/hardware/neuralnetworks/IPreparedModel.aidl
@@ -73,8 +73,8 @@
      *                runs from the time the driver sees the call to the executeSynchronously
      *                function to the time the driver returns from the function.
      * @param deadline The time by which the execution is expected to complete. The time is measured
-     *                 in nanoseconds since epoch of the steady clock (as from
-     *                 std::chrono::steady_clock). If the execution cannot be finished by the
+     *                 in nanoseconds since boot (as from clock_gettime(CLOCK_BOOTTIME, &ts) or
+     *                 ::android::base::boot_clock). If the execution cannot be finished by the
      *                 deadline, the execution may be aborted. Passing -1 means the deadline is
      *                 omitted. Other negative values are invalid.
      * @param loopTimeoutDuration The maximum amount of time in nanoseconds that should be spent
@@ -138,8 +138,8 @@
      *                sync fences have been signaled.
      * @param measure Specifies whether or not to measure duration of the execution.
      * @param deadline The time by which the execution is expected to complete. The time is measured
-     *                 in nanoseconds since epoch of the steady clock (as from
-     *                 std::chrono::steady_clock).If the execution cannot be finished by the
+     *                 in nanoseconds since boot (as from clock_gettime(CLOCK_BOOTTIME, &ts) or
+     *                 ::android::base::boot_clock). If the execution cannot be finished by the
      *                 deadline, the execution may be aborted. Passing -1 means the deadline is
      *                 omitted. Other negative values are invalid.
      * @param loopTimeoutDuration The maximum amount of time in nanoseconds that should be spent
diff --git a/neuralnetworks/aidl/android/hardware/neuralnetworks/Memory.aidl b/neuralnetworks/aidl/android/hardware/neuralnetworks/Memory.aidl
index 870f0ae..244ac87 100644
--- a/neuralnetworks/aidl/android/hardware/neuralnetworks/Memory.aidl
+++ b/neuralnetworks/aidl/android/hardware/neuralnetworks/Memory.aidl
@@ -15,16 +15,26 @@
  */
 
 package android.hardware.neuralnetworks;
-import android.hardware.common.NativeHandle;
-import android.os.ParcelFileDescriptor;
+
+import android.hardware.common.Ashmem;
+import android.hardware.common.MappableFile;
+import android.hardware.graphics.common.HardwareBuffer;
 
 /**
- * A type that is used to pass pieces of shared memory between processes.
- * The type structure mimics hidl_memory type from HIDL.
+ * The different types of memory that can be shared across processes.
  */
 @VintfStability
-parcelable Memory {
-    NativeHandle handle;
-    long size;
-    String name;
+union Memory {
+    /**
+     * Ashmem hidl_memory type from HIDL.
+     */
+    Ashmem ashmem;
+    /**
+     * File that can be mapped.
+     */
+    MappableFile mappableFile;
+    /**
+     * AIDL representation of AHardwareBuffer.
+     */
+    HardwareBuffer hardwareBuffer;
 }
diff --git a/neuralnetworks/aidl/utils/Android.bp b/neuralnetworks/aidl/utils/Android.bp
index ad961cf..0ccc711 100644
--- a/neuralnetworks/aidl/utils/Android.bp
+++ b/neuralnetworks/aidl/utils/Android.bp
@@ -31,6 +31,8 @@
     export_include_dirs: ["include"],
     cflags: ["-Wthread-safety"],
     static_libs: [
+        "android.hardware.graphics.common-V2-ndk_platform",
+        "libaidlcommonsupport",
         "libarect",
         "neuralnetworks_types",
         "neuralnetworks_utils_hal_common",
@@ -51,7 +53,9 @@
     ],
     static_libs: [
         "android.hardware.common-V2-ndk_platform",
+        "android.hardware.graphics.common-V2-ndk_platform",
         "android.hardware.neuralnetworks-V1-ndk_platform",
+        "libaidlcommonsupport",
         "libgmock",
         "libneuralnetworks_common",
         "neuralnetworks_types",
diff --git a/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/InvalidDevice.h b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/InvalidDevice.h
new file mode 100644
index 0000000..e66507a
--- /dev/null
+++ b/neuralnetworks/aidl/utils/include/nnapi/hal/aidl/InvalidDevice.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/neuralnetworks/BnBuffer.h>
+#include <aidl/android/hardware/neuralnetworks/BnDevice.h>
+#include <aidl/android/hardware/neuralnetworks/BnPreparedModel.h>
+#include <android/binder_auto_utils.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace aidl::android::hardware::neuralnetworks {
+
+class InvalidDevice : public BnDevice {
+  public:
+    static std::shared_ptr<InvalidDevice> create();
+
+    InvalidDevice(Capabilities capabilities, const NumberOfCacheFiles& numberOfCacheFiles,
+                  std::vector<Extension> extensions, DeviceType deviceType,
+                  std::string versionString);
+
+    ndk::ScopedAStatus allocate(const BufferDesc& desc,
+                                const std::vector<IPreparedModelParcel>& preparedModels,
+                                const std::vector<BufferRole>& inputRoles,
+                                const std::vector<BufferRole>& outputRoles,
+                                DeviceBuffer* deviceBuffer) override;
+    ndk::ScopedAStatus getCapabilities(Capabilities* capabilities) override;
+    ndk::ScopedAStatus getNumberOfCacheFilesNeeded(NumberOfCacheFiles* numberOfCacheFiles) override;
+    ndk::ScopedAStatus getSupportedExtensions(std::vector<Extension>* extensions) override;
+    ndk::ScopedAStatus getSupportedOperations(const Model& model,
+                                              std::vector<bool>* supportedOperations) override;
+    ndk::ScopedAStatus getType(DeviceType* deviceType) override;
+    ndk::ScopedAStatus getVersionString(std::string* versionString) override;
+    ndk::ScopedAStatus prepareModel(
+            const Model& model, ExecutionPreference preference, Priority priority, int64_t deadline,
+            const std::vector<ndk::ScopedFileDescriptor>& modelCache,
+            const std::vector<ndk::ScopedFileDescriptor>& dataCache,
+            const std::vector<uint8_t>& token,
+            const std::shared_ptr<IPreparedModelCallback>& callback) override;
+    ndk::ScopedAStatus prepareModelFromCache(
+            int64_t deadline, const std::vector<ndk::ScopedFileDescriptor>& modelCache,
+            const std::vector<ndk::ScopedFileDescriptor>& dataCache,
+            const std::vector<uint8_t>& token,
+            const std::shared_ptr<IPreparedModelCallback>& callback) override;
+
+  private:
+    const Capabilities kCapabilities;
+    const NumberOfCacheFiles kNumberOfCacheFiles;
+    const std::vector<Extension> kExtensions;
+    const DeviceType kDeviceType;
+    const std::string kVersionString;
+};
+
+}  // namespace aidl::android::hardware::neuralnetworks
diff --git a/neuralnetworks/aidl/utils/src/Conversions.cpp b/neuralnetworks/aidl/utils/src/Conversions.cpp
index c74c509..93ac51c 100644
--- a/neuralnetworks/aidl/utils/src/Conversions.cpp
+++ b/neuralnetworks/aidl/utils/src/Conversions.cpp
@@ -16,8 +16,13 @@
 
 #include "Conversions.h"
 
+#include <aidl/android/hardware/common/Ashmem.h>
+#include <aidl/android/hardware/common/MappableFile.h>
 #include <aidl/android/hardware/common/NativeHandle.h>
+#include <aidl/android/hardware/graphics/common/HardwareBuffer.h>
+#include <aidlcommonsupport/NativeHandle.h>
 #include <android-base/logging.h>
+#include <android-base/mapped_file.h>
 #include <android-base/unique_fd.h>
 #include <android/binder_auto_utils.h>
 #include <android/hardware_buffer.h>
@@ -125,28 +130,17 @@
 
 using UniqueNativeHandle = std::unique_ptr<native_handle_t, NativeHandleDeleter>;
 
-static GeneralResult<UniqueNativeHandle> nativeHandleFromAidlHandle(const NativeHandle& handle) {
-    std::vector<base::unique_fd> fds;
-    fds.reserve(handle.fds.size());
-    for (const auto& fd : handle.fds) {
-        auto duplicatedFd = NN_TRY(dupFd(fd.get()));
-        fds.emplace_back(duplicatedFd.release());
+GeneralResult<UniqueNativeHandle> nativeHandleFromAidlHandle(const NativeHandle& handle) {
+    auto nativeHandle = UniqueNativeHandle(dupFromAidl(handle));
+    if (nativeHandle.get() == nullptr) {
+        return NN_ERROR() << "android::dupFromAidl failed to convert the common::NativeHandle to a "
+                             "native_handle_t";
     }
-
-    constexpr size_t kIntMax = std::numeric_limits<int>::max();
-    CHECK_LE(handle.fds.size(), kIntMax);
-    CHECK_LE(handle.ints.size(), kIntMax);
-    native_handle_t* nativeHandle = native_handle_create(static_cast<int>(handle.fds.size()),
-                                                         static_cast<int>(handle.ints.size()));
-    if (nativeHandle == nullptr) {
-        return NN_ERROR() << "Failed to create native_handle";
+    if (!std::all_of(nativeHandle->data + 0, nativeHandle->data + nativeHandle->numFds,
+                     [](int fd) { return fd >= 0; })) {
+        return NN_ERROR() << "android::dupFromAidl returned an invalid native_handle_t";
     }
-    for (size_t i = 0; i < fds.size(); ++i) {
-        nativeHandle->data[i] = fds[i].release();
-    }
-    std::copy(handle.ints.begin(), handle.ints.end(), &nativeHandle->data[nativeHandle->numFds]);
-
-    return UniqueNativeHandle(nativeHandle);
+    return nativeHandle;
 }
 
 }  // anonymous namespace
@@ -353,67 +347,66 @@
     return measureTiming ? MeasureTiming::YES : MeasureTiming::NO;
 }
 
-static uint32_t roundUpToMultiple(uint32_t value, uint32_t multiple) {
-    return (value + multiple - 1) / multiple * multiple;
-}
-
 GeneralResult<SharedMemory> unvalidatedConvert(const aidl_hal::Memory& memory) {
-    VERIFY_NON_NEGATIVE(memory.size) << "Memory size must not be negative";
-    if (memory.size > std::numeric_limits<size_t>::max()) {
-        return NN_ERROR() << "Memory: size must be <= std::numeric_limits<size_t>::max()";
-    }
+    using Tag = aidl_hal::Memory::Tag;
+    switch (memory.getTag()) {
+        case Tag::ashmem: {
+            const auto& ashmem = memory.get<Tag::ashmem>();
+            VERIFY_NON_NEGATIVE(ashmem.size) << "Memory size must not be negative";
+            if (ashmem.size > std::numeric_limits<size_t>::max()) {
+                return NN_ERROR() << "Memory: size must be <= std::numeric_limits<size_t>::max()";
+            }
 
-    if (memory.name != "hardware_buffer_blob") {
-        return std::make_shared<const Memory>(Memory{
-                .handle = NN_TRY(unvalidatedConvertHelper(memory.handle)),
-                .size = static_cast<size_t>(memory.size),
-                .name = memory.name,
-        });
-    }
+            auto handle = Memory::Ashmem{
+                    .fd = NN_TRY(dupFd(ashmem.fd.get())),
+                    .size = static_cast<size_t>(ashmem.size),
+            };
+            return std::make_shared<const Memory>(Memory{.handle = std::move(handle)});
+        }
+        case Tag::mappableFile: {
+            const auto& mappableFile = memory.get<Tag::mappableFile>();
+            VERIFY_NON_NEGATIVE(mappableFile.length) << "Memory size must not be negative";
+            VERIFY_NON_NEGATIVE(mappableFile.offset) << "Memory offset must not be negative";
+            if (mappableFile.length > std::numeric_limits<size_t>::max()) {
+                return NN_ERROR() << "Memory: size must be <= std::numeric_limits<size_t>::max()";
+            }
+            if (mappableFile.offset > std::numeric_limits<size_t>::max()) {
+                return NN_ERROR() << "Memory: offset must be <= std::numeric_limits<size_t>::max()";
+            }
 
-    const auto size = static_cast<uint32_t>(memory.size);
-    const auto format = AHARDWAREBUFFER_FORMAT_BLOB;
-    const auto usage = AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN | AHARDWAREBUFFER_USAGE_CPU_WRITE_OFTEN;
-    const uint32_t width = size;
-    const uint32_t height = 1;  // height is always 1 for BLOB mode AHardwareBuffer.
-    const uint32_t layers = 1;  // layers is always 1 for BLOB mode AHardwareBuffer.
+            const size_t size = static_cast<size_t>(mappableFile.length);
+            const int prot = mappableFile.prot;
+            const int fd = mappableFile.fd.get();
+            const size_t offset = static_cast<size_t>(mappableFile.offset);
 
-    const UniqueNativeHandle handle = NN_TRY(nativeHandleFromAidlHandle(memory.handle));
-    const native_handle_t* nativeHandle = handle.get();
+            return createSharedMemoryFromFd(size, prot, fd, offset);
+        }
+        case Tag::hardwareBuffer: {
+            const auto& hardwareBuffer = memory.get<Tag::hardwareBuffer>();
 
-    // AHardwareBuffer_createFromHandle() might fail because an allocator
-    // expects a specific stride value. In that case, we try to guess it by
-    // aligning the width to small powers of 2.
-    // TODO(b/174120849): Avoid stride assumptions.
-    AHardwareBuffer* hardwareBuffer = nullptr;
-    status_t status = UNKNOWN_ERROR;
-    for (uint32_t alignment : {1, 4, 32, 64, 128, 2, 8, 16}) {
-        const uint32_t stride = roundUpToMultiple(width, alignment);
-        AHardwareBuffer_Desc desc{
-                .width = width,
-                .height = height,
-                .layers = layers,
-                .format = format,
-                .usage = usage,
-                .stride = stride,
-        };
-        status = AHardwareBuffer_createFromHandle(&desc, nativeHandle,
-                                                  AHARDWAREBUFFER_CREATE_FROM_HANDLE_METHOD_CLONE,
-                                                  &hardwareBuffer);
-        if (status == NO_ERROR) {
-            break;
+            const UniqueNativeHandle handle =
+                    NN_TRY(nativeHandleFromAidlHandle(hardwareBuffer.handle));
+            const native_handle_t* nativeHandle = handle.get();
+
+            const AHardwareBuffer_Desc desc{
+                    .width = static_cast<uint32_t>(hardwareBuffer.description.width),
+                    .height = static_cast<uint32_t>(hardwareBuffer.description.height),
+                    .layers = static_cast<uint32_t>(hardwareBuffer.description.layers),
+                    .format = static_cast<uint32_t>(hardwareBuffer.description.format),
+                    .usage = static_cast<uint64_t>(hardwareBuffer.description.usage),
+                    .stride = static_cast<uint32_t>(hardwareBuffer.description.stride),
+            };
+            AHardwareBuffer* ahwb = nullptr;
+            const status_t status = AHardwareBuffer_createFromHandle(
+                    &desc, nativeHandle, AHARDWAREBUFFER_CREATE_FROM_HANDLE_METHOD_CLONE, &ahwb);
+            if (status != NO_ERROR) {
+                return NN_ERROR() << "createFromHandle failed";
+            }
+
+            return createSharedMemoryFromAHWB(ahwb, /*takeOwnership=*/true);
         }
     }
-    if (status != NO_ERROR) {
-        return NN_ERROR(ErrorStatus::GENERAL_FAILURE)
-               << "Can't create AHardwareBuffer from handle. Error: " << status;
-    }
-
-    return std::make_shared<const Memory>(Memory{
-            .handle = HardwareBufferHandle(hardwareBuffer, /*takeOwnership=*/true),
-            .size = static_cast<size_t>(memory.size),
-            .name = memory.name,
-    });
+    return NN_ERROR() << "Unrecognized Memory::Tag: " << memory.getTag();
 }
 
 GeneralResult<Timing> unvalidatedConvert(const aidl_hal::Timing& timing) {
@@ -645,20 +638,95 @@
 template <class... Ts>
 overloaded(Ts...)->overloaded<Ts...>;
 
-static nn::GeneralResult<common::NativeHandle> aidlHandleFromNativeHandle(
-        const native_handle_t& handle) {
-    common::NativeHandle aidlNativeHandle;
+nn::GeneralResult<common::NativeHandle> aidlHandleFromNativeHandle(
+        const native_handle_t& nativeHandle) {
+    auto handle = ::android::dupToAidl(&nativeHandle);
+    if (!std::all_of(handle.fds.begin(), handle.fds.end(),
+                     [](const ndk::ScopedFileDescriptor& fd) { return fd.get() >= 0; })) {
+        return NN_ERROR() << "android::dupToAidl returned an invalid common::NativeHandle";
+    }
+    return handle;
+}
 
-    aidlNativeHandle.fds.reserve(handle.numFds);
-    for (int i = 0; i < handle.numFds; ++i) {
-        auto duplicatedFd = NN_TRY(nn::dupFd(handle.data[i]));
-        aidlNativeHandle.fds.emplace_back(duplicatedFd.release());
+nn::GeneralResult<Memory> unvalidatedConvert(const nn::Memory::Ashmem& memory) {
+    if constexpr (std::numeric_limits<size_t>::max() > std::numeric_limits<int64_t>::max()) {
+        if (memory.size > std::numeric_limits<int64_t>::max()) {
+            return (
+                           NN_ERROR()
+                           << "Memory::Ashmem: size must be <= std::numeric_limits<int64_t>::max()")
+                    .
+                    operator nn::GeneralResult<Memory>();
+        }
     }
 
-    aidlNativeHandle.ints = std::vector<int>(&handle.data[handle.numFds],
-                                             &handle.data[handle.numFds + handle.numInts]);
+    auto fd = NN_TRY(nn::dupFd(memory.fd));
+    auto handle = common::Ashmem{
+            .fd = ndk::ScopedFileDescriptor(fd.release()),
+            .size = static_cast<int64_t>(memory.size),
+    };
+    return Memory::make<Memory::Tag::ashmem>(std::move(handle));
+}
 
-    return aidlNativeHandle;
+nn::GeneralResult<Memory> unvalidatedConvert(const nn::Memory::Fd& memory) {
+    if constexpr (std::numeric_limits<size_t>::max() > std::numeric_limits<int64_t>::max()) {
+        if (memory.size > std::numeric_limits<int64_t>::max()) {
+            return (NN_ERROR() << "Memory::Fd: size must be <= std::numeric_limits<int64_t>::max()")
+                    .
+                    operator nn::GeneralResult<Memory>();
+        }
+        if (memory.offset > std::numeric_limits<int64_t>::max()) {
+            return (
+                           NN_ERROR()
+                           << "Memory::Fd: offset must be <= std::numeric_limits<int64_t>::max()")
+                    .
+                    operator nn::GeneralResult<Memory>();
+        }
+    }
+
+    auto fd = NN_TRY(nn::dupFd(memory.fd));
+    auto handle = common::MappableFile{
+            .length = static_cast<int64_t>(memory.size),
+            .prot = memory.prot,
+            .fd = ndk::ScopedFileDescriptor(fd.release()),
+            .offset = static_cast<int64_t>(memory.offset),
+    };
+    return Memory::make<Memory::Tag::mappableFile>(std::move(handle));
+}
+
+nn::GeneralResult<Memory> unvalidatedConvert(const nn::Memory::HardwareBuffer& memory) {
+    const native_handle_t* nativeHandle = AHardwareBuffer_getNativeHandle(memory.handle.get());
+    if (nativeHandle == nullptr) {
+        return (NN_ERROR() << "unvalidatedConvert failed because AHardwareBuffer_getNativeHandle "
+                              "returned nullptr")
+                .
+                operator nn::GeneralResult<Memory>();
+    }
+
+    auto handle = NN_TRY(aidlHandleFromNativeHandle(*nativeHandle));
+
+    AHardwareBuffer_Desc desc;
+    AHardwareBuffer_describe(memory.handle.get(), &desc);
+
+    const auto description = graphics::common::HardwareBufferDescription{
+            .width = static_cast<int32_t>(desc.width),
+            .height = static_cast<int32_t>(desc.height),
+            .layers = static_cast<int32_t>(desc.layers),
+            .format = static_cast<graphics::common::PixelFormat>(desc.format),
+            .usage = static_cast<graphics::common::BufferUsage>(desc.usage),
+            .stride = static_cast<int32_t>(desc.stride),
+    };
+
+    auto hardwareBuffer = graphics::common::HardwareBuffer{
+            .description = std::move(description),
+            .handle = std::move(handle),
+    };
+    return Memory::make<Memory::Tag::hardwareBuffer>(std::move(hardwareBuffer));
+}
+
+nn::GeneralResult<Memory> unvalidatedConvert(const nn::Memory::Unknown& /*memory*/) {
+    return (NN_ERROR() << "Unable to convert Unknown memory type")
+            .
+            operator nn::GeneralResult<Memory>();
 }
 
 }  // namespace
@@ -693,41 +761,12 @@
 }
 
 nn::GeneralResult<Memory> unvalidatedConvert(const nn::SharedMemory& memory) {
-    CHECK(memory != nullptr);
-    if (memory->size > std::numeric_limits<int64_t>::max()) {
-        return NN_ERROR() << "Memory size doesn't fit into int64_t.";
+    if (memory == nullptr) {
+        return (NN_ERROR() << "Unable to convert nullptr memory")
+                .
+                operator nn::GeneralResult<Memory>();
     }
-    if (const auto* handle = std::get_if<nn::Handle>(&memory->handle)) {
-        return Memory{
-                .handle = NN_TRY(unvalidatedConvert(*handle)),
-                .size = static_cast<int64_t>(memory->size),
-                .name = memory->name,
-        };
-    }
-
-    const auto* ahwb = std::get<nn::HardwareBufferHandle>(memory->handle).get();
-    AHardwareBuffer_Desc bufferDesc;
-    AHardwareBuffer_describe(ahwb, &bufferDesc);
-
-    if (bufferDesc.format == AHARDWAREBUFFER_FORMAT_BLOB) {
-        CHECK_EQ(memory->size, bufferDesc.width);
-        CHECK_EQ(memory->name, "hardware_buffer_blob");
-    } else {
-        CHECK_EQ(memory->size, 0u);
-        CHECK_EQ(memory->name, "hardware_buffer");
-    }
-
-    const native_handle_t* nativeHandle = AHardwareBuffer_getNativeHandle(ahwb);
-    if (nativeHandle == nullptr) {
-        return NN_ERROR() << "unvalidatedConvert failed because AHardwareBuffer_getNativeHandle "
-                             "returned nullptr";
-    }
-
-    return Memory{
-            .handle = NN_TRY(aidlHandleFromNativeHandle(*nativeHandle)),
-            .size = static_cast<int64_t>(memory->size),
-            .name = memory->name,
-    };
+    return std::visit([](const auto& x) { return unvalidatedConvert(x); }, memory->handle);
 }
 
 nn::GeneralResult<ErrorStatus> unvalidatedConvert(const nn::ErrorStatus& errorStatus) {
@@ -931,11 +970,12 @@
 }
 
 nn::GeneralResult<int64_t> unvalidatedConvert(const nn::Duration& duration) {
-    const uint64_t nanoseconds = duration.count();
-    if (nanoseconds > std::numeric_limits<int64_t>::max()) {
-        return std::numeric_limits<int64_t>::max();
+    if (duration < nn::Duration::zero()) {
+        return NN_ERROR() << "Unable to convert invalid (negative) duration";
     }
-    return static_cast<int64_t>(nanoseconds);
+    constexpr std::chrono::nanoseconds::rep kIntMax = std::numeric_limits<int64_t>::max();
+    const auto count = duration.count();
+    return static_cast<int64_t>(std::min(count, kIntMax));
 }
 
 nn::GeneralResult<int64_t> unvalidatedConvert(const nn::OptionalDuration& optionalDuration) {
diff --git a/neuralnetworks/aidl/utils/src/InvalidDevice.cpp b/neuralnetworks/aidl/utils/src/InvalidDevice.cpp
new file mode 100644
index 0000000..c9d9955
--- /dev/null
+++ b/neuralnetworks/aidl/utils/src/InvalidDevice.cpp
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2021 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 "InvalidDevice"
+
+#include "InvalidDevice.h"
+
+#include <aidl/android/hardware/neuralnetworks/BnBuffer.h>
+#include <aidl/android/hardware/neuralnetworks/BnDevice.h>
+#include <aidl/android/hardware/neuralnetworks/BnPreparedModel.h>
+#include <android/binder_auto_utils.h>
+
+#include "Conversions.h"
+#include "Utils.h"
+
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+namespace aidl::android::hardware::neuralnetworks {
+namespace {
+
+ndk::ScopedAStatus toAStatus(ErrorStatus errorStatus, const std::string& errorMessage) {
+    if (errorStatus == ErrorStatus::NONE) {
+        return ndk::ScopedAStatus::ok();
+    }
+    return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(
+            static_cast<int32_t>(errorStatus), errorMessage.c_str());
+}
+
+}  // namespace
+
+std::shared_ptr<InvalidDevice> InvalidDevice::create() {
+    constexpr auto perf = PerformanceInfo{
+            .execTime = std::numeric_limits<float>::max(),
+            .powerUsage = std::numeric_limits<float>::max(),
+    };
+    auto capabilities = Capabilities{
+            .relaxedFloat32toFloat16PerformanceScalar = perf,
+            .relaxedFloat32toFloat16PerformanceTensor = perf,
+            .operandPerformance = {},
+            .ifPerformance = perf,
+            .whilePerformance = perf,
+    };
+    constexpr auto numberOfCacheFiles = NumberOfCacheFiles{
+            .numModelCache = 0,
+            .numDataCache = 0,
+    };
+    std::vector<Extension> extensions{};
+    constexpr auto deviceType = DeviceType::OTHER;
+    std::string versionString = "invalid";
+
+    return ndk::SharedRefBase::make<InvalidDevice>(std::move(capabilities), numberOfCacheFiles,
+                                                   std::move(extensions), deviceType,
+                                                   std::move(versionString));
+}
+
+InvalidDevice::InvalidDevice(Capabilities capabilities,
+                             const NumberOfCacheFiles& numberOfCacheFiles,
+                             std::vector<Extension> extensions, DeviceType deviceType,
+                             std::string versionString)
+    : kCapabilities(std::move(capabilities)),
+      kNumberOfCacheFiles(numberOfCacheFiles),
+      kExtensions(std::move(extensions)),
+      kDeviceType(deviceType),
+      kVersionString(std::move(versionString)) {}
+
+ndk::ScopedAStatus InvalidDevice::allocate(
+        const BufferDesc& /*desc*/, const std::vector<IPreparedModelParcel>& /*preparedModels*/,
+        const std::vector<BufferRole>& /*inputRoles*/,
+        const std::vector<BufferRole>& /*outputRoles*/, DeviceBuffer* /*deviceBuffer*/) {
+    return toAStatus(ErrorStatus::GENERAL_FAILURE, "InvalidDevice");
+}
+
+ndk::ScopedAStatus InvalidDevice::getCapabilities(Capabilities* capabilities) {
+    *capabilities = kCapabilities;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus InvalidDevice::getNumberOfCacheFilesNeeded(
+        NumberOfCacheFiles* numberOfCacheFiles) {
+    *numberOfCacheFiles = kNumberOfCacheFiles;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus InvalidDevice::getSupportedExtensions(std::vector<Extension>* extensions) {
+    *extensions = kExtensions;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus InvalidDevice::getSupportedOperations(const Model& model,
+                                                         std::vector<bool>* supportedOperations) {
+    if (const auto result = utils::validate(model); !result.ok()) {
+        return toAStatus(ErrorStatus::INVALID_ARGUMENT, result.error());
+    }
+    *supportedOperations = std::vector<bool>(model.main.operations.size(), false);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus InvalidDevice::getType(DeviceType* deviceType) {
+    *deviceType = kDeviceType;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus InvalidDevice::getVersionString(std::string* versionString) {
+    *versionString = kVersionString;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus InvalidDevice::prepareModel(
+        const Model& model, ExecutionPreference preference, Priority priority, int64_t deadline,
+        const std::vector<ndk::ScopedFileDescriptor>& modelCache,
+        const std::vector<ndk::ScopedFileDescriptor>& dataCache, const std::vector<uint8_t>& token,
+        const std::shared_ptr<IPreparedModelCallback>& callback) {
+    if (callback.get() == nullptr) {
+        return toAStatus(ErrorStatus::INVALID_ARGUMENT,
+                         "invalid callback passed to InvalidDevice::prepareModel");
+    }
+    if (const auto result = utils::validate(model); !result.ok()) {
+        callback->notify(ErrorStatus::INVALID_ARGUMENT, nullptr);
+        return toAStatus(ErrorStatus::INVALID_ARGUMENT, result.error());
+    }
+    if (const auto result = utils::validate(preference); !result.ok()) {
+        callback->notify(ErrorStatus::INVALID_ARGUMENT, nullptr);
+        return toAStatus(ErrorStatus::INVALID_ARGUMENT, result.error());
+    }
+    if (const auto result = utils::validate(priority); !result.ok()) {
+        callback->notify(ErrorStatus::INVALID_ARGUMENT, nullptr);
+        return toAStatus(ErrorStatus::INVALID_ARGUMENT, result.error());
+    }
+    if (deadline < -1) {
+        callback->notify(ErrorStatus::INVALID_ARGUMENT, nullptr);
+        return toAStatus(ErrorStatus::INVALID_ARGUMENT,
+                         "Invalid deadline " + std::to_string(deadline));
+    }
+    if (modelCache.size() != static_cast<size_t>(kNumberOfCacheFiles.numModelCache)) {
+        callback->notify(ErrorStatus::INVALID_ARGUMENT, nullptr);
+        return toAStatus(ErrorStatus::INVALID_ARGUMENT,
+                         "Invalid modelCache, size = " + std::to_string(modelCache.size()));
+    }
+    if (dataCache.size() != static_cast<size_t>(kNumberOfCacheFiles.numDataCache)) {
+        callback->notify(ErrorStatus::INVALID_ARGUMENT, nullptr);
+        return toAStatus(ErrorStatus::INVALID_ARGUMENT,
+                         "Invalid modelCache, size = " + std::to_string(dataCache.size()));
+    }
+    if (token.size() != IDevice::BYTE_SIZE_OF_CACHE_TOKEN) {
+        callback->notify(ErrorStatus::INVALID_ARGUMENT, nullptr);
+        return toAStatus(
+                ErrorStatus::INVALID_ARGUMENT,
+                "Invalid cache token, size = " + std::to_string(IDevice::BYTE_SIZE_OF_CACHE_TOKEN));
+    }
+    callback->notify(ErrorStatus::GENERAL_FAILURE, nullptr);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus InvalidDevice::prepareModelFromCache(
+        int64_t /*deadline*/, const std::vector<ndk::ScopedFileDescriptor>& /*modelCache*/,
+        const std::vector<ndk::ScopedFileDescriptor>& /*dataCache*/,
+        const std::vector<uint8_t>& /*token*/,
+        const std::shared_ptr<IPreparedModelCallback>& callback) {
+    callback->notify(ErrorStatus::GENERAL_FAILURE, nullptr);
+    return toAStatus(ErrorStatus::GENERAL_FAILURE, "InvalidDevice");
+}
+
+}  // namespace aidl::android::hardware::neuralnetworks
diff --git a/neuralnetworks/aidl/utils/src/Service.cpp b/neuralnetworks/aidl/utils/src/Service.cpp
index 511de55..ac182a2 100644
--- a/neuralnetworks/aidl/utils/src/Service.cpp
+++ b/neuralnetworks/aidl/utils/src/Service.cpp
@@ -16,6 +16,7 @@
 
 #include "Service.h"
 
+#include <AndroidVersionUtil.h>
 #include <android/binder_auto_utils.h>
 #include <android/binder_manager.h>
 #include <android/binder_process.h>
@@ -35,13 +36,23 @@
     hal::utils::ResilientDevice::Factory makeDevice =
             [instanceName,
              name = std::move(fullName)](bool blocking) -> nn::GeneralResult<nn::SharedDevice> {
-        const auto& getService =
-                blocking ? AServiceManager_getService : AServiceManager_checkService;
+        std::add_pointer_t<AIBinder*(const char*)> getService;
+        if (blocking) {
+            if (__builtin_available(android __NNAPI_AIDL_MIN_ANDROID_API__, *)) {
+                getService = AServiceManager_waitForService;
+            } else {
+                getService = AServiceManager_getService;
+            }
+        } else {
+            getService = AServiceManager_checkService;
+        }
+
         auto service = IDevice::fromBinder(ndk::SpAIBinder(getService(name.c_str())));
         if (service == nullptr) {
-            return NN_ERROR() << (blocking ? "AServiceManager_getService"
-                                           : "AServiceManager_checkService")
-                              << " returned nullptr";
+            return NN_ERROR()
+                   << (blocking ? "AServiceManager_waitForService (or AServiceManager_getService)"
+                                : "AServiceManager_checkService")
+                   << " returned nullptr";
         }
         ABinderProcess_startThreadPool();
         return Device::create(instanceName, std::move(service));
diff --git a/neuralnetworks/aidl/utils/src/Utils.cpp b/neuralnetworks/aidl/utils/src/Utils.cpp
index 95516c8..03407be 100644
--- a/neuralnetworks/aidl/utils/src/Utils.cpp
+++ b/neuralnetworks/aidl/utils/src/Utils.cpp
@@ -16,12 +16,20 @@
 
 #include "Utils.h"
 
+#include <aidl/android/hardware/common/Ashmem.h>
+#include <aidl/android/hardware/common/MappableFile.h>
+#include <aidl/android/hardware/graphics/common/HardwareBuffer.h>
+#include <android/binder_auto_utils.h>
 #include <android/binder_status.h>
 #include <nnapi/Result.h>
+#include <nnapi/SharedMemory.h>
 
 namespace aidl::android::hardware::neuralnetworks::utils {
 namespace {
 
+nn::GeneralResult<ndk::ScopedFileDescriptor> clone(const ndk::ScopedFileDescriptor& fd);
+using utils::clone;
+
 template <typename Type>
 nn::GeneralResult<std::vector<Type>> cloneVec(const std::vector<Type>& arguments) {
     std::vector<Type> clonedObjects;
@@ -37,24 +45,52 @@
     return cloneVec(arguments);
 }
 
+nn::GeneralResult<ndk::ScopedFileDescriptor> clone(const ndk::ScopedFileDescriptor& fd) {
+    auto duplicatedFd = NN_TRY(nn::dupFd(fd.get()));
+    return ndk::ScopedFileDescriptor(duplicatedFd.release());
+}
+
+nn::GeneralResult<common::NativeHandle> clone(const common::NativeHandle& handle) {
+    return common::NativeHandle{
+            .fds = NN_TRY(cloneVec(handle.fds)),
+            .ints = handle.ints,
+    };
+}
+
 }  // namespace
 
 nn::GeneralResult<Memory> clone(const Memory& memory) {
-    common::NativeHandle nativeHandle;
-    nativeHandle.ints = memory.handle.ints;
-    nativeHandle.fds.reserve(memory.handle.fds.size());
-    for (const auto& fd : memory.handle.fds) {
-        const int newFd = dup(fd.get());
-        if (newFd < 0) {
-            return NN_ERROR() << "Couldn't dup a file descriptor";
+    switch (memory.getTag()) {
+        case Memory::Tag::ashmem: {
+            const auto& ashmem = memory.get<Memory::Tag::ashmem>();
+            auto handle = common::Ashmem{
+                    .fd = NN_TRY(clone(ashmem.fd)),
+                    .size = ashmem.size,
+            };
+            return Memory::make<Memory::Tag::ashmem>(std::move(handle));
         }
-        nativeHandle.fds.emplace_back(newFd);
+        case Memory::Tag::mappableFile: {
+            const auto& memFd = memory.get<Memory::Tag::mappableFile>();
+            auto handle = common::MappableFile{
+                    .length = memFd.length,
+                    .prot = memFd.prot,
+                    .fd = NN_TRY(clone(memFd.fd)),
+                    .offset = memFd.offset,
+            };
+            return Memory::make<Memory::Tag::mappableFile>(std::move(handle));
+        }
+        case Memory::Tag::hardwareBuffer: {
+            const auto& hardwareBuffer = memory.get<Memory::Tag::hardwareBuffer>();
+            auto handle = graphics::common::HardwareBuffer{
+                    .description = hardwareBuffer.description,
+                    .handle = NN_TRY(clone(hardwareBuffer.handle)),
+            };
+            return Memory::make<Memory::Tag::hardwareBuffer>(std::move(handle));
+        }
     }
-    return Memory{
-            .handle = std::move(nativeHandle),
-            .size = memory.size,
-            .name = memory.name,
-    };
+    return (NN_ERROR() << "Unrecognized Memory::Tag: " << memory.getTag())
+            .
+            operator nn::GeneralResult<Memory>();
 }
 
 nn::GeneralResult<RequestMemoryPool> clone(const RequestMemoryPool& requestPool) {
diff --git a/neuralnetworks/aidl/vts/functional/Android.bp b/neuralnetworks/aidl/vts/functional/Android.bp
index 7804c2a..d5b150a 100644
--- a/neuralnetworks/aidl/vts/functional/Android.bp
+++ b/neuralnetworks/aidl/vts/functional/Android.bp
@@ -50,9 +50,11 @@
     ],
     static_libs: [
         "android.hardware.common-V2-ndk_platform",
+        "android.hardware.graphics.common-V2-ndk_platform",
         "android.hardware.neuralnetworks-V1-ndk_platform",
         "android.hidl.allocator@1.0",
         "android.hidl.memory@1.0",
+        "libaidlcommonsupport",
         "libgmock",
         "libhidlmemory",
         "libneuralnetworks_generated_test_harness",
diff --git a/neuralnetworks/aidl/vts/functional/MemoryDomainTests.cpp b/neuralnetworks/aidl/vts/functional/MemoryDomainTests.cpp
index 596f8ae..e8313f1 100644
--- a/neuralnetworks/aidl/vts/functional/MemoryDomainTests.cpp
+++ b/neuralnetworks/aidl/vts/functional/MemoryDomainTests.cpp
@@ -16,6 +16,7 @@
 
 #define LOG_TAG "neuralnetworks_aidl_hal_test"
 
+#include <aidl/android/hardware/graphics/common/PixelFormat.h>
 #include <android-base/logging.h>
 #include <android/binder_auto_utils.h>
 #include <android/binder_interface_utils.h>
@@ -659,10 +660,26 @@
         return allocateBuffer(preparedModel, inputIndexes, outputIndexes, {});
     }
 
+    size_t getSize(const Memory& memory) {
+        switch (memory.getTag()) {
+            case Memory::Tag::ashmem:
+                return memory.get<Memory::Tag::ashmem>().size;
+            case Memory::Tag::mappableFile:
+                return memory.get<Memory::Tag::mappableFile>().length;
+            case Memory::Tag::hardwareBuffer: {
+                const auto& hardwareBuffer = memory.get<Memory::Tag::hardwareBuffer>();
+                const bool isBlob =
+                        hardwareBuffer.description.format == graphics::common::PixelFormat::BLOB;
+                return isBlob ? hardwareBuffer.description.width : 0;
+            }
+        }
+        return 0;
+    }
+
     Memory allocateSharedMemory(uint32_t size) {
         const auto sharedMemory = nn::createSharedMemory(size).value();
         auto memory = utils::convert(sharedMemory).value();
-        EXPECT_EQ(memory.size, size);
+        EXPECT_EQ(getSize(memory), size);
         return memory;
     }
 
@@ -690,7 +707,7 @@
 
     void initializeDeviceMemory(const std::shared_ptr<IBuffer>& buffer) {
         Memory memory = allocateSharedMemory(kTestOperandDataSize);
-        ASSERT_EQ(memory.size, kTestOperandDataSize);
+        ASSERT_EQ(getSize(memory), kTestOperandDataSize);
         testCopyFrom(buffer, memory, utils::toSigned(kTestOperand.dimensions).value(),
                      ErrorStatus::NONE);
     }
diff --git a/neuralnetworks/aidl/vts/functional/QualityOfServiceTests.cpp b/neuralnetworks/aidl/vts/functional/QualityOfServiceTests.cpp
index 9ace1a9..e803e38 100644
--- a/neuralnetworks/aidl/vts/functional/QualityOfServiceTests.cpp
+++ b/neuralnetworks/aidl/vts/functional/QualityOfServiceTests.cpp
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
+#include <android-base/chrono_utils.h>
 #include <android/binder_enums.h>
 #include <android/binder_interface_utils.h>
 #include <android/binder_status.h>
-
 #include <nnapi/hal/aidl/Conversions.h>
 
 #include "Callbacks.h"
@@ -61,16 +61,16 @@
         return std::chrono::duration_cast<std::chrono::nanoseconds>(timeSinceEpoch).count();
     };
 
-    std::chrono::steady_clock::time_point timePoint;
+    ::android::base::boot_clock::time_point timePoint;
     switch (deadlineBoundType) {
         case DeadlineBoundType::NOW:
-            timePoint = std::chrono::steady_clock::now();
+            timePoint = ::android::base::boot_clock::now();
             break;
         case DeadlineBoundType::UNLIMITED:
-            timePoint = std::chrono::steady_clock::time_point::max();
+            timePoint = ::android::base::boot_clock::time_point::max();
             break;
         case DeadlineBoundType::SHORT:
-            timePoint = std::chrono::steady_clock::now() + kShortDuration;
+            timePoint = ::android::base::boot_clock::now() + kShortDuration;
             break;
     }
 
diff --git a/neuralnetworks/aidl/vts/functional/ValidateModel.cpp b/neuralnetworks/aidl/vts/functional/ValidateModel.cpp
index 94d3daf..698c054 100644
--- a/neuralnetworks/aidl/vts/functional/ValidateModel.cpp
+++ b/neuralnetworks/aidl/vts/functional/ValidateModel.cpp
@@ -259,12 +259,16 @@
 size_t sizeForBinder(const Memory& memory) {
     // This is just a guess.
 
-    size_t size = 0;
-    const NativeHandle& handle = memory.handle;
-    size += sizeof(decltype(handle.fds)::value_type) * handle.fds.size();
-    size += sizeof(decltype(handle.ints)::value_type) * handle.ints.size();
-    size += sizeForBinder(memory.name);
-    size += sizeof(memory);
+    size_t size = sizeof(Memory);
+
+    // Only hardwareBuffer type memory has dynamic memory that needs to be accounted for (in the
+    // form of a NativeHandle type). The other other types of memory (MappableFile, Ashmem) use a
+    // single file descriptor (with metadata) instead.
+    if (memory.getTag() == Memory::Tag::hardwareBuffer) {
+        const NativeHandle& handle = memory.get<Memory::Tag::hardwareBuffer>().handle;
+        size += sizeof(decltype(handle.fds)::value_type) * handle.fds.size();
+        size += sizeof(decltype(handle.ints)::value_type) * handle.ints.size();
+    }
 
     return size;
 }
diff --git a/neuralnetworks/aidl/vts/functional/VtsHalNeuralnetworks.cpp b/neuralnetworks/aidl/vts/functional/VtsHalNeuralnetworks.cpp
index 0c3a196..ee7cf89 100644
--- a/neuralnetworks/aidl/vts/functional/VtsHalNeuralnetworks.cpp
+++ b/neuralnetworks/aidl/vts/functional/VtsHalNeuralnetworks.cpp
@@ -94,7 +94,7 @@
 }
 
 static NamedDevice makeNamedDevice(const std::string& name) {
-    ndk::SpAIBinder binder(AServiceManager_getService(name.c_str()));
+    ndk::SpAIBinder binder(AServiceManager_waitForService(name.c_str()));
     return {name, IDevice::fromBinder(binder)};
 }
 
diff --git a/neuralnetworks/utils/common/src/CommonUtils.cpp b/neuralnetworks/utils/common/src/CommonUtils.cpp
index 924ecb2..4d26795 100644
--- a/neuralnetworks/utils/common/src/CommonUtils.cpp
+++ b/neuralnetworks/utils/common/src/CommonUtils.cpp
@@ -89,6 +89,59 @@
                   });
 }
 
+nn::GeneralResult<hidl_handle> createNativeHandleFrom(base::unique_fd fd,
+                                                      const std::vector<int32_t>& ints) {
+    constexpr size_t kIntMax = std::numeric_limits<int>::max();
+    CHECK_LE(ints.size(), kIntMax);
+    native_handle_t* nativeHandle = native_handle_create(1, static_cast<int>(ints.size()));
+    if (nativeHandle == nullptr) {
+        return NN_ERROR() << "Failed to create native_handle";
+    }
+
+    nativeHandle->data[0] = fd.release();
+    std::copy(ints.begin(), ints.end(), nativeHandle->data + 1);
+
+    hidl_handle handle;
+    handle.setTo(nativeHandle, /*shouldOwn=*/true);
+    return handle;
+}
+
+nn::GeneralResult<hidl_memory> createHidlMemoryFrom(const nn::Memory::Ashmem& memory) {
+    auto fd = NN_TRY(nn::dupFd(memory.fd));
+    auto handle = NN_TRY(createNativeHandleFrom(std::move(fd), {}));
+    return hidl_memory("ashmem", std::move(handle), memory.size);
+}
+
+nn::GeneralResult<hidl_memory> createHidlMemoryFrom(const nn::Memory::Fd& memory) {
+    auto fd = NN_TRY(nn::dupFd(memory.fd));
+
+    const auto [lowOffsetBits, highOffsetBits] = nn::getIntsFromOffset(memory.offset);
+    const std::vector<int> ints = {memory.prot, lowOffsetBits, highOffsetBits};
+
+    auto handle = NN_TRY(createNativeHandleFrom(std::move(fd), ints));
+    return hidl_memory("mmap_fd", std::move(handle), memory.size);
+}
+
+nn::GeneralResult<hidl_memory> createHidlMemoryFrom(const nn::Memory::HardwareBuffer& memory) {
+    const auto* ahwb = memory.handle.get();
+    AHardwareBuffer_Desc bufferDesc;
+    AHardwareBuffer_describe(ahwb, &bufferDesc);
+
+    const bool isBlob = bufferDesc.format == AHARDWAREBUFFER_FORMAT_BLOB;
+    const size_t size = isBlob ? bufferDesc.width : 0;
+    const char* const name = isBlob ? "hardware_buffer_blob" : "hardware_buffer";
+
+    const native_handle_t* nativeHandle = AHardwareBuffer_getNativeHandle(ahwb);
+    const hidl_handle hidlHandle(nativeHandle);
+    hidl_handle copiedHandle(hidlHandle);
+
+    return hidl_memory(name, std::move(copiedHandle), size);
+}
+
+nn::GeneralResult<hidl_memory> createHidlMemoryFrom(const nn::Memory::Unknown& memory) {
+    return hidl_memory(memory.name, NN_TRY(hidlHandleFromSharedHandle(memory.handle)), memory.size);
+}
+
 }  // anonymous namespace
 
 nn::Capabilities::OperandPerformanceTable makeQuantized8PerformanceConsistentWithP(
@@ -255,27 +308,7 @@
     if (memory == nullptr) {
         return NN_ERROR() << "Memory must be non-empty";
     }
-    if (const auto* handle = std::get_if<nn::Handle>(&memory->handle)) {
-        return hidl_memory(memory->name, NN_TRY(hidlHandleFromSharedHandle(*handle)), memory->size);
-    }
-
-    const auto* ahwb = std::get<nn::HardwareBufferHandle>(memory->handle).get();
-    AHardwareBuffer_Desc bufferDesc;
-    AHardwareBuffer_describe(ahwb, &bufferDesc);
-
-    if (bufferDesc.format == AHARDWAREBUFFER_FORMAT_BLOB) {
-        CHECK_EQ(memory->size, bufferDesc.width);
-        CHECK_EQ(memory->name, "hardware_buffer_blob");
-    } else {
-        CHECK_EQ(memory->size, 0u);
-        CHECK_EQ(memory->name, "hardware_buffer");
-    }
-
-    const native_handle_t* nativeHandle = AHardwareBuffer_getNativeHandle(ahwb);
-    const hidl_handle hidlHandle(nativeHandle);
-    hidl_handle handle(hidlHandle);
-
-    return hidl_memory(memory->name, std::move(handle), memory->size);
+    return std::visit([](const auto& x) { return createHidlMemoryFrom(x); }, memory->handle);
 }
 
 static uint32_t roundUpToMultiple(uint32_t value, uint32_t multiple) {
@@ -283,14 +316,53 @@
 }
 
 nn::GeneralResult<nn::SharedMemory> createSharedMemoryFromHidlMemory(const hidl_memory& memory) {
-    CHECK_LE(memory.size(), std::numeric_limits<uint32_t>::max());
+    CHECK_LE(memory.size(), std::numeric_limits<size_t>::max());
+    if (!memory.valid()) {
+        return NN_ERROR() << "Unable to convert invalid hidl_memory";
+    }
+
+    if (memory.name() == "ashmem") {
+        if (memory.handle()->numFds != 1) {
+            return NN_ERROR() << "Unable to convert invalid ashmem memory object with "
+                              << memory.handle()->numFds << " numFds, but expected 1";
+        }
+        if (memory.handle()->numInts != 0) {
+            return NN_ERROR() << "Unable to convert invalid ashmem memory object with "
+                              << memory.handle()->numInts << " numInts, but expected 0";
+        }
+        auto handle = nn::Memory::Ashmem{
+                .fd = NN_TRY(nn::dupFd(memory.handle()->data[0])),
+                .size = static_cast<size_t>(memory.size()),
+        };
+        return std::make_shared<const nn::Memory>(nn::Memory{.handle = std::move(handle)});
+    }
+
+    if (memory.name() == "mmap_fd") {
+        if (memory.handle()->numFds != 1) {
+            return NN_ERROR() << "Unable to convert invalid mmap_fd memory object with "
+                              << memory.handle()->numFds << " numFds, but expected 1";
+        }
+        if (memory.handle()->numInts != 3) {
+            return NN_ERROR() << "Unable to convert invalid mmap_fd memory object with "
+                              << memory.handle()->numInts << " numInts, but expected 3";
+        }
+
+        const int fd = memory.handle()->data[0];
+        const int prot = memory.handle()->data[1];
+        const int lower = memory.handle()->data[2];
+        const int higher = memory.handle()->data[3];
+        const size_t offset = nn::getOffsetFromInts(lower, higher);
+
+        return nn::createSharedMemoryFromFd(static_cast<size_t>(memory.size()), prot, fd, offset);
+    }
 
     if (memory.name() != "hardware_buffer_blob") {
-        return std::make_shared<const nn::Memory>(nn::Memory{
+        auto handle = nn::Memory::Unknown{
                 .handle = NN_TRY(sharedHandleFromNativeHandle(memory.handle())),
-                .size = static_cast<uint32_t>(memory.size()),
+                .size = static_cast<size_t>(memory.size()),
                 .name = memory.name(),
-        });
+        };
+        return std::make_shared<const nn::Memory>(nn::Memory{.handle = std::move(handle)});
     }
 
     const auto size = memory.size();
@@ -328,11 +400,7 @@
                << "Can't create AHardwareBuffer from handle. Error: " << status;
     }
 
-    return std::make_shared<const nn::Memory>(nn::Memory{
-            .handle = nn::HardwareBufferHandle(hardwareBuffer, /*takeOwnership=*/true),
-            .size = static_cast<uint32_t>(memory.size()),
-            .name = memory.name(),
-    });
+    return nn::createSharedMemoryFromAHWB(hardwareBuffer, /*takeOwnership=*/true);
 }
 
 nn::GeneralResult<hidl_handle> hidlHandleFromSharedHandle(const nn::Handle& handle) {
diff --git a/neuralnetworks/utils/service/src/Service.cpp b/neuralnetworks/utils/service/src/Service.cpp
index c83bcc9..75ab1f9 100644
--- a/neuralnetworks/utils/service/src/Service.cpp
+++ b/neuralnetworks/utils/service/src/Service.cpp
@@ -16,6 +16,7 @@
 
 #include "Service.h"
 
+#include <AndroidVersionUtil.h>
 #include <aidl/android/hardware/neuralnetworks/IDevice.h>
 #include <android-base/logging.h>
 #include <android/binder_manager.h>
@@ -82,7 +83,7 @@
 
     // Devices with SDK level lower than 31 (Android S) don't have any AIDL drivers available, so
     // there is no need for a workaround supported on lower levels.
-    if (__builtin_available(android __ANDROID_API_S__, *)) {
+    if (__builtin_available(android __NNAPI_AIDL_MIN_ANDROID_API__, *)) {
         AServiceManager_forEachDeclaredInstance(aidl_hal::IDevice::descriptor,
                                                 static_cast<void*>(&names), callback);
     }
diff --git a/power/aidl/android/hardware/power/IPowerHintSession.aidl b/power/aidl/android/hardware/power/IPowerHintSession.aidl
index 9a85bee..c289448 100644
--- a/power/aidl/android/hardware/power/IPowerHintSession.aidl
+++ b/power/aidl/android/hardware/power/IPowerHintSession.aidl
@@ -43,17 +43,17 @@
     void reportActualWorkDuration(in WorkDuration[] durations);
 
     /**
-     * Pause the session when the application is not in foreground and above
+     * Pause the session when the application is not allowed to send hint in framework.
      */
     void pause();
 
     /**
-     * Resume the session when the application is not in foreground and above
+     * Resume the session when the application is allowed to send hint in framework.
      */
     void resume();
 
     /**
-     * Close the session to release resources
+     * Close the session to release resources.
      */
     void close();
 }
diff --git a/power/aidl/default/power-default.xml b/power/aidl/default/power-default.xml
index caf6ea2..9f56deb 100644
--- a/power/aidl/default/power-default.xml
+++ b/power/aidl/default/power-default.xml
@@ -1,6 +1,7 @@
 <manifest version="1.0" type="device">
     <hal format="aidl">
         <name>android.hardware.power</name>
+        <version>2</version>
         <fqname>IPower/default</fqname>
     </hal>
 </manifest>
diff --git a/power/stats/aidl/vts/VtsHalPowerStatsTargetTest.cpp b/power/stats/aidl/vts/VtsHalPowerStatsTargetTest.cpp
index bed3fdf..c7ba96c 100644
--- a/power/stats/aidl/vts/VtsHalPowerStatsTargetTest.cpp
+++ b/power/stats/aidl/vts/VtsHalPowerStatsTargetTest.cpp
@@ -40,6 +40,12 @@
 
 using ndk::SpAIBinder;
 
+#define ASSERT_OK(a)                                     \
+    do {                                                 \
+        auto ret = a;                                    \
+        ASSERT_TRUE(ret.isOk()) << ret.getDescription(); \
+    } while (0)
+
 class PowerStatsAidl : public testing::TestWithParam<std::string> {
   public:
     virtual void SetUp() override {
@@ -108,7 +114,7 @@
 // Each PowerEntity must have a valid name
 TEST_P(PowerStatsAidl, ValidatePowerEntityNames) {
     std::vector<PowerEntity> infos;
-    ASSERT_TRUE(powerstats->getPowerEntityInfo(&infos).isOk());
+    ASSERT_OK(powerstats->getPowerEntityInfo(&infos));
 
     for (auto info : infos) {
         testNameValid(info.name);
@@ -118,7 +124,7 @@
 // Each power entity must have a unique name
 TEST_P(PowerStatsAidl, ValidatePowerEntityUniqueNames) {
     std::vector<PowerEntity> entities;
-    ASSERT_TRUE(powerstats->getPowerEntityInfo(&entities).isOk());
+    ASSERT_OK(powerstats->getPowerEntityInfo(&entities));
 
     testUnique(entities, &PowerEntity::name);
 }
@@ -126,7 +132,7 @@
 // Each PowerEntity must have a unique ID
 TEST_P(PowerStatsAidl, ValidatePowerEntityIds) {
     std::vector<PowerEntity> entities;
-    ASSERT_TRUE(powerstats->getPowerEntityInfo(&entities).isOk());
+    ASSERT_OK(powerstats->getPowerEntityInfo(&entities));
 
     testUnique(entities, &PowerEntity::id);
 }
@@ -134,7 +140,7 @@
 // Each power entity must have at least one state
 TEST_P(PowerStatsAidl, ValidateStateSize) {
     std::vector<PowerEntity> entities;
-    ASSERT_TRUE(powerstats->getPowerEntityInfo(&entities).isOk());
+    ASSERT_OK(powerstats->getPowerEntityInfo(&entities));
 
     for (auto entity : entities) {
         EXPECT_GT(entity.states.size(), 0);
@@ -144,7 +150,7 @@
 // Each state must have a valid name
 TEST_P(PowerStatsAidl, ValidateStateNames) {
     std::vector<PowerEntity> entities;
-    ASSERT_TRUE(powerstats->getPowerEntityInfo(&entities).isOk());
+    ASSERT_OK(powerstats->getPowerEntityInfo(&entities));
 
     for (auto entity : entities) {
         for (auto state : entity.states) {
@@ -156,7 +162,7 @@
 // Each state must have a name that is unique to the given PowerEntity
 TEST_P(PowerStatsAidl, ValidateStateUniqueNames) {
     std::vector<PowerEntity> entities;
-    ASSERT_TRUE(powerstats->getPowerEntityInfo(&entities).isOk());
+    ASSERT_OK(powerstats->getPowerEntityInfo(&entities));
 
     for (auto entity : entities) {
         testUnique(entity.states, &State::name);
@@ -166,7 +172,7 @@
 // Each state must have an ID that is unique to the given PowerEntity
 TEST_P(PowerStatsAidl, ValidateStateUniqueIds) {
     std::vector<PowerEntity> entities;
-    ASSERT_TRUE(powerstats->getPowerEntityInfo(&entities).isOk());
+    ASSERT_OK(powerstats->getPowerEntityInfo(&entities));
 
     for (auto entity : entities) {
         testUnique(entity.states, &State::id);
@@ -176,16 +182,16 @@
 // State residency must return a valid status
 TEST_P(PowerStatsAidl, TestGetStateResidency) {
     std::vector<StateResidencyResult> results;
-    ASSERT_TRUE(powerstats->getStateResidency({}, &results).isOk());
+    ASSERT_OK(powerstats->getStateResidency({}, &results));
 }
 
 // State residency must return all results
 TEST_P(PowerStatsAidl, TestGetStateResidencyAllResults) {
     std::vector<PowerEntity> entities;
-    ASSERT_TRUE(powerstats->getPowerEntityInfo(&entities).isOk());
+    ASSERT_OK(powerstats->getPowerEntityInfo(&entities));
 
     std::vector<StateResidencyResult> results;
-    ASSERT_TRUE(powerstats->getStateResidency({}, &results).isOk());
+    ASSERT_OK(powerstats->getStateResidency({}, &results));
 
     testMatching(entities, &PowerEntity::id, results, &StateResidencyResult::id);
 }
@@ -193,10 +199,10 @@
 // Each result must contain all state residencies
 TEST_P(PowerStatsAidl, TestGetStateResidencyAllStateResidencies) {
     std::vector<PowerEntity> entities;
-    ASSERT_TRUE(powerstats->getPowerEntityInfo(&entities).isOk());
+    ASSERT_OK(powerstats->getPowerEntityInfo(&entities));
 
     std::vector<StateResidencyResult> results;
-    ASSERT_TRUE(powerstats->getStateResidency({}, &results).isOk());
+    ASSERT_OK(powerstats->getStateResidency({}, &results));
 
     for (auto entity : entities) {
         auto it = std::find_if(results.begin(), results.end(),
@@ -210,7 +216,7 @@
 // State residency must return results for each requested power entity
 TEST_P(PowerStatsAidl, TestGetStateResidencySelectedResults) {
     std::vector<PowerEntity> entities;
-    ASSERT_TRUE(powerstats->getPowerEntityInfo(&entities).isOk());
+    ASSERT_OK(powerstats->getPowerEntityInfo(&entities));
     if (entities.empty()) {
         return;
     }
@@ -222,7 +228,7 @@
     }
 
     std::vector<StateResidencyResult> selectedResults;
-    ASSERT_TRUE(powerstats->getStateResidency(selectedIds, &selectedResults).isOk());
+    ASSERT_OK(powerstats->getStateResidency(selectedIds, &selectedResults));
 
     testMatching(selectedEntities, &PowerEntity::id, selectedResults, &StateResidencyResult::id);
 }
@@ -230,15 +236,25 @@
 // Energy meter info must return a valid status
 TEST_P(PowerStatsAidl, TestGetEnergyMeterInfo) {
     std::vector<Channel> info;
-    ASSERT_TRUE(powerstats->getEnergyMeterInfo(&info).isOk());
+    ASSERT_OK(powerstats->getEnergyMeterInfo(&info));
 }
 
-// Each channel must have a valid name and subsystem
+// Each channel must have a valid name
 TEST_P(PowerStatsAidl, ValidateChannelNames) {
     std::vector<Channel> channels;
-    ASSERT_TRUE(powerstats->getEnergyMeterInfo(&channels).isOk());
+    ASSERT_OK(powerstats->getEnergyMeterInfo(&channels));
+
     for (auto channel : channels) {
         testNameValid(channel.name);
+    }
+}
+
+// Each channel must have a valid subsystem
+TEST_P(PowerStatsAidl, ValidateSubsystemNames) {
+    std::vector<Channel> channels;
+    ASSERT_OK(powerstats->getEnergyMeterInfo(&channels));
+
+    for (auto channel : channels) {
         testNameValid(channel.subsystem);
     }
 }
@@ -246,7 +262,7 @@
 // Each channel must have a unique name
 TEST_P(PowerStatsAidl, ValidateChannelUniqueNames) {
     std::vector<Channel> channels;
-    ASSERT_TRUE(powerstats->getEnergyMeterInfo(&channels).isOk());
+    ASSERT_OK(powerstats->getEnergyMeterInfo(&channels));
 
     testUnique(channels, &Channel::name);
 }
@@ -254,7 +270,7 @@
 // Each channel must have a unique ID
 TEST_P(PowerStatsAidl, ValidateChannelUniqueIds) {
     std::vector<Channel> channels;
-    ASSERT_TRUE(powerstats->getEnergyMeterInfo(&channels).isOk());
+    ASSERT_OK(powerstats->getEnergyMeterInfo(&channels));
 
     testUnique(channels, &Channel::id);
 }
@@ -262,16 +278,16 @@
 // Reading energy meter must return a valid status
 TEST_P(PowerStatsAidl, TestReadEnergyMeter) {
     std::vector<EnergyMeasurement> data;
-    ASSERT_TRUE(powerstats->readEnergyMeter({}, &data).isOk());
+    ASSERT_OK(powerstats->readEnergyMeter({}, &data));
 }
 
 // Reading energy meter must return results for all available channels
 TEST_P(PowerStatsAidl, TestGetAllEnergyMeasurements) {
     std::vector<Channel> channels;
-    ASSERT_TRUE(powerstats->getEnergyMeterInfo(&channels).isOk());
+    ASSERT_OK(powerstats->getEnergyMeterInfo(&channels));
 
     std::vector<EnergyMeasurement> measurements;
-    ASSERT_TRUE(powerstats->readEnergyMeter({}, &measurements).isOk());
+    ASSERT_OK(powerstats->readEnergyMeter({}, &measurements));
 
     testMatching(channels, &Channel::id, measurements, &EnergyMeasurement::id);
 }
@@ -279,7 +295,7 @@
 // Reading energy must must return results for each selected channel
 TEST_P(PowerStatsAidl, TestGetSelectedEnergyMeasurements) {
     std::vector<Channel> channels;
-    ASSERT_TRUE(powerstats->getEnergyMeterInfo(&channels).isOk());
+    ASSERT_OK(powerstats->getEnergyMeterInfo(&channels));
     if (channels.empty()) {
         return;
     }
@@ -291,7 +307,7 @@
     }
 
     std::vector<EnergyMeasurement> selectedMeasurements;
-    ASSERT_TRUE(powerstats->readEnergyMeter(selectedIds, &selectedMeasurements).isOk());
+    ASSERT_OK(powerstats->readEnergyMeter(selectedIds, &selectedMeasurements));
 
     testMatching(selectedChannels, &Channel::id, selectedMeasurements, &EnergyMeasurement::id);
 }
@@ -299,13 +315,13 @@
 // Energy consumer info must return a valid status
 TEST_P(PowerStatsAidl, TestGetEnergyConsumerInfo) {
     std::vector<EnergyConsumer> consumers;
-    ASSERT_TRUE(powerstats->getEnergyConsumerInfo(&consumers).isOk());
+    ASSERT_OK(powerstats->getEnergyConsumerInfo(&consumers));
 }
 
 // Each energy consumer must have a unique id
 TEST_P(PowerStatsAidl, TestGetEnergyConsumerUniqueId) {
     std::vector<EnergyConsumer> consumers;
-    ASSERT_TRUE(powerstats->getEnergyConsumerInfo(&consumers).isOk());
+    ASSERT_OK(powerstats->getEnergyConsumerInfo(&consumers));
 
     testUnique(consumers, &EnergyConsumer::id);
 }
@@ -313,7 +329,7 @@
 // Each energy consumer must have a valid name
 TEST_P(PowerStatsAidl, ValidateEnergyConsumerNames) {
     std::vector<EnergyConsumer> consumers;
-    ASSERT_TRUE(powerstats->getEnergyConsumerInfo(&consumers).isOk());
+    ASSERT_OK(powerstats->getEnergyConsumerInfo(&consumers));
 
     for (auto consumer : consumers) {
         testNameValid(consumer.name);
@@ -323,7 +339,7 @@
 // Each energy consumer must have a unique name
 TEST_P(PowerStatsAidl, ValidateEnergyConsumerUniqueNames) {
     std::vector<EnergyConsumer> consumers;
-    ASSERT_TRUE(powerstats->getEnergyConsumerInfo(&consumers).isOk());
+    ASSERT_OK(powerstats->getEnergyConsumerInfo(&consumers));
 
     testUnique(consumers, &EnergyConsumer::name);
 }
@@ -331,7 +347,7 @@
 // Energy consumers of the same type must have ordinals that are 0,1,2,..., N - 1
 TEST_P(PowerStatsAidl, ValidateEnergyConsumerOrdinals) {
     std::vector<EnergyConsumer> consumers;
-    ASSERT_TRUE(powerstats->getEnergyConsumerInfo(&consumers).isOk());
+    ASSERT_OK(powerstats->getEnergyConsumerInfo(&consumers));
 
     std::unordered_map<EnergyConsumerType, std::set<int32_t>> ordinalMap;
 
@@ -350,16 +366,16 @@
 // Energy consumed must return a valid status
 TEST_P(PowerStatsAidl, TestGetEnergyConsumed) {
     std::vector<EnergyConsumerResult> results;
-    ASSERT_TRUE(powerstats->getEnergyConsumed({}, &results).isOk());
+    ASSERT_OK(powerstats->getEnergyConsumed({}, &results));
 }
 
 // Energy consumed must return data for all energy consumers
 TEST_P(PowerStatsAidl, TestGetAllEnergyConsumed) {
     std::vector<EnergyConsumer> consumers;
-    ASSERT_TRUE(powerstats->getEnergyConsumerInfo(&consumers).isOk());
+    ASSERT_OK(powerstats->getEnergyConsumerInfo(&consumers));
 
     std::vector<EnergyConsumerResult> results;
-    ASSERT_TRUE(powerstats->getEnergyConsumed({}, &results).isOk());
+    ASSERT_OK(powerstats->getEnergyConsumed({}, &results));
 
     testMatching(consumers, &EnergyConsumer::id, results, &EnergyConsumerResult::id);
 }
@@ -367,7 +383,7 @@
 // Energy consumed must return data for each selected energy consumer
 TEST_P(PowerStatsAidl, TestGetSelectedEnergyConsumed) {
     std::vector<EnergyConsumer> consumers;
-    ASSERT_TRUE(powerstats->getEnergyConsumerInfo(&consumers).isOk());
+    ASSERT_OK(powerstats->getEnergyConsumerInfo(&consumers));
     if (consumers.empty()) {
         return;
     }
@@ -379,7 +395,7 @@
     }
 
     std::vector<EnergyConsumerResult> selectedResults;
-    ASSERT_TRUE(powerstats->getEnergyConsumed(selectedIds, &selectedResults).isOk());
+    ASSERT_OK(powerstats->getEnergyConsumed(selectedIds, &selectedResults));
 
     testMatching(selectedConsumers, &EnergyConsumer::id, selectedResults,
                  &EnergyConsumerResult::id);
@@ -388,7 +404,7 @@
 // Energy consumed attribution uids must be unique for a given energy consumer
 TEST_P(PowerStatsAidl, ValidateEnergyConsumerAttributionUniqueUids) {
     std::vector<EnergyConsumerResult> results;
-    ASSERT_TRUE(powerstats->getEnergyConsumed({}, &results).isOk());
+    ASSERT_OK(powerstats->getEnergyConsumed({}, &results));
 
     for (auto result : results) {
         testUnique(result.attribution, &EnergyConsumerAttribution::uid);
@@ -398,7 +414,7 @@
 // Energy consumed total energy >= sum total of uid-attributed energy
 TEST_P(PowerStatsAidl, TestGetEnergyConsumedAttributedEnergy) {
     std::vector<EnergyConsumerResult> results;
-    ASSERT_TRUE(powerstats->getEnergyConsumed({}, &results).isOk());
+    ASSERT_OK(powerstats->getEnergyConsumed({}, &results));
 
     for (auto result : results) {
         int64_t totalAttributedEnergyUWs = 0;
diff --git a/radio/1.6/IRadioIndication.hal b/radio/1.6/IRadioIndication.hal
index 9788345..05a7585 100644
--- a/radio/1.6/IRadioIndication.hal
+++ b/radio/1.6/IRadioIndication.hal
@@ -107,7 +107,7 @@
     /**
      * Indicates physical channel configurations.
      *
-     * An empty configs list indicates that the radio is in idle mode.
+     * An empty configs list shall be returned when the radio is in idle mode (i.e. RRC idle).
      *
      * @param type Type of radio indication
      * @param configs Vector of PhysicalChannelConfigs
diff --git a/radio/1.6/IRadioResponse.hal b/radio/1.6/IRadioResponse.hal
index d8614f7..3ee46c2 100644
--- a/radio/1.6/IRadioResponse.hal
+++ b/radio/1.6/IRadioResponse.hal
@@ -232,6 +232,7 @@
      *   RadioError:RADIO_NOT_AVAILABLE
      *   RadioError:INTERNAL_ERR
      *   RadioError:REQUEST_NOT_SUPPORTED
+     *   RadioError:INVALID_STATE
      */
     oneway setNrDualConnectivityStateResponse(RadioResponseInfo info);
 
diff --git a/radio/1.6/vts/functional/radio_hidl_hal_api.cpp b/radio/1.6/vts/functional/radio_hidl_hal_api.cpp
index be2be76..36eee10 100644
--- a/radio/1.6/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.6/vts/functional/radio_hidl_hal_api.cpp
@@ -175,12 +175,17 @@
     EXPECT_EQ(std::cv_status::no_timeout, wait());
     EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
     EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
-    if (getRadioHalCapabilities().modemReducedFeatureSet1) {
+    if (getRadioHalCapabilities()) {
         ASSERT_TRUE(CheckAnyOfErrors(
                 radioRsp_v1_6->rspInfo.error,
                 {::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED}));
     } else {
-        EXPECT_EQ(::android::hardware::radio::V1_6::RadioError::NONE, radioRsp_v1_6->rspInfo.error);
+        ASSERT_TRUE(
+                CheckAnyOfErrors(radioRsp_v1_6->rspInfo.error,
+                                 {::android::hardware::radio::V1_6::RadioError::NONE,
+                                  ::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE,
+                                  ::android::hardware::radio::V1_6::RadioError::INTERNAL_ERR,
+                                  ::android::hardware::radio::V1_6::RadioError::MODEM_ERR}));
     }
 }
 
@@ -378,7 +383,7 @@
     EXPECT_EQ(std::cv_status::no_timeout, wait());
     EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
     EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
-    if (getRadioHalCapabilities().modemReducedFeatureSet1) {
+    if (getRadioHalCapabilities()) {
         ASSERT_TRUE(CheckAnyOfErrors(
                 radioRsp_v1_6->rspInfo.error,
                 {::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED}));
@@ -387,6 +392,7 @@
                 CheckAnyOfErrors(radioRsp_v1_6->rspInfo.error,
                                  {::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE,
                                   ::android::hardware::radio::V1_6::RadioError::INTERNAL_ERR,
+                                  ::android::hardware::radio::V1_6::RadioError::INVALID_STATE,
                                   ::android::hardware::radio::V1_6::RadioError::NONE}));
     }
 }
@@ -403,7 +409,7 @@
     EXPECT_EQ(std::cv_status::no_timeout, wait());
     EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
     EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
-    if (getRadioHalCapabilities().modemReducedFeatureSet1) {
+    if (getRadioHalCapabilities()) {
         ASSERT_TRUE(CheckAnyOfErrors(
                 radioRsp_v1_6->rspInfo.error,
                 {::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED}));
@@ -429,7 +435,7 @@
     EXPECT_EQ(std::cv_status::no_timeout, wait());
     EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
     EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
-    if (getRadioHalCapabilities().modemReducedFeatureSet1) {
+    if (getRadioHalCapabilities()) {
         ASSERT_TRUE(CheckAnyOfErrors(
                 radioRsp_v1_6->rspInfo.error,
                 {::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED}));
@@ -449,7 +455,7 @@
     EXPECT_EQ(std::cv_status::no_timeout, wait());
     EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
     EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
-    if (getRadioHalCapabilities().modemReducedFeatureSet1) {
+    if (getRadioHalCapabilities()) {
         ASSERT_TRUE(CheckAnyOfErrors(
                 radioRsp_v1_6->rspInfo.error,
                 {::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED}));
@@ -469,7 +475,7 @@
     EXPECT_EQ(std::cv_status::no_timeout, wait());
     EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
     EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
-    if (getRadioHalCapabilities().modemReducedFeatureSet1) {
+    if (getRadioHalCapabilities()) {
         ASSERT_TRUE(CheckAnyOfErrors(
                 radioRsp_v1_6->rspInfo.error,
                 {::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED}));
@@ -488,7 +494,7 @@
     EXPECT_EQ(std::cv_status::no_timeout, wait());
     EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
     EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
-    if (getRadioHalCapabilities().modemReducedFeatureSet1) {
+    if (getRadioHalCapabilities()) {
         ASSERT_TRUE(CheckAnyOfErrors(
                 radioRsp_v1_6->rspInfo.error,
                 {::android::hardware::radio::V1_6::RadioError::REQUEST_NOT_SUPPORTED}));
diff --git a/radio/1.6/vts/functional/radio_hidl_hal_test.cpp b/radio/1.6/vts/functional/radio_hidl_hal_test.cpp
index 6255f66..5d514a0 100644
--- a/radio/1.6/vts/functional/radio_hidl_hal_test.cpp
+++ b/radio/1.6/vts/functional/radio_hidl_hal_test.cpp
@@ -86,16 +86,14 @@
  * disabled.
  * <p/>
  * Typical usage within VTS:
- * if (getRadioHalCapabilities().modemReducedFeatureSet) return;
+ * if (getRadioHalCapabilities()) return;
  */
-HalDeviceCapabilities RadioHidlTest_v1_6::getRadioHalCapabilities() {
+bool RadioHidlTest_v1_6::getRadioHalCapabilities() {
     sp<::android::hardware::radio::config::V1_3::IRadioConfig> radioConfig_v1_3 =
             ::android::hardware::radio::config::V1_3::IRadioConfig::getService();
     if (radioConfig_v1_3.get() == nullptr) {
         // If v1_3 isn't present, the values are initialized to false
-        HalDeviceCapabilities radioHalCapabilities;
-        memset(&radioHalCapabilities, 0, sizeof(radioHalCapabilities));
-        return radioHalCapabilities;
+        return false;
     } else {
         // Get radioHalDeviceCapabilities from the radio config
         sp<RadioConfigResponse> radioConfigRsp = new (std::nothrow) RadioConfigResponse(*this);
@@ -104,6 +102,6 @@
 
         radioConfig_v1_3->getHalDeviceCapabilities(serial);
         EXPECT_EQ(std::cv_status::no_timeout, wait());
-        return radioConfigRsp->halDeviceCapabilities;
+        return radioConfigRsp->modemReducedFeatureSet1;
     }
 }
diff --git a/radio/1.6/vts/functional/radio_hidl_hal_utils_v1_6.h b/radio/1.6/vts/functional/radio_hidl_hal_utils_v1_6.h
index 0689e9b..950d82a 100644
--- a/radio/1.6/vts/functional/radio_hidl_hal_utils_v1_6.h
+++ b/radio/1.6/vts/functional/radio_hidl_hal_utils_v1_6.h
@@ -38,14 +38,12 @@
 using namespace ::android::hardware::radio::V1_2;
 using namespace ::android::hardware::radio::V1_1;
 using namespace ::android::hardware::radio::V1_0;
-using namespace ::android::hardware::radio::config::V1_3;
 
 using ::android::sp;
 using ::android::hardware::hidl_string;
 using ::android::hardware::hidl_vec;
 using ::android::hardware::Return;
 using ::android::hardware::Void;
-using ::android::hardware::radio::config::V1_3::HalDeviceCapabilities;
 
 #define MODEM_EMERGENCY_CALL_ESTABLISH_TIME 3
 #define MODEM_EMERGENCY_CALL_DISCONNECT_TIME 3
@@ -1115,7 +1113,7 @@
   public:
     virtual void SetUp() override;
 
-    HalDeviceCapabilities getRadioHalCapabilities();
+    bool getRadioHalCapabilities();
 
     /* radio service handle */
     sp<::android::hardware::radio::V1_6::IRadio> radio_v1_6;
diff --git a/radio/config/1.3/Android.bp b/radio/config/1.3/Android.bp
index cc5944d..dc0d82c 100644
--- a/radio/config/1.3/Android.bp
+++ b/radio/config/1.3/Android.bp
@@ -13,7 +13,6 @@
     name: "android.hardware.radio.config@1.3",
     root: "android.hardware",
     srcs: [
-        "types.hal",
         "IRadioConfig.hal",
         "IRadioConfigResponse.hal",
     ],
diff --git a/radio/config/1.3/IRadioConfigResponse.hal b/radio/config/1.3/IRadioConfigResponse.hal
index 863754f..15eefed 100644
--- a/radio/config/1.3/IRadioConfigResponse.hal
+++ b/radio/config/1.3/IRadioConfigResponse.hal
@@ -18,7 +18,6 @@
 
 import android.hardware.radio@1.6::RadioResponseInfo;
 import @1.2::IRadioConfigResponse;
-import HalDeviceCapabilities;
 
 /**
  * Interface declaring response functions to solicited radio config requests.
@@ -26,8 +25,18 @@
 interface IRadioConfigResponse extends @1.2::IRadioConfigResponse {
     /**
      * @param info Response info struct containing response type, serial no. and error
-     * @param capabilities Capabilities struct containing the capabilities of the
-     * device related to the Radio HAL
+     * @param modemReducedFeatureSet1 True indicates that the modem does NOT support the following
+     *        features.
+     *        - Providing either
+     *          android.hardware.radio@1.6::LinkCapacityEstimate:secondaryDownlinkCapacityKbps
+     *          or android.hardware.radio@1.6::LinkCapacityEstimate:secondaryUplinkCapacityKbps
+     *          when given from
+     *          android.hardware.radio@1.6::RadioIndication:currentLinkCapacityEstimate
+     *        - Calling android.hardware.radio@1.6::IRadio.setNrDualConnectivityState
+     *          or querying android.hardware.radio@1.6::IRadio.isNrDualConnectivityEnabled
+     *        - Requesting android.hardware.radio@1.6::IRadio.setDataThrottling()
+     *        - Providing android.hardware.radio@1.6::SlicingConfig through
+     *          android.hardware.radio@1.6::getSlicingConfig()
      *
      * Valid errors returned:
      *   RadioError:NONE
@@ -35,5 +44,5 @@
      *   RadioError:INTERNAL_ERR
      */
     oneway getHalDeviceCapabilitiesResponse(RadioResponseInfo info,
-        HalDeviceCapabilities capabilities);
+        bool modemReducedFeatureSet1);
 };
diff --git a/radio/config/1.3/types.hal b/radio/config/1.3/types.hal
deleted file mode 100644
index 8667f0a..0000000
--- a/radio/config/1.3/types.hal
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2020 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.radio.config@1.3;
-
-/**
- * Contains the device capabilities with respect to the Radio HAL.
- */
-struct HalDeviceCapabilities {
-  /**
-   * True indicates that the modem does NOT support the following features:
-   * <ul>
-   * <li>Providing either
-   * android.hardware.radio@1.6::LinkCapacityEstimate:secondaryDownlinkCapacityKbps
-   * or android.hardware.radio@1.6::LinkCapacityEstimate:secondaryUplinkCapacityKbps
-   * when given from android.hardware.radio@1.6::RadioIndication:currentLinkCapacityEstimate
-   * </li>
-   * <li> calling android.hardware.radio@1.6::IRadio.setNrDualConnectivityState
-   * or querying android.hardware.radio@1.6::IRadio.isNrDualConnectivityEnabled
-   * </li>
-   * <li>Requesting android.hardware.radio@1.6::IRadio.setDataThrottling()
-   * </li>
-   * <li>Providing android.hardware.radio@1.6::SlicingConfig through
-   * android.hardware.radio@1.6::getSlicingConfig()
-   * </li>
-   * </ul>
-   */
-  bool modemReducedFeatureSet1;
-};
diff --git a/radio/config/1.3/vts/functional/radio_config_hidl_hal_utils.h b/radio/config/1.3/vts/functional/radio_config_hidl_hal_utils.h
index 50038eb..7235798 100644
--- a/radio/config/1.3/vts/functional/radio_config_hidl_hal_utils.h
+++ b/radio/config/1.3/vts/functional/radio_config_hidl_hal_utils.h
@@ -29,7 +29,6 @@
 #include <android/hardware/radio/config/1.2/types.h>
 #include <android/hardware/radio/config/1.3/IRadioConfig.h>
 #include <android/hardware/radio/config/1.3/IRadioConfigResponse.h>
-#include <android/hardware/radio/config/1.3/types.h>
 #include <gtest/gtest.h>
 #include <hidl/GtestPrinter.h>
 #include <hidl/ServiceManagement.h>
@@ -48,7 +47,6 @@
 using ::android::hardware::radio::config::V1_1::PhoneCapability;
 using ::android::hardware::radio::config::V1_2::IRadioConfigIndication;
 using ::android::hardware::radio::config::V1_2::SimSlotStatus;
-using ::android::hardware::radio::config::V1_3::HalDeviceCapabilities;
 using ::android::hardware::radio::config::V1_3::IRadioConfig;
 using ::android::hardware::radio::config::V1_3::IRadioConfigResponse;
 using ::android::hardware::radio::V1_0::RadioResponseInfo;
@@ -65,7 +63,7 @@
   public:
     RadioResponseInfo rspInfo;
     PhoneCapability phoneCap;
-    HalDeviceCapabilities halDeviceCapabilities;
+    bool modemReducedFeatureSet1;
 
     RadioConfigResponse(RadioResponseWaiter& parent);
     virtual ~RadioConfigResponse() = default;
@@ -93,7 +91,7 @@
 
     Return<void> getHalDeviceCapabilitiesResponse(
             const ::android::hardware::radio::V1_6::RadioResponseInfo& info,
-            const HalDeviceCapabilities& halDeviceCapabilities);
+            bool modemReducedFeatureSet1);
 };
 
 /* Callback class for radio config indication */
diff --git a/radio/config/1.3/vts/functional/radio_config_response.cpp b/radio/config/1.3/vts/functional/radio_config_response.cpp
index 5501ae2..6188733 100644
--- a/radio/config/1.3/vts/functional/radio_config_response.cpp
+++ b/radio/config/1.3/vts/functional/radio_config_response.cpp
@@ -65,8 +65,8 @@
 
 Return<void> RadioConfigResponse::getHalDeviceCapabilitiesResponse(
         const ::android::hardware::radio::V1_6::RadioResponseInfo& info,
-        const ::android::hardware::radio::config::V1_3::HalDeviceCapabilities& capabilities) {
-    halDeviceCapabilities = capabilities;
+        bool modemReducedFeatures) {
+    modemReducedFeatureSet1 = modemReducedFeatures;
     parent.notify(info.serial);
     return Void();
 }
diff --git a/security/keymint/aidl/Android.bp b/security/keymint/aidl/Android.bp
index 6766d99..0c11f3b 100644
--- a/security/keymint/aidl/Android.bp
+++ b/security/keymint/aidl/Android.bp
@@ -26,6 +26,7 @@
             vndk: {
                 enabled: true,
             },
+            apps_enabled: false,
         },
         rust: {
             enabled: true,
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/ErrorCode.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/ErrorCode.aidl
index 69ec4ce..b05a0f3 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/ErrorCode.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/ErrorCode.aidl
@@ -118,6 +118,7 @@
   MISSING_ISSUER_SUBJECT = -82,
   INVALID_ISSUER_SUBJECT = -83,
   BOOT_LEVEL_EXCEEDED = -84,
+  HARDWARE_NOT_YET_AVAILABLE = -85,
   UNIMPLEMENTED = -100,
   VERSION_MISMATCH = -101,
   UNKNOWN_ERROR = -1000,
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintDevice.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintDevice.aidl
index 4f6fb28..bf30999 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintDevice.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintDevice.aidl
@@ -33,7 +33,7 @@
 
 package android.hardware.security.keymint;
 /* @hide */
-@VintfStability
+@SensitiveData @VintfStability
 interface IKeyMintDevice {
   android.hardware.security.keymint.KeyMintHardwareInfo getHardwareInfo();
   void addRngEntropy(in byte[] data);
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintOperation.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintOperation.aidl
index 5ac2b4a..4ab4ffe 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintOperation.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintOperation.aidl
@@ -33,7 +33,7 @@
 
 package android.hardware.security.keymint;
 /* @hide */
-@VintfStability
+@SensitiveData @VintfStability
 interface IKeyMintOperation {
   void updateAad(in byte[] input, in @nullable android.hardware.security.keymint.HardwareAuthToken authToken, in @nullable android.hardware.security.secureclock.TimeStampToken timeStampToken);
   byte[] update(in byte[] input, in @nullable android.hardware.security.keymint.HardwareAuthToken authToken, in @nullable android.hardware.security.secureclock.TimeStampToken timeStampToken);
diff --git a/security/keymint/aidl/android/hardware/security/keymint/ErrorCode.aidl b/security/keymint/aidl/android/hardware/security/keymint/ErrorCode.aidl
index 0e2c5f2..137e6b6 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/ErrorCode.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/ErrorCode.aidl
@@ -107,6 +107,7 @@
     MISSING_ISSUER_SUBJECT = -82,
     INVALID_ISSUER_SUBJECT = -83,
     BOOT_LEVEL_EXCEEDED = -84,
+    HARDWARE_NOT_YET_AVAILABLE = -85,
 
     UNIMPLEMENTED = -100,
     VERSION_MISMATCH = -101,
diff --git a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
index 5aa3070..1c503c2 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
@@ -214,6 +214,7 @@
  * @hide
  */
 @VintfStability
+@SensitiveData
 interface IKeyMintDevice {
     const int AUTH_TOKEN_MAC_LENGTH = 32;
 
diff --git a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintOperation.aidl b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintOperation.aidl
index 5ad54cd..d2a993f 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintOperation.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintOperation.aidl
@@ -22,6 +22,7 @@
 
 /** @hide */
 @VintfStability
+@SensitiveData
 interface IKeyMintOperation {
     /**
      * Provides additional authentication data (AAD) to a cryptographic operation begun with
diff --git a/security/keymint/aidl/android/hardware/security/keymint/KeyCreationResult.aidl b/security/keymint/aidl/android/hardware/security/keymint/KeyCreationResult.aidl
index f3c5477..c2e21b6 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/KeyCreationResult.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/KeyCreationResult.aidl
@@ -60,29 +60,36 @@
      * `attestationKey` parameter of `generateKey()`, `importKey()` or `importWrappedKey()`), and in
      * the non-attestaion case, whether the key can self-sign.
      *
-     * 1.  Attestation with factory key.  If Tag::ATTESTATION_CHALLENGE is provided and the
-     *     `attestationKey` parameter on the generate/import call is null, the returned certificate
-     *     chain must contain an attestation certificate signed with a factory-provisioned
-     *     attestation key, and the full certificate chain for that factory-provisioned attestation
-     *     key.
+     * 1.  Asymmetric key attestation with factory key.  If Tag::ATTESTATION_CHALLENGE is provided
+     *     and the `attestationKey` parameter on the generate/import call is null, the returned
+     *     certificate chain must contain an attestation certificate signed with a factory-
+     *     provisioned attestation key, and the full certificate chain for that factory-provisioned
+     *     attestation key.  Tag::ATTESTATION_APPLICATION_ID must also be provided when the
+     *     ATTESTATION_CHALLENGE is provided, otherwise ATTESTATION_APPLICATION_ID_MISSING will be
+     *     returned.
      *
-     * 2.  Attestation with caller-provided key.  If Tag::ATTESTATION_CHALLENGE is provided and the
-     *     `attestationKey` parameter on the generat/import call is non-null and contains the key
-     *     blob of a key with KeyPurpose::ATTEST_KEY, the returned certificate chain must contain
-     *     only an attestation certificate signed with the specified key.  The caller must know the
-     *     certificate chain for the provided key.
+     * 2.  Asymmetric key attestation with caller-provided key.  If Tag::ATTESTATION_CHALLENGE is
+     *     provided and the `attestationKey` parameter on the generat/import call is non-null and
+     *     contains the key blob of a key with KeyPurpose::ATTEST_KEY, the returned certificate
+     *     chain must contain only an attestation certificate signed with the specified key.  The
+     *     caller must know the certificate chain for the provided key.  Tag::
+     *     ATTESTATION_APPLICATION_ID must also be provided when the ATTESTATION_CHALLENGE is
+     *     provided, otherwise ATTESTATION_APPLICATION_ID_MISSING will be returned.
      *
-     * 3.  Non-attestation with signing key.  If Tag::ATTESTATION_CHALLENGE is not provided and the
-     *     generated/imported key has KeyPurpose::SIGN, then the returned certificate chain must
-     *     contain only a single self-signed certificate with no attestation extension.
+     * 3.  Asymmetric key non-attestation with signing key.  If Tag::ATTESTATION_CHALLENGE is not
+     *     provided and the generated/imported key has KeyPurpose::SIGN, then the returned
+     *     certificate chain must contain only a single self-signed certificate with no attestation
+     *     extension.  Tag::ATTESTATION_APPLICATION_ID will be ignored if provided.
      *
-     * 4.  Non-attestation with non-signing key.  If TAG::ATTESTATION_CHALLENGE is not provided and
-     *     the generated/imported key does not have KeyPurpose::SIGN, then the returned certificate
-     *     chain must contain only a single certificate with an empty signature and no attestation
-     *     extension.
+     * 4.  Asymmetric key non-attestation with non-signing key.  If TAG::ATTESTATION_CHALLENGE is
+     *     not provided and the generated/imported key does not have KeyPurpose::SIGN, then the
+     *     returned certificate chain must contain only a single certificate with an empty signature
+     *     and no attestation extension.  Tag::ATTESTATION_APPLICATION_ID will be ignored if
+     *     provided.
      *
-     * 5.  Symmetric key.  If the generated/imported key is symmetric, the certificate chain must be
-     *     empty.
+     * 5.  Symmetric key.  If the generated/imported key is symmetric, the certificate chain must
+     *     return empty, any Tag::ATTESTATION_CHALLENGE or Tag::ATTESTATION_APPLICATION_ID inputs,
+     *     if provided, are ignored.
      */
     Certificate[] certificateChain;
 }
diff --git a/security/keymint/aidl/vts/functional/Android.bp b/security/keymint/aidl/vts/functional/Android.bp
index c1affa6..6c7309e 100644
--- a/security/keymint/aidl/vts/functional/Android.bp
+++ b/security/keymint/aidl/vts/functional/Android.bp
@@ -43,6 +43,8 @@
         "android.hardware.security.keymint-V1-ndk_platform",
         "android.hardware.security.secureclock-V1-ndk_platform",
         "libcppbor_external",
+        "libcppcose",
+        "libkeymint_remote_prov_support",
         "libkeymint_vts_test_utils",
     ],
     test_suites: [
@@ -73,6 +75,9 @@
         "android.hardware.security.keymint-V1-ndk_platform",
         "android.hardware.security.secureclock-V1-ndk_platform",
         "libcppbor_external",
+        "libcppcose",
+        "libgmock_ndk",
+        "libkeymint_remote_prov_support",
     ],
 }
 
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
index ce6f67a..3da0484 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
@@ -22,8 +22,12 @@
 
 #include <android-base/logging.h>
 #include <android/binder_manager.h>
+#include <cppbor_parse.h>
+#include <cppcose/cppcose.h>
 #include <cutils/properties.h>
+#include <gmock/gmock.h>
 #include <openssl/mem.h>
+#include <remote_prov/remote_prov_utils.h>
 
 #include <keymint_support/attestation_record.h>
 #include <keymint_support/key_param_output.h>
@@ -32,6 +36,7 @@
 
 namespace aidl::android::hardware::security::keymint {
 
+using namespace cppcose;
 using namespace std::literals::chrono_literals;
 using std::endl;
 using std::optional;
@@ -39,6 +44,7 @@
 using ::testing::AssertionFailure;
 using ::testing::AssertionResult;
 using ::testing::AssertionSuccess;
+using ::testing::MatchesRegex;
 
 ::std::ostream& operator<<(::std::ostream& os, const AuthorizationSet& set) {
     if (set.size() == 0)
@@ -897,7 +903,7 @@
             if (att_hw_enforced[i].tag == TAG_BOOT_PATCHLEVEL ||
                 att_hw_enforced[i].tag == TAG_VENDOR_PATCHLEVEL) {
                 std::string date =
-                        std::to_string(att_hw_enforced[i].value.get<KeyParameterValue::dateTime>());
+                        std::to_string(att_hw_enforced[i].value.get<KeyParameterValue::integer>());
                 // strptime seems to require delimiters, but the tag value will
                 // be YYYYMMDD
                 date.insert(6, "-");
@@ -1118,6 +1124,121 @@
     return retval;
 }
 
+namespace {
+
+void check_cose_key(const vector<uint8_t>& data, bool testMode) {
+    auto [parsedPayload, __, payloadParseErr] = cppbor::parse(data);
+    ASSERT_TRUE(parsedPayload) << "Key parse failed: " << payloadParseErr;
+
+    // The following check assumes that canonical CBOR encoding is used for the COSE_Key.
+    if (testMode) {
+        EXPECT_THAT(cppbor::prettyPrint(parsedPayload.get()),
+                    MatchesRegex("{\n"
+                                 "  1 : 2,\n"   // kty: EC2
+                                 "  3 : -7,\n"  // alg: ES256
+                                 "  -1 : 1,\n"  // EC id: P256
+                                 // The regex {(0x[0-9a-f]{2}, ){31}0x[0-9a-f]{2}} matches a
+                                 // sequence of 32 hexadecimal bytes, enclosed in braces and
+                                 // separated by commas. In this case, some Ed25519 public key.
+                                 "  -2 : {(0x[0-9a-f]{2}, ){31}0x[0-9a-f]{2}},\n"  // pub_x: data
+                                 "  -3 : {(0x[0-9a-f]{2}, ){31}0x[0-9a-f]{2}},\n"  // pub_y: data
+                                 "  -70000 : null,\n"                              // test marker
+                                 "}"));
+    } else {
+        EXPECT_THAT(cppbor::prettyPrint(parsedPayload.get()),
+                    MatchesRegex("{\n"
+                                 "  1 : 2,\n"   // kty: EC2
+                                 "  3 : -7,\n"  // alg: ES256
+                                 "  -1 : 1,\n"  // EC id: P256
+                                 // The regex {(0x[0-9a-f]{2}, ){31}0x[0-9a-f]{2}} matches a
+                                 // sequence of 32 hexadecimal bytes, enclosed in braces and
+                                 // separated by commas. In this case, some Ed25519 public key.
+                                 "  -2 : {(0x[0-9a-f]{2}, ){31}0x[0-9a-f]{2}},\n"  // pub_x: data
+                                 "  -3 : {(0x[0-9a-f]{2}, ){31}0x[0-9a-f]{2}},\n"  // pub_y: data
+                                 "}"));
+    }
+}
+
+}  // namespace
+
+void check_maced_pubkey(const MacedPublicKey& macedPubKey, bool testMode,
+                        vector<uint8_t>* payload_value) {
+    auto [coseMac0, _, mac0ParseErr] = cppbor::parse(macedPubKey.macedKey);
+    ASSERT_TRUE(coseMac0) << "COSE Mac0 parse failed " << mac0ParseErr;
+
+    ASSERT_NE(coseMac0->asArray(), nullptr);
+    ASSERT_EQ(coseMac0->asArray()->size(), kCoseMac0EntryCount);
+
+    auto protParms = coseMac0->asArray()->get(kCoseMac0ProtectedParams)->asBstr();
+    ASSERT_NE(protParms, nullptr);
+
+    // Header label:value of 'alg': HMAC-256
+    ASSERT_EQ(cppbor::prettyPrint(protParms->value()), "{\n  1 : 5,\n}");
+
+    auto unprotParms = coseMac0->asArray()->get(kCoseMac0UnprotectedParams)->asMap();
+    ASSERT_NE(unprotParms, nullptr);
+    ASSERT_EQ(unprotParms->size(), 0);
+
+    // The payload is a bstr holding an encoded COSE_Key
+    auto payload = coseMac0->asArray()->get(kCoseMac0Payload)->asBstr();
+    ASSERT_NE(payload, nullptr);
+    check_cose_key(payload->value(), testMode);
+
+    auto coseMac0Tag = coseMac0->asArray()->get(kCoseMac0Tag)->asBstr();
+    ASSERT_TRUE(coseMac0Tag);
+    auto extractedTag = coseMac0Tag->value();
+    EXPECT_EQ(extractedTag.size(), 32U);
+
+    // Compare with tag generated with kTestMacKey.  Should only match in test mode
+    auto testTag = cppcose::generateCoseMac0Mac(remote_prov::kTestMacKey, {} /* external_aad */,
+                                                payload->value());
+    ASSERT_TRUE(testTag) << "Tag calculation failed: " << testTag.message();
+
+    if (testMode) {
+        EXPECT_EQ(*testTag, extractedTag);
+    } else {
+        EXPECT_NE(*testTag, extractedTag);
+    }
+    if (payload_value != nullptr) {
+        *payload_value = payload->value();
+    }
+}
+
+void p256_pub_key(const vector<uint8_t>& coseKeyData, EVP_PKEY_Ptr* signingKey) {
+    // Extract x and y affine coordinates from the encoded Cose_Key.
+    auto [parsedPayload, __, payloadParseErr] = cppbor::parse(coseKeyData);
+    ASSERT_TRUE(parsedPayload) << "Key parse failed: " << payloadParseErr;
+    auto coseKey = parsedPayload->asMap();
+    const std::unique_ptr<cppbor::Item>& xItem = coseKey->get(cppcose::CoseKey::PUBKEY_X);
+    ASSERT_NE(xItem->asBstr(), nullptr);
+    vector<uint8_t> x = xItem->asBstr()->value();
+    const std::unique_ptr<cppbor::Item>& yItem = coseKey->get(cppcose::CoseKey::PUBKEY_Y);
+    ASSERT_NE(yItem->asBstr(), nullptr);
+    vector<uint8_t> y = yItem->asBstr()->value();
+
+    // Concatenate: 0x04 (uncompressed form marker) | x | y
+    vector<uint8_t> pubKeyData{0x04};
+    pubKeyData.insert(pubKeyData.end(), x.begin(), x.end());
+    pubKeyData.insert(pubKeyData.end(), y.begin(), y.end());
+
+    EC_KEY_Ptr ecKey = EC_KEY_Ptr(EC_KEY_new());
+    ASSERT_NE(ecKey, nullptr);
+    EC_GROUP_Ptr group = EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
+    ASSERT_NE(group, nullptr);
+    ASSERT_EQ(EC_KEY_set_group(ecKey.get(), group.get()), 1);
+    EC_POINT_Ptr point = EC_POINT_Ptr(EC_POINT_new(group.get()));
+    ASSERT_NE(point, nullptr);
+    ASSERT_EQ(EC_POINT_oct2point(group.get(), point.get(), pubKeyData.data(), pubKeyData.size(),
+                                 nullptr),
+              1);
+    ASSERT_EQ(EC_KEY_set_public_key(ecKey.get(), point.get()), 1);
+
+    EVP_PKEY_Ptr pubKey = EVP_PKEY_Ptr(EVP_PKEY_new());
+    ASSERT_NE(pubKey, nullptr);
+    EVP_PKEY_assign_EC_KEY(pubKey.get(), ecKey.release());
+    *signingKey = std::move(pubKey);
+}
+
 }  // namespace test
 
 }  // namespace aidl::android::hardware::security::keymint
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
index 4d97ea9..da174ce 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
@@ -25,6 +25,7 @@
 
 #include <aidl/android/hardware/security/keymint/ErrorCode.h>
 #include <aidl/android/hardware/security/keymint/IKeyMintDevice.h>
+#include <aidl/android/hardware/security/keymint/MacedPublicKey.h>
 
 #include <keymint_support/authorization_set.h>
 #include <keymint_support/openssl_utils.h>
@@ -277,6 +278,10 @@
 string bin2hex(const vector<uint8_t>& data);
 X509_Ptr parse_cert_blob(const vector<uint8_t>& blob);
 vector<uint8_t> make_name_from_str(const string& name);
+void check_maced_pubkey(const MacedPublicKey& macedPubKey, bool testMode,
+                        vector<uint8_t>* payload_value);
+void p256_pub_key(const vector<uint8_t>& coseKeyData, EVP_PKEY_Ptr* signingKey);
+
 AuthorizationSet HwEnforcedAuthorizations(const vector<KeyCharacteristics>& key_characteristics);
 AuthorizationSet SwEnforcedAuthorizations(const vector<KeyCharacteristics>& key_characteristics);
 ::testing::AssertionResult ChainSignaturesAreValid(const vector<Certificate>& chain);
diff --git a/security/keymint/aidl/vts/functional/KeyMintTest.cpp b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
index 7ecfa37..2d28845 100644
--- a/security/keymint/aidl/vts/functional/KeyMintTest.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
@@ -27,6 +27,9 @@
 
 #include <cutils/properties.h>
 
+#include <android/binder_manager.h>
+
+#include <aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.h>
 #include <aidl/android/hardware/security/keymint/KeyFormat.h>
 
 #include <keymint_support/key_param_output.h>
@@ -134,6 +137,54 @@
                 "d5f33645e8ed8b4a1cb3cc4a1d67987399f2a09f5b3fb68c88d5e5d90ac3"
                 "3492d6");
 
+/*
+ * DER-encoded PKCS#8 format RSA key. Generated using:
+ *
+ * openssl genrsa 2048 | openssl pkcs8 -topk8 -nocrypt -outform der | hexdump -e '30/1  "%02X" "\n"'
+ */
+string rsa_2048_key =
+        hex2str("308204BD020100300D06092A864886F70D0101010500048204A7308204A3"
+                "0201000282010100BEBC342B56D443B1299F9A6A7056E80A897E318476A5"
+                "A18029E63B2ED739A61791D339F58DC763D9D14911F2EDEC383DEE11F631"
+                "9B44510E7A3ECD9B79B97382E49500ACF8117DC89CAF0E621F77756554A2"
+                "FD4664BFE7AB8B59AB48340DBFA27B93B5A81F6ECDEB02D0759307128DF3"
+                "E3BAD4055C8B840216DFAA5700670E6C5126F0962FCB70FF308F25049164"
+                "CCF76CC2DA66A7DD9A81A714C2809D69186133D29D84568E892B6FFBF319"
+                "9BDB14383EE224407F190358F111A949552ABA6714227D1BD7F6B20DD0CB"
+                "88F9467B719339F33BFF35B3870B3F62204E4286B0948EA348B524544B5F"
+                "9838F29EE643B079EEF8A713B220D7806924CDF7295070C5020301000102"
+                "82010069F377F35F2F584EF075353CCD1CA99738DB3DBC7C7FF35F9366CE"
+                "176DFD1B135AB10030344ABF5FBECF1D4659FDEF1C0FC430834BE1BE3911"
+                "951377BB3D563A2EA9CA8F4AD9C48A8CE6FD516A735C662686C7B4B3C09A"
+                "7B8354133E6F93F790D59EAEB92E84C9A4339302CCE28FDF04CCCAFA7DE3"
+                "F3A827D4F6F7D38E68B0EC6AB706645BF074A4E4090D06FB163124365FD5"
+                "EE7A20D350E9958CC30D91326E1B292E9EF5DB408EC42DAF737D20149704"
+                "D0A678A0FB5B5446863B099228A352D604BA8091A164D01D5AB05397C71E"
+                "AD20BE2A08FC528FE442817809C787FEE4AB97F97B9130D022153EDC6EB6"
+                "CBE7B0F8E3473F2E901209B5DB10F93604DB0102818100E83C0998214941"
+                "EA4F9293F1B77E2E99E6CF305FAF358238E126124FEAF2EB9724B2EA7B78"
+                "E6032343821A80E55D1D88FB12D220C3F41A56142FEC85796D1917F1E8C7"
+                "74F142B67D3D6E7B7E6B4383E94DB5929089DBB346D5BDAB40CC2D96EE04"
+                "09475E175C63BF78CFD744136740838127EA723FF3FE7FA368C1311B4A4E"
+                "0502818100D240FCC0F5D7715CDE21CB2DC86EA146132EA3B06F61FF2AF5"
+                "4BF38473F59DADCCE32B5F4CC32DD0BA6F509347B4B5B1B58C39F95E4798"
+                "CCBB43E83D0119ACF532F359CA743C85199F0286610E200997D731291717"
+                "9AC9B67558773212EC961E8BCE7A3CC809BC5486A96E4B0E6AF394D94E06"
+                "6A0900B7B70E82A44FB30053C102818100AD15DA1CBD6A492B66851BA8C3"
+                "16D38AB700E2CFDDD926A658003513C54BAA152B30021D667D20078F500F"
+                "8AD3E7F3945D74A891ED1A28EAD0FEEAEC8C14A8E834CF46A13D1378C99D"
+                "18940823CFDD27EC5810D59339E0C34198AC638E09C87CBB1B634A9864AE"
+                "9F4D5EB2D53514F67B4CAEC048C8AB849A02E397618F3271350281801FA2"
+                "C1A5331880A92D8F3E281C617108BF38244F16E352E69ED417C7153F9EC3"
+                "18F211839C643DCF8B4DD67CE2AC312E95178D5D952F06B1BF779F491692"
+                "4B70F582A23F11304E02A5E7565AE22A35E74FECC8B6FDC93F92A1A37703"
+                "E4CF0E63783BD02EB716A7ECBBFA606B10B74D01579522E7EF84D91FC522"
+                "292108D902C1028180796FE3825F9DCC85DF22D58690065D93898ACD65C0"
+                "87BEA8DA3A63BF4549B795E2CD0E3BE08CDEBD9FCF1720D9CDC5070D74F4"
+                "0DED8E1102C52152A31B6165F83A6722AECFCC35A493D7634664B888A08D"
+                "3EB034F12EA28BFEE346E205D334827F778B16ED40872BD29FCB36536B6E"
+                "93FFB06778696B4A9D81BB0A9423E63DE5");
+
 string ec_256_key =
         hex2str("308187020100301306072a8648ce3d020106082a8648ce3d030107046d30"
                 "6b0201010420737c2ecd7b8d1940bf2930aa9b4ed3ff941eed09366bc032"
@@ -209,6 +260,32 @@
     string to_string() const { return string(reinterpret_cast<const char*>(data()), size()); }
 };
 
+string device_suffix(const string& name) {
+    size_t pos = name.find('/');
+    if (pos == string::npos) {
+        return name;
+    }
+    return name.substr(pos + 1);
+}
+
+bool matching_rp_instance(const string& km_name,
+                          std::shared_ptr<IRemotelyProvisionedComponent>* rp) {
+    string km_suffix = device_suffix(km_name);
+
+    vector<string> rp_names =
+            ::android::getAidlHalInstanceNames(IRemotelyProvisionedComponent::descriptor);
+    for (const string& rp_name : rp_names) {
+        // If the suffix of the RemotelyProvisionedComponent instance equals the suffix of the
+        // KeyMint instance, assume they match.
+        if (device_suffix(rp_name) == km_suffix && AServiceManager_isDeclared(rp_name.c_str())) {
+            ::ndk::SpAIBinder binder(AServiceManager_waitForService(rp_name.c_str()));
+            *rp = IRemotelyProvisionedComponent::fromBinder(binder);
+            return true;
+        }
+    }
+    return false;
+}
+
 }  // namespace
 
 class NewKeyGenerationTest : public KeyMintAidlTestBase {
@@ -322,6 +399,77 @@
 }
 
 /*
+ * NewKeyGenerationTest.RsaWithRpkAttestation
+ *
+ * Verifies that keymint can generate all required RSA key sizes, using an attestation key
+ * that has been generated using an associate IRemotelyProvisionedComponent.
+ */
+TEST_P(NewKeyGenerationTest, RsaWithRpkAttestation) {
+    // There should be an IRemotelyProvisionedComponent instance associated with the KeyMint
+    // instance.
+    std::shared_ptr<IRemotelyProvisionedComponent> rp;
+    ASSERT_TRUE(matching_rp_instance(GetParam(), &rp))
+            << "No IRemotelyProvisionedComponent found that matches KeyMint device " << GetParam();
+
+    // Generate a P-256 keypair to use as an attestation key.
+    MacedPublicKey macedPubKey;
+    std::vector<uint8_t> privateKeyBlob;
+    auto status =
+            rp->generateEcdsaP256KeyPair(/* testMode= */ false, &macedPubKey, &privateKeyBlob);
+    ASSERT_TRUE(status.isOk());
+    vector<uint8_t> coseKeyData;
+    check_maced_pubkey(macedPubKey, /* testMode= */ false, &coseKeyData);
+
+    AttestationKey attestation_key;
+    attestation_key.keyBlob = std::move(privateKeyBlob);
+    attestation_key.issuerSubjectName = make_name_from_str("Android Keystore Key");
+
+    for (auto key_size : ValidKeySizes(Algorithm::RSA)) {
+        auto challenge = "hello";
+        auto app_id = "foo";
+
+        vector<uint8_t> key_blob;
+        vector<KeyCharacteristics> key_characteristics;
+        ASSERT_EQ(ErrorCode::OK,
+                  GenerateKey(AuthorizationSetBuilder()
+                                      .RsaSigningKey(key_size, 65537)
+                                      .Digest(Digest::NONE)
+                                      .Padding(PaddingMode::NONE)
+                                      .AttestationChallenge(challenge)
+                                      .AttestationApplicationId(app_id)
+                                      .Authorization(TAG_NO_AUTH_REQUIRED)
+                                      .SetDefaultValidity(),
+                              attestation_key, &key_blob, &key_characteristics, &cert_chain_));
+
+        ASSERT_GT(key_blob.size(), 0U);
+        CheckBaseParams(key_characteristics);
+
+        AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
+
+        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, 65537U));
+
+        // Attestation by itself is not valid (last entry is not self-signed).
+        EXPECT_FALSE(ChainSignaturesAreValid(cert_chain_));
+
+        // The signature over the attested key should correspond to the P256 public key.
+        X509_Ptr key_cert(parse_cert_blob(cert_chain_[0].encodedCertificate));
+        ASSERT_TRUE(key_cert.get());
+        EVP_PKEY_Ptr signing_pubkey;
+        p256_pub_key(coseKeyData, &signing_pubkey);
+        ASSERT_TRUE(signing_pubkey.get());
+
+        ASSERT_TRUE(X509_verify(key_cert.get(), signing_pubkey.get()))
+                << "Verification of attested certificate failed "
+                << "OpenSSL error string: " << ERR_error_string(ERR_get_error(), NULL);
+
+        CheckedDeleteKey(&key_blob);
+    }
+}
+
+/*
  * NewKeyGenerationTest.LimitedUsageRsa
  *
  * Verifies that KeyMint can generate all required RSA key sizes with limited usage, and that the
@@ -1711,16 +1859,27 @@
  * Verifies that importing and using an RSA key pair works correctly.
  */
 TEST_P(ImportKeyTest, RsaSuccess) {
+    uint32_t key_size;
+    string key;
+
+    if (SecLevel() == SecurityLevel::STRONGBOX) {
+        key_size = 2048;
+        key = rsa_2048_key;
+    } else {
+        key_size = 1024;
+        key = rsa_key;
+    }
+
     ASSERT_EQ(ErrorCode::OK, ImportKey(AuthorizationSetBuilder()
                                                .Authorization(TAG_NO_AUTH_REQUIRED)
-                                               .RsaSigningKey(1024, 65537)
+                                               .RsaSigningKey(key_size, 65537)
                                                .Digest(Digest::SHA_2_256)
                                                .Padding(PaddingMode::RSA_PSS)
                                                .SetDefaultValidity(),
-                                       KeyFormat::PKCS8, rsa_key));
+                                       KeyFormat::PKCS8, key));
 
     CheckCryptoParam(TAG_ALGORITHM, Algorithm::RSA);
-    CheckCryptoParam(TAG_KEY_SIZE, 1024U);
+    CheckCryptoParam(TAG_KEY_SIZE, key_size);
     CheckCryptoParam(TAG_RSA_PUBLIC_EXPONENT, 65537U);
     CheckCryptoParam(TAG_DIGEST, Digest::SHA_2_256);
     CheckCryptoParam(TAG_PADDING, PaddingMode::RSA_PSS);
diff --git a/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp b/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
index 57bc27a..9e52b20 100644
--- a/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
+++ b/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
@@ -55,117 +55,6 @@
     return bytevec(p, p + strlen(s));
 }
 
-void p256_pub_key(const vector<uint8_t>& coseKeyData, EVP_PKEY_Ptr* signingKey) {
-    // Extract x and y affine coordinates from the encoded Cose_Key.
-    auto [parsedPayload, __, payloadParseErr] = cppbor::parse(coseKeyData);
-    ASSERT_TRUE(parsedPayload) << "Key parse failed: " << payloadParseErr;
-    auto coseKey = parsedPayload->asMap();
-    const std::unique_ptr<cppbor::Item>& xItem = coseKey->get(cppcose::CoseKey::PUBKEY_X);
-    ASSERT_NE(xItem->asBstr(), nullptr);
-    vector<uint8_t> x = xItem->asBstr()->value();
-    const std::unique_ptr<cppbor::Item>& yItem = coseKey->get(cppcose::CoseKey::PUBKEY_Y);
-    ASSERT_NE(yItem->asBstr(), nullptr);
-    vector<uint8_t> y = yItem->asBstr()->value();
-
-    // Concatenate: 0x04 (uncompressed form marker) | x | y
-    vector<uint8_t> pubKeyData{0x04};
-    pubKeyData.insert(pubKeyData.end(), x.begin(), x.end());
-    pubKeyData.insert(pubKeyData.end(), y.begin(), y.end());
-
-    EC_KEY_Ptr ecKey = EC_KEY_Ptr(EC_KEY_new());
-    ASSERT_NE(ecKey, nullptr);
-    EC_GROUP_Ptr group = EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
-    ASSERT_NE(group, nullptr);
-    ASSERT_EQ(EC_KEY_set_group(ecKey.get(), group.get()), 1);
-    EC_POINT_Ptr point = EC_POINT_Ptr(EC_POINT_new(group.get()));
-    ASSERT_NE(point, nullptr);
-    ASSERT_EQ(EC_POINT_oct2point(group.get(), point.get(), pubKeyData.data(), pubKeyData.size(),
-                                 nullptr),
-              1);
-    ASSERT_EQ(EC_KEY_set_public_key(ecKey.get(), point.get()), 1);
-
-    EVP_PKEY_Ptr pubKey = EVP_PKEY_Ptr(EVP_PKEY_new());
-    ASSERT_NE(pubKey, nullptr);
-    EVP_PKEY_assign_EC_KEY(pubKey.get(), ecKey.release());
-    *signingKey = std::move(pubKey);
-}
-
-void check_cose_key(const vector<uint8_t>& data, bool testMode) {
-    auto [parsedPayload, __, payloadParseErr] = cppbor::parse(data);
-    ASSERT_TRUE(parsedPayload) << "Key parse failed: " << payloadParseErr;
-
-    // The following check assumes that canonical CBOR encoding is used for the COSE_Key.
-    if (testMode) {
-        EXPECT_THAT(cppbor::prettyPrint(parsedPayload.get()),
-                    MatchesRegex("{\n"
-                                 "  1 : 2,\n"   // kty: EC2
-                                 "  3 : -7,\n"  // alg: ES256
-                                 "  -1 : 1,\n"  // EC id: P256
-                                 // The regex {(0x[0-9a-f]{2}, ){31}0x[0-9a-f]{2}} matches a
-                                 // sequence of 32 hexadecimal bytes, enclosed in braces and
-                                 // separated by commas. In this case, some Ed25519 public key.
-                                 "  -2 : {(0x[0-9a-f]{2}, ){31}0x[0-9a-f]{2}},\n"  // pub_x: data
-                                 "  -3 : {(0x[0-9a-f]{2}, ){31}0x[0-9a-f]{2}},\n"  // pub_y: data
-                                 "  -70000 : null,\n"                              // test marker
-                                 "}"));
-    } else {
-        EXPECT_THAT(cppbor::prettyPrint(parsedPayload.get()),
-                    MatchesRegex("{\n"
-                                 "  1 : 2,\n"   // kty: EC2
-                                 "  3 : -7,\n"  // alg: ES256
-                                 "  -1 : 1,\n"  // EC id: P256
-                                 // The regex {(0x[0-9a-f]{2}, ){31}0x[0-9a-f]{2}} matches a
-                                 // sequence of 32 hexadecimal bytes, enclosed in braces and
-                                 // separated by commas. In this case, some Ed25519 public key.
-                                 "  -2 : {(0x[0-9a-f]{2}, ){31}0x[0-9a-f]{2}},\n"  // pub_x: data
-                                 "  -3 : {(0x[0-9a-f]{2}, ){31}0x[0-9a-f]{2}},\n"  // pub_y: data
-                                 "}"));
-    }
-}
-
-void check_maced_pubkey(const MacedPublicKey& macedPubKey, bool testMode,
-                        vector<uint8_t>* payload_value) {
-    auto [coseMac0, _, mac0ParseErr] = cppbor::parse(macedPubKey.macedKey);
-    ASSERT_TRUE(coseMac0) << "COSE Mac0 parse failed " << mac0ParseErr;
-
-    ASSERT_NE(coseMac0->asArray(), nullptr);
-    ASSERT_EQ(coseMac0->asArray()->size(), kCoseMac0EntryCount);
-
-    auto protParms = coseMac0->asArray()->get(kCoseMac0ProtectedParams)->asBstr();
-    ASSERT_NE(protParms, nullptr);
-
-    // Header label:value of 'alg': HMAC-256
-    ASSERT_EQ(cppbor::prettyPrint(protParms->value()), "{\n  1 : 5,\n}");
-
-    auto unprotParms = coseMac0->asArray()->get(kCoseMac0UnprotectedParams)->asMap();
-    ASSERT_NE(unprotParms, nullptr);
-    ASSERT_EQ(unprotParms->size(), 0);
-
-    // The payload is a bstr holding an encoded COSE_Key
-    auto payload = coseMac0->asArray()->get(kCoseMac0Payload)->asBstr();
-    ASSERT_NE(payload, nullptr);
-    check_cose_key(payload->value(), testMode);
-
-    auto coseMac0Tag = coseMac0->asArray()->get(kCoseMac0Tag)->asBstr();
-    ASSERT_TRUE(coseMac0Tag);
-    auto extractedTag = coseMac0Tag->value();
-    EXPECT_EQ(extractedTag.size(), 32U);
-
-    // Compare with tag generated with kTestMacKey.  Should only match in test mode
-    auto testTag = cppcose::generateCoseMac0Mac(remote_prov::kTestMacKey, {} /* external_aad */,
-                                                payload->value());
-    ASSERT_TRUE(testTag) << "Tag calculation failed: " << testTag.message();
-
-    if (testMode) {
-        EXPECT_EQ(*testTag, extractedTag);
-    } else {
-        EXPECT_NE(*testTag, extractedTag);
-    }
-    if (payload_value != nullptr) {
-        *payload_value = payload->value();
-    }
-}
-
 ErrMsgOr<MacedPublicKey> corrupt_maced_key(const MacedPublicKey& macedPubKey) {
     auto [coseMac0, _, mac0ParseErr] = cppbor::parse(macedPubKey.macedKey);
     if (!coseMac0 || coseMac0->asArray()->size() != kCoseMac0EntryCount) {
diff --git a/security/keymint/support/Android.bp b/security/keymint/support/Android.bp
index fe04ede..4c4258b 100644
--- a/security/keymint/support/Android.bp
+++ b/security/keymint/support/Android.bp
@@ -66,6 +66,7 @@
 cc_library {
     name: "libcppcose",
     vendor_available: true,
+    host_supported: true,
     srcs: [
         "cppcose.cpp",
     ],
@@ -73,13 +74,8 @@
         "include",
     ],
     shared_libs: [
-        "libbinder_ndk",
         "libcppbor_external",
         "libcrypto",
         "liblog",
     ],
-    static_libs: [
-        // TODO(swillden): Remove keymint NDK
-        "android.hardware.security.keymint-V1-ndk_platform",
-    ],
 }
diff --git a/sensors/2.1/default/SensorsV2_1.cpp b/sensors/2.1/default/SensorsV2_1.cpp
index 4c5386a..06446a2 100644
--- a/sensors/2.1/default/SensorsV2_1.cpp
+++ b/sensors/2.1/default/SensorsV2_1.cpp
@@ -46,7 +46,8 @@
         mSensorInfo.fifoMaxEventCount = 0;
         mSensorInfo.requiredPermission = "";
         mSensorInfo.flags = static_cast<uint32_t>(V1_0::SensorFlagBits::ON_CHANGE_MODE |
-                                                  V1_0::SensorFlagBits::WAKE_UP);
+                                                  V1_0::SensorFlagBits::WAKE_UP |
+                                                  V1_0::SensorFlagBits::DATA_INJECTION);
     }
 };
 
diff --git a/tv/tuner/1.0/default/Tuner.cpp b/tv/tuner/1.0/default/Tuner.cpp
index 9a6ecf7..c4f610e 100644
--- a/tv/tuner/1.0/default/Tuner.cpp
+++ b/tv/tuner/1.0/default/Tuner.cpp
@@ -139,6 +139,8 @@
 
     // IP filter can be an MMTP filter's data source.
     caps.linkCaps = {0x00, 0x00, 0x02, 0x00, 0x00};
+    // Support time filter testing
+    caps.bTimeFilter = true;
     _hidl_cb(Result::SUCCESS, caps);
     return Void();
 }
diff --git a/tv/tuner/1.0/vts/functional/Android.bp b/tv/tuner/1.0/vts/functional/Android.bp
index c27a935..6187c73 100644
--- a/tv/tuner/1.0/vts/functional/Android.bp
+++ b/tv/tuner/1.0/vts/functional/Android.bp
@@ -35,6 +35,15 @@
         "DescramblerTests.cpp",
         "LnbTests.cpp",
     ],
+    generated_headers: [
+        "tuner_testing_dynamic_configuration_V1_0_enums",
+        "tuner_testing_dynamic_configuration_V1_0_parser",
+    ],
+    generated_sources: [
+        "tuner_testing_dynamic_configuration_V1_0_enums",
+        "tuner_testing_dynamic_configuration_V1_0_parser",
+    ],
+    header_libs: ["libxsdc-utils"],
     static_libs: [
         "android.hardware.cas@1.0",
         "android.hardware.cas@1.1",
@@ -49,9 +58,12 @@
     ],
     shared_libs: [
         "libbinder",
+        "libxml2",
     ],
     data: [
         ":tuner_frontend_input_ts",
+        ":tuner_frontend_input_es",
+        ":tuner_testing_dynamic_configuration_V1_0",
     ],
     test_suites: [
         "general-tests",
diff --git a/tv/tuner/1.0/vts/functional/FrontendTests.h b/tv/tuner/1.0/vts/functional/FrontendTests.h
index 4974ff3..33ff603 100644
--- a/tv/tuner/1.0/vts/functional/FrontendTests.h
+++ b/tv/tuner/1.0/vts/functional/FrontendTests.h
@@ -132,6 +132,7 @@
     static AssertionResult failure() { return ::testing::AssertionFailure(); }
     static AssertionResult success() { return ::testing::AssertionSuccess(); }
 
+    // TODO: replace with customized dvr input
     void getDefaultSoftwareFrontendPlaybackConfig(DvrConfig& dvrConfig) {
         PlaybackSettings playbackSettings{
                 .statusMask = 0xf,
diff --git a/tv/tuner/1.0/vts/functional/LnbTests.cpp b/tv/tuner/1.0/vts/functional/LnbTests.cpp
index 9080f59..9338c73 100644
--- a/tv/tuner/1.0/vts/functional/LnbTests.cpp
+++ b/tv/tuner/1.0/vts/functional/LnbTests.cpp
@@ -48,10 +48,11 @@
     return AssertionResult(status == Result::SUCCESS);
 }
 
-AssertionResult LnbTests::openLnbByName(string lnbName) {
+AssertionResult LnbTests::openLnbByName(string lnbName, uint32_t& id) {
     Result status;
-    mService->openLnbByName(lnbName, [&](Result result, uint32_t /*lnbId*/, const sp<ILnb>& lnb) {
+    mService->openLnbByName(lnbName, [&](Result result, uint32_t lnbId, const sp<ILnb>& lnb) {
         mLnb = lnb;
+        id = lnbId;
         status = result;
     });
 
diff --git a/tv/tuner/1.0/vts/functional/LnbTests.h b/tv/tuner/1.0/vts/functional/LnbTests.h
index 2fdbe2c..62b42ff 100644
--- a/tv/tuner/1.0/vts/functional/LnbTests.h
+++ b/tv/tuner/1.0/vts/functional/LnbTests.h
@@ -64,7 +64,7 @@
 
     AssertionResult getLnbIds(vector<uint32_t>& ids);
     AssertionResult openLnbById(uint32_t lnbId);
-    AssertionResult openLnbByName(string lnbName);
+    AssertionResult openLnbByName(string lnbName, uint32_t& lnbId);
     AssertionResult setLnbCallback();
     AssertionResult setVoltage(LnbVoltage voltage);
     AssertionResult setTone(LnbTone tone);
diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
index 891619a..4c92665 100644
--- a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
+++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
@@ -18,16 +18,15 @@
 
 namespace {
 
-AssertionResult TunerBroadcastHidlTest::filterDataOutputTest(vector<string> /*goldenOutputFiles*/) {
+AssertionResult TunerBroadcastHidlTest::filterDataOutputTest() {
     return filterDataOutputTestBase(mFilterTests);
 }
 
-AssertionResult TunerPlaybackHidlTest::filterDataOutputTest(vector<string> /*goldenOutputFiles*/) {
+AssertionResult TunerPlaybackHidlTest::filterDataOutputTest() {
     return filterDataOutputTestBase(mFilterTests);
 }
 
-AssertionResult TunerDescramblerHidlTest::filterDataOutputTest(
-        vector<string> /*goldenOutputFiles*/) {
+AssertionResult TunerDescramblerHidlTest::filterDataOutputTest() {
     return filterDataOutputTestBase(mFilterTests);
 }
 
@@ -57,13 +56,16 @@
 }
 
 void TunerFilterHidlTest::testTimeFilter(TimeFilterConfig filterConf) {
-    if (!filterConf.supportTimeFilter) {
+    if (!timeFilter.support) {
         return;
     }
     uint32_t demuxId;
     sp<IDemux> demux;
+    DemuxCapabilities caps;
 
     ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
+    ASSERT_TRUE(mDemuxTests.getDemuxCaps(caps));
+    ASSERT_TRUE(caps.bTimeFilter);
     mFilterTests.setDemux(demux);
     ASSERT_TRUE(mFilterTests.openTimeFilterInDemux());
     ASSERT_TRUE(mFilterTests.setTimeStamp(filterConf.timeStamp));
@@ -75,26 +77,20 @@
 
 void TunerBroadcastHidlTest::broadcastSingleFilterTest(FilterConfig filterConf,
                                                        FrontendConfig frontendConf) {
-    if (!frontendConf.enable) {
-        return;
-    }
     uint32_t feId;
     uint32_t demuxId;
     sp<IDemux> demux;
     uint32_t filterId;
 
     mFrontendTests.getFrontendIdByType(frontendConf.type, feId);
-    if (feId == INVALID_ID) {
-        // TODO broadcast test on Cuttlefish needs licensed ts input,
-        // these tests are runnable on vendor device with real frontend module
-        // or with manual ts installing and use DVBT frontend.
-        return;
-    }
     ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
     ASSERT_TRUE(mFrontendTests.setFrontendCallback());
     if (mLnbId) {
         ASSERT_TRUE(mFrontendTests.setLnb(*mLnbId));
     }
+    if (frontendConf.isSoftwareFe) {
+        mFrontendTests.setSoftwareFrontendDvrConfig(dvrMap[live.dvrSoftwareFeId]);
+    }
     ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
     ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
     mFrontendTests.setDemux(demux);
@@ -106,7 +102,7 @@
     ASSERT_TRUE(mFilterTests.startFilter(filterId));
     // tune test
     ASSERT_TRUE(mFrontendTests.tuneFrontend(frontendConf, true /*testWithDemux*/));
-    ASSERT_TRUE(filterDataOutputTest(goldenOutputFiles));
+    ASSERT_TRUE(filterDataOutputTest());
     ASSERT_TRUE(mFrontendTests.stopTuneFrontend(true /*testWithDemux*/));
     ASSERT_TRUE(mFilterTests.stopFilter(filterId));
     ASSERT_TRUE(mFilterTests.closeFilter(filterId));
@@ -117,14 +113,16 @@
 void TunerBroadcastHidlTest::broadcastSingleFilterTestWithLnb(FilterConfig filterConf,
                                                               FrontendConfig frontendConf,
                                                               LnbConfig lnbConf) {
-    vector<uint32_t> ids;
-    ASSERT_TRUE(mLnbTests.getLnbIds(ids));
-    if (!lnbConf.usingLnb) {
-        return;
+    if (lnbConf.name.compare(emptyHardwareId) == 0) {
+        vector<uint32_t> ids;
+        ASSERT_TRUE(mLnbTests.getLnbIds(ids));
+        ASSERT_TRUE(ids.size() > 0);
+        ASSERT_TRUE(mLnbTests.openLnbById(ids[0]));
+        mLnbId = &ids[0];
+    } else {
+        mLnbId = (uint32_t*)malloc(sizeof(uint32_t));
+        ASSERT_TRUE(mLnbTests.openLnbByName(lnbConf.name, *mLnbId));
     }
-    ASSERT_TRUE(ids.size() > 0);
-    ASSERT_TRUE(mLnbTests.openLnbById(ids[0]));
-    *mLnbId = ids[0];
     ASSERT_TRUE(mLnbTests.setLnbCallback());
     ASSERT_TRUE(mLnbTests.setVoltage(lnbConf.voltage));
     ASSERT_TRUE(mLnbTests.setTone(lnbConf.tone));
@@ -152,7 +150,7 @@
     mDvrTests.startPlaybackInputThread(dvrConf.playbackInputFile, dvrConf.settings.playback());
     ASSERT_TRUE(mDvrTests.startDvrPlayback());
     ASSERT_TRUE(mFilterTests.startFilter(filterId));
-    ASSERT_TRUE(filterDataOutputTest(goldenOutputFiles));
+    ASSERT_TRUE(filterDataOutputTest());
     mDvrTests.stopPlaybackThread();
     ASSERT_TRUE(mFilterTests.stopFilter(filterId));
     ASSERT_TRUE(mDvrTests.stopDvrPlayback());
@@ -163,9 +161,6 @@
 
 void TunerRecordHidlTest::recordSingleFilterTest(FilterConfig filterConf,
                                                  FrontendConfig frontendConf, DvrConfig dvrConf) {
-    if (!frontendConf.enable) {
-        return;
-    }
     uint32_t feId;
     uint32_t demuxId;
     sp<IDemux> demux;
@@ -179,6 +174,9 @@
     if (mLnbId) {
         ASSERT_TRUE(mFrontendTests.setLnb(*mLnbId));
     }
+    if (frontendConf.isSoftwareFe) {
+        mFrontendTests.setSoftwareFrontendDvrConfig(dvrMap[record.dvrSoftwareFeId]);
+    }
     ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
     ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
     mFilterTests.setDemux(demux);
@@ -213,18 +211,23 @@
 void TunerRecordHidlTest::recordSingleFilterTestWithLnb(FilterConfig filterConf,
                                                         FrontendConfig frontendConf,
                                                         DvrConfig dvrConf, LnbConfig lnbConf) {
-    vector<uint32_t> ids;
-    ASSERT_TRUE(mLnbTests.getLnbIds(ids));
-    if (!lnbConf.usingLnb) {
-        return;
+    if (lnbConf.name.compare(emptyHardwareId) == 0) {
+        vector<uint32_t> ids;
+        ASSERT_TRUE(mLnbTests.getLnbIds(ids));
+        ASSERT_TRUE(ids.size() > 0);
+        ASSERT_TRUE(mLnbTests.openLnbById(ids[0]));
+        mLnbId = &ids[0];
+    } else {
+        mLnbId = (uint32_t*)malloc(sizeof(uint32_t));
+        ASSERT_TRUE(mLnbTests.openLnbByName(lnbConf.name, *mLnbId));
     }
-    ASSERT_TRUE(ids.size() > 0);
-    ASSERT_TRUE(mLnbTests.openLnbById(ids[0]));
-    *mLnbId = ids[0];
     ASSERT_TRUE(mLnbTests.setLnbCallback());
     ASSERT_TRUE(mLnbTests.setVoltage(lnbConf.voltage));
     ASSERT_TRUE(mLnbTests.setTone(lnbConf.tone));
     ASSERT_TRUE(mLnbTests.setSatellitePosition(lnbConf.position));
+    for (auto msgName : lnbRecord.diseqcMsgs) {
+        ASSERT_TRUE(mLnbTests.sendDiseqcMessage(diseqcMsgMap[msgName]));
+    }
     recordSingleFilterTest(filterConf, frontendConf, dvrConf);
     ASSERT_TRUE(mLnbTests.closeLnb());
     mLnbId = nullptr;
@@ -271,9 +274,6 @@
 void TunerDescramblerHidlTest::scrambledBroadcastTest(set<struct FilterConfig> mediaFilterConfs,
                                                       FrontendConfig frontendConf,
                                                       DescramblerConfig descConfig) {
-    if (!frontendConf.enable) {
-        return;
-    }
     uint32_t feId;
     uint32_t demuxId;
     sp<IDemux> demux;
@@ -283,14 +283,11 @@
     set<uint32_t>::iterator id;
 
     mFrontendTests.getFrontendIdByType(frontendConf.type, feId);
-    if (feId == INVALID_ID) {
-        // TODO broadcast test on Cuttlefish needs licensed ts input,
-        // these tests are runnable on vendor device with real frontend module
-        // or with manual ts installing and use DVBT frontend.
-        return;
-    }
     ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
     ASSERT_TRUE(mFrontendTests.setFrontendCallback());
+    if (frontendConf.isSoftwareFe) {
+        mFrontendTests.setSoftwareFrontendDvrConfig(dvrMap[descrambling.dvrSoftwareFeId]);
+    }
     ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
     ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
     mFilterTests.setDemux(demux);
@@ -305,7 +302,7 @@
     TunerKeyToken token;
     ASSERT_TRUE(mDescramblerTests.getKeyToken(descConfig.casSystemId, descConfig.provisionStr,
                                               descConfig.hidlPvtData, token));
-    ASSERT_TRUE(mDescramblerTests.setKeyToken(token));
+    mDescramblerTests.setKeyToken(token);
     vector<DemuxPid> pids;
     DemuxPid pid;
     for (config = mediaFilterConfs.begin(); config != mediaFilterConfs.end(); config++) {
@@ -319,7 +316,7 @@
     }
     // tune test
     ASSERT_TRUE(mFrontendTests.tuneFrontend(frontendConf, true /*testWithDemux*/));
-    ASSERT_TRUE(filterDataOutputTest(goldenOutputFiles));
+    ASSERT_TRUE(filterDataOutputTest());
     ASSERT_TRUE(mFrontendTests.stopTuneFrontend(true /*testWithDemux*/));
     for (id = filterIds.begin(); id != filterIds.end(); id++) {
         ASSERT_TRUE(mFilterTests.stopFilter(*id));
@@ -337,44 +334,37 @@
 
 TEST_P(TunerFrontendHidlTest, TuneFrontend) {
     description("Tune one Frontend with specific setting and check Lock event");
-    mFrontendTests.tuneTest(frontendArray[defaultFrontend]);
+    mFrontendTests.tuneTest(frontendMap[live.frontendId]);
 }
 
 TEST_P(TunerFrontendHidlTest, AutoScanFrontend) {
     description("Run an auto frontend scan with specific setting and check lock scanMessage");
-    mFrontendTests.scanTest(frontendScanArray[defaultScanFrontend], FrontendScanType::SCAN_AUTO);
+    mFrontendTests.scanTest(frontendMap[scan.frontendId], FrontendScanType::SCAN_AUTO);
 }
 
 TEST_P(TunerFrontendHidlTest, BlindScanFrontend) {
     description("Run an blind frontend scan with specific setting and check lock scanMessage");
-    mFrontendTests.scanTest(frontendScanArray[defaultScanFrontend], FrontendScanType::SCAN_BLIND);
-}
-
-TEST_P(TunerLnbHidlTest, OpenLnbByName) {
-    description("Open and configure an Lnb with name then send a diseqc msg to it.");
-    ASSERT_TRUE(mLnbTests.openLnbByName(lnbArray[LNB_EXTERNAL].name));
-    ASSERT_TRUE(mLnbTests.setLnbCallback());
-    ASSERT_TRUE(mLnbTests.setVoltage(lnbArray[LNB_EXTERNAL].voltage));
-    ASSERT_TRUE(mLnbTests.setTone(lnbArray[LNB_EXTERNAL].tone));
-    ASSERT_TRUE(mLnbTests.setSatellitePosition(lnbArray[LNB_EXTERNAL].position));
-    ASSERT_TRUE(mLnbTests.sendDiseqcMessage(diseqcMsgArray[DISEQC_POWER_ON]));
-    ASSERT_TRUE(mLnbTests.closeLnb());
+    mFrontendTests.scanTest(frontendMap[scan.frontendId], FrontendScanType::SCAN_BLIND);
 }
 
 TEST_P(TunerLnbHidlTest, SendDiseqcMessageToLnb) {
     description("Open and configure an Lnb with specific settings then send a diseqc msg to it.");
-    vector<uint32_t> ids;
-    ASSERT_TRUE(mLnbTests.getLnbIds(ids));
-    if (!lnbArray[LNB0].usingLnb) {
-        return;
+    if (lnbMap[lnbLive.lnbId].name.compare(emptyHardwareId) == 0) {
+        vector<uint32_t> ids;
+        ASSERT_TRUE(mLnbTests.getLnbIds(ids));
+        ASSERT_TRUE(ids.size() > 0);
+        ASSERT_TRUE(mLnbTests.openLnbById(ids[0]));
+    } else {
+        uint32_t id;
+        ASSERT_TRUE(mLnbTests.openLnbByName(lnbMap[lnbLive.lnbId].name, id));
     }
-    ASSERT_TRUE(ids.size() > 0);
-    ASSERT_TRUE(mLnbTests.openLnbById(ids[0]));
     ASSERT_TRUE(mLnbTests.setLnbCallback());
-    ASSERT_TRUE(mLnbTests.setVoltage(lnbArray[LNB0].voltage));
-    ASSERT_TRUE(mLnbTests.setTone(lnbArray[LNB0].tone));
-    ASSERT_TRUE(mLnbTests.setSatellitePosition(lnbArray[LNB0].position));
-    ASSERT_TRUE(mLnbTests.sendDiseqcMessage(diseqcMsgArray[DISEQC_POWER_ON]));
+    ASSERT_TRUE(mLnbTests.setVoltage(lnbMap[lnbLive.lnbId].voltage));
+    ASSERT_TRUE(mLnbTests.setTone(lnbMap[lnbLive.lnbId].tone));
+    ASSERT_TRUE(mLnbTests.setSatellitePosition(lnbMap[lnbLive.lnbId].position));
+    for (auto msgName : lnbLive.diseqcMsgs) {
+        ASSERT_TRUE(mLnbTests.sendDiseqcMessage(diseqcMsgMap[msgName]));
+    }
     ASSERT_TRUE(mLnbTests.closeLnb());
 }
 
@@ -383,7 +373,7 @@
     uint32_t feId;
     uint32_t demuxId;
     sp<IDemux> demux;
-    mFrontendTests.getFrontendIdByType(frontendArray[defaultFrontend].type, feId);
+    mFrontendTests.getFrontendIdByType(frontendMap[live.frontendId].type, feId);
     ASSERT_TRUE(feId != INVALID_ID);
     ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
     ASSERT_TRUE(mFrontendTests.setFrontendCallback());
@@ -395,6 +385,9 @@
 
 TEST_P(TunerDemuxHidlTest, getAvSyncTime) {
     description("Get the A/V sync time from a PCR filter.");
+    if (live.pcrFilterId.compare(emptyHardwareId) == 0) {
+        return;
+    }
     uint32_t feId;
     uint32_t demuxId;
     sp<IDemux> demux;
@@ -403,22 +396,22 @@
     uint32_t avSyncHwId;
     sp<IFilter> mediaFilter;
 
-    mFrontendTests.getFrontendIdByType(frontendArray[defaultFrontend].type, feId);
+    mFrontendTests.getFrontendIdByType(frontendMap[live.frontendId].type, feId);
     ASSERT_TRUE(feId != INVALID_ID);
     ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
     ASSERT_TRUE(mFrontendTests.setFrontendCallback());
     ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
     ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
     mFilterTests.setDemux(demux);
-    ASSERT_TRUE(mFilterTests.openFilterInDemux(filterArray[TS_VIDEO1].type,
-                                               filterArray[TS_VIDEO1].bufferSize));
+    ASSERT_TRUE(mFilterTests.openFilterInDemux(filterMap[live.videoFilterId].type,
+                                               filterMap[live.videoFilterId].bufferSize));
     ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(mediaFilterId));
-    ASSERT_TRUE(mFilterTests.configFilter(filterArray[TS_VIDEO1].settings, mediaFilterId));
+    ASSERT_TRUE(mFilterTests.configFilter(filterMap[live.videoFilterId].settings, mediaFilterId));
     mediaFilter = mFilterTests.getFilterById(mediaFilterId);
-    ASSERT_TRUE(mFilterTests.openFilterInDemux(filterArray[TS_PCR0].type,
-                                               filterArray[TS_PCR0].bufferSize));
+    ASSERT_TRUE(mFilterTests.openFilterInDemux(filterMap[live.pcrFilterId].type,
+                                               filterMap[live.pcrFilterId].bufferSize));
     ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(pcrFilterId));
-    ASSERT_TRUE(mFilterTests.configFilter(filterArray[TS_PCR0].settings, pcrFilterId));
+    ASSERT_TRUE(mFilterTests.configFilter(filterMap[live.pcrFilterId].settings, pcrFilterId));
     ASSERT_TRUE(mDemuxTests.getAvSyncId(mediaFilter, avSyncHwId));
     ASSERT_TRUE(pcrFilterId == avSyncHwId);
     ASSERT_TRUE(mDemuxTests.getAvSyncTime(pcrFilterId));
@@ -431,7 +424,7 @@
 TEST_P(TunerFilterHidlTest, StartFilterInDemux) {
     description("Open and start a filter in Demux.");
     // TODO use paramterized tests
-    configSingleFilterInDemuxTest(filterArray[TS_VIDEO0], frontendArray[defaultFrontend]);
+    configSingleFilterInDemuxTest(filterMap[live.videoFilterId], frontendMap[live.frontendId]);
 }
 
 TEST_P(TunerFilterHidlTest, SetFilterLinkage) {
@@ -448,11 +441,9 @@
             if (caps.linkCaps[i] & (bitMask << j)) {
                 uint32_t sourceFilterId;
                 uint32_t sinkFilterId;
-                ASSERT_TRUE(mFilterTests.openFilterInDemux(filterLinkageTypes[SOURCE][i],
-                                                           FMQ_SIZE_16M));
+                ASSERT_TRUE(mFilterTests.openFilterInDemux(getLinkageFilterType(i), FMQ_SIZE_16M));
                 ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(sourceFilterId));
-                ASSERT_TRUE(
-                        mFilterTests.openFilterInDemux(filterLinkageTypes[SINK][j], FMQ_SIZE_16M));
+                ASSERT_TRUE(mFilterTests.openFilterInDemux(getLinkageFilterType(j), FMQ_SIZE_16M));
                 ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(sinkFilterId));
                 ASSERT_TRUE(mFilterTests.setFilterDataSource(sourceFilterId, sinkFilterId));
                 ASSERT_TRUE(mFilterTests.setFilterDataSourceToDemux(sinkFilterId));
@@ -467,120 +458,87 @@
 TEST_P(TunerFilterHidlTest, testTimeFilter) {
     description("Open a timer filter in Demux and set time stamp.");
     // TODO use paramterized tests
-    testTimeFilter(timeFilterArray[TIMER0]);
+    testTimeFilter(timeFilterMap[timeFilter.timeFilterId]);
 }
 
 TEST_P(TunerBroadcastHidlTest, BroadcastDataFlowVideoFilterTest) {
     description("Test Video Filter functionality in Broadcast use case.");
-    broadcastSingleFilterTest(filterArray[TS_VIDEO1], frontendArray[defaultFrontend]);
+    broadcastSingleFilterTest(filterMap[live.videoFilterId], frontendMap[live.frontendId]);
 }
 
 TEST_P(TunerBroadcastHidlTest, BroadcastDataFlowAudioFilterTest) {
     description("Test Audio Filter functionality in Broadcast use case.");
-    broadcastSingleFilterTest(filterArray[TS_AUDIO0], frontendArray[defaultFrontend]);
+    broadcastSingleFilterTest(filterMap[live.audioFilterId], frontendMap[live.frontendId]);
 }
 
 TEST_P(TunerBroadcastHidlTest, BroadcastDataFlowSectionFilterTest) {
     description("Test Section Filter functionality in Broadcast use case.");
-    broadcastSingleFilterTest(filterArray[TS_SECTION0], frontendArray[defaultFrontend]);
+    if (live.sectionFilterId.compare(emptyHardwareId) == 0) {
+        return;
+    }
+    broadcastSingleFilterTest(filterMap[live.sectionFilterId], frontendMap[live.frontendId]);
 }
 
 TEST_P(TunerBroadcastHidlTest, IonBufferTest) {
     description("Test the av filter data bufferring.");
-    broadcastSingleFilterTest(filterArray[TS_VIDEO0], frontendArray[defaultFrontend]);
+    broadcastSingleFilterTest(filterMap[live.videoFilterId], frontendMap[live.frontendId]);
 }
 
 TEST_P(TunerBroadcastHidlTest, LnbBroadcastDataFlowVideoFilterTest) {
     description("Test Video Filter functionality in Broadcast with Lnb use case.");
-    broadcastSingleFilterTest(filterArray[TS_VIDEO0], frontendArray[DVBS]);
-}
-
-TEST_P(TunerBroadcastHidlTest, BroadcastEsDataFlowMediaFiltersTest) {
-    description("Test Meida Filters functionality in Broadcast use case with ES input.");
-    uint32_t feId;
-    uint32_t demuxId;
-    sp<IDemux> demux;
-    uint32_t filterId;
-
-    mFrontendTests.getFrontendIdByType(frontendArray[defaultFrontend].type, feId);
-    if (feId == INVALID_ID) {
-        // TODO broadcast test on Cuttlefish needs licensed ts input,
-        // these tests are runnable on vendor device with real frontend module
-        // or with manual ts installing and use defaultFrontend frontend.
+    if (!lnbLive.support) {
         return;
     }
-    ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
-    ASSERT_TRUE(mFrontendTests.setFrontendCallback());
-    ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
-    ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
-    mFrontendTests.setDemux(demux);
-    mFilterTests.setDemux(demux);
-    ASSERT_TRUE(mFilterTests.openFilterInDemux(filterArray[TS_AUDIO1].type,
-                                               filterArray[TS_AUDIO1].bufferSize));
-    ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(filterId));
-    ASSERT_TRUE(mFilterTests.configFilter(filterArray[TS_AUDIO1].settings, filterId));
-    ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId, filterArray[TS_AUDIO1].getMqDesc));
-    ASSERT_TRUE(mFilterTests.startFilter(filterId));
-    ASSERT_TRUE(mFilterTests.openFilterInDemux(filterArray[TS_VIDEO1].type,
-                                               filterArray[TS_VIDEO1].bufferSize));
-    ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(filterId));
-    ASSERT_TRUE(mFilterTests.configFilter(filterArray[TS_VIDEO1].settings, filterId));
-    ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId, filterArray[TS_VIDEO1].getMqDesc));
-    ASSERT_TRUE(mFilterTests.startFilter(filterId));
-    // tune test
-    PlaybackSettings playbackSettings{
-            .statusMask = 0xf,
-            .lowThreshold = 0x1000,
-            .highThreshold = 0x07fff,
-            .dataFormat = DataFormat::ES,
-            .packetSize = 188,
-    };
-    DvrConfig dvrConfig{
-            .type = DvrType::PLAYBACK,
-            .playbackInputFile = "/data/local/tmp/test.es",
-            .bufferSize = FMQ_SIZE_4M,
-    };
-    dvrConfig.settings.playback(playbackSettings);
-    mFrontendTests.setSoftwareFrontendDvrConfig(dvrConfig);
-    ASSERT_TRUE(
-            mFrontendTests.tuneFrontend(frontendArray[defaultFrontend], true /*testWithDemux*/));
-    ASSERT_TRUE(filterDataOutputTest(goldenOutputFiles));
-    ASSERT_TRUE(mFrontendTests.stopTuneFrontend(true /*testWithDemux*/));
-    ASSERT_TRUE(mFilterTests.stopFilter(filterId));
-    ASSERT_TRUE(mFilterTests.closeFilter(filterId));
-    ASSERT_TRUE(mDemuxTests.closeDemux());
-    ASSERT_TRUE(mFrontendTests.closeFrontend());
+    broadcastSingleFilterTestWithLnb(filterMap[lnbLive.videoFilterId],
+                                     frontendMap[lnbLive.frontendId], lnbMap[lnbLive.lnbId]);
 }
 
 TEST_P(TunerPlaybackHidlTest, PlaybackDataFlowWithTsSectionFilterTest) {
     description("Feed ts data from playback and configure Ts section filter to get output");
-    playbackSingleFilterTest(filterArray[TS_SECTION0], dvrArray[DVR_PLAYBACK0]);
+    if (!playback.support || playback.sectionFilterId.compare(emptyHardwareId) == 0) {
+        return;
+    }
+    playbackSingleFilterTest(filterMap[playback.sectionFilterId], dvrMap[playback.dvrId]);
 }
 
 TEST_P(TunerRecordHidlTest, AttachFiltersToRecordTest) {
     description("Attach a single filter to the record dvr test.");
     // TODO use paramterized tests
-    attachSingleFilterToRecordDvrTest(filterArray[TS_RECORD0], frontendArray[defaultFrontend],
-                                      dvrArray[DVR_RECORD0]);
+    if (!record.support) {
+        return;
+    }
+    attachSingleFilterToRecordDvrTest(filterMap[record.recordFilterId],
+                                      frontendMap[record.frontendId], dvrMap[record.dvrRecordId]);
 }
 
 TEST_P(TunerRecordHidlTest, RecordDataFlowWithTsRecordFilterTest) {
     description("Feed ts data from frontend to recording and test with ts record filter");
-    recordSingleFilterTest(filterArray[TS_RECORD0], frontendArray[defaultFrontend],
-                           dvrArray[DVR_RECORD0]);
+    if (!record.support) {
+        return;
+    }
+    recordSingleFilterTest(filterMap[record.recordFilterId], frontendMap[record.frontendId],
+                           dvrMap[record.dvrRecordId]);
 }
 
 TEST_P(TunerRecordHidlTest, LnbRecordDataFlowWithTsRecordFilterTest) {
     description("Feed ts data from Fe with Lnb to recording and test with ts record filter");
-    recordSingleFilterTest(filterArray[TS_RECORD0], frontendArray[DVBS], dvrArray[DVR_RECORD0]);
+    if (lnbRecord.support) {
+        return;
+    }
+    recordSingleFilterTestWithLnb(filterMap[lnbRecord.recordFilterId],
+                                  frontendMap[lnbRecord.frontendId], dvrMap[lnbRecord.dvrRecordId],
+                                  lnbMap[lnbRecord.lnbId]);
 }
 
 TEST_P(TunerDescramblerHidlTest, CreateDescrambler) {
     description("Create Descrambler");
+    if (descrambling.support) {
+        return;
+    }
     uint32_t feId;
     uint32_t demuxId;
     sp<IDemux> demux;
-    mFrontendTests.getFrontendIdByType(frontendArray[defaultFrontend].type, feId);
+    mFrontendTests.getFrontendIdByType(frontendMap[descrambling.frontendId].type, feId);
     ASSERT_TRUE(feId != INVALID_ID);
     ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
     ASSERT_TRUE(mFrontendTests.setFrontendCallback());
@@ -594,10 +552,14 @@
 
 TEST_P(TunerDescramblerHidlTest, ScrambledBroadcastDataFlowMediaFiltersTest) {
     description("Test ts audio filter in scrambled broadcast use case");
+    if (descrambling.support) {
+        return;
+    }
     set<FilterConfig> filterConfs;
-    filterConfs.insert(filterArray[TS_AUDIO0]);
-    filterConfs.insert(filterArray[TS_VIDEO1]);
-    scrambledBroadcastTest(filterConfs, frontendArray[defaultFrontend], descramblerArray[DESC_0]);
+    filterConfs.insert(static_cast<FilterConfig>(filterMap[descrambling.audioFilterId]));
+    filterConfs.insert(static_cast<FilterConfig>(filterMap[descrambling.videoFilterId]));
+    scrambledBroadcastTest(filterConfs, frontendMap[descrambling.frontendId],
+                           descramblerMap[descrambling.descramblerId]);
 }
 
 INSTANTIATE_TEST_SUITE_P(
diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h
index 5a23ca5..e240604 100644
--- a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h
+++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h
@@ -20,6 +20,9 @@
 #include "LnbTests.h"
 
 using android::hardware::tv::tuner::V1_0::DataFormat;
+using android::hardware::tv::tuner::V1_0::DemuxAlpFilterType;
+using android::hardware::tv::tuner::V1_0::DemuxMmtpFilterType;
+using android::hardware::tv::tuner::V1_0::DemuxTlvFilterType;
 using android::hardware::tv::tuner::V1_0::IDescrambler;
 
 static AssertionResult success() {
@@ -28,14 +31,22 @@
 
 namespace {
 
-void initConfiguration() {
+bool initConfiguration() {
+    if (!TunerTestingConfigReader::checkConfigFileExists()) {
+        return false;
+    }
     initFrontendConfig();
-    initFrontendScanConfig();
-    initLnbConfig();
     initFilterConfig();
-    initTimeFilterConfig();
     initDvrConfig();
+    initLnbConfig();
+    initTimeFilterConfig();
     initDescramblerConfig();
+    connectHardwaresToTestCases();
+    if (!validateConnections()) {
+        ALOGW("[vts] failed to validate connections.");
+        return false;
+    }
+    return true;
 }
 
 AssertionResult filterDataOutputTestBase(FilterTests tests) {
@@ -53,7 +64,7 @@
     virtual void SetUp() override {
         mService = ITuner::getService(GetParam());
         ASSERT_NE(mService, nullptr);
-        initConfiguration();
+        ASSERT_TRUE(initConfiguration());
 
         mFrontendTests.setService(mService);
     }
@@ -75,7 +86,7 @@
     virtual void SetUp() override {
         mService = ITuner::getService(GetParam());
         ASSERT_NE(mService, nullptr);
-        initConfiguration();
+        ASSERT_TRUE(initConfiguration());
 
         mLnbTests.setService(mService);
     }
@@ -97,7 +108,7 @@
     virtual void SetUp() override {
         mService = ITuner::getService(GetParam());
         ASSERT_NE(mService, nullptr);
-        initConfiguration();
+        ASSERT_TRUE(initConfiguration());
 
         mFrontendTests.setService(mService);
         mDemuxTests.setService(mService);
@@ -123,7 +134,7 @@
     virtual void SetUp() override {
         mService = ITuner::getService(GetParam());
         ASSERT_NE(mService, nullptr);
-        initConfiguration();
+        ASSERT_TRUE(initConfiguration());
 
         mFrontendTests.setService(mService);
         mDemuxTests.setService(mService);
@@ -138,6 +149,29 @@
     void configSingleFilterInDemuxTest(FilterConfig filterConf, FrontendConfig frontendConf);
     void testTimeFilter(TimeFilterConfig filterConf);
 
+    DemuxFilterType getLinkageFilterType(int bit) {
+        DemuxFilterType type;
+        type.mainType = static_cast<DemuxFilterMainType>(1 << bit);
+        switch (type.mainType) {
+            case DemuxFilterMainType::TS:
+                type.subType.tsFilterType(DemuxTsFilterType::UNDEFINED);
+                break;
+            case DemuxFilterMainType::MMTP:
+                type.subType.mmtpFilterType(DemuxMmtpFilterType::UNDEFINED);
+                break;
+            case DemuxFilterMainType::IP:
+                type.subType.ipFilterType(DemuxIpFilterType::UNDEFINED);
+                break;
+            case DemuxFilterMainType::TLV:
+                type.subType.tlvFilterType(DemuxTlvFilterType::UNDEFINED);
+                break;
+            case DemuxFilterMainType::ALP:
+                type.subType.alpFilterType(DemuxAlpFilterType::UNDEFINED);
+                break;
+        }
+        return type;
+    }
+
     sp<ITuner> mService;
     FrontendTests mFrontendTests;
     DemuxTests mDemuxTests;
@@ -152,7 +186,7 @@
     virtual void SetUp() override {
         mService = ITuner::getService(GetParam());
         ASSERT_NE(mService, nullptr);
-        initConfiguration();
+        ASSERT_TRUE(initConfiguration());
 
         mFrontendTests.setService(mService);
         mDemuxTests.setService(mService);
@@ -173,7 +207,7 @@
     LnbTests mLnbTests;
     DvrTests mDvrTests;
 
-    AssertionResult filterDataOutputTest(vector<string> goldenOutputFiles);
+    AssertionResult filterDataOutputTest();
 
     void broadcastSingleFilterTest(FilterConfig filterConf, FrontendConfig frontendConf);
     void broadcastSingleFilterTestWithLnb(FilterConfig filterConf, FrontendConfig frontendConf,
@@ -191,7 +225,7 @@
     virtual void SetUp() override {
         mService = ITuner::getService(GetParam());
         ASSERT_NE(mService, nullptr);
-        initConfiguration();
+        ASSERT_TRUE(initConfiguration());
 
         mFrontendTests.setService(mService);
         mDemuxTests.setService(mService);
@@ -210,7 +244,7 @@
     FilterTests mFilterTests;
     DvrTests mDvrTests;
 
-    AssertionResult filterDataOutputTest(vector<string> goldenOutputFiles);
+    AssertionResult filterDataOutputTest();
 
     void playbackSingleFilterTest(FilterConfig filterConf, DvrConfig dvrConf);
 };
@@ -223,7 +257,7 @@
     virtual void SetUp() override {
         mService = ITuner::getService(GetParam());
         ASSERT_NE(mService, nullptr);
-        initConfiguration();
+        ASSERT_TRUE(initConfiguration());
 
         mFrontendTests.setService(mService);
         mDemuxTests.setService(mService);
@@ -265,7 +299,7 @@
         mCasService = IMediaCasService::getService();
         ASSERT_NE(mService, nullptr);
         ASSERT_NE(mCasService, nullptr);
-        initConfiguration();
+        ASSERT_TRUE(initConfiguration());
 
         mFrontendTests.setService(mService);
         mDemuxTests.setService(mService);
@@ -281,7 +315,7 @@
 
     void scrambledBroadcastTest(set<struct FilterConfig> mediaFilterConfs,
                                 FrontendConfig frontendConf, DescramblerConfig descConfig);
-    AssertionResult filterDataOutputTest(vector<string> /*goldenOutputFiles*/);
+    AssertionResult filterDataOutputTest();
 
     sp<ITuner> mService;
     sp<IMediaCasService> mCasService;
diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h
index 834e296..65f8615 100644
--- a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h
+++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h
@@ -21,366 +21,224 @@
 #include <hidl/Status.h>
 #include <hidlmemory/FrameworkUtils.h>
 
-using android::hardware::tv::tuner::V1_0::DataFormat;
-using android::hardware::tv::tuner::V1_0::DemuxAlpFilterType;
-using android::hardware::tv::tuner::V1_0::DemuxFilterEvent;
+#include "../../../config/TunerTestingConfigReader.h"
+
 using android::hardware::tv::tuner::V1_0::DemuxFilterMainType;
-using android::hardware::tv::tuner::V1_0::DemuxFilterSettings;
-using android::hardware::tv::tuner::V1_0::DemuxFilterType;
-using android::hardware::tv::tuner::V1_0::DemuxIpFilterType;
-using android::hardware::tv::tuner::V1_0::DemuxMmtpFilterType;
-using android::hardware::tv::tuner::V1_0::DemuxRecordScIndexType;
-using android::hardware::tv::tuner::V1_0::DemuxTlvFilterType;
-using android::hardware::tv::tuner::V1_0::DemuxTpid;
 using android::hardware::tv::tuner::V1_0::DemuxTsFilterType;
-using android::hardware::tv::tuner::V1_0::DvrSettings;
-using android::hardware::tv::tuner::V1_0::DvrType;
 using android::hardware::tv::tuner::V1_0::FrontendDvbtBandwidth;
-using android::hardware::tv::tuner::V1_0::FrontendDvbtCoderate;
-using android::hardware::tv::tuner::V1_0::FrontendDvbtConstellation;
-using android::hardware::tv::tuner::V1_0::FrontendDvbtGuardInterval;
-using android::hardware::tv::tuner::V1_0::FrontendDvbtHierarchy;
 using android::hardware::tv::tuner::V1_0::FrontendDvbtSettings;
-using android::hardware::tv::tuner::V1_0::FrontendDvbtStandard;
 using android::hardware::tv::tuner::V1_0::FrontendDvbtTransmissionMode;
 using android::hardware::tv::tuner::V1_0::FrontendSettings;
 using android::hardware::tv::tuner::V1_0::FrontendStatus;
 using android::hardware::tv::tuner::V1_0::FrontendStatusType;
 using android::hardware::tv::tuner::V1_0::FrontendType;
-using android::hardware::tv::tuner::V1_0::LnbPosition;
-using android::hardware::tv::tuner::V1_0::LnbTone;
-using android::hardware::tv::tuner::V1_0::LnbVoltage;
-using android::hardware::tv::tuner::V1_0::PlaybackSettings;
-using android::hardware::tv::tuner::V1_0::RecordSettings;
 
 using namespace std;
+using namespace android::media::tuner::testing::configuration::V1_0;
 
-const uint32_t FMQ_SIZE_512K = 0x80000;
-const uint32_t FMQ_SIZE_1M = 0x100000;
 const uint32_t FMQ_SIZE_4M = 0x400000;
 const uint32_t FMQ_SIZE_16M = 0x1000000;
 
-#define CLEAR_KEY_SYSTEM_ID 0xF6D8
-#define FILTER_MAIN_TYPE_BIT_COUNT 32
-#define PROVISION_STR                                      \
-    "{                                                   " \
-    "  \"id\": 21140844,                                 " \
-    "  \"name\": \"Test Title\",                         " \
-    "  \"lowercase_organization_name\": \"Android\",     " \
-    "  \"asset_key\": {                                  " \
-    "  \"encryption_key\": \"nezAr3CHFrmBR9R8Tedotw==\"  " \
-    "  },                                                " \
-    "  \"cas_type\": 1,                                  " \
-    "  \"track_types\": [ ]                              " \
-    "}                                                   "
+#define FILTER_MAIN_TYPE_BIT_COUNT 5
 
-typedef enum {
-    TS_VIDEO0,
-    TS_VIDEO1,
-    TS_AUDIO0,
-    TS_AUDIO1,
-    TS_PES0,
-    TS_PCR0,
-    TS_SECTION0,
-    TS_TS0,
-    TS_RECORD0,
-    FILTER_MAX,
-} Filter;
+// Hardware configs
+static map<string, FrontendConfig> frontendMap;
+static map<string, FilterConfig> filterMap;
+static map<string, DvrConfig> dvrMap;
+static map<string, LnbConfig> lnbMap;
+static map<string, TimeFilterConfig> timeFilterMap;
+static map<string, vector<uint8_t>> diseqcMsgMap;
+static map<string, DescramblerConfig> descramblerMap;
 
-typedef enum {
-    TIMER0,
-    TIMER_MAX,
-} TimeFilter;
+// Hardware and test cases connections
+static LiveBroadcastHardwareConnections live;
+static ScanHardwareConnections scan;
+static DvrPlaybackHardwareConnections playback;
+static DvrRecordHardwareConnections record;
+static DescramblingHardwareConnections descrambling;
+static LnbLiveHardwareConnections lnbLive;
+static LnbRecordHardwareConnections lnbRecord;
+static TimeFilterHardwareConnections timeFilter;
 
-typedef enum {
-    SOURCE,
-    SINK,
-    LINKAGE_DIR,
-} Linkage;
-
-typedef enum {
-    DVBT,
-    DVBS,
-    FRONTEND_MAX,
-} Frontend;
-
-typedef enum {
-    LNB0,
-    LNB_EXTERNAL,
-    LNB_MAX,
-} Lnb;
-
-typedef enum {
-    DISEQC_POWER_ON,
-    DISEQC_MAX,
-} Diseqc;
-
-typedef enum {
-    SCAN_DVBT,
-    SCAN_MAX,
-} FrontendScan;
-
-typedef enum {
-    DVR_RECORD0,
-    DVR_PLAYBACK0,
-    DVR_MAX,
-} Dvr;
-
-typedef enum {
-    DESC_0,
-    DESC_MAX,
-} Descrambler;
-
-struct FilterConfig {
-    uint32_t bufferSize;
-    DemuxFilterType type;
-    DemuxFilterSettings settings;
-    bool getMqDesc;
-
-    bool operator<(const FilterConfig& /*c*/) const { return false; }
-};
-
-struct TimeFilterConfig {
-    bool supportTimeFilter;
-    uint64_t timeStamp;
-};
-
-struct FrontendConfig {
-    bool enable;
-    bool isSoftwareFe;
-    FrontendType type;
-    FrontendSettings settings;
-    vector<FrontendStatusType> tuneStatusTypes;
-    vector<FrontendStatus> expectTuneStatuses;
-};
-
-struct LnbConfig {
-    bool usingLnb;
-    string name;
-    LnbVoltage voltage;
-    LnbTone tone;
-    LnbPosition position;
-};
-
-struct ChannelConfig {
-    int32_t frontendId;
-    int32_t channelId;
-    std::string channelName;
-    DemuxTpid videoPid;
-    DemuxTpid audioPid;
-};
-
-struct DvrConfig {
-    DvrType type;
-    uint32_t bufferSize;
-    DvrSettings settings;
-    string playbackInputFile;
-};
-
-struct DescramblerConfig {
-    uint32_t casSystemId;
-    string provisionStr;
-    vector<uint8_t> hidlPvtData;
-};
-
-static FrontendConfig frontendArray[FILTER_MAX];
-static FrontendConfig frontendScanArray[SCAN_MAX];
-static LnbConfig lnbArray[LNB_MAX];
-static vector<uint8_t> diseqcMsgArray[DISEQC_MAX];
-static ChannelConfig channelArray[FRONTEND_MAX];
-static FilterConfig filterArray[FILTER_MAX];
-static TimeFilterConfig timeFilterArray[TIMER_MAX];
-static DemuxFilterType filterLinkageTypes[LINKAGE_DIR][FILTER_MAIN_TYPE_BIT_COUNT];
-static DvrConfig dvrArray[DVR_MAX];
-static DescramblerConfig descramblerArray[DESC_MAX];
-static vector<string> goldenOutputFiles;
-static int defaultFrontend = DVBT;
-static int defaultScanFrontend = SCAN_DVBT;
-
-/** Configuration array for the frontend tune test */
+/** Config all the frontends that would be used in the tests */
 inline void initFrontendConfig() {
+    // The test will use the internal default fe when default fe is connected to any data flow
+    // without overriding in the xml config.
+    string defaultFeId = "FE_DEFAULT";
     FrontendDvbtSettings dvbtSettings{
             .frequency = 578000,
             .transmissionMode = FrontendDvbtTransmissionMode::AUTO,
             .bandwidth = FrontendDvbtBandwidth::BANDWIDTH_8MHZ,
-            .constellation = FrontendDvbtConstellation::AUTO,
-            .hierarchy = FrontendDvbtHierarchy::AUTO,
-            .hpCoderate = FrontendDvbtCoderate::AUTO,
-            .lpCoderate = FrontendDvbtCoderate::AUTO,
-            .guardInterval = FrontendDvbtGuardInterval::AUTO,
             .isHighPriority = true,
-            .standard = FrontendDvbtStandard::T,
     };
-    frontendArray[DVBT].type = FrontendType::DVBT, frontendArray[DVBT].settings.dvbt(dvbtSettings);
+    frontendMap[defaultFeId].type = FrontendType::DVBT;
+    frontendMap[defaultFeId].settings.dvbt(dvbtSettings);
+
     vector<FrontendStatusType> types;
     types.push_back(FrontendStatusType::DEMOD_LOCK);
     FrontendStatus status;
     status.isDemodLocked(true);
     vector<FrontendStatus> statuses;
     statuses.push_back(status);
-    frontendArray[DVBT].tuneStatusTypes = types;
-    frontendArray[DVBT].expectTuneStatuses = statuses;
-    frontendArray[DVBT].isSoftwareFe = true;
-    frontendArray[DVBT].enable = true;
-    frontendArray[DVBS].type = FrontendType::DVBS;
-    frontendArray[DVBS].enable = true;
-    frontendArray[DVBS].isSoftwareFe = true;
+    frontendMap[defaultFeId].tuneStatusTypes = types;
+    frontendMap[defaultFeId].expectTuneStatuses = statuses;
+    frontendMap[defaultFeId].isSoftwareFe = true;
+
+    // Read customized config
+    TunerTestingConfigReader::readFrontendConfig1_0(frontendMap);
 };
 
-/** Configuration array for the frontend scan test */
-inline void initFrontendScanConfig() {
-    frontendScanArray[SCAN_DVBT].type = FrontendType::DVBT;
-    frontendScanArray[SCAN_DVBT].settings.dvbt({
-            .frequency = 578000,
-            .transmissionMode = FrontendDvbtTransmissionMode::MODE_8K,
-            .bandwidth = FrontendDvbtBandwidth::BANDWIDTH_8MHZ,
-            .constellation = FrontendDvbtConstellation::AUTO,
-            .hierarchy = FrontendDvbtHierarchy::AUTO,
-            .hpCoderate = FrontendDvbtCoderate::AUTO,
-            .lpCoderate = FrontendDvbtCoderate::AUTO,
-            .guardInterval = FrontendDvbtGuardInterval::AUTO,
-            .isHighPriority = true,
-            .standard = FrontendDvbtStandard::T,
-    });
-};
-
-/** Configuration array for the Lnb test */
-inline void initLnbConfig() {
-    lnbArray[LNB0].usingLnb = true;
-    lnbArray[LNB0].voltage = LnbVoltage::VOLTAGE_12V;
-    lnbArray[LNB0].tone = LnbTone::NONE;
-    lnbArray[LNB0].position = LnbPosition::UNDEFINED;
-    lnbArray[LNB_EXTERNAL].usingLnb = true;
-    lnbArray[LNB_EXTERNAL].name = "default_lnb_external";
-    lnbArray[LNB_EXTERNAL].voltage = LnbVoltage::VOLTAGE_5V;
-    lnbArray[LNB_EXTERNAL].tone = LnbTone::NONE;
-    lnbArray[LNB_EXTERNAL].position = LnbPosition::UNDEFINED;
-};
-
-/** Diseqc messages array for the Lnb test */
-inline void initDiseqcMsg() {
-    diseqcMsgArray[DISEQC_POWER_ON] = {0xE, 0x0, 0x0, 0x0, 0x0, 0x3};
-};
-
-/** Configuration array for the filter test */
 inline void initFilterConfig() {
-    // TS VIDEO filter setting for default implementation testing
-    filterArray[TS_VIDEO0].type.mainType = DemuxFilterMainType::TS;
-    filterArray[TS_VIDEO0].type.subType.tsFilterType(DemuxTsFilterType::VIDEO);
-    filterArray[TS_VIDEO0].bufferSize = FMQ_SIZE_16M;
-    filterArray[TS_VIDEO0].settings.ts().tpid = 256;
-    filterArray[TS_VIDEO0].settings.ts().filterSettings.av({.isPassthrough = false});
-    filterArray[TS_VIDEO1].type.mainType = DemuxFilterMainType::TS;
-    filterArray[TS_VIDEO1].type.subType.tsFilterType(DemuxTsFilterType::VIDEO);
-    filterArray[TS_VIDEO1].bufferSize = FMQ_SIZE_16M;
-    filterArray[TS_VIDEO1].settings.ts().tpid = 256;
-    filterArray[TS_VIDEO1].settings.ts().filterSettings.av({.isPassthrough = false});
-    // TS AUDIO filter setting
-    filterArray[TS_AUDIO0].type.mainType = DemuxFilterMainType::TS;
-    filterArray[TS_AUDIO0].type.subType.tsFilterType(DemuxTsFilterType::AUDIO);
-    filterArray[TS_AUDIO0].bufferSize = FMQ_SIZE_16M;
-    filterArray[TS_AUDIO0].settings.ts().tpid = 256;
-    filterArray[TS_AUDIO0].settings.ts().filterSettings.av({.isPassthrough = false});
-    filterArray[TS_AUDIO1].type.mainType = DemuxFilterMainType::TS;
-    filterArray[TS_AUDIO1].type.subType.tsFilterType(DemuxTsFilterType::AUDIO);
-    filterArray[TS_AUDIO1].bufferSize = FMQ_SIZE_16M;
-    filterArray[TS_AUDIO1].settings.ts().tpid = 257;
-    filterArray[TS_AUDIO1].settings.ts().filterSettings.av({.isPassthrough = false});
-    // TS PES filter setting
-    filterArray[TS_PES0].type.mainType = DemuxFilterMainType::TS;
-    filterArray[TS_PES0].type.subType.tsFilterType(DemuxTsFilterType::PES);
-    filterArray[TS_PES0].bufferSize = FMQ_SIZE_16M;
-    filterArray[TS_PES0].settings.ts().tpid = 256;
-    filterArray[TS_PES0].settings.ts().filterSettings.pesData({
-            .isRaw = false,
-            .streamId = 0xbd,
-    });
-    filterArray[TS_PES0].getMqDesc = true;
-    // TS PCR filter setting
-    filterArray[TS_PCR0].type.mainType = DemuxFilterMainType::TS;
-    filterArray[TS_PCR0].type.subType.tsFilterType(DemuxTsFilterType::PCR);
-    filterArray[TS_PCR0].bufferSize = FMQ_SIZE_16M;
-    filterArray[TS_PCR0].settings.ts().tpid = 256;
-    filterArray[TS_PCR0].settings.ts().filterSettings.noinit();
-    // TS filter setting
-    filterArray[TS_TS0].type.mainType = DemuxFilterMainType::TS;
-    filterArray[TS_TS0].type.subType.tsFilterType(DemuxTsFilterType::TS);
-    filterArray[TS_TS0].bufferSize = FMQ_SIZE_16M;
-    filterArray[TS_TS0].settings.ts().tpid = 256;
-    filterArray[TS_TS0].settings.ts().filterSettings.noinit();
-    // TS SECTION filter setting
-    filterArray[TS_SECTION0].type.mainType = DemuxFilterMainType::TS;
-    filterArray[TS_SECTION0].type.subType.tsFilterType(DemuxTsFilterType::SECTION);
-    filterArray[TS_SECTION0].bufferSize = FMQ_SIZE_16M;
-    filterArray[TS_SECTION0].settings.ts().tpid = 256;
-    filterArray[TS_SECTION0].settings.ts().filterSettings.section({
-            .isRaw = false,
-    });
-    filterArray[TS_SECTION0].getMqDesc = true;
-    // TS RECORD filter setting
-    filterArray[TS_RECORD0].type.mainType = DemuxFilterMainType::TS;
-    filterArray[TS_RECORD0].type.subType.tsFilterType(DemuxTsFilterType::RECORD);
-    filterArray[TS_RECORD0].settings.ts().tpid = 81;
-    filterArray[TS_RECORD0].settings.ts().filterSettings.record({
-            .scIndexType = DemuxRecordScIndexType::NONE,
-    });
+    // The test will use the internal default filter when default filter is connected to any
+    // data flow without overriding in the xml config.
+    string defaultAudioFilterId = "FILTER_AUDIO_DEFAULT";
+    string defaultVideoFilterId = "FILTER_VIDEO_DEFAULT";
 
-    // TS Linkage filter setting
-    filterLinkageTypes[SOURCE][0].mainType = DemuxFilterMainType::TS;
-    filterLinkageTypes[SOURCE][0].subType.tsFilterType(DemuxTsFilterType::TS);
-    filterLinkageTypes[SINK][0] = filterLinkageTypes[SOURCE][0];
-    // MMTP Linkage filter setting
-    filterLinkageTypes[SOURCE][1].mainType = DemuxFilterMainType::MMTP;
-    filterLinkageTypes[SOURCE][1].subType.mmtpFilterType(DemuxMmtpFilterType::AUDIO);
-    filterLinkageTypes[SINK][1] = filterLinkageTypes[SOURCE][1];
-    // IP Linkage filter setting
-    filterLinkageTypes[SOURCE][2].mainType = DemuxFilterMainType::IP;
-    filterLinkageTypes[SOURCE][2].subType.ipFilterType(DemuxIpFilterType::IP);
-    filterLinkageTypes[SINK][2] = filterLinkageTypes[SOURCE][2];
-    // TLV Linkage filter setting
-    filterLinkageTypes[SOURCE][3].mainType = DemuxFilterMainType::TLV;
-    filterLinkageTypes[SOURCE][3].subType.tlvFilterType(DemuxTlvFilterType::TLV);
-    filterLinkageTypes[SINK][3] = filterLinkageTypes[SOURCE][3];
-    // ALP Linkage PTP filter setting
-    filterLinkageTypes[SOURCE][4].mainType = DemuxFilterMainType::ALP;
-    filterLinkageTypes[SOURCE][4].subType.alpFilterType(DemuxAlpFilterType::PTP);
-    filterLinkageTypes[SINK][4] = filterLinkageTypes[SOURCE][4];
+    filterMap[defaultVideoFilterId].type.mainType = DemuxFilterMainType::TS;
+    filterMap[defaultVideoFilterId].type.subType.tsFilterType(DemuxTsFilterType::VIDEO);
+    filterMap[defaultVideoFilterId].bufferSize = FMQ_SIZE_16M;
+    filterMap[defaultVideoFilterId].settings.ts().tpid = 256;
+    filterMap[defaultVideoFilterId].settings.ts().filterSettings.av({.isPassthrough = false});
+
+    filterMap[defaultAudioFilterId].type.mainType = DemuxFilterMainType::TS;
+    filterMap[defaultAudioFilterId].type.subType.tsFilterType(DemuxTsFilterType::AUDIO);
+    filterMap[defaultAudioFilterId].bufferSize = FMQ_SIZE_16M;
+    filterMap[defaultAudioFilterId].settings.ts().tpid = 256;
+    filterMap[defaultAudioFilterId].settings.ts().filterSettings.av({.isPassthrough = false});
+
+    // Read customized config
+    TunerTestingConfigReader::readFilterConfig1_0(filterMap);
 };
 
-/** Configuration array for the timer filter test */
-inline void initTimeFilterConfig() {
-    timeFilterArray[TIMER0].supportTimeFilter = true;
-    timeFilterArray[TIMER0].timeStamp = 1;
-}
-
-/** Configuration array for the dvr test */
+/** Config all the dvrs that would be used in the tests */
 inline void initDvrConfig() {
-    RecordSettings recordSettings{
-            .statusMask = 0xf,
-            .lowThreshold = 0x1000,
-            .highThreshold = 0x07fff,
-            .dataFormat = DataFormat::TS,
-            .packetSize = 188,
-    };
-    dvrArray[DVR_RECORD0].type = DvrType::RECORD;
-    dvrArray[DVR_RECORD0].bufferSize = FMQ_SIZE_4M;
-    dvrArray[DVR_RECORD0].settings.record(recordSettings);
-    PlaybackSettings playbackSettings{
-            .statusMask = 0xf,
-            .lowThreshold = 0x1000,
-            .highThreshold = 0x07fff,
-            .dataFormat = DataFormat::TS,
-            .packetSize = 188,
-    };
-    dvrArray[DVR_PLAYBACK0].type = DvrType::PLAYBACK;
-    dvrArray[DVR_PLAYBACK0].playbackInputFile = "/data/local/tmp/segment000000.ts";
-    dvrArray[DVR_PLAYBACK0].bufferSize = FMQ_SIZE_4M;
-    dvrArray[DVR_PLAYBACK0].settings.playback(playbackSettings);
+    // Read customized config
+    TunerTestingConfigReader::readDvrConfig1_0(dvrMap);
 };
 
-/** Configuration array for the descrambler test */
-inline void initDescramblerConfig() {
-    descramblerArray[DESC_0].casSystemId = CLEAR_KEY_SYSTEM_ID;
-    descramblerArray[DESC_0].provisionStr = PROVISION_STR;
-    descramblerArray[DESC_0].hidlPvtData.resize(256);
+/** Config all the lnbs that would be used in the tests */
+inline void initLnbConfig() {
+    // Read customized config
+    TunerTestingConfigReader::readLnbConfig1_0(lnbMap);
+    TunerTestingConfigReader::readDiseqcMessages(diseqcMsgMap);
 };
+
+/** Config all the time filters that would be used in the tests */
+inline void initTimeFilterConfig() {
+    // Read customized config
+    TunerTestingConfigReader::readTimeFilterConfig1_0(timeFilterMap);
+};
+
+/** Config all the descramblers that would be used in the tests */
+inline void initDescramblerConfig() {
+    // Read customized config
+    TunerTestingConfigReader::readDescramblerConfig1_0(descramblerMap);
+};
+
+/** Read the vendor configurations of which hardware to use for each test cases/data flows */
+inline void connectHardwaresToTestCases() {
+    TunerTestingConfigReader::connectLiveBroadcast(live);
+    TunerTestingConfigReader::connectScan(scan);
+    TunerTestingConfigReader::connectDvrPlayback(playback);
+    TunerTestingConfigReader::connectDvrRecord(record);
+    TunerTestingConfigReader::connectDescrambling(descrambling);
+    TunerTestingConfigReader::connectLnbLive(lnbLive);
+    TunerTestingConfigReader::connectLnbRecord(lnbRecord);
+    TunerTestingConfigReader::connectTimeFilter(timeFilter);
+};
+
+inline bool validateConnections() {
+    bool feIsValid = frontendMap.find(live.frontendId) != frontendMap.end() &&
+                     frontendMap.find(scan.frontendId) != frontendMap.end();
+    feIsValid &= record.support ? frontendMap.find(record.frontendId) != frontendMap.end() : true;
+    feIsValid &= descrambling.support
+                         ? frontendMap.find(descrambling.frontendId) != frontendMap.end()
+                         : true;
+    feIsValid &= lnbLive.support ? frontendMap.find(lnbLive.frontendId) != frontendMap.end() : true;
+    feIsValid &=
+            lnbRecord.support ? frontendMap.find(lnbRecord.frontendId) != frontendMap.end() : true;
+
+    if (!feIsValid) {
+        ALOGW("[vts config] dynamic config fe connection is invalid.");
+        return false;
+    }
+
+    bool dvrIsValid = frontendMap[live.frontendId].isSoftwareFe
+                              ? dvrMap.find(live.dvrSoftwareFeId) != dvrMap.end()
+                              : true;
+    dvrIsValid &= playback.support ? dvrMap.find(playback.dvrId) != dvrMap.end() : true;
+    if (record.support) {
+        if (frontendMap[record.frontendId].isSoftwareFe) {
+            dvrIsValid &= dvrMap.find(record.dvrSoftwareFeId) != dvrMap.end();
+        }
+        dvrIsValid &= dvrMap.find(record.dvrRecordId) != dvrMap.end();
+    }
+    if (descrambling.support && frontendMap[descrambling.frontendId].isSoftwareFe) {
+        dvrIsValid &= dvrMap.find(descrambling.dvrSoftwareFeId) != dvrMap.end();
+    }
+
+    if (!dvrIsValid) {
+        ALOGW("[vts config] dynamic config dvr connection is invalid.");
+        return false;
+    }
+
+    bool filterIsValid = filterMap.find(live.audioFilterId) != filterMap.end() &&
+                         filterMap.find(live.videoFilterId) != filterMap.end();
+    filterIsValid &= playback.support
+                             ? (filterMap.find(playback.audioFilterId) != filterMap.end() &&
+                                filterMap.find(playback.videoFilterId) != filterMap.end())
+                             : true;
+    filterIsValid &=
+            record.support ? filterMap.find(record.recordFilterId) != filterMap.end() : true;
+    filterIsValid &= descrambling.support
+                             ? (filterMap.find(descrambling.audioFilterId) != filterMap.end() &&
+                                filterMap.find(descrambling.videoFilterId) != filterMap.end())
+                             : true;
+    filterIsValid &= lnbLive.support ? (filterMap.find(lnbLive.audioFilterId) != filterMap.end() &&
+                                        filterMap.find(lnbLive.videoFilterId) != filterMap.end())
+                                     : true;
+    filterIsValid &=
+            lnbRecord.support ? filterMap.find(lnbRecord.recordFilterId) != filterMap.end() : true;
+
+    if (!filterIsValid) {
+        ALOGW("[vts config] dynamic config filter connection is invalid.");
+        return false;
+    }
+
+    bool lnbIsValid = lnbLive.support ? lnbMap.find(lnbLive.lnbId) != lnbMap.end() : true;
+    lnbIsValid &= lnbRecord.support ? lnbMap.find(lnbRecord.lnbId) != lnbMap.end() : true;
+
+    if (!lnbIsValid) {
+        ALOGW("[vts config] dynamic config lnb connection is invalid.");
+        return false;
+    }
+
+    bool descramblerIsValid =
+            descrambling.support
+                    ? descramblerMap.find(descrambling.descramblerId) != descramblerMap.end()
+                    : true;
+
+    if (!descramblerIsValid) {
+        ALOGW("[vts config] dynamic config descrambler connection is invalid.");
+        return false;
+    }
+
+    bool diseqcMsgIsValid = true;
+    if (lnbLive.support) {
+        for (auto msgName : lnbLive.diseqcMsgs) {
+            diseqcMsgIsValid &= diseqcMsgMap.find(msgName) != diseqcMsgMap.end();
+        }
+    }
+    if (lnbRecord.support) {
+        for (auto msgName : lnbRecord.diseqcMsgs) {
+            diseqcMsgIsValid &= diseqcMsgMap.find(msgName) != diseqcMsgMap.end();
+        }
+    }
+
+    if (!diseqcMsgIsValid) {
+        ALOGW("[vts config] dynamic config diseqcMsg sender is invalid.");
+        return false;
+    }
+
+    return true;
+}
diff --git a/tv/tuner/1.1/default/Tuner.cpp b/tv/tuner/1.1/default/Tuner.cpp
index 38b2a26..1e940ba 100644
--- a/tv/tuner/1.1/default/Tuner.cpp
+++ b/tv/tuner/1.1/default/Tuner.cpp
@@ -237,6 +237,8 @@
 
     // IP filter can be an MMTP filter's data source.
     caps.linkCaps = {0x00, 0x00, 0x02, 0x00, 0x00};
+    // Support time filter testing
+    caps.bTimeFilter = true;
     _hidl_cb(Result::SUCCESS, caps);
     return Void();
 }
diff --git a/tv/tuner/config/Android.bp b/tv/tuner/config/Android.bp
new file mode 100644
index 0000000..ddbf3a7
--- /dev/null
+++ b/tv/tuner/config/Android.bp
@@ -0,0 +1,31 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_interfaces_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+xsd_config {
+    name: "tuner_testing_dynamic_configuration_V1_0",
+    srcs: ["tuner_testing_dynamic_configuration.xsd"],
+    package_name: "android.media.tuner.testing.configuration.V1_0",
+    nullability: true,
+}
+
+xsd_config {
+    name: "tuner_testing_dynamic_configuration_V1_0_enums",
+    srcs: ["tuner_testing_dynamic_configuration.xsd"],
+    package_name: "android.media.tuner.testing.configuration.V1_0",
+    nullability: true,
+    enums_only: true,
+}
+
+xsd_config {
+    name: "tuner_testing_dynamic_configuration_V1_0_parser",
+    srcs: ["tuner_testing_dynamic_configuration.xsd"],
+    package_name: "android.media.tuner.testing.configuration.V1_0",
+    nullability: true,
+    parser_only: true,
+}
diff --git a/tv/tuner/config/OWNERS b/tv/tuner/config/OWNERS
new file mode 100644
index 0000000..1b3d095
--- /dev/null
+++ b/tv/tuner/config/OWNERS
@@ -0,0 +1,4 @@
+nchalko@google.com
+amyjojo@google.com
+shubang@google.com
+quxiangfang@google.com
diff --git a/tv/tuner/config/TunerTestingConfigReader.h b/tv/tuner/config/TunerTestingConfigReader.h
new file mode 100644
index 0000000..90499c4
--- /dev/null
+++ b/tv/tuner/config/TunerTestingConfigReader.h
@@ -0,0 +1,732 @@
+/*
+ * Copyright 2021 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/tv/tuner/1.0/types.h>
+#include <android_media_tuner_testing_configuration_V1_0.h>
+#include <android_media_tuner_testing_configuration_V1_0_enums.h>
+#include <binder/MemoryDealer.h>
+#include <hidl/HidlSupport.h>
+#include <hidl/HidlTransportSupport.h>
+#include <hidl/Status.h>
+#include <hidlmemory/FrameworkUtils.h>
+
+using namespace std;
+using namespace android::media::tuner::testing::configuration::V1_0;
+
+using android::hardware::tv::tuner::V1_0::DataFormat;
+using android::hardware::tv::tuner::V1_0::DemuxAlpFilterType;
+using android::hardware::tv::tuner::V1_0::DemuxFilterAvSettings;
+using android::hardware::tv::tuner::V1_0::DemuxFilterEvent;
+using android::hardware::tv::tuner::V1_0::DemuxFilterMainType;
+using android::hardware::tv::tuner::V1_0::DemuxFilterRecordSettings;
+using android::hardware::tv::tuner::V1_0::DemuxFilterSectionSettings;
+using android::hardware::tv::tuner::V1_0::DemuxFilterSettings;
+using android::hardware::tv::tuner::V1_0::DemuxFilterType;
+using android::hardware::tv::tuner::V1_0::DemuxIpFilterType;
+using android::hardware::tv::tuner::V1_0::DemuxMmtpFilterType;
+using android::hardware::tv::tuner::V1_0::DemuxRecordScIndexType;
+using android::hardware::tv::tuner::V1_0::DemuxTlvFilterType;
+using android::hardware::tv::tuner::V1_0::DemuxTpid;
+using android::hardware::tv::tuner::V1_0::DemuxTsFilterType;
+using android::hardware::tv::tuner::V1_0::DvrSettings;
+using android::hardware::tv::tuner::V1_0::DvrType;
+using android::hardware::tv::tuner::V1_0::FrontendDvbsSettings;
+using android::hardware::tv::tuner::V1_0::FrontendDvbtBandwidth;
+using android::hardware::tv::tuner::V1_0::FrontendDvbtCoderate;
+using android::hardware::tv::tuner::V1_0::FrontendDvbtConstellation;
+using android::hardware::tv::tuner::V1_0::FrontendDvbtGuardInterval;
+using android::hardware::tv::tuner::V1_0::FrontendDvbtHierarchy;
+using android::hardware::tv::tuner::V1_0::FrontendDvbtSettings;
+using android::hardware::tv::tuner::V1_0::FrontendDvbtStandard;
+using android::hardware::tv::tuner::V1_0::FrontendDvbtTransmissionMode;
+using android::hardware::tv::tuner::V1_0::FrontendSettings;
+using android::hardware::tv::tuner::V1_0::FrontendStatus;
+using android::hardware::tv::tuner::V1_0::FrontendStatusType;
+using android::hardware::tv::tuner::V1_0::FrontendType;
+using android::hardware::tv::tuner::V1_0::LnbPosition;
+using android::hardware::tv::tuner::V1_0::LnbTone;
+using android::hardware::tv::tuner::V1_0::LnbVoltage;
+using android::hardware::tv::tuner::V1_0::PlaybackSettings;
+using android::hardware::tv::tuner::V1_0::RecordSettings;
+
+const string configFilePath = "/vendor/etc/tuner_vts_config.xml";
+const string emptyHardwareId = "";
+
+#define PROVISION_STR                                      \
+    "{                                                   " \
+    "  \"id\": 21140844,                                 " \
+    "  \"name\": \"Test Title\",                         " \
+    "  \"lowercase_organization_name\": \"Android\",     " \
+    "  \"asset_key\": {                                  " \
+    "  \"encryption_key\": \"nezAr3CHFrmBR9R8Tedotw==\"  " \
+    "  },                                                " \
+    "  \"cas_type\": 1,                                  " \
+    "  \"track_types\": [ ]                              " \
+    "}                                                   "
+
+struct FrontendConfig {
+    bool isSoftwareFe;
+    FrontendType type;
+    FrontendSettings settings;
+    vector<FrontendStatusType> tuneStatusTypes;
+    vector<FrontendStatus> expectTuneStatuses;
+};
+
+struct FilterConfig {
+    uint32_t bufferSize;
+    DemuxFilterType type;
+    DemuxFilterSettings settings;
+    bool getMqDesc;
+
+    bool operator<(const FilterConfig& /*c*/) const { return false; }
+};
+
+struct DvrConfig {
+    DvrType type;
+    uint32_t bufferSize;
+    DvrSettings settings;
+    string playbackInputFile;
+};
+
+struct LnbConfig {
+    string name;
+    LnbVoltage voltage;
+    LnbTone tone;
+    LnbPosition position;
+};
+
+struct TimeFilterConfig {
+    uint64_t timeStamp;
+};
+
+struct DescramblerConfig {
+    uint32_t casSystemId;
+    string provisionStr;
+    vector<uint8_t> hidlPvtData;
+};
+
+struct LiveBroadcastHardwareConnections {
+    string frontendId;
+    string dvrSoftwareFeId;
+    string audioFilterId;
+    string videoFilterId;
+    string sectionFilterId;
+    string pcrFilterId;
+    /* list string of extra filters; */
+};
+
+struct ScanHardwareConnections {
+    string frontendId;
+};
+
+struct DvrPlaybackHardwareConnections {
+    bool support;
+    string frontendId;
+    string dvrId;
+    string audioFilterId;
+    string videoFilterId;
+    string sectionFilterId;
+    /* list string of extra filters; */
+};
+
+struct DvrRecordHardwareConnections {
+    bool support;
+    string frontendId;
+    string dvrRecordId;
+    string dvrSoftwareFeId;
+    string recordFilterId;
+};
+
+struct DescramblingHardwareConnections {
+    bool support;
+    string frontendId;
+    string dvrSoftwareFeId;
+    string audioFilterId;
+    string videoFilterId;
+    string descramblerId;
+    /* list string of extra filters; */
+};
+
+struct LnbLiveHardwareConnections {
+    bool support;
+    string frontendId;
+    string audioFilterId;
+    string videoFilterId;
+    string lnbId;
+    vector<string> diseqcMsgs;
+    /* list string of extra filters; */
+};
+
+struct LnbRecordHardwareConnections {
+    bool support;
+    string frontendId;
+    string dvrRecordId;
+    string recordFilterId;
+    string lnbId;
+    vector<string> diseqcMsgs;
+    /* list string of extra filters; */
+};
+
+struct TimeFilterHardwareConnections {
+    bool support;
+    string timeFilterId;
+};
+
+struct TunerTestingConfigReader {
+  public:
+    static bool checkConfigFileExists() {
+        auto res = read(configFilePath.c_str());
+        if (res == nullopt) {
+            ALOGW("[ConfigReader] Couldn't read /vendor/etc/tuner_vts_config.xml."
+                  "Please check tuner_testing_dynamic_configuration.xsd"
+                  "and sample_tuner_vts_config.xml for more details on how to config Tune VTS.");
+        }
+        return (res != nullopt);
+    }
+
+    static void readFrontendConfig1_0(map<string, FrontendConfig>& frontendMap) {
+        auto hardwareConfig = getHardwareConfig();
+        if (hardwareConfig.hasFrontends()) {
+            // TODO: b/182519645 complete the tune status config
+            vector<FrontendStatusType> types;
+            types.push_back(FrontendStatusType::DEMOD_LOCK);
+            FrontendStatus status;
+            status.isDemodLocked(true);
+            vector<FrontendStatus> statuses;
+            statuses.push_back(status);
+
+            auto frontends = *hardwareConfig.getFirstFrontends();
+            for (auto feConfig : frontends.getFrontend()) {
+                string id = feConfig.getId();
+                if (id.compare(string("FE_DEFAULT")) == 0) {
+                    // overrid default
+                    frontendMap.erase(string("FE_DEFAULT"));
+                }
+                FrontendType type;
+                switch (feConfig.getType()) {
+                    case FrontendTypeEnum::UNDEFINED:
+                        type = FrontendType::UNDEFINED;
+                        break;
+                    // TODO: b/182519645 finish all other frontend settings
+                    case FrontendTypeEnum::ANALOG:
+                        type = FrontendType::ANALOG;
+                        break;
+                    case FrontendTypeEnum::ATSC:
+                        type = FrontendType::ATSC;
+                        break;
+                    case FrontendTypeEnum::ATSC3:
+                        type = FrontendType::ATSC3;
+                        break;
+                    case FrontendTypeEnum::DVBC:
+                        type = FrontendType::DVBC;
+                        break;
+                    case FrontendTypeEnum::DVBS:
+                        type = FrontendType::DVBS;
+                        frontendMap[id].settings.dvbs(readDvbsFrontendSettings(feConfig));
+                        break;
+                    case FrontendTypeEnum::DVBT: {
+                        type = FrontendType::DVBT;
+                        frontendMap[id].settings.dvbt(readDvbtFrontendSettings(feConfig));
+                        break;
+                    }
+                    case FrontendTypeEnum::ISDBS:
+                        type = FrontendType::ISDBS;
+                        break;
+                    case FrontendTypeEnum::ISDBS3:
+                        type = FrontendType::ISDBS3;
+                        break;
+                    case FrontendTypeEnum::ISDBT:
+                        type = FrontendType::ISDBT;
+                        break;
+                    case FrontendTypeEnum::DTMB:
+                        // dtmb will be handled in readFrontendConfig1_1;
+                        continue;
+                    case FrontendTypeEnum::UNKNOWN:
+                        ALOGW("[ConfigReader] invalid frontend type");
+                        return;
+                }
+                frontendMap[id].type = type;
+                frontendMap[id].isSoftwareFe = feConfig.getIsSoftwareFrontend();
+                // TODO: b/182519645 complete the tune status config
+                frontendMap[id].tuneStatusTypes = types;
+                frontendMap[id].expectTuneStatuses = statuses;
+            }
+        }
+    }
+
+    static void readFilterConfig1_0(map<string, FilterConfig>& filterMap) {
+        auto hardwareConfig = getHardwareConfig();
+        if (hardwareConfig.hasFilters()) {
+            auto filters = *hardwareConfig.getFirstFilters();
+            for (auto filterConfig : filters.getFilter()) {
+                string id = filterConfig.getId();
+                if (id.compare(string("FILTER_AUDIO_DEFAULT")) == 0) {
+                    // overrid default
+                    filterMap.erase(string("FILTER_AUDIO_DEFAULT"));
+                }
+                if (id.compare(string("FILTER_VIDEO_DEFAULT")) == 0) {
+                    // overrid default
+                    filterMap.erase(string("FILTER_VIDEO_DEFAULT"));
+                }
+
+                DemuxFilterType type;
+                DemuxFilterSettings settings;
+                if (!readFilterTypeAndSettings(filterConfig, type, settings)) {
+                    ALOGW("[ConfigReader] invalid filter type");
+                    return;
+                }
+                filterMap[id].type = type;
+                filterMap[id].bufferSize = filterConfig.getBufferSize();
+                filterMap[id].getMqDesc = filterConfig.getUseFMQ();
+                filterMap[id].settings = settings;
+            }
+        }
+    }
+
+    static void readDvrConfig1_0(map<string, DvrConfig>& dvrMap) {
+        auto hardwareConfig = getHardwareConfig();
+        if (hardwareConfig.hasDvrs()) {
+            auto dvrs = *hardwareConfig.getFirstDvrs();
+            for (auto dvrConfig : dvrs.getDvr()) {
+                string id = dvrConfig.getId();
+                DvrType type;
+                switch (dvrConfig.getType()) {
+                    case DvrTypeEnum::PLAYBACK:
+                        type = DvrType::PLAYBACK;
+                        dvrMap[id].settings.playback(readPlaybackSettings(dvrConfig));
+                        break;
+                    case DvrTypeEnum::RECORD:
+                        type = DvrType::RECORD;
+                        dvrMap[id].settings.record(readRecordSettings(dvrConfig));
+                        break;
+                    case DvrTypeEnum::UNKNOWN:
+                        ALOGW("[ConfigReader] invalid DVR type");
+                        return;
+                }
+                dvrMap[id].type = type;
+                dvrMap[id].bufferSize = static_cast<uint32_t>(dvrConfig.getBufferSize());
+                if (dvrConfig.hasInputFilePath()) {
+                    dvrMap[id].playbackInputFile = dvrConfig.getInputFilePath();
+                }
+            }
+        }
+    }
+
+    static void readLnbConfig1_0(map<string, LnbConfig>& lnbMap) {
+        auto hardwareConfig = getHardwareConfig();
+        if (hardwareConfig.hasLnbs()) {
+            auto lnbs = *hardwareConfig.getFirstLnbs();
+            for (auto lnbConfig : lnbs.getLnb()) {
+                string id = lnbConfig.getId();
+                if (lnbConfig.hasName()) {
+                    lnbMap[id].name = lnbConfig.getName();
+                } else {
+                    lnbMap[id].name = emptyHardwareId;
+                }
+                lnbMap[id].voltage = static_cast<LnbVoltage>(lnbConfig.getVoltage());
+                lnbMap[id].tone = static_cast<LnbTone>(lnbConfig.getTone());
+                lnbMap[id].position = static_cast<LnbPosition>(lnbConfig.getPosition());
+            }
+        }
+    }
+
+    static void readDescramblerConfig1_0(map<string, DescramblerConfig>& descramblerMap) {
+        auto hardwareConfig = getHardwareConfig();
+        if (hardwareConfig.hasDescramblers()) {
+            auto descramblers = *hardwareConfig.getFirstDescramblers();
+            for (auto descramblerConfig : descramblers.getDescrambler()) {
+                string id = descramblerConfig.getId();
+                descramblerMap[id].casSystemId =
+                        static_cast<uint32_t>(descramblerConfig.getCasSystemId());
+                if (descramblerConfig.hasProvisionStr()) {
+                    descramblerMap[id].provisionStr = descramblerConfig.getProvisionStr();
+                } else {
+                    descramblerMap[id].provisionStr = PROVISION_STR;
+                }
+                if (descramblerConfig.hasSesstionPrivatData()) {
+                    auto privateData = descramblerConfig.getSesstionPrivatData();
+                    int size = privateData.size();
+                    descramblerMap[id].hidlPvtData.resize(size);
+                    memcpy(descramblerMap[id].hidlPvtData.data(), privateData.data(), size);
+                } else {
+                    descramblerMap[id].hidlPvtData.resize(256);
+                }
+            }
+        }
+    }
+
+    static void readDiseqcMessages(map<string, vector<uint8_t>>& diseqcMsgMap) {
+        auto hardwareConfig = getHardwareConfig();
+        if (hardwareConfig.hasDiseqcMessages()) {
+            auto msgs = *hardwareConfig.getFirstDiseqcMessages();
+            for (auto msgConfig : msgs.getDiseqcMessage()) {
+                string name = msgConfig.getMsgName();
+                for (uint8_t atom : msgConfig.getMsgBody()) {
+                    diseqcMsgMap[name].push_back(atom);
+                }
+            }
+        }
+    }
+
+    static void readTimeFilterConfig1_0(map<string, TimeFilterConfig>& timeFilterMap) {
+        auto hardwareConfig = getHardwareConfig();
+        if (hardwareConfig.hasTimeFilters()) {
+            auto timeFilters = *hardwareConfig.getFirstTimeFilters();
+            for (auto timeFilterConfig : timeFilters.getTimeFilter()) {
+                string id = timeFilterConfig.getId();
+                timeFilterMap[id].timeStamp =
+                        static_cast<uint64_t>(timeFilterConfig.getTimeStamp());
+            }
+        }
+    }
+
+    static void connectLiveBroadcast(LiveBroadcastHardwareConnections& live) {
+        auto liveConfig = *getDataFlowConfiguration().getFirstClearLiveBroadcast();
+        live.frontendId = liveConfig.getFrontendConnection();
+
+        live.audioFilterId = liveConfig.getAudioFilterConnection();
+        live.videoFilterId = liveConfig.getVideoFilterConnection();
+        if (liveConfig.hasPcrFilterConnection()) {
+            live.pcrFilterId = liveConfig.getPcrFilterConnection();
+        } else {
+            live.pcrFilterId = emptyHardwareId;
+        }
+        if (liveConfig.hasSectionFilterConnection()) {
+            live.sectionFilterId = liveConfig.getSectionFilterConnection();
+        } else {
+            live.sectionFilterId = emptyHardwareId;
+        }
+        if (liveConfig.hasDvrSoftwareFeConnection()) {
+            live.dvrSoftwareFeId = liveConfig.getDvrSoftwareFeConnection();
+        }
+    }
+
+    static void connectScan(ScanHardwareConnections& scan) {
+        auto scanConfig = getDataFlowConfiguration().getFirstScan();
+        scan.frontendId = scanConfig->getFrontendConnection();
+    }
+
+    static void connectDvrPlayback(DvrPlaybackHardwareConnections& playback) {
+        auto dataFlow = getDataFlowConfiguration();
+        if (dataFlow.hasDvrPlayback()) {
+            playback.support = true;
+        } else {
+            return;
+        }
+        auto playbackConfig = *dataFlow.getFirstDvrPlayback();
+        playback.dvrId = playbackConfig.getDvrConnection();
+        playback.audioFilterId = playbackConfig.getAudioFilterConnection();
+        playback.videoFilterId = playbackConfig.getVideoFilterConnection();
+        if (playbackConfig.hasSectionFilterConnection()) {
+            playback.sectionFilterId = playbackConfig.getSectionFilterConnection();
+        } else {
+            playback.sectionFilterId = emptyHardwareId;
+        }
+    }
+
+    static void connectDvrRecord(DvrRecordHardwareConnections& record) {
+        auto dataFlow = getDataFlowConfiguration();
+        if (dataFlow.hasDvrRecord()) {
+            record.support = true;
+        } else {
+            return;
+        }
+        auto recordConfig = *dataFlow.getFirstDvrRecord();
+        record.frontendId = recordConfig.getFrontendConnection();
+        record.recordFilterId = recordConfig.getRecordFilterConnection();
+        record.dvrRecordId = recordConfig.getDvrRecordConnection();
+        if (recordConfig.hasDvrSoftwareFeConnection()) {
+            record.dvrSoftwareFeId = recordConfig.getDvrSoftwareFeConnection();
+        }
+    }
+
+    static void connectDescrambling(DescramblingHardwareConnections& descrambling) {
+        auto dataFlow = getDataFlowConfiguration();
+        if (dataFlow.hasDescrambling()) {
+            descrambling.support = true;
+        } else {
+            return;
+        }
+        auto descConfig = *dataFlow.getFirstDescrambling();
+        descrambling.frontendId = descConfig.getFrontendConnection();
+        descrambling.descramblerId = descConfig.getDescramblerConnection();
+        descrambling.audioFilterId = descConfig.getAudioFilterConnection();
+        descrambling.videoFilterId = descConfig.getVideoFilterConnection();
+        if (descConfig.hasDvrSoftwareFeConnection()) {
+            descrambling.dvrSoftwareFeId = descConfig.getDvrSoftwareFeConnection();
+        }
+    }
+
+    static void connectLnbLive(LnbLiveHardwareConnections& lnbLive) {
+        auto dataFlow = getDataFlowConfiguration();
+        if (dataFlow.hasLnbLive()) {
+            lnbLive.support = true;
+        } else {
+            return;
+        }
+        auto lnbLiveConfig = *dataFlow.getFirstLnbLive();
+        lnbLive.frontendId = lnbLiveConfig.getFrontendConnection();
+        lnbLive.audioFilterId = lnbLiveConfig.getAudioFilterConnection();
+        lnbLive.videoFilterId = lnbLiveConfig.getVideoFilterConnection();
+        lnbLive.lnbId = lnbLiveConfig.getLnbConnection();
+        if (lnbLiveConfig.hasDiseqcMsgSender()) {
+            for (auto msgName : lnbLiveConfig.getDiseqcMsgSender()) {
+                lnbLive.diseqcMsgs.push_back(msgName);
+            }
+        }
+    }
+
+    static void connectLnbRecord(LnbRecordHardwareConnections& lnbRecord) {
+        auto dataFlow = getDataFlowConfiguration();
+        if (dataFlow.hasLnbRecord()) {
+            lnbRecord.support = true;
+        } else {
+            return;
+        }
+        auto lnbRecordConfig = *dataFlow.getFirstLnbRecord();
+        lnbRecord.frontendId = lnbRecordConfig.getFrontendConnection();
+        lnbRecord.recordFilterId = lnbRecordConfig.getRecordFilterConnection();
+        lnbRecord.dvrRecordId = lnbRecordConfig.getDvrRecordConnection();
+        lnbRecord.lnbId = lnbRecordConfig.getLnbConnection();
+        if (lnbRecordConfig.hasDiseqcMsgSender()) {
+            for (auto msgName : lnbRecordConfig.getDiseqcMsgSender()) {
+                lnbRecord.diseqcMsgs.push_back(msgName);
+            }
+        }
+    }
+
+    static void connectTimeFilter(TimeFilterHardwareConnections& timeFilter) {
+        auto dataFlow = getDataFlowConfiguration();
+        if (dataFlow.hasTimeFilter()) {
+            timeFilter.support = true;
+        } else {
+            return;
+        }
+        auto timeFilterConfig = *dataFlow.getFirstTimeFilter();
+        timeFilter.timeFilterId = timeFilterConfig.getTimeFilterConnection();
+    }
+
+  private:
+    static FrontendDvbtSettings readDvbtFrontendSettings(Frontend feConfig) {
+        ALOGW("[ConfigReader] fe type is dvbt");
+        FrontendDvbtSettings dvbtSettings{
+                .frequency = (uint32_t)feConfig.getFrequency(),
+        };
+        if (!feConfig.hasDvbtFrontendSettings_optional()) {
+            ALOGW("[ConfigReader] no more dvbt settings");
+            return dvbtSettings;
+        }
+        dvbtSettings.transmissionMode = static_cast<FrontendDvbtTransmissionMode>(
+                feConfig.getFirstDvbtFrontendSettings_optional()->getTransmissionMode());
+        dvbtSettings.bandwidth = static_cast<FrontendDvbtBandwidth>(
+                feConfig.getFirstDvbtFrontendSettings_optional()->getBandwidth());
+        dvbtSettings.isHighPriority =
+                feConfig.getFirstDvbtFrontendSettings_optional()->getIsHighPriority();
+        return dvbtSettings;
+    }
+
+    static FrontendDvbsSettings readDvbsFrontendSettings(Frontend feConfig) {
+        ALOGW("[ConfigReader] fe type is dvbs");
+        FrontendDvbsSettings dvbsSettings{
+                .frequency = (uint32_t)feConfig.getFrequency(),
+        };
+        if (!feConfig.hasDvbsFrontendSettings_optional()) {
+            ALOGW("[ConfigReader] no more dvbs settings");
+            return dvbsSettings;
+        }
+        dvbsSettings.symbolRate = static_cast<uint32_t>(
+                feConfig.getFirstDvbsFrontendSettings_optional()->getSymbolRate());
+        dvbsSettings.inputStreamId = static_cast<uint32_t>(
+                feConfig.getFirstDvbsFrontendSettings_optional()->getInputStreamId());
+        return dvbsSettings;
+    }
+
+    static bool readFilterTypeAndSettings(Filter filterConfig, DemuxFilterType& type,
+                                          DemuxFilterSettings& settings) {
+        auto mainType = filterConfig.getMainType();
+        auto subType = filterConfig.getSubType();
+        uint32_t pid = static_cast<uint32_t>(filterConfig.getPid());
+        switch (mainType) {
+            case FilterMainTypeEnum::TS: {
+                ALOGW("[ConfigReader] filter main type is ts");
+                type.mainType = DemuxFilterMainType::TS;
+                switch (subType) {
+                    case FilterSubTypeEnum::UNDEFINED:
+                        break;
+                    case FilterSubTypeEnum::SECTION:
+                        type.subType.tsFilterType(DemuxTsFilterType::SECTION);
+                        settings.ts().filterSettings.section(
+                                readSectionFilterSettings(filterConfig));
+                        break;
+                    case FilterSubTypeEnum::PES:
+                        // TODO: b/182519645 support all the filter settings
+                        /*settings.ts().filterSettings.pesData(
+                                getPesFilterSettings(filterConfig));*/
+                        type.subType.tsFilterType(DemuxTsFilterType::PES);
+                        break;
+                    case FilterSubTypeEnum::TS:
+                        type.subType.tsFilterType(DemuxTsFilterType::TS);
+                        settings.ts().filterSettings.noinit();
+                        break;
+                    case FilterSubTypeEnum::PCR:
+                        type.subType.tsFilterType(DemuxTsFilterType::PCR);
+                        settings.ts().filterSettings.noinit();
+                        break;
+                    case FilterSubTypeEnum::TEMI:
+                        type.subType.tsFilterType(DemuxTsFilterType::TEMI);
+                        settings.ts().filterSettings.noinit();
+                        break;
+                    case FilterSubTypeEnum::AUDIO:
+                        type.subType.tsFilterType(DemuxTsFilterType::AUDIO);
+                        settings.ts().filterSettings.av(readAvFilterSettings(filterConfig));
+                        break;
+                    case FilterSubTypeEnum::VIDEO:
+                        type.subType.tsFilterType(DemuxTsFilterType::VIDEO);
+                        settings.ts().filterSettings.av(readAvFilterSettings(filterConfig));
+                        break;
+                    case FilterSubTypeEnum::RECORD:
+                        type.subType.tsFilterType(DemuxTsFilterType::RECORD);
+                        settings.ts().filterSettings.record(readRecordFilterSettings(filterConfig));
+                        break;
+                    default:
+                        ALOGW("[ConfigReader] ts subtype is not supported");
+                        return false;
+                }
+                settings.ts().tpid = pid;
+                break;
+            }
+            case FilterMainTypeEnum::MMTP: {
+                ALOGW("[ConfigReader] filter main type is mmtp");
+                type.mainType = DemuxFilterMainType::MMTP;
+                switch (subType) {
+                    case FilterSubTypeEnum::UNDEFINED:
+                        break;
+                    case FilterSubTypeEnum::SECTION:
+                        type.subType.mmtpFilterType(DemuxMmtpFilterType::SECTION);
+                        settings.mmtp().filterSettings.section(
+                                readSectionFilterSettings(filterConfig));
+                        break;
+                    case FilterSubTypeEnum::PES:
+                        type.subType.mmtpFilterType(DemuxMmtpFilterType::PES);
+                        // TODO: b/182519645 support all the filter settings
+                        /*settings.mmtp().filterSettings.pesData(
+                                getPesFilterSettings(filterConfig));*/
+                        break;
+                    case FilterSubTypeEnum::MMTP:
+                        type.subType.mmtpFilterType(DemuxMmtpFilterType::MMTP);
+                        settings.mmtp().filterSettings.noinit();
+                        break;
+                    case FilterSubTypeEnum::AUDIO:
+                        type.subType.mmtpFilterType(DemuxMmtpFilterType::AUDIO);
+                        settings.mmtp().filterSettings.av(readAvFilterSettings(filterConfig));
+                        break;
+                    case FilterSubTypeEnum::VIDEO:
+                        settings.mmtp().filterSettings.av(readAvFilterSettings(filterConfig));
+                        break;
+                    case FilterSubTypeEnum::RECORD:
+                        type.subType.mmtpFilterType(DemuxMmtpFilterType::RECORD);
+                        settings.mmtp().filterSettings.record(
+                                readRecordFilterSettings(filterConfig));
+                        break;
+                    case FilterSubTypeEnum::DOWNLOAD:
+                        type.subType.mmtpFilterType(DemuxMmtpFilterType::DOWNLOAD);
+                        // TODO: b/182519645 support all the filter settings
+                        /*settings.mmtp().filterSettings.download(
+                                getDownloadFilterSettings(filterConfig));*/
+                        break;
+                    default:
+                        ALOGW("[ConfigReader] mmtp subtype is not supported");
+                        return false;
+                }
+                settings.mmtp().mmtpPid = pid;
+                break;
+            }
+            default:
+                // TODO: b/182519645 support all the filter configs
+                ALOGW("[ConfigReader] filter main type is not supported in dynamic config");
+                return false;
+        }
+        return true;
+    }
+
+    static DemuxFilterSectionSettings readSectionFilterSettings(Filter filterConfig) {
+        DemuxFilterSectionSettings settings;
+        if (!filterConfig.hasSectionFilterSettings_optional()) {
+            return settings;
+        }
+        auto section = filterConfig.getFirstSectionFilterSettings_optional();
+        settings.isCheckCrc = section->getIsCheckCrc();
+        settings.isRepeat = section->getIsRepeat();
+        settings.isRaw = section->getIsRaw();
+        return settings;
+    }
+
+    static DemuxFilterAvSettings readAvFilterSettings(Filter filterConfig) {
+        DemuxFilterAvSettings settings;
+        if (!filterConfig.hasAvFilterSettings_optional()) {
+            return settings;
+        }
+        auto av = filterConfig.getFirstAvFilterSettings_optional();
+        settings.isPassthrough = av->getIsPassthrough();
+        return settings;
+    }
+
+    static DemuxFilterRecordSettings readRecordFilterSettings(Filter filterConfig) {
+        DemuxFilterRecordSettings settings;
+        if (!filterConfig.hasRecordFilterSettings_optional()) {
+            return settings;
+        }
+        auto record = filterConfig.getFirstRecordFilterSettings_optional();
+        settings.tsIndexMask = static_cast<uint32_t>(record->getTsIndexMask());
+        settings.scIndexType = static_cast<DemuxRecordScIndexType>(record->getScIndexType());
+        return settings;
+    }
+
+    static PlaybackSettings readPlaybackSettings(Dvr dvrConfig) {
+        ALOGW("[ConfigReader] dvr type is playback");
+        PlaybackSettings playbackSettings{
+                .statusMask = static_cast<uint8_t>(dvrConfig.getStatusMask()),
+                .lowThreshold = static_cast<uint32_t>(dvrConfig.getLowThreshold()),
+                .highThreshold = static_cast<uint32_t>(dvrConfig.getHighThreshold()),
+                .dataFormat = static_cast<DataFormat>(dvrConfig.getDataFormat()),
+                .packetSize = static_cast<uint8_t>(dvrConfig.getPacketSize()),
+        };
+        return playbackSettings;
+    }
+
+    static RecordSettings readRecordSettings(Dvr dvrConfig) {
+        ALOGW("[ConfigReader] dvr type is record");
+        RecordSettings recordSettings{
+                .statusMask = static_cast<uint8_t>(dvrConfig.getStatusMask()),
+                .lowThreshold = static_cast<uint32_t>(dvrConfig.getLowThreshold()),
+                .highThreshold = static_cast<uint32_t>(dvrConfig.getHighThreshold()),
+                .dataFormat = static_cast<DataFormat>(dvrConfig.getDataFormat()),
+                .packetSize = static_cast<uint8_t>(dvrConfig.getPacketSize()),
+        };
+        return recordSettings;
+    }
+
+    static TunerConfiguration getTunerConfig() { return *read(configFilePath.c_str()); }
+
+    static HardwareConfiguration getHardwareConfig() {
+        return *getTunerConfig().getFirstHardwareConfiguration();
+    }
+
+    static DataFlowConfiguration getDataFlowConfiguration() {
+        return *getTunerConfig().getFirstDataFlowConfiguration();
+    }
+};
diff --git a/tv/tuner/config/api/current.txt b/tv/tuner/config/api/current.txt
new file mode 100644
index 0000000..4255a60
--- /dev/null
+++ b/tv/tuner/config/api/current.txt
@@ -0,0 +1,433 @@
+// Signature format: 2.0
+package android.media.tuner.testing.configuration.V1_0 {
+
+  public class AvFilterSettings {
+    ctor public AvFilterSettings();
+    method @Nullable public boolean getIsPassthrough();
+    method public void setIsPassthrough(@Nullable boolean);
+  }
+
+  public class DataFlowConfiguration {
+    ctor public DataFlowConfiguration();
+    method @Nullable public android.media.tuner.testing.configuration.V1_0.DataFlowConfiguration.ClearLiveBroadcast getClearLiveBroadcast();
+    method @Nullable public android.media.tuner.testing.configuration.V1_0.DataFlowConfiguration.Descrambling getDescrambling();
+    method @Nullable public android.media.tuner.testing.configuration.V1_0.DataFlowConfiguration.DvrPlayback getDvrPlayback();
+    method @Nullable public android.media.tuner.testing.configuration.V1_0.DataFlowConfiguration.DvrRecord getDvrRecord();
+    method @Nullable public android.media.tuner.testing.configuration.V1_0.DataFlowConfiguration.LnbLive getLnbLive();
+    method @Nullable public android.media.tuner.testing.configuration.V1_0.DataFlowConfiguration.LnbRecord getLnbRecord();
+    method @Nullable public android.media.tuner.testing.configuration.V1_0.DataFlowConfiguration.Scan getScan();
+    method @Nullable public android.media.tuner.testing.configuration.V1_0.DataFlowConfiguration.TimeFilter getTimeFilter();
+    method public void setClearLiveBroadcast(@Nullable android.media.tuner.testing.configuration.V1_0.DataFlowConfiguration.ClearLiveBroadcast);
+    method public void setDescrambling(@Nullable android.media.tuner.testing.configuration.V1_0.DataFlowConfiguration.Descrambling);
+    method public void setDvrPlayback(@Nullable android.media.tuner.testing.configuration.V1_0.DataFlowConfiguration.DvrPlayback);
+    method public void setDvrRecord(@Nullable android.media.tuner.testing.configuration.V1_0.DataFlowConfiguration.DvrRecord);
+    method public void setLnbLive(@Nullable android.media.tuner.testing.configuration.V1_0.DataFlowConfiguration.LnbLive);
+    method public void setLnbRecord(@Nullable android.media.tuner.testing.configuration.V1_0.DataFlowConfiguration.LnbRecord);
+    method public void setScan(@Nullable android.media.tuner.testing.configuration.V1_0.DataFlowConfiguration.Scan);
+    method public void setTimeFilter(@Nullable android.media.tuner.testing.configuration.V1_0.DataFlowConfiguration.TimeFilter);
+  }
+
+  public static class DataFlowConfiguration.ClearLiveBroadcast {
+    ctor public DataFlowConfiguration.ClearLiveBroadcast();
+    method @Nullable public String getAudioFilterConnection();
+    method @Nullable public String getDvrSoftwareFeConnection();
+    method @Nullable public String getFrontendConnection();
+    method @Nullable public String getPcrFilterConnection();
+    method @Nullable public String getSectionFilterConnection();
+    method @Nullable public String getVideoFilterConnection();
+    method public void setAudioFilterConnection(@Nullable String);
+    method public void setDvrSoftwareFeConnection(@Nullable String);
+    method public void setFrontendConnection(@Nullable String);
+    method public void setPcrFilterConnection(@Nullable String);
+    method public void setSectionFilterConnection(@Nullable String);
+    method public void setVideoFilterConnection(@Nullable String);
+  }
+
+  public static class DataFlowConfiguration.Descrambling {
+    ctor public DataFlowConfiguration.Descrambling();
+    method @Nullable public String getAudioFilterConnection();
+    method @Nullable public String getDescramblerConnection();
+    method @Nullable public String getDvrSoftwareFeConnection();
+    method @Nullable public String getFrontendConnection();
+    method @Nullable public String getVideoFilterConnection();
+    method public void setAudioFilterConnection(@Nullable String);
+    method public void setDescramblerConnection(@Nullable String);
+    method public void setDvrSoftwareFeConnection(@Nullable String);
+    method public void setFrontendConnection(@Nullable String);
+    method public void setVideoFilterConnection(@Nullable String);
+  }
+
+  public static class DataFlowConfiguration.DvrPlayback {
+    ctor public DataFlowConfiguration.DvrPlayback();
+    method @Nullable public String getAudioFilterConnection();
+    method @Nullable public String getDvrConnection();
+    method @Nullable public String getSectionFilterConnection();
+    method @Nullable public String getVideoFilterConnection();
+    method public void setAudioFilterConnection(@Nullable String);
+    method public void setDvrConnection(@Nullable String);
+    method public void setSectionFilterConnection(@Nullable String);
+    method public void setVideoFilterConnection(@Nullable String);
+  }
+
+  public static class DataFlowConfiguration.DvrRecord {
+    ctor public DataFlowConfiguration.DvrRecord();
+    method @Nullable public String getDvrRecordConnection();
+    method @Nullable public String getDvrSoftwareFeConnection();
+    method @Nullable public String getFrontendConnection();
+    method @Nullable public String getRecordFilterConnection();
+    method public void setDvrRecordConnection(@Nullable String);
+    method public void setDvrSoftwareFeConnection(@Nullable String);
+    method public void setFrontendConnection(@Nullable String);
+    method public void setRecordFilterConnection(@Nullable String);
+  }
+
+  public static class DataFlowConfiguration.LnbLive {
+    ctor public DataFlowConfiguration.LnbLive();
+    method @Nullable public String getAudioFilterConnection();
+    method @Nullable public java.util.List<java.lang.String> getDiseqcMsgSender();
+    method @Nullable public String getFrontendConnection();
+    method @Nullable public String getLnbConnection();
+    method @Nullable public String getVideoFilterConnection();
+    method public void setAudioFilterConnection(@Nullable String);
+    method public void setDiseqcMsgSender(@Nullable java.util.List<java.lang.String>);
+    method public void setFrontendConnection(@Nullable String);
+    method public void setLnbConnection(@Nullable String);
+    method public void setVideoFilterConnection(@Nullable String);
+  }
+
+  public static class DataFlowConfiguration.LnbRecord {
+    ctor public DataFlowConfiguration.LnbRecord();
+    method @Nullable public java.util.List<java.lang.String> getDiseqcMsgSender();
+    method @Nullable public String getDvrRecordConnection();
+    method @Nullable public String getFrontendConnection();
+    method @Nullable public String getLnbConnection();
+    method @Nullable public String getRecordFilterConnection();
+    method public void setDiseqcMsgSender(@Nullable java.util.List<java.lang.String>);
+    method public void setDvrRecordConnection(@Nullable String);
+    method public void setFrontendConnection(@Nullable String);
+    method public void setLnbConnection(@Nullable String);
+    method public void setRecordFilterConnection(@Nullable String);
+  }
+
+  public static class DataFlowConfiguration.Scan {
+    ctor public DataFlowConfiguration.Scan();
+    method @Nullable public String getFrontendConnection();
+    method public void setFrontendConnection(@Nullable String);
+  }
+
+  public static class DataFlowConfiguration.TimeFilter {
+    ctor public DataFlowConfiguration.TimeFilter();
+    method @Nullable public String getTimeFilterConnection();
+    method public void setTimeFilterConnection(@Nullable String);
+  }
+
+  public class Descrambler {
+    ctor public Descrambler();
+    method @Nullable public java.math.BigInteger getCasSystemId();
+    method @Nullable public String getId();
+    method @Nullable public String getProvisionStr();
+    method @Nullable public java.util.List<java.lang.Short> getSesstionPrivatData();
+    method public void setCasSystemId(@Nullable java.math.BigInteger);
+    method public void setId(@Nullable String);
+    method public void setProvisionStr(@Nullable String);
+    method public void setSesstionPrivatData(@Nullable java.util.List<java.lang.Short>);
+  }
+
+  public class DiseqcMessage {
+    ctor public DiseqcMessage();
+    method @Nullable public java.util.List<java.lang.Short> getMsgBody();
+    method @Nullable public String getMsgName();
+    method public void setMsgBody(@Nullable java.util.List<java.lang.Short>);
+    method public void setMsgName(@Nullable String);
+  }
+
+  public class DvbsFrontendSettings {
+    ctor public DvbsFrontendSettings();
+    method @Nullable public java.math.BigInteger getInputStreamId();
+    method @Nullable public java.math.BigInteger getSymbolRate();
+    method public void setInputStreamId(@Nullable java.math.BigInteger);
+    method public void setSymbolRate(@Nullable java.math.BigInteger);
+  }
+
+  public class DvbtFrontendSettings {
+    ctor public DvbtFrontendSettings();
+    method @Nullable public java.math.BigInteger getBandwidth();
+    method @Nullable public java.math.BigInteger getIsHighPriority();
+    method @Nullable public java.math.BigInteger getTransmissionMode();
+    method public void setBandwidth(@Nullable java.math.BigInteger);
+    method public void setIsHighPriority(@Nullable java.math.BigInteger);
+    method public void setTransmissionMode(@Nullable java.math.BigInteger);
+  }
+
+  public class Dvr {
+    ctor public Dvr();
+    method @Nullable public java.math.BigInteger getBufferSize();
+    method @Nullable public android.media.tuner.testing.configuration.V1_0.DvrDataFormatEnum getDataFormat();
+    method @Nullable public java.math.BigInteger getHighThreshold();
+    method @Nullable public String getId();
+    method @Nullable public String getInputFilePath();
+    method @Nullable public java.math.BigInteger getLowThreshold();
+    method @Nullable public java.math.BigInteger getPacketSize();
+    method @Nullable public java.math.BigInteger getStatusMask();
+    method @Nullable public android.media.tuner.testing.configuration.V1_0.DvrTypeEnum getType();
+    method public void setBufferSize(@Nullable java.math.BigInteger);
+    method public void setDataFormat(@Nullable android.media.tuner.testing.configuration.V1_0.DvrDataFormatEnum);
+    method public void setHighThreshold(@Nullable java.math.BigInteger);
+    method public void setId(@Nullable String);
+    method public void setInputFilePath(@Nullable String);
+    method public void setLowThreshold(@Nullable java.math.BigInteger);
+    method public void setPacketSize(@Nullable java.math.BigInteger);
+    method public void setStatusMask(@Nullable java.math.BigInteger);
+    method public void setType(@Nullable android.media.tuner.testing.configuration.V1_0.DvrTypeEnum);
+  }
+
+  public enum DvrDataFormatEnum {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.DvrDataFormatEnum ES;
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.DvrDataFormatEnum PES;
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.DvrDataFormatEnum SHV_TLV;
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.DvrDataFormatEnum TS;
+  }
+
+  public enum DvrStatusEnum {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.DvrStatusEnum DATA_READY;
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.DvrStatusEnum HIGH_WATER;
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.DvrStatusEnum LOW_WATER;
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.DvrStatusEnum OVERFLOW;
+  }
+
+  public enum DvrTypeEnum {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.DvrTypeEnum PLAYBACK;
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.DvrTypeEnum RECORD;
+  }
+
+  public class Filter {
+    ctor public Filter();
+    method @Nullable public android.media.tuner.testing.configuration.V1_0.AvFilterSettings getAvFilterSettings_optional();
+    method @Nullable public java.math.BigInteger getBufferSize();
+    method @Nullable public String getId();
+    method @Nullable public android.media.tuner.testing.configuration.V1_0.FilterMainTypeEnum getMainType();
+    method @Nullable public java.math.BigInteger getPid();
+    method @Nullable public android.media.tuner.testing.configuration.V1_0.RecordFilterSettings getRecordFilterSettings_optional();
+    method @Nullable public android.media.tuner.testing.configuration.V1_0.SectionFilterSettings getSectionFilterSettings_optional();
+    method @Nullable public android.media.tuner.testing.configuration.V1_0.FilterSubTypeEnum getSubType();
+    method @Nullable public boolean getUseFMQ();
+    method public void setAvFilterSettings_optional(@Nullable android.media.tuner.testing.configuration.V1_0.AvFilterSettings);
+    method public void setBufferSize(@Nullable java.math.BigInteger);
+    method public void setId(@Nullable String);
+    method public void setMainType(@Nullable android.media.tuner.testing.configuration.V1_0.FilterMainTypeEnum);
+    method public void setPid(@Nullable java.math.BigInteger);
+    method public void setRecordFilterSettings_optional(@Nullable android.media.tuner.testing.configuration.V1_0.RecordFilterSettings);
+    method public void setSectionFilterSettings_optional(@Nullable android.media.tuner.testing.configuration.V1_0.SectionFilterSettings);
+    method public void setSubType(@Nullable android.media.tuner.testing.configuration.V1_0.FilterSubTypeEnum);
+    method public void setUseFMQ(@Nullable boolean);
+  }
+
+  public enum FilterMainTypeEnum {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.FilterMainTypeEnum MMTP;
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.FilterMainTypeEnum TS;
+  }
+
+  public enum FilterSubTypeEnum {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.FilterSubTypeEnum AUDIO;
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.FilterSubTypeEnum DOWNLOAD;
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.FilterSubTypeEnum MMTP;
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.FilterSubTypeEnum PCR;
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.FilterSubTypeEnum PES;
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.FilterSubTypeEnum RECORD;
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.FilterSubTypeEnum SECTION;
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.FilterSubTypeEnum TEMI;
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.FilterSubTypeEnum TS;
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.FilterSubTypeEnum UNDEFINED;
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.FilterSubTypeEnum VIDEO;
+  }
+
+  public class Frontend {
+    ctor public Frontend();
+    method @Nullable public java.math.BigInteger getConnectToCicamId();
+    method @Nullable public android.media.tuner.testing.configuration.V1_0.DvbsFrontendSettings getDvbsFrontendSettings_optional();
+    method @Nullable public android.media.tuner.testing.configuration.V1_0.DvbtFrontendSettings getDvbtFrontendSettings_optional();
+    method @Nullable public java.math.BigInteger getEndFrequency();
+    method @Nullable public java.math.BigInteger getFrequency();
+    method @Nullable public String getId();
+    method @Nullable public boolean getIsSoftwareFrontend();
+    method @Nullable public android.media.tuner.testing.configuration.V1_0.FrontendTypeEnum getType();
+    method public void setConnectToCicamId(@Nullable java.math.BigInteger);
+    method public void setDvbsFrontendSettings_optional(@Nullable android.media.tuner.testing.configuration.V1_0.DvbsFrontendSettings);
+    method public void setDvbtFrontendSettings_optional(@Nullable android.media.tuner.testing.configuration.V1_0.DvbtFrontendSettings);
+    method public void setEndFrequency(@Nullable java.math.BigInteger);
+    method public void setFrequency(@Nullable java.math.BigInteger);
+    method public void setId(@Nullable String);
+    method public void setIsSoftwareFrontend(@Nullable boolean);
+    method public void setType(@Nullable android.media.tuner.testing.configuration.V1_0.FrontendTypeEnum);
+  }
+
+  public enum FrontendTypeEnum {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.FrontendTypeEnum ANALOG;
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.FrontendTypeEnum ATSC;
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.FrontendTypeEnum ATSC3;
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.FrontendTypeEnum DTMB;
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.FrontendTypeEnum DVBC;
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.FrontendTypeEnum DVBS;
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.FrontendTypeEnum DVBT;
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.FrontendTypeEnum ISDBS;
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.FrontendTypeEnum ISDBS3;
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.FrontendTypeEnum ISDBT;
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.FrontendTypeEnum UNDEFINED;
+  }
+
+  public class HardwareConfiguration {
+    ctor public HardwareConfiguration();
+    method @Nullable public android.media.tuner.testing.configuration.V1_0.HardwareConfiguration.Descramblers getDescramblers();
+    method @Nullable public android.media.tuner.testing.configuration.V1_0.HardwareConfiguration.DiseqcMessages getDiseqcMessages();
+    method @Nullable public android.media.tuner.testing.configuration.V1_0.HardwareConfiguration.Dvrs getDvrs();
+    method @Nullable public android.media.tuner.testing.configuration.V1_0.HardwareConfiguration.Filters getFilters();
+    method @Nullable public android.media.tuner.testing.configuration.V1_0.HardwareConfiguration.Frontends getFrontends();
+    method @Nullable public android.media.tuner.testing.configuration.V1_0.HardwareConfiguration.Lnbs getLnbs();
+    method @Nullable public android.media.tuner.testing.configuration.V1_0.HardwareConfiguration.TimeFilters getTimeFilters();
+    method public void setDescramblers(@Nullable android.media.tuner.testing.configuration.V1_0.HardwareConfiguration.Descramblers);
+    method public void setDiseqcMessages(@Nullable android.media.tuner.testing.configuration.V1_0.HardwareConfiguration.DiseqcMessages);
+    method public void setDvrs(@Nullable android.media.tuner.testing.configuration.V1_0.HardwareConfiguration.Dvrs);
+    method public void setFilters(@Nullable android.media.tuner.testing.configuration.V1_0.HardwareConfiguration.Filters);
+    method public void setFrontends(@Nullable android.media.tuner.testing.configuration.V1_0.HardwareConfiguration.Frontends);
+    method public void setLnbs(@Nullable android.media.tuner.testing.configuration.V1_0.HardwareConfiguration.Lnbs);
+    method public void setTimeFilters(@Nullable android.media.tuner.testing.configuration.V1_0.HardwareConfiguration.TimeFilters);
+  }
+
+  public static class HardwareConfiguration.Descramblers {
+    ctor public HardwareConfiguration.Descramblers();
+    method @Nullable public java.util.List<android.media.tuner.testing.configuration.V1_0.Descrambler> getDescrambler();
+  }
+
+  public static class HardwareConfiguration.DiseqcMessages {
+    ctor public HardwareConfiguration.DiseqcMessages();
+    method @Nullable public java.util.List<android.media.tuner.testing.configuration.V1_0.DiseqcMessage> getDiseqcMessage();
+  }
+
+  public static class HardwareConfiguration.Dvrs {
+    ctor public HardwareConfiguration.Dvrs();
+    method @Nullable public java.util.List<android.media.tuner.testing.configuration.V1_0.Dvr> getDvr();
+  }
+
+  public static class HardwareConfiguration.Filters {
+    ctor public HardwareConfiguration.Filters();
+    method @Nullable public java.util.List<android.media.tuner.testing.configuration.V1_0.Filter> getFilter();
+  }
+
+  public static class HardwareConfiguration.Frontends {
+    ctor public HardwareConfiguration.Frontends();
+    method @Nullable public java.util.List<android.media.tuner.testing.configuration.V1_0.Frontend> getFrontend();
+  }
+
+  public static class HardwareConfiguration.Lnbs {
+    ctor public HardwareConfiguration.Lnbs();
+    method @Nullable public java.util.List<android.media.tuner.testing.configuration.V1_0.Lnb> getLnb();
+  }
+
+  public static class HardwareConfiguration.TimeFilters {
+    ctor public HardwareConfiguration.TimeFilters();
+    method @Nullable public java.util.List<android.media.tuner.testing.configuration.V1_0.TimeFilter> getTimeFilter();
+  }
+
+  public class Lnb {
+    ctor public Lnb();
+    method @Nullable public String getId();
+    method @Nullable public String getName();
+    method @Nullable public android.media.tuner.testing.configuration.V1_0.LnbPositionEnum getPosition();
+    method @Nullable public android.media.tuner.testing.configuration.V1_0.LnbToneEnum getTone();
+    method @Nullable public android.media.tuner.testing.configuration.V1_0.LnbVoltageEnum getVoltage();
+    method public void setId(@Nullable String);
+    method public void setName(@Nullable String);
+    method public void setPosition(@Nullable android.media.tuner.testing.configuration.V1_0.LnbPositionEnum);
+    method public void setTone(@Nullable android.media.tuner.testing.configuration.V1_0.LnbToneEnum);
+    method public void setVoltage(@Nullable android.media.tuner.testing.configuration.V1_0.LnbVoltageEnum);
+  }
+
+  public enum LnbPositionEnum {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.LnbPositionEnum POSITION_A;
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.LnbPositionEnum POSITION_B;
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.LnbPositionEnum UNDEFINED;
+  }
+
+  public enum LnbToneEnum {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.LnbToneEnum CONTINUOUS;
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.LnbToneEnum NONE;
+  }
+
+  public enum LnbVoltageEnum {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.LnbVoltageEnum NONE;
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.LnbVoltageEnum VOLTAGE_11V;
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.LnbVoltageEnum VOLTAGE_12V;
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.LnbVoltageEnum VOLTAGE_13V;
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.LnbVoltageEnum VOLTAGE_14V;
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.LnbVoltageEnum VOLTAGE_15V;
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.LnbVoltageEnum VOLTAGE_18V;
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.LnbVoltageEnum VOLTAGE_19V;
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.LnbVoltageEnum VOLTAGE_5V;
+  }
+
+  public class RecordFilterSettings {
+    ctor public RecordFilterSettings();
+    method @Nullable public android.media.tuner.testing.configuration.V1_0.ScIndexTypeEnum getScIndexType();
+    method @Nullable public java.math.BigInteger getTsIndexMask();
+    method public void setScIndexType(@Nullable android.media.tuner.testing.configuration.V1_0.ScIndexTypeEnum);
+    method public void setTsIndexMask(@Nullable java.math.BigInteger);
+  }
+
+  public enum ScIndexTypeEnum {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.ScIndexTypeEnum NONE;
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.ScIndexTypeEnum SC;
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.ScIndexTypeEnum SC_HEVC;
+  }
+
+  public class SectionFilterSettings {
+    ctor public SectionFilterSettings();
+    method @Nullable public boolean getIsCheckCrc();
+    method @Nullable public boolean getIsRaw();
+    method @Nullable public boolean getIsRepeat();
+    method public void setIsCheckCrc(@Nullable boolean);
+    method public void setIsRaw(@Nullable boolean);
+    method public void setIsRepeat(@Nullable boolean);
+  }
+
+  public class TimeFilter {
+    ctor public TimeFilter();
+    method @Nullable public String getId();
+    method @Nullable public java.math.BigInteger getTimeStamp();
+    method public void setId(@Nullable String);
+    method public void setTimeStamp(@Nullable java.math.BigInteger);
+  }
+
+  public class TunerConfiguration {
+    ctor public TunerConfiguration();
+    method @Nullable public android.media.tuner.testing.configuration.V1_0.DataFlowConfiguration getDataFlowConfiguration();
+    method @Nullable public android.media.tuner.testing.configuration.V1_0.HardwareConfiguration getHardwareConfiguration();
+    method @Nullable public android.media.tuner.testing.configuration.V1_0.Version getVersion();
+    method public void setDataFlowConfiguration(@Nullable android.media.tuner.testing.configuration.V1_0.DataFlowConfiguration);
+    method public void setHardwareConfiguration(@Nullable android.media.tuner.testing.configuration.V1_0.HardwareConfiguration);
+    method public void setVersion(@Nullable android.media.tuner.testing.configuration.V1_0.Version);
+  }
+
+  public enum Version {
+    method @NonNull public String getRawName();
+    enum_constant public static final android.media.tuner.testing.configuration.V1_0.Version _1_0;
+  }
+
+  public class XmlParser {
+    ctor public XmlParser();
+    method @Nullable public static android.media.tuner.testing.configuration.V1_0.TunerConfiguration read(@NonNull java.io.InputStream) throws javax.xml.datatype.DatatypeConfigurationException, java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method @Nullable public static String readText(@NonNull org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+    method public static void skip(@NonNull org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+  }
+
+}
+
diff --git a/tv/tuner/config/api/last_current.txt b/tv/tuner/config/api/last_current.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tv/tuner/config/api/last_current.txt
diff --git a/tv/tuner/config/api/last_removed.txt b/tv/tuner/config/api/last_removed.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tv/tuner/config/api/last_removed.txt
diff --git a/tv/tuner/config/api/removed.txt b/tv/tuner/config/api/removed.txt
new file mode 100644
index 0000000..d802177
--- /dev/null
+++ b/tv/tuner/config/api/removed.txt
@@ -0,0 +1 @@
+// Signature format: 2.0
diff --git a/tv/tuner/config/sample_tuner_vts_config.xml b/tv/tuner/config/sample_tuner_vts_config.xml
new file mode 100644
index 0000000..570171e
--- /dev/null
+++ b/tv/tuner/config/sample_tuner_vts_config.xml
@@ -0,0 +1,224 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!-- Copyright (C) 2021 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.
+-->
+
+<!-- The Sample Tuner Testing Configuration.
+    Name the customized xml with "tuner_vts_config.xml" and push into the device
+    "/vendor/etc" path. Please use "tuner_testing_dynamic_configuration.xsd" to verify the xml.
+    The version section contains a “version” tag in the form “major.minor” e.g version=”1.0”
+    This shows the tuner dynamic configuration version. -->
+<TunerConfiguration version="1.0" xmlns:xi="http://www.w3.org/2001/XInclude">
+    <!-- Hardware Configuration section contains the configurations of all the hardwares
+        that would be used in the tests. In the "dataFlowConfiguration" section, each data flow
+        under test has its required/optional hardwares. The ids configured in the
+        "dataFlowConfiguration" would be used to connect the hardware to each data flow test. -->
+    <hardwareConfiguration>
+        <!-- Frontends section:
+            This section contains configurations of all the frontends that would be used
+                in the tests.
+                - This section is optional and can be skipped to use the default fe settings.
+                - The default settings can be found in the sample_tuner_vts_configurations.xml.
+                - The users can also override the default frontend settings using id="FE_DEFAULT".
+                - The users can configure 1 or more frontend elements in the frontends sections.
+
+            Each frontend element contain the following attributes:
+                "id": unique id of the frontend that could be used to connect to the test the
+                    "dataFlowConfiguration"
+                "type": the frontend type. The enums are defined in the xsd.
+                "isSoftwareFrontend": if the test environment is using hardware or software
+                    frontend. If using software, a ts input file path needs to be configured.
+                "softwareFeInputPath": used as the source of the software frontend.
+                "connectToCicamId": if the device supports frontend connecting to cicam, the target
+                    cicam id needs to be configured here. Supported in Tuner 1.1 or higher.
+                "frequency": the frequency used to configure tune and scan.
+                "endFrequency": the end frequency of scan. Supported in Tuner 1.1 or higher.
+
+            Each frontend element also contains one and only one type-related "frontendSettings".
+                - The settings type should match the frontend "type" attribute.
+                - For example, when frontend type="DVBT", dvbtFrontendSettings can be configured.
+                - This is optional and skipping the settings would pass a setting with frequency
+                    config only to the hal.
+        -->
+        <frontends>
+            <frontend id="FE_DEFAULT" type="DVBT" isSoftwareFrontend="true"
+                      connectToCicamId="0" frequency="578000" endFrequency="800000">
+                <dvbtFrontendSettings bandwidth="8" transmissionMode="1" isHighPriority="1"/>
+            </frontend>
+            <frontend id="FE_DVBS_0" type="DVBS" isSoftwareFrontend="true"
+                      connectToCicamId="0" frequency="578000" endFrequency="800000">
+            </frontend>
+        </frontends>
+        <!-- Filter section:
+            This section contains configurations of all the filters that would be used in the tests.
+                - This section is optional and can be skipped to use the default filter settings.
+                - The default settings can be found in the sample_tuner_vts_configurations.xml.
+                - The users can also override the default filter settings using
+                - id="FILTER_AUDIO_DEFAULT" or "FILTER_VIDEO_DEFAULT".
+                - The users can configure 1 or more filter elements in the filters sections.
+
+            Each filter element contain the following attributes:
+                "id": unique id of the filter that could be used to connect to the test the
+                    "dataFlowConfiguration"
+                "mainType": the main filter type. The enums are defined in the xsd.
+                "subType": the sub filter type. The enums are defined in the xsd.
+                "bufferSize": the buffer size of the filter in hex.
+                "pid": the pid that would be used to configure the filter.
+                "useFMQ": if the filter uses FMQ.
+
+            Each filter element also contains at most one type-related "filterSettings".
+                - The settings type should match the filter "subType" attribute.
+                - For example, when filter subType is audio or video, the avFilterSettings can be
+                    configured.
+                - This is optional and skipping the settings would pass a setting with tpid config
+                    only to the hal.
+        -->
+        <filters>
+            <filter id="FILTER_AUDIO_DEFAULT" mainType="TS" subType="AUDIO"
+                    bufferSize="16777216" pid="257" useFMQ="false">
+                <avFilterSettings isPassthrough="false"/>
+            </filter>
+            <filter id="FILTER_VIDEO_DEFAULT" mainType="TS" subType="VIDEO"
+                    bufferSize="16777216" pid="256" useFMQ="false">
+                <avFilterSettings isPassthrough="false"/>
+            </filter>
+            <filter id="FILTER_TS_RECORD_0" mainType="TS" subType="RECORD"
+                    bufferSize="16777216" pid="257" useFMQ="false">
+                <recordFilterSettings tsIndexMask="1" scIndexType="NONE"/>
+            </filter>
+            <filter id="FILTER_TS_SECTION_0" mainType="TS" subType="SECTION"
+                    bufferSize="16777216" pid="257" useFMQ="true">
+                <sectionFilterSettings isCheckCrc="false" isRepeat="false" isRaw="false"/>
+            </filter>
+            <filter id="FILTER_TS_PCR_0" mainType="TS" subType="PCR"
+                    bufferSize="16777216" pid="256" useFMQ="false">
+            </filter>
+        </filters>
+        <!-- Dvr section:
+            This section contains configurations of all the dvrs that would be used in the tests.
+                - This section is optional and can be skipped if DVR is not supported.
+                - The users can configure 1 or more dvr elements in the dvrs sections.
+
+            Each dvr element contain the following attributes:
+                "id": unique id of the dvr that could be used to connect to the test the
+                    "dataFlowConfiguration"
+                "type": the dvr type.
+                "bufferSize": the dvr buffer size.
+                "statusMask": register callbacks of specific status.
+                "lowThreshold": the dvr status low threshold.
+                "highThreshold": the dvr status high threshold.
+                "dataFormat": the dvr data format.
+                "packetSize": the dvr packet size.
+                "inputFilePath": the dvr playback input file path. Only required in playback dvr.
+        -->
+        <dvrs>
+            <dvr id="DVR_PLAYBACK_0" type="PLAYBACK" bufferSize="4194304"
+                 statusMask="15" lowThreshold="4096" highThreshold="32767"
+                 dataFormat="TS" packetSize="188" inputFilePath="/data/local/tmp/segment000000.ts"/>
+            <dvr id="DVR_RECORD_0" type="RECORD" bufferSize="4194304"
+                 statusMask="15" lowThreshold="4096" highThreshold="32767"
+                 dataFormat="TS" packetSize="188"/>
+            <dvr id="DVR_PLAYBACK_1" type="PLAYBACK" bufferSize="4194304"
+                 statusMask="15" lowThreshold="4096" highThreshold="32767"
+                 dataFormat="ES" packetSize="188" inputFilePath="/data/local/tmp/test.es"/>
+        </dvrs>
+        <!-- Lnb section:
+            This section contains configurations of all the lnbs that would be used in the tests.
+                - This section is optional and can be skipped if LNB is not supported.
+                - The users can configure 1 or more lnb elements in the lnbs sections.
+
+            Each lnb element contain the following attributes:
+                "id": unique id of the lnb that could be used to connect to the test the
+                    "dataFlowConfiguration"
+                "name": the external lnb device name.
+                "voltage": the voltage used to config the lnb.
+                "tone": the voltage used to config the lnb.
+                "position": the voltage used to config the lnb.
+        -->
+        <diseqcMessages>
+            <diseqcMessage msgName="DISEQC_POWER_ON" msgBody="14 0 0 0 0 3"/>
+        </diseqcMessages>
+        <lnbs>
+            <lnb id="LNB_0" voltage="VOLTAGE_12V" tone="NONE" position="UNDEFINED"/>
+            <lnb id="LNB_1" name="default_lnb_external" voltage="VOLTAGE_5V"
+                            tone="NONE" position="UNDEFINED"/>
+        </lnbs>
+        <!-- TimeFilter section:
+            This section contains configurations of all the time filters that would be used in
+            the tests.
+                - This section is optional and can be skipped if Time Filter is not supported.
+                - The users can configure 1 or more timeFilter elements in the timeFilters sections.
+
+            Each timeFilter element contain the following attributes:
+                "id": unique id of the time filter that could be used to connect to the test the
+                    "dataFlowConfiguration"
+                "timeStamp": the time stamp used to config the time filter.
+        -->
+        <timeFilters>
+            <timeFilter id="TIME_FILTER_0" timeStamp="1"/>
+        </timeFilters>
+        <!-- Descrambler section:
+            This section contains configurations of all the descramblers that would be used in
+            the tests.
+                - This section is optional and can be skipped if Descrambler is not supported.
+                - The users can configure 1 or more descrambler elements in the descramblers sections.
+
+            Each Descrambler element contain the following attributes:
+                "id": unique id of the descrambler that could be used to connect to the test the
+                    "dataFlowConfiguration"
+                "casSystemId": the cas system id to connect to the descrambler.
+                "provisionStr": the provision string to use with the cas plugin.
+                "sesstionPrivatData": the session private data used to open the cas session.
+        -->
+        <descramblers>
+            <descrambler id="DESCRAMBLER_0" casSystemId="63192"/>
+        </descramblers>
+    </hardwareConfiguration>
+
+    <!-- Data flow configuration section connects each data flow under test to the ids of the
+        hardwares that would be used during the tests. -->
+    <dataFlowConfiguration>
+        <clearLiveBroadcast frontendConnection="FE_DEFAULT"
+                            audioFilterConnection="FILTER_AUDIO_DEFAULT"
+                            videoFilterConnection="FILTER_VIDEO_DEFAULT"
+                            pcrFilterConnection="FILTER_TS_PCR_0"
+                            sectionFilterConnection="FILTER_TS_SECTION_0"
+                            dvrSoftwareFeConnection="DVR_PLAYBACK_0"/>
+        <scan frontendConnection="FE_DEFAULT"/>
+        <descrambling frontendConnection="FE_DEFAULT"
+                      descramblerConnection="DESCRAMBLER_0"
+                      audioFilterConnection="FILTER_AUDIO_DEFAULT"
+                      videoFilterConnection="FILTER_VIDEO_DEFAULT"
+                      dvrSoftwareFeConnection="DVR_PLAYBACK_0"/>
+        <dvrPlayback dvrConnection="DVR_PLAYBACK_0"
+                     audioFilterConnection="FILTER_AUDIO_DEFAULT"
+                     videoFilterConnection="FILTER_VIDEO_DEFAULT"
+                     sectionFilterConnection="FILTER_TS_SECTION_0"/>
+        <dvrRecord frontendConnection="FE_DEFAULT"
+                   recordFilterConnection="FILTER_TS_RECORD_0"
+                   dvrRecordConnection="DVR_RECORD_0"
+                   dvrSoftwareFeConnection="DVR_PLAYBACK_0"/>
+        <lnbLive frontendConnection="FE_DVBS_0"
+                 audioFilterConnection="FILTER_AUDIO_DEFAULT"
+                 videoFilterConnection="FILTER_VIDEO_DEFAULT"
+                 lnbConnection="LNB_1"
+                 diseqcMsgSender="DISEQC_POWER_ON"/>
+        <lnbRecord frontendConnection="FE_DVBS_0"
+                   recordFilterConnection="FILTER_TS_RECORD_0"
+                   dvrRecordConnection="DVR_RECORD_0"
+                   lnbConnection="LNB_0"
+                   diseqcMsgSender="DISEQC_POWER_ON"/>
+        <timeFilter timeFilterConnection="TIME_FILTER_0"/>
+    </dataFlowConfiguration>
+</TunerConfiguration>
diff --git a/tv/tuner/config/tuner_testing_dynamic_configuration.xsd b/tv/tuner/config/tuner_testing_dynamic_configuration.xsd
new file mode 100644
index 0000000..3fe93ff
--- /dev/null
+++ b/tv/tuner/config/tuner_testing_dynamic_configuration.xsd
@@ -0,0 +1,644 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2021 The Android Open Source Project
+
+         Licensed under the Apache License, Version 2.0 (the "License");
+         you may not use this file except in compliance with the License.
+         You may obtain a copy of the License at
+
+                    http://www.apache.org/licenses/LICENSE-2.0
+
+         Unless required by applicable law or agreed to in writing, software
+         distributed under the License is distributed on an "AS IS" BASIS,
+         WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+         See the License for the specific language governing permissions and
+         limitations under the License.
+-->
+<xs:schema version="2.0"
+           elementFormDefault="qualified"
+           attributeFormDefault="unqualified"
+           xmlns:xs="http://www.w3.org/2001/XMLSchema">
+    <!-- List the dynamic config versions supported by tuner testing. -->
+    <xs:simpleType name="version">
+        <xs:restriction base="xs:decimal">
+            <xs:enumeration value="1.0"/>
+        </xs:restriction>
+    </xs:simpleType>
+
+    <!-- FRONTEND SESSION -->
+    <xs:simpleType name="frontendId">
+        <!-- Frontend id must be either FE_DEFAULT or FE_TYPE_NUM
+            <frontend id="FE_DVBS_0"/>
+        -->
+        <xs:restriction base="xs:string">
+            <xs:pattern value="FE_DEFAULT|FE_[A-Z]+_[0-9]+"/>
+        </xs:restriction>
+    </xs:simpleType>
+
+    <xs:simpleType name="frontendTypeEnum">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="UNDEFINED" />
+            <xs:enumeration value="ANALOG" />
+            <xs:enumeration value="ATSC" />
+            <xs:enumeration value="ATSC3"/>
+            <xs:enumeration value="DVBC"/>
+            <xs:enumeration value="DVBS"/>
+            <xs:enumeration value="DVBT"/>
+            <xs:enumeration value="ISDBS"/>
+            <xs:enumeration value="ISDBS3"/>
+            <xs:enumeration value="ISDBT"/>
+            <xs:enumeration value="DTMB"/>
+        </xs:restriction>
+    </xs:simpleType>
+
+    <xs:complexType name="dvbtFrontendSettings">
+        <xs:attribute name="bandwidth" type="xs:nonNegativeInteger" use="required"/>
+        <xs:attribute name="transmissionMode" type="xs:nonNegativeInteger" use="required"/>
+        <xs:attribute name="isHighPriority" type="xs:nonNegativeInteger" use="required"/>
+    </xs:complexType>
+    <xs:complexType name="dvbsFrontendSettings">
+        <xs:attribute name="inputStreamId" type="xs:nonNegativeInteger" use="required"/>
+        <xs:attribute name="symbolRate" type="xs:nonNegativeInteger" use="required"/>
+    </xs:complexType>
+
+    <xs:complexType name="frontend">
+        <xs:annotation>
+            <xs:documentation>
+                Each frontend element contain the following attributes:
+                    "id": unique id of the frontend that could be used to connect to the test the
+                        "dataFlowConfiguration"
+                    "type": the frontend type. The enums are defined in the xsd.
+                    "isSoftwareFrontend": if the test environment is using hardware or software
+                        frontend. If using software, a ts input file path needs to be configured.
+                    "softwareFeInputPath": used as the source of the software frontend.
+                    "connectToCicamId": if the device supports frontend connecting to cicam, the
+                        target cicam id needs to be configured here. Supported in Tuner 1.1 or
+                        higher.
+                    "frequency": the frequency used to configure tune and scan.
+                    "endFrequency": the end frequency of scan. Supported in Tuner 1.1 or higher.
+
+                Each frontend element also contains at most one type-related "frontendSettings".
+                    - The settings type should match the frontend "type" attribute.
+                    - For example, when frontend type="DVBT", dvbtFrontendSettings can be
+                        configured.
+                    - This is optional and skipping the settings would pass a setting with frequency
+                        config only to the hal.
+            </xs:documentation>
+        </xs:annotation>
+        <xs:choice minOccurs="0" maxOccurs="1">
+            <!-- TODO: b/182519645 finish all the frontend settings structures. -->
+            <!--xs:element name="analog" type="analogSettings"/>
+            <xs:element name="atsc" type="atscSettings"/>
+            <xs:element name="atsc3" type="atsc3Settings"/>
+            <xs:element name="dvbc" type="dvbcSettings"/-->
+            <xs:element name="dvbsFrontendSettings" type="dvbsFrontendSettings"/>
+            <xs:element name="dvbtFrontendSettings" type="dvbtFrontendSettings"/>
+            <!--xs:element name="isdbs" type="isdbsSettings"/>
+            <xs:element name="isdbs3" type="isdbs3Settings"/>
+            <xs:element name="isdbt" type="isdbtSettings"/>
+            <xs:element name="dtmb" type="dtmbSettings"/-->
+        </xs:choice>
+        <xs:attribute name="id" type="frontendId" use="required"/>
+        <xs:attribute name="type" type="frontendTypeEnum" use="required"/>
+        <!-- A dvr connection is required in the data flow config section when
+            "isSoftwareFrontend" is true. -->
+        <xs:attribute name="isSoftwareFrontend" type="xs:boolean" use="required"/>
+        <xs:attribute name="frequency" type="xs:nonNegativeInteger" use="required"/>
+        <xs:attribute name="connectToCicamId" type="xs:nonNegativeInteger" use="optional"/>
+        <xs:attribute name="endFrequency" type="xs:nonNegativeInteger" use="optional"/>
+    </xs:complexType>
+
+    <!-- FILTER SESSION -->
+    <xs:simpleType name="filterId">
+        <!-- Filter id must be either FILTER_AUDIO_DEFAULT or FILTER_VIDEO_DEFAULT
+             or FILTER_MAINTYPE_SUBTYPE_NUM
+            <filter id="FILTER_TS_AUDIO_0"/>
+        -->
+        <xs:restriction base="xs:string">
+            <xs:pattern value="FILTER_AUDIO_DEFAULT|FILTER_VIDEO_DEFAULT|FILTER_[A-Z]+_[A-Z]+_[0-9]+"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <!-- A list of filter ids that could be used in the data flow configurations to connect
+        filters under testing. -->
+    <xs:simpleType name="filterConnections">
+        <xs:list itemType="filterId" />
+    </xs:simpleType>
+    <!-- DemuxFilterRecordSettings::tsIndexMask -->
+    <xs:simpleType name="tsIndexMask">
+        <xs:restriction base="xs:integer">
+            <xs:minInclusive value="0"/>
+            <xs:maxInclusive value="8191"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <!-- DemuxFilterRecordSettings::scIndexType -->
+    <xs:simpleType name="scIndexTypeEnum">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="NONE" />
+            <xs:enumeration value="SC" />
+            <xs:enumeration value="SC_HEVC"/>
+        </xs:restriction>
+    </xs:simpleType>
+
+    <xs:simpleType name="filterMainTypeEnum">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="TS" />
+            <xs:enumeration value="MMTP" />
+            <!-- TODO: b/182519645 Support IP/TLV/ALP filter config
+            <xs:enumeration value="IP"/>
+            <xs:enumeration value="TLV"/>
+            <xs:enumeration value="ALP"/-->
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:simpleType name="filterSubTypeEnum">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="UNDEFINED" />
+            <xs:enumeration value="SECTION" />
+            <xs:enumeration value="PES" />
+            <xs:enumeration value="TS"/>
+            <xs:enumeration value="AUDIO"/>
+            <xs:enumeration value="VIDEO"/>
+            <xs:enumeration value="PCR"/>
+            <xs:enumeration value="RECORD"/>
+            <xs:enumeration value="TEMI"/>
+            <xs:enumeration value="MMTP"/>
+            <xs:enumeration value="DOWNLOAD"/>
+        </xs:restriction>
+    </xs:simpleType>
+
+    <xs:complexType name="avFilterSettings">
+        <xs:attribute name="isPassthrough" type="xs:boolean" use="required"/>
+    </xs:complexType>
+    <xs:complexType name="sectionFilterSettings">
+        <xs:attribute name="isCheckCrc" type="xs:boolean" use="required"/>
+        <xs:attribute name="isRepeat" type="xs:boolean" use="required"/>
+        <xs:attribute name="isRaw" type="xs:boolean" use="required"/>
+    </xs:complexType>
+    <xs:complexType name="recordFilterSettings">
+        <xs:attribute name="tsIndexMask" type="tsIndexMask" use="required"/>
+        <xs:attribute name="scIndexType" type="scIndexTypeEnum" use="required"/>
+    </xs:complexType>
+
+    <xs:complexType name="filter">
+        <xs:annotation>
+            <xs:documentation>
+                Each filter element contain the following attributes:
+                    "id": unique id of the filter that could be used to connect to the test the
+                        "dataFlowConfiguration"
+                    "mainType": the main filter type. The enums are defined in the xsd.
+                    "subType": the sub filter type. The enums are defined in the xsd.
+                    "bufferSize": the buffer size of the filter in hex.
+                    "pid": the pid that would be used to configure the filter.
+                    "useFMQ": if the filter uses FMQ.
+
+                Each filter element also contains at most one type-related "filterSettings".
+                    - The settings type should match the filter "subType" attribute.
+                    - For example, when filter subType is audio or video, the avFilterSettings
+                        can be configured.
+                    - This is optional and skipping the settings would pass a setting with tpid
+                        config only to the hal.
+            </xs:documentation>
+        </xs:annotation>
+        <xs:choice minOccurs="0" maxOccurs="1">
+            <!-- TODO: b/182519645 finish all the filter settings structures. -->
+            <xs:element name="sectionFilterSettings" type="sectionFilterSettings"/>
+            <xs:element name="avFilterSettings" type="avFilterSettings"/>
+            <xs:element name="recordFilterSettings" type="recordFilterSettings"/>
+            <!--xs:element name="pes" type="pesFilterSettings"/>
+            <xs:element name="download" type="downloadFilterSettings"/-->
+        </xs:choice>
+        <xs:attribute name="id" type="filterId" use="required"/>
+        <xs:attribute name="mainType" type="filterMainTypeEnum" use="required"/>
+        <xs:attribute name="subType" type="filterSubTypeEnum" use="required"/>
+        <xs:attribute name="bufferSize" type="xs:nonNegativeInteger" use="required"/>
+        <xs:attribute name="pid" type="xs:nonNegativeInteger" use="optional"/>
+        <xs:attribute name="useFMQ" type="xs:boolean" use="required"/>
+    </xs:complexType>
+
+    <!-- DVR SESSION -->
+    <xs:simpleType name="dvrId">
+        <!-- Dvr id must be DVR_TYPE_NUM. <dvr id="DVR_PLAYBACK_0"/> -->
+        <xs:restriction base="xs:string">
+            <xs:pattern value="DVR_RECORD_[0-9]+|DVR_PLAYBACK_[0-9]+"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:simpleType name="dvrStatusMask">
+        <!-- Dvr status mask must masking the <dvrStatusEnum> -->
+        <xs:restriction base="xs:integer">
+            <xs:minInclusive value="0"/>
+            <xs:maxInclusive value="15"/>
+        </xs:restriction>
+    </xs:simpleType>
+
+    <xs:simpleType name="dvrStatusEnum">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="DATA_READY" />
+            <xs:enumeration value="LOW_WATER" />
+            <xs:enumeration value="HIGH_WATER" />
+            <xs:enumeration value="OVERFLOW" />
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:simpleType name="dvrTypeEnum">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="PLAYBACK" />
+            <xs:enumeration value="RECORD" />
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:simpleType name="dvrDataFormatEnum">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="TS" />
+            <xs:enumeration value="PES" />
+            <xs:enumeration value="ES" />
+            <xs:enumeration value="SHV_TLV" />
+        </xs:restriction>
+    </xs:simpleType>
+
+    <xs:complexType name="dvr">
+        <xs:annotation>
+            <xs:documentation>
+                Each dvr element contain the following attributes:
+                    "id": unique id of the dvr that could be used to connect to the test the
+                        "dataFlowConfiguration"
+                    "type": the dvr type.
+                    "bufferSize": the dvr buffer size.
+                    "statusMask": register callbacks of specific status.
+                    "lowThreshold": the dvr status low threshold.
+                    "highThreshold": the dvr status high threshold.
+                    "dataFormat": the dvr data format.
+                    "packetSize": the dvr packet size.
+                    "inputFilePath": the dvr playback input file path. Only required in playback
+                        dvr.
+            </xs:documentation>
+        </xs:annotation>
+        <xs:attribute name="id" type="dvrId" use="required"/>
+        <xs:attribute name="type" type="dvrTypeEnum" use="required"/>
+        <xs:attribute name="bufferSize" type="xs:nonNegativeInteger" use="required"/>
+        <xs:attribute name="statusMask" type="dvrStatusMask" use="required"/>
+        <xs:attribute name="lowThreshold" type="xs:nonNegativeInteger" use="required"/>
+        <xs:attribute name="highThreshold" type="xs:nonNegativeInteger" use="required"/>
+        <xs:attribute name="dataFormat" type="dvrDataFormatEnum" use="required"/>
+        <xs:attribute name="packetSize" type="xs:nonNegativeInteger" use="required"/>
+        <xs:attribute name="inputFilePath" type="xs:anyURI" use="optional"/>
+    </xs:complexType>
+
+    <!-- LNB SESSION -->
+    <xs:simpleType name="lnbId">
+        <!-- Lnb id must be LNB_NUM: <lnb id="LNB_10"/> -->
+        <xs:restriction base="xs:string">
+            <xs:pattern value="LNB_[0-9]+"/>
+        </xs:restriction>
+    </xs:simpleType>
+
+    <xs:simpleType name="lnbVoltageEnum">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="NONE" />
+            <xs:enumeration value="VOLTAGE_5V" />
+            <xs:enumeration value="VOLTAGE_11V" />
+            <xs:enumeration value="VOLTAGE_12V"/>
+            <xs:enumeration value="VOLTAGE_13V"/>
+            <xs:enumeration value="VOLTAGE_14V"/>
+            <xs:enumeration value="VOLTAGE_15V"/>
+            <xs:enumeration value="VOLTAGE_18V"/>
+            <xs:enumeration value="VOLTAGE_19V"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:simpleType name="lnbToneEnum">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="NONE" />
+            <xs:enumeration value="CONTINUOUS" />
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:simpleType name="lnbPositionEnum">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="UNDEFINED" />
+            <xs:enumeration value="POSITION_A" />
+            <xs:enumeration value="POSITION_B" />
+        </xs:restriction>
+    </xs:simpleType>
+
+    <!-- Diseqc Messages that would be used to send to the lnb under test. -->
+    <xs:simpleType name="diseqcMsgName">
+        <xs:restriction base="xs:string">
+            <xs:pattern value="[A-Z_]+"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:simpleType name="diseqcMsgBody">
+        <xs:list itemType="xs:unsignedByte"/>
+    </xs:simpleType>
+    <xs:complexType name="diseqcMessage">
+        <xs:attribute name="msgName" type="diseqcMsgName"/>
+        <xs:attribute name="msgBody" type="diseqcMsgBody"/>
+    </xs:complexType>
+    <xs:simpleType name="diseqcMsgSender">
+        <xs:list itemType="diseqcMsgName"/>
+    </xs:simpleType>
+
+    <xs:complexType name="lnb">
+        <xs:annotation>
+            <xs:documentation>
+                Each lnb element contain the following attributes:
+                    "id": unique id of the lnb that could be used to connect to the test the
+                        "dataFlowConfiguration"
+                    "name": the external lnb device name.
+                    "voltage": the voltage used to config the lnb.
+                    "tone": the voltage used to config the lnb.
+                    "position": the voltage used to config the lnb.
+            </xs:documentation>
+        </xs:annotation>
+        <xs:attribute name="id" type="lnbId" use="required"/>
+        <!-- Only required on external lnb with no device id. -->
+        <xs:attribute name="name" type="xs:string" use="optional"/>
+        <xs:attribute name="voltage" type="lnbVoltageEnum" use="required"/>
+        <xs:attribute name="tone" type="lnbToneEnum" use="required"/>
+        <xs:attribute name="position" type="lnbPositionEnum" use="required"/>
+    </xs:complexType>
+
+    <!-- TIME FILTER SESSION -->
+    <xs:simpleType name="timeFilterId">
+        <!-- Time Filter id must be TIME_FILTER_NUM: <timeFilter id="TIME_FILTER_1"/> -->
+        <xs:restriction base="xs:string">
+            <xs:pattern value="TIME_FILTER_[0-9]+"/>
+        </xs:restriction>
+    </xs:simpleType>
+
+    <xs:complexType name="timeFilter">
+        <xs:annotation>
+            <xs:documentation>
+                Each timeFilter element contain the following attributes:
+                    "id": unique id of the time filter that could be used to connect to the test the
+                        "dataFlowConfiguration"
+                    "timeStamp": the time stamp used to config the time filter.
+            </xs:documentation>
+        </xs:annotation>
+        <xs:attribute name="id" type="timeFilterId" use="required"/>
+        <xs:attribute name="timeStamp" type="xs:nonNegativeInteger" use="required"/>
+    </xs:complexType>
+
+    <!-- DESCRAMBLER SESSION -->
+    <xs:simpleType name="descramblerId">
+        <!-- Descrambler id must be DESCRAMBLER_NUM: <descrambler id="DESCRAMBLER_2"/> -->
+        <xs:restriction base="xs:string">
+            <xs:pattern value="DESCRAMBLER_[0-9]+"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:simpleType name="sessionPrivateData">
+        <xs:list itemType="xs:unsignedByte"/>
+    </xs:simpleType>
+
+    <xs:complexType name="descrambler">
+        <xs:annotation>
+            <xs:documentation>
+                Each descrambler element contain the following attributes:
+                    "id": unique id of the descrambler that could be used to connect to the test the
+                        "dataFlowConfiguration"
+                    "casSystemId": the cas system id to connect to the descrambler.
+                    "provisionStr": the provision string to use with the cas plugin.
+                    "sesstionPrivatData": the session private data used to open the cas session.
+            </xs:documentation>
+        </xs:annotation>
+        <xs:attribute name="id" type="descramblerId" use="required"/>
+        <xs:attribute name="casSystemId" type="xs:nonNegativeInteger" use="required"/>
+        <xs:attribute name="provisionStr" type="xs:string" use="required"/>
+        <xs:attribute name="sesstionPrivatData" type="sessionPrivateData" use="optional"/>
+    </xs:complexType>
+
+    <!-- HARDWARE CONFIGURATION SESSION -->
+    <xs:complexType name="hardwareConfiguration">
+        <xs:sequence>
+            <xs:element name="frontends" minOccurs="0" maxOccurs="1">
+                <xs:complexType>
+                    <xs:annotation>
+                        <xs:documentation xml:lang="en">
+                            This section contains configurations of all the frontends that would be
+                                used in the tests.
+                                - This section is optional and can be skipped to use the default
+                                    fe settings.
+                                - The default settings can be found in the
+                                    sample_tuner_vts_configurations.xml.
+                                - The users can also override the default frontend settings using
+                                    id="FE_DEFAULT".
+                                - The users can configure 1 or more frontend elements in the
+                                    frontends sections.
+                        </xs:documentation>
+                    </xs:annotation>
+                    <xs:sequence>
+                        <xs:element name="frontend" type="frontend" minOccurs="1" maxOccurs="unbounded"/>
+                    </xs:sequence>
+                </xs:complexType>
+            </xs:element>
+            <xs:element name="filters" minOccurs="0" maxOccurs="1">
+                <xs:complexType>
+                    <xs:annotation>
+                        <xs:documentation xml:lang="en">
+                            This section contains configurations of all the filters that would be
+                                used in the tests.
+                                - This section is optional and can be skipped to use the default
+                                    filter settings.
+                                - The default settings can be found in the
+                                    sample_tuner_vts_configurations.xml.
+                                - The users can also override the default filter settings using
+                                - id="FILTER_AUDIO_DEFAULT" or "FILTER_VIDEO_DEFAULT".
+                                - The users can configure 1 or more filter elements in the filters
+                                    sections.
+                        </xs:documentation>
+                    </xs:annotation>
+                    <xs:sequence>
+                        <xs:element name="filter" type="filter" minOccurs="1" maxOccurs="unbounded"/>
+                    </xs:sequence>
+                </xs:complexType>
+            </xs:element>
+            <xs:element name="dvrs" minOccurs="0" maxOccurs="1">
+                <xs:complexType>
+                    <xs:annotation>
+                        <xs:documentation xml:lang="en">
+                            This section contains configurations of all the dvrs that would be used
+                                in the tests.
+                                - This section is optional and can be skipped if the device does
+                                    not support dvr.
+                                - The users can configure 1 or more dvr elements in the dvrs
+                                   sections.
+                        </xs:documentation>
+                    </xs:annotation>
+                    <xs:sequence>
+                        <xs:element name="dvr" type="dvr" minOccurs="1" maxOccurs="unbounded"/>
+                    </xs:sequence>
+                </xs:complexType>
+            </xs:element>
+            <xs:element name="diseqcMessages" minOccurs="0" maxOccurs="1">
+                <xs:complexType>
+                    <xs:annotation>
+                        <xs:documentation xml:lang="en">
+                            This section contains configurations of all the diseqc messages that
+                            would be used in the lnb tests.
+                                - This section is optional and can be skipped if lnb is not suppoted
+                                - The users can configure 1 or more message elements in the
+                                    diseqcMessages sections.
+                        </xs:documentation>
+                    </xs:annotation>
+                    <xs:sequence>
+                        <xs:element name="diseqcMessage" type="diseqcMessage" minOccurs="1" maxOccurs="unbounded"/>
+                    </xs:sequence>
+                </xs:complexType>
+            </xs:element>
+            <xs:element name="lnbs" minOccurs="0" maxOccurs="1">
+                <xs:complexType>
+                    <xs:annotation>
+                        <xs:documentation xml:lang="en">
+                            This section contains configurations of all the lnbs that would be used
+                                in the tests.
+                                - This section is optional and can be skipped if lnb is not suppoted
+                                - The users can configure 1 or more lnb elements in the lnbs
+                                    sections.
+                        </xs:documentation>
+                    </xs:annotation>
+                    <xs:sequence>
+                        <xs:element name="lnb" type="lnb" minOccurs="1" maxOccurs="unbounded"/>
+                    </xs:sequence>
+                </xs:complexType>
+            </xs:element>
+            <xs:element name="timeFilters" minOccurs="0" maxOccurs="1">
+                <xs:complexType>
+                    <xs:annotation>
+                        <xs:documentation xml:lang="en">
+                            This section contains configurations of all the time filters that would
+                                be used in the tests.
+                                - This section is optional and can be skipped if time filter is
+                                    not supported.
+                                - The users can configure 1 or more time filter elements in the
+                                    time filters sections.
+                        </xs:documentation>
+                    </xs:annotation>
+                    <xs:sequence>
+                        <xs:element name="timeFilter" type="timeFilter" minOccurs="1" maxOccurs="unbounded"/>
+                    </xs:sequence>
+                </xs:complexType>
+            </xs:element>
+            <xs:element name="descramblers" minOccurs="0" maxOccurs="1">
+                <xs:complexType>
+                    <xs:annotation>
+                        <xs:documentation xml:lang="en">
+                            This section contains configurations of all the descramblers that would
+                                be used in the tests.
+                                - This section is optional and can be skipped if descrambling is not
+                                    supported.
+                                - The users can configure 1 or more descrambler elements in the
+                                    descramblers sections.
+                        </xs:documentation>
+                    </xs:annotation>
+                    <xs:sequence>
+                        <xs:element name="descrambler" type="descrambler" minOccurs="1" maxOccurs="unbounded"/>
+                    </xs:sequence>
+                </xs:complexType>
+            </xs:element>
+        </xs:sequence>
+    </xs:complexType>
+
+    <!-- DATA FLOW CONFIGURATION SESSION -->
+    <xs:complexType name="dataFlowConfiguration">
+        <xs:sequence>
+            <xs:element name="clearLiveBroadcast" minOccurs="1" maxOccurs="1">
+                <xs:complexType>
+                    <xs:attribute name="frontendConnection" type="frontendId" use="required"/>
+                    <xs:attribute name="audioFilterConnection" type="filterId" use="required"/>
+                    <xs:attribute name="videoFilterConnection" type="filterId" use="required"/>
+                    <xs:attribute name="pcrFilterConnection" type="filterId" use="optional"/>
+                    <xs:attribute name="sectionFilterConnection" type="filterId" use="optional"/>
+                    <!-- TODO: b/182519645 allow the users to insert extra filters -->
+                    <!-- DVR is only required when the frontend is using the software input -->
+                    <xs:attribute name="dvrSoftwareFeConnection" type="dvrId" use="optional"/>
+                </xs:complexType>
+            </xs:element>
+            <xs:element name="scan" minOccurs="1" maxOccurs="1">
+                <xs:complexType>
+                    <xs:attribute name="frontendConnection" type="frontendId" use="required"/>
+                </xs:complexType>
+            </xs:element>
+            <xs:element name="descrambling" minOccurs="0" maxOccurs="1">
+                <xs:complexType>
+                    <xs:attribute name="frontendConnection" type="frontendId" use="required"/>
+                    <xs:attribute name="descramblerConnection" type="descramblerId" use="required"/>
+                    <xs:attribute name="audioFilterConnection" type="filterId" use="required"/>
+                    <xs:attribute name="videoFilterConnection" type="filterId" use="required"/>
+                    <!-- TODO: b/182519645 allow the users to insert extra filters -->
+                    <!-- DVR is only required when the frontend is using the software input -->
+                    <xs:attribute name="dvrSoftwareFeConnection" type="dvrId" use="optional"/>
+                </xs:complexType>
+            </xs:element>
+            <xs:element name="dvrPlayback" minOccurs="0" maxOccurs="1">
+                <xs:complexType>
+                    <xs:attribute name="dvrConnection" type="dvrId" use="required"/>
+                    <xs:attribute name="audioFilterConnection" type="filterId" use="required"/>
+                    <xs:attribute name="videoFilterConnection" type="filterId" use="required"/>
+                    <xs:attribute name="sectionFilterConnection" type="filterId" use="optional"/>
+                    <!-- TODO: b/182519645 allow the users to insert extra filters -->
+                </xs:complexType>
+            </xs:element>
+            <xs:element name="dvrRecord" minOccurs="0" maxOccurs="1">
+                <xs:complexType>
+                    <xs:attribute name="frontendConnection" type="frontendId" use="required"/>
+                    <xs:attribute name="dvrRecordConnection" type="dvrId" use="required"/>
+                    <!-- DVR is only required when the frontend is using the software input -->
+                    <xs:attribute name="dvrSoftwareFeConnection" type="dvrId" use="optional"/>
+                    <xs:attribute name="recordFilterConnection" type="filterId" use="required"/>
+                </xs:complexType>
+            </xs:element>
+            <xs:element name="lnbLive" minOccurs="0" maxOccurs="1">
+                <xs:complexType>
+                    <xs:attribute name="frontendConnection" type="frontendId" use="required"/>
+                    <xs:attribute name="audioFilterConnection" type="filterId" use="required"/>
+                    <xs:attribute name="videoFilterConnection" type="filterId" use="required"/>
+                    <xs:attribute name="lnbConnection" type="lnbId" use="required"/>
+                    <xs:attribute name="diseqcMsgSender" type="diseqcMsgSender" use="optional"/>
+                    <!-- TODO: b/182519645 allow the users to insert extra filters -->
+                </xs:complexType>
+            </xs:element>
+            <xs:element name="lnbRecord" minOccurs="0" maxOccurs="1">
+                <xs:complexType>
+                    <xs:attribute name="frontendConnection" type="frontendId" use="required"/>
+                    <xs:attribute name="recordFilterConnection" type="filterId" use="required"/>
+                    <xs:attribute name="dvrRecordConnection" type="dvrId" use="required"/>
+                    <xs:attribute name="lnbConnection" type="lnbId" use="required"/>
+                    <xs:attribute name="diseqcMsgSender" type="diseqcMsgSender" use="optional"/>
+                </xs:complexType>
+            </xs:element>
+            <xs:element name="timeFilter" minOccurs="0" maxOccurs="1">
+                <xs:complexType>
+                    <xs:attribute name="timeFilterConnection" type="timeFilterId" use="required"/>
+                </xs:complexType>
+            </xs:element>
+        </xs:sequence>
+    </xs:complexType>
+
+    <!-- Full Tuner Configuration. This is the root element of the configuration xml. -->
+    <xs:element name="TunerConfiguration">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element name="hardwareConfiguration" type="hardwareConfiguration" minOccurs="1" maxOccurs="1"/>
+                <xs:element name="dataFlowConfiguration" type="dataFlowConfiguration" minOccurs="1" maxOccurs="1"/>
+            </xs:sequence>
+            <xs:attribute name="version" type="version"/>
+        </xs:complexType>
+        <xs:key name="frontendIdUniqueness">
+            <xs:selector xpath="hardwareConfiguration/frontends/frontend"/>
+            <xs:field xpath="@id"/>
+        </xs:key>
+        <xs:key name="filterIdUniqueness">
+            <xs:selector xpath="hardwareConfiguration/filters/filter"/>
+            <xs:field xpath="@id"/>
+        </xs:key>
+        <xs:key name="dvrIdUniqueness">
+            <xs:selector xpath="hardwareConfiguration/dvrs/dvr"/>
+            <xs:field xpath="@id"/>
+        </xs:key>
+        <xs:key name="lnbIdUniqueness">
+            <xs:selector xpath="hardwareConfiguration/lnbs/lnb"/>
+            <xs:field xpath="@id"/>
+        </xs:key>
+        <xs:key name="timeFilterIdUniqueness">
+            <xs:selector xpath="hardwareConfiguration/timeFilters/timeFilter"/>
+            <xs:field xpath="@id"/>
+        </xs:key>
+        <xs:key name="descramblerIdUniqueness">
+            <xs:selector xpath="hardwareConfiguration/descramblers/descrambler"/>
+            <xs:field xpath="@id"/>
+        </xs:key>
+    </xs:element>
+</xs:schema>
diff --git a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
index a9d1ed5..4d03ebf 100644
--- a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
+++ b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
@@ -553,8 +553,6 @@
 }
 
 TEST_P(VibratorAidl, ComposeCallback) {
-    constexpr std::chrono::milliseconds allowedLatency{10};
-
     if (capabilities & IVibrator::CAP_COMPOSE_EFFECTS) {
         std::vector<CompositePrimitive> supported;
 
@@ -586,17 +584,16 @@
                 << toString(primitive);
             duration = std::chrono::milliseconds(durationMs);
 
+            start = high_resolution_clock::now();
             EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, callback).exceptionCode())
                 << toString(primitive);
-            start = high_resolution_clock::now();
 
-            EXPECT_EQ(completionFuture.wait_for(duration + allowedLatency), std::future_status::ready)
+            EXPECT_EQ(completionFuture.wait_for(duration * 2), std::future_status::ready)
                 << toString(primitive);
             end = high_resolution_clock::now();
 
             elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
-            EXPECT_LE(elapsed.count(), (duration + allowedLatency).count()) << toString(primitive);
-            EXPECT_GE(elapsed.count(), (duration - allowedLatency).count()) << toString(primitive);
+            EXPECT_GE(elapsed.count(), duration.count()) << toString(primitive);
         }
     }
 }
diff --git a/weaver/aidl/aidl_api/android.hardware.weaver/current/android/hardware/weaver/IWeaver.aidl b/weaver/aidl/aidl_api/android.hardware.weaver/current/android/hardware/weaver/IWeaver.aidl
index 29bd9a9..61627d9 100644
--- a/weaver/aidl/aidl_api/android.hardware.weaver/current/android/hardware/weaver/IWeaver.aidl
+++ b/weaver/aidl/aidl_api/android.hardware.weaver/current/android/hardware/weaver/IWeaver.aidl
@@ -12,7 +12,8 @@
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
- *////////////////////////////////////////////////////////////////////////////////
+ */
+///////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -37,6 +38,6 @@
   android.hardware.weaver.WeaverReadResponse read(in int slotId, in byte[] key);
   void write(in int slotId, in byte[] key, in byte[] value);
   const int STATUS_FAILED = 1;
-  const int INCORRECT_KEY = 2;
-  const int THROTTLE = 3;
+  const int STATUS_INCORRECT_KEY = 2;
+  const int STATUS_THROTTLE = 3;
 }
diff --git a/weaver/aidl/aidl_api/android.hardware.weaver/current/android/hardware/weaver/WeaverConfig.aidl b/weaver/aidl/aidl_api/android.hardware.weaver/current/android/hardware/weaver/WeaverConfig.aidl
index 239cdac..7491f32 100644
--- a/weaver/aidl/aidl_api/android.hardware.weaver/current/android/hardware/weaver/WeaverConfig.aidl
+++ b/weaver/aidl/aidl_api/android.hardware.weaver/current/android/hardware/weaver/WeaverConfig.aidl
@@ -12,7 +12,8 @@
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
- *////////////////////////////////////////////////////////////////////////////////
+ */
+///////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -33,7 +34,7 @@
 package android.hardware.weaver;
 @VintfStability
 parcelable WeaverConfig {
-  long slots;
-  long keySize;
-  long valueSize;
+  int slots;
+  int keySize;
+  int valueSize;
 }
diff --git a/weaver/aidl/aidl_api/android.hardware.weaver/current/android/hardware/weaver/WeaverReadResponse.aidl b/weaver/aidl/aidl_api/android.hardware.weaver/current/android/hardware/weaver/WeaverReadResponse.aidl
index 7e5db59..47ee4c8 100644
--- a/weaver/aidl/aidl_api/android.hardware.weaver/current/android/hardware/weaver/WeaverReadResponse.aidl
+++ b/weaver/aidl/aidl_api/android.hardware.weaver/current/android/hardware/weaver/WeaverReadResponse.aidl
@@ -12,7 +12,8 @@
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
- *////////////////////////////////////////////////////////////////////////////////
+ */
+///////////////////////////////////////////////////////////////////////////////
 // THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/weaver/aidl/android/hardware/weaver/IWeaver.aidl b/weaver/aidl/android/hardware/weaver/IWeaver.aidl
index ebbfabe..f51034a 100644
--- a/weaver/aidl/android/hardware/weaver/IWeaver.aidl
+++ b/weaver/aidl/android/hardware/weaver/IWeaver.aidl
@@ -46,8 +46,8 @@
      * Read binder calls may return a ServiceSpecificException with the following error codes.
      */
     const int STATUS_FAILED = 1;
-    const int INCORRECT_KEY = 2;
-    const int THROTTLE = 3;
+    const int STATUS_INCORRECT_KEY = 2;
+    const int STATUS_THROTTLE = 3;
 
     /**
      * Attempts to retrieve the value stored in the identified slot.
diff --git a/weaver/aidl/android/hardware/weaver/WeaverConfig.aidl b/weaver/aidl/android/hardware/weaver/WeaverConfig.aidl
index 75d961e..a156a7b 100644
--- a/weaver/aidl/android/hardware/weaver/WeaverConfig.aidl
+++ b/weaver/aidl/android/hardware/weaver/WeaverConfig.aidl
@@ -21,14 +21,14 @@
     /**
      * The number of slots available.
      */
-    long slots;
+    int slots;
     /**
      * The number of bytes used for a key.
      */
-    long keySize;
+    int keySize;
     /**
      * The number of bytes used for a value.
      */
-    long valueSize;
+    int valueSize;
 }
 
diff --git a/weaver/aidl/vts/VtsHalWeaverTargetTest.cpp b/weaver/aidl/vts/VtsHalWeaverTargetTest.cpp
index 7d8daa2..878c762 100644
--- a/weaver/aidl/vts/VtsHalWeaverTargetTest.cpp
+++ b/weaver/aidl/vts/VtsHalWeaverTargetTest.cpp
@@ -156,7 +156,7 @@
 
     ASSERT_FALSE(readRet.isOk());
     ASSERT_EQ(EX_SERVICE_SPECIFIC, readRet.getExceptionCode());
-    ASSERT_EQ(IWeaver::INCORRECT_KEY, readRet.getServiceSpecificError());
+    ASSERT_EQ(IWeaver::STATUS_INCORRECT_KEY, readRet.getServiceSpecificError());
     EXPECT_TRUE(readValue.empty());
 }
 
diff --git a/wifi/1.0/vts/OWNERS b/wifi/1.0/vts/OWNERS
index 8bfb148..e7b2fc5 100644
--- a/wifi/1.0/vts/OWNERS
+++ b/wifi/1.0/vts/OWNERS
@@ -1,2 +1,2 @@
-rpius@google.com
+kumaranand@google.com
 etancohen@google.com
diff --git a/wifi/1.1/vts/OWNERS b/wifi/1.1/vts/OWNERS
index 8bfb148..e7b2fc5 100644
--- a/wifi/1.1/vts/OWNERS
+++ b/wifi/1.1/vts/OWNERS
@@ -1,2 +1,2 @@
-rpius@google.com
+kumaranand@google.com
 etancohen@google.com
diff --git a/wifi/1.2/vts/OWNERS b/wifi/1.2/vts/OWNERS
index 8bfb148..e7b2fc5 100644
--- a/wifi/1.2/vts/OWNERS
+++ b/wifi/1.2/vts/OWNERS
@@ -1,2 +1,2 @@
-rpius@google.com
+kumaranand@google.com
 etancohen@google.com
diff --git a/wifi/1.3/vts/OWNERS b/wifi/1.3/vts/OWNERS
index 8bfb148..e7b2fc5 100644
--- a/wifi/1.3/vts/OWNERS
+++ b/wifi/1.3/vts/OWNERS
@@ -1,2 +1,2 @@
-rpius@google.com
+kumaranand@google.com
 etancohen@google.com
diff --git a/wifi/1.4/vts/OWNERS b/wifi/1.4/vts/OWNERS
index 8bfb148..e7b2fc5 100644
--- a/wifi/1.4/vts/OWNERS
+++ b/wifi/1.4/vts/OWNERS
@@ -1,2 +1,2 @@
-rpius@google.com
+kumaranand@google.com
 etancohen@google.com
diff --git a/wifi/1.5/IWifiChip.hal b/wifi/1.5/IWifiChip.hal
index e199850..8d7a36e 100644
--- a/wifi/1.5/IWifiChip.hal
+++ b/wifi/1.5/IWifiChip.hal
@@ -47,6 +47,15 @@
      *   - This will be invoked before an active wifi connection is established on the second
      *     interface.
      *   - This use-case hint is implicitly void when the second STA interface is brought down.
+     *   - When there is only 1 STA interface, the must should still retain the last use case
+     *     set, which must become active the next time multi STA is enabled.
+     *     1. Initialize with single STA.
+     *     2. Framework creates second STA.
+     *     3. Framework sets use case to DUAL_STA_NON_TRANSIENT_UNBIASED.
+     *     4. Framework destroys second STA. Only 1 STA remains.
+     *     5. Framework recreates second STA.
+     *     6. The active use case remains DUAL_STA_NON_TRANSIENT_UNBIASED (i.e. firmware should not
+     *        automatically change it during period of single STA unless requested by framework).
      */
     enum MultiStaUseCase : uint8_t {
         /**
@@ -100,11 +109,14 @@
     /**
      * Invoked to indicate that the provided iface is the primary STA iface when there are more
      * than 1 STA iface concurrently active.
-     * Note: If the wifi firmware/chip cannot support multiple instances of any offload
-     * (like roaming, APF, rssi threshold, etc), the firmware should ensure that these
-     * offloads are at least enabled for the primary interface. If the new primary interface is
-     * already connected to a network, the firmware must switch all the offloads on
-     * this new interface without disconnecting.
+     * Notes:
+     * - If the wifi firmware/chip cannot support multiple instances of any offload
+     *   (like roaming, APF, rssi threshold, etc), the firmware should ensure that these
+     *   offloads are at least enabled for the primary interface. If the new primary interface is
+     *   already connected to a network, the firmware must switch all the offloads on
+     *   this new interface without disconnecting.
+     * - When there is only 1 STA interface, the firmware must still retain the last primary
+     *   connection, which must become active the next time multi STA is enabled.
      *
      * @param ifname Name of the STA iface.
      * @return status WifiStatus of the operation.
diff --git a/wifi/1.5/default/OWNERS b/wifi/1.5/default/OWNERS
index 8bfb148..e7b2fc5 100644
--- a/wifi/1.5/default/OWNERS
+++ b/wifi/1.5/default/OWNERS
@@ -1,2 +1,2 @@
-rpius@google.com
+kumaranand@google.com
 etancohen@google.com
diff --git a/wifi/1.5/default/wifi_legacy_hal.cpp b/wifi/1.5/default/wifi_legacy_hal.cpp
index 848fbd6..5074252 100644
--- a/wifi/1.5/default/wifi_legacy_hal.cpp
+++ b/wifi/1.5/default/wifi_legacy_hal.cpp
@@ -1677,7 +1677,7 @@
 }
 
 wifi_error WifiLegacyHal::triggerSubsystemRestart() {
-    return global_func_table_.wifi_trigger_subsystem_restart();
+    return global_func_table_.wifi_trigger_subsystem_restart(global_handle_);
 }
 
 void WifiLegacyHal::invalidate() {
diff --git a/wifi/1.5/vts/OWNERS b/wifi/1.5/vts/OWNERS
index 8bfb148..e7b2fc5 100644
--- a/wifi/1.5/vts/OWNERS
+++ b/wifi/1.5/vts/OWNERS
@@ -1,2 +1,2 @@
-rpius@google.com
+kumaranand@google.com
 etancohen@google.com
diff --git a/wifi/hostapd/1.0/vts/OWNERS b/wifi/hostapd/1.0/vts/OWNERS
index 8bfb148..e7b2fc5 100644
--- a/wifi/hostapd/1.0/vts/OWNERS
+++ b/wifi/hostapd/1.0/vts/OWNERS
@@ -1,2 +1,2 @@
-rpius@google.com
+kumaranand@google.com
 etancohen@google.com
diff --git a/wifi/hostapd/1.1/vts/OWNERS b/wifi/hostapd/1.1/vts/OWNERS
index 8bfb148..e7b2fc5 100644
--- a/wifi/hostapd/1.1/vts/OWNERS
+++ b/wifi/hostapd/1.1/vts/OWNERS
@@ -1,2 +1,2 @@
-rpius@google.com
+kumaranand@google.com
 etancohen@google.com
diff --git a/wifi/hostapd/1.2/vts/OWNERS b/wifi/hostapd/1.2/vts/OWNERS
index 8bfb148..e7b2fc5 100644
--- a/wifi/hostapd/1.2/vts/OWNERS
+++ b/wifi/hostapd/1.2/vts/OWNERS
@@ -1,2 +1,2 @@
-rpius@google.com
+kumaranand@google.com
 etancohen@google.com
diff --git a/wifi/hostapd/1.3/vts/OWNERS b/wifi/hostapd/1.3/vts/OWNERS
index 8bfb148..e7b2fc5 100644
--- a/wifi/hostapd/1.3/vts/OWNERS
+++ b/wifi/hostapd/1.3/vts/OWNERS
@@ -1,2 +1,2 @@
-rpius@google.com
+kumaranand@google.com
 etancohen@google.com
diff --git a/wifi/supplicant/1.2/vts/OWNERS b/wifi/supplicant/1.2/vts/OWNERS
index 8bfb148..e7b2fc5 100644
--- a/wifi/supplicant/1.2/vts/OWNERS
+++ b/wifi/supplicant/1.2/vts/OWNERS
@@ -1,2 +1,2 @@
-rpius@google.com
+kumaranand@google.com
 etancohen@google.com
diff --git a/wifi/supplicant/1.3/vts/OWNERS b/wifi/supplicant/1.3/vts/OWNERS
index 8bfb148..e7b2fc5 100644
--- a/wifi/supplicant/1.3/vts/OWNERS
+++ b/wifi/supplicant/1.3/vts/OWNERS
@@ -1,2 +1,2 @@
-rpius@google.com
+kumaranand@google.com
 etancohen@google.com
diff --git a/wifi/supplicant/1.4/vts/OWNERS b/wifi/supplicant/1.4/vts/OWNERS
index 8bfb148..e7b2fc5 100644
--- a/wifi/supplicant/1.4/vts/OWNERS
+++ b/wifi/supplicant/1.4/vts/OWNERS
@@ -1,2 +1,2 @@
-rpius@google.com
+kumaranand@google.com
 etancohen@google.com