Merge changes from topic "IFace-enrollment-API"

* changes:
  Update the VTS test
  Update the default implementation
  Update the enrollment API
diff --git a/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp b/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp
index 0f0cdcf..0ebe4c2 100644
--- a/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/all-versions/vts/functional/6.0/AudioPrimaryHidlHalTest.cpp
@@ -128,7 +128,7 @@
 INSTANTIATE_TEST_CASE_P(SingleConfigOutputStream, SingleConfigOutputStreamTest,
                         ::testing::ValuesIn(getOutputDeviceSingleConfigParameters()),
                         &DeviceConfigParameterToString);
-GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SingleConfigOutputStream);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SingleConfigOutputStreamTest);
 
 class SingleConfigInputStreamTest : public InputStreamTest {};
 TEST_P(SingleConfigInputStreamTest, CloseDeviceWithOpenedInputStreams) {
@@ -142,7 +142,7 @@
 INSTANTIATE_TEST_CASE_P(SingleConfigInputStream, SingleConfigInputStreamTest,
                         ::testing::ValuesIn(getInputDeviceSingleConfigParameters()),
                         &DeviceConfigParameterToString);
-GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SingleConfigInputStream);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SingleConfigInputStreamTest);
 
 TEST_P(AudioPatchHidlTest, UpdatePatchInvalidHandle) {
     doc::test("Verify that passing an invalid handle to updateAudioPatch is checked");
diff --git a/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp b/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp
index ef4daba..7fca610 100644
--- a/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/all-versions/vts/functional/7.0/AudioPrimaryHidlHalTest.cpp
@@ -296,7 +296,7 @@
         InputBufferSizeInvalidConfig, InvalidInputConfigNoFlagsTest,
         ::testing::ValuesIn(getInputDeviceInvalidConfigParameters(false /*generateInvalidFlags*/)),
         &DeviceConfigParameterToString);
-GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(InputBufferSizeInvalidConfig);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(InvalidInputConfigNoFlagsTest);
 
 static const DeviceAddress& getValidInputDeviceAddress() {
     static const DeviceAddress valid = {
@@ -682,9 +682,7 @@
                            ::testing::Values(getValidInputDeviceAddress()),
                            ::testing::ValuesIn(wrapMetadata(getInvalidSinkMetadatas()))),
         &StreamOpenParameterToString);
-GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(InputStreamInvalidConfig);
-GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(InputStreamInvalidAddress);
-GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(InputStreamInvalidMetadata);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(StreamOpenTest);
 
 INSTANTIATE_TEST_CASE_P(
         OutputStreamInvalidConfig, StreamOpenTest,
@@ -706,9 +704,6 @@
                            ::testing::Values(getValidOutputDeviceAddress()),
                            ::testing::ValuesIn(wrapMetadata(getInvalidSourceMetadatas()))),
         &StreamOpenParameterToString);
-GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(OutputStreamInvalidConfig);
-GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(OutputStreamInvalidAddress);
-GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(OutputStreamInvalidMetadata);
 
 #define TEST_SINGLE_CONFIG_IO_STREAM(test_name, documentation, code) \
     TEST_P(SingleConfigInputStreamTest, test_name) {                 \
diff --git a/authsecret/aidl/vts/OWNERS b/authsecret/aidl/vts/OWNERS
new file mode 100644
index 0000000..40d95e4
--- /dev/null
+++ b/authsecret/aidl/vts/OWNERS
@@ -0,0 +1,2 @@
+chengyouho@google.com
+frankwoo@google.com
diff --git a/bluetooth/1.0/default/test/bluetooth_address_test.cc b/bluetooth/1.0/default/test/bluetooth_address_test.cc
index ee52d33..422d6a3 100644
--- a/bluetooth/1.0/default/test/bluetooth_address_test.cc
+++ b/bluetooth/1.0/default/test/bluetooth_address_test.cc
@@ -14,7 +14,6 @@
 // limitations under the License.
 //
 
-#include <cutils/properties.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <gtest/gtest.h>
@@ -39,12 +38,6 @@
     "00:00:00:00:00:00";
 constexpr uint8_t kZeros_bytes[BluetoothAddress::kBytes] = {0x00, 0x00, 0x00,
                                                             0x00, 0x00, 0x00};
-constexpr char kTestAddrBad1[BluetoothAddress::kStringLength + 1] =
-    "bb:aa:dd:00:00:01";
-constexpr uint8_t kTestAddrBad1_bytes[BluetoothAddress::kBytes] = {
-    0xbb, 0xaa, 0xdd, 0x00, 0x00, 0x01};
-
-constexpr char kAddrPath[] = "/tmp/my_address_in_a_file.txt";
 
 class BluetoothAddressTest : public ::testing::Test {
  public:
@@ -120,45 +113,6 @@
   EXPECT_FALSE(memcmp(addrA, addrB, BluetoothAddress::kStringLength) == 0);
 }
 
-TEST_F(BluetoothAddressTest, get_local_address) {
-  EXPECT_TRUE(property_set(PERSIST_BDADDR_PROPERTY, "") == 0);
-  EXPECT_TRUE(property_set(FACTORY_BDADDR_PROPERTY, "") == 0);
-  uint8_t address[BluetoothAddress::kBytes];
-
-  // File contains a non-zero Address.
-  FileWriteString(kAddrPath, kTestAddr1);
-  EXPECT_TRUE(property_set(PROPERTY_BT_BDADDR_PATH, kAddrPath) == 0);
-  EXPECT_TRUE(BluetoothAddress::get_local_address(address));
-  EXPECT_TRUE(memcmp(address, kTestAddr1_bytes, BluetoothAddress::kBytes) == 0);
-
-  // File contains a zero address.  A random address will be generated.
-  FileWriteString(kAddrPath, kZeros);
-  EXPECT_TRUE(property_set(PROPERTY_BT_BDADDR_PATH, kAddrPath) == 0);
-  EXPECT_TRUE(property_set(PERSIST_BDADDR_PROPERTY, kTestAddrBad1) == 0);
-  EXPECT_TRUE(BluetoothAddress::get_local_address(address));
-  EXPECT_TRUE(memcmp(address, kZeros_bytes, BluetoothAddress::kBytes) != 0);
-  char prop[PROP_VALUE_MAX] = "Before reading";
-  EXPECT_TRUE(property_get(PERSIST_BDADDR_PROPERTY, prop, NULL) ==
-              BluetoothAddress::kStringLength);
-  char address_str[BluetoothAddress::kStringLength + 1];
-  BluetoothAddress::bytes_to_string(address, address_str);
-  EXPECT_TRUE(memcmp(address_str, prop, BluetoothAddress::kStringLength) == 0);
-
-  // Factory property contains an address.
-  EXPECT_TRUE(property_set(PERSIST_BDADDR_PROPERTY, kTestAddrBad1) == 0);
-  EXPECT_TRUE(property_set(FACTORY_BDADDR_PROPERTY, kTestAddr1) == 0);
-  EXPECT_TRUE(BluetoothAddress::get_local_address(address));
-  EXPECT_TRUE(memcmp(address, kTestAddr1_bytes, BluetoothAddress::kBytes) == 0);
-
-  // Persistent property contains an address.
-  memcpy(address, kTestAddrBad1_bytes, BluetoothAddress::kBytes);
-  EXPECT_TRUE(property_set(PERSIST_BDADDR_PROPERTY, kTestAddr1) == 0);
-  EXPECT_TRUE(property_set(FACTORY_BDADDR_PROPERTY, "") == 0);
-  EXPECT_TRUE(property_set(PROPERTY_BT_BDADDR_PATH, "") == 0);
-  EXPECT_TRUE(BluetoothAddress::get_local_address(address));
-  EXPECT_TRUE(memcmp(address, kTestAddr1_bytes, BluetoothAddress::kBytes) == 0);
-}
-
 }  // namespace implementation
 }  // namespace V1_0
 }  // namespace bluetooth
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index b8676b0..cdf72ae 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -198,7 +198,7 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.drm</name>
-        <version>1.3</version>
+        <version>1.3-4</version>
         <interface>
             <name>ICryptoFactory</name>
             <regex-instance>.*</regex-instance>
@@ -287,6 +287,14 @@
         </interface>
     </hal>
     <hal format="aidl" optional="true">
+        <name>android.hardware.health.storage</name>
+        <version>1</version>
+        <interface>
+            <name>IStorage</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="aidl" optional="true">
         <name>android.hardware.identity</name>
         <version>1-2</version>
         <interface>
diff --git a/drm/1.4/Android.bp b/drm/1.4/Android.bp
new file mode 100644
index 0000000..8e1dc93
--- /dev/null
+++ b/drm/1.4/Android.bp
@@ -0,0 +1,20 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.drm@1.4",
+    root: "android.hardware",
+    srcs: [
+        "ICryptoFactory.hal",
+        "ICryptoPlugin.hal",
+        "IDrmFactory.hal",
+        "IDrmPlugin.hal",
+    ],
+    interfaces: [
+        "android.hardware.drm@1.0",
+        "android.hardware.drm@1.1",
+        "android.hardware.drm@1.2",
+        "android.hardware.drm@1.3",
+        "android.hidl.base@1.0",
+    ],
+    gen_java: false,
+}
diff --git a/drm/1.4/ICryptoFactory.hal b/drm/1.4/ICryptoFactory.hal
new file mode 100644
index 0000000..6cbf9e3
--- /dev/null
+++ b/drm/1.4/ICryptoFactory.hal
@@ -0,0 +1,32 @@
+/*
+ * 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.drm@1.4;
+
+import @1.3::ICryptoFactory;
+
+/**
+ * ICryptoFactory is the main entry point for interacting with a vendor's
+ * crypto HAL to create crypto plugins. Crypto plugins create crypto sessions
+ * which are used by a codec to decrypt protected video content.
+ *
+ * The 1.4 factory must always create 1.4 ICryptoPlugin interfaces, which are
+ * returned via the 1.0 createPlugin method.
+ *
+ * To use 1.4 features the caller must cast the returned interface to a
+ * 1.4 HAL, using V1_4::ICryptoPlugin::castFrom().
+ */
+interface ICryptoFactory extends @1.3::ICryptoFactory {
+};
diff --git a/drm/1.4/ICryptoPlugin.hal b/drm/1.4/ICryptoPlugin.hal
new file mode 100644
index 0000000..874ef4c
--- /dev/null
+++ b/drm/1.4/ICryptoPlugin.hal
@@ -0,0 +1,26 @@
+/**
+ * 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.drm@1.4;
+
+import @1.2::ICryptoPlugin;
+
+/**
+ * ICryptoPlugin is the HAL for vendor-provided crypto plugins.
+ * It allows crypto sessions to be opened and operated on, to
+ * load crypto keys for a codec to decrypt protected video content.
+ */
+interface ICryptoPlugin extends @1.2::ICryptoPlugin {
+};
diff --git a/drm/1.4/IDrmFactory.hal b/drm/1.4/IDrmFactory.hal
new file mode 100644
index 0000000..035a298
--- /dev/null
+++ b/drm/1.4/IDrmFactory.hal
@@ -0,0 +1,34 @@
+/*
+ * 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.drm@1.4;
+
+import @1.3::IDrmFactory;
+
+/**
+ * IDrmFactory is the main entry point for interacting with a vendor's
+ * drm HAL to create drm plugin instances. A drm plugin instance
+ * creates drm sessions which are used to obtain keys for a crypto
+ * session so it can decrypt protected video content.
+ *
+ * The 1.4 factory must always create 1.4 IDrmPlugin interfaces, which are
+ * returned via the 1.0 createPlugin method.
+ *
+ * To use 1.4 features the caller must cast the returned interface to a
+ * 1.4 HAL, using V1_4::IDrmPlugin::castFrom().
+ */
+
+interface IDrmFactory extends @1.3::IDrmFactory {
+};
diff --git a/drm/1.4/IDrmPlugin.hal b/drm/1.4/IDrmPlugin.hal
new file mode 100644
index 0000000..e8af230
--- /dev/null
+++ b/drm/1.4/IDrmPlugin.hal
@@ -0,0 +1,64 @@
+/**
+ * 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.drm@1.4;
+
+import @1.0::Status;
+import @1.0::SessionId;
+import @1.1::SecurityLevel;
+import @1.2::IDrmPlugin;
+
+/**
+ * IDrmPlugin is used to interact with a specific drm plugin that was
+ * created by IDrmFactory::createPlugin. A drm plugin provides methods for
+ * obtaining drm keys to be used by a codec to decrypt protected video
+ * content.
+ */
+interface IDrmPlugin extends @1.2::IDrmPlugin {
+
+    /**
+     * Check if the specified mime-type & security level require a secure decoder
+     * component.
+     *
+     * @param mime The content mime-type
+     * @param level the requested security level
+     * @return secureRequired must be true if and only if a secure decoder is required
+     * for the specified mime-type & security level
+     */
+    requiresSecureDecoder(string mime, @1.1::SecurityLevel level) generates (bool secureRequired);
+
+    /**
+     * Check if the specified mime-type requires a secure decoder component
+     * at the highest security level supported on the device.
+     *
+     * @param mime The content mime-type
+     * @return secureRequired must be true if and only if a secure decoder is required
+     * for the specified mime-type
+     */
+    requiresSecureDecoderDefault(string mime) generates (bool secureRequired);
+
+    /**
+     * Set playback id of a drm session. The playback id can be used to join drm session metrics
+     * with metrics from other low level media components, e.g. codecs, or metrics from the high
+     * level player.
+     *
+     * @param sessionId drm session id
+     * @param playbackId high level playback id
+     * @return status the status of the call. The status must be OK on success, or
+     *     ERROR_DRM_SESSION_NOT_OPENED if the drm session cannot be found
+     */
+    setPlaybackId(SessionId sessionId, string playbackId) generates (@1.0::Status status);
+
+};
diff --git a/health/1.0/default/Android.bp b/health/1.0/default/Android.bp
index aab9cc7..ff4b875 100644
--- a/health/1.0/default/Android.bp
+++ b/health/1.0/default/Android.bp
@@ -17,62 +17,3 @@
     ],
 
 }
-
-cc_library_static {
-    name: "android.hardware.health@1.0-impl-helper",
-    vendor: true,
-    srcs: ["Health.cpp"],
-
-    header_libs: [
-        "libbase_headers",
-        "libhealthd_headers",
-    ],
-
-    shared_libs: [
-        "libcutils",
-        "libhidlbase",
-        "liblog",
-        "libutils",
-        "android.hardware.health@1.0",
-    ],
-
-    static_libs: [
-        "android.hardware.health@1.0-convert",
-    ],
-}
-
-cc_library_shared {
-    name: "android.hardware.health@1.0-impl",
-    vendor: true,
-    relative_install_path: "hw",
-
-    static_libs: [
-        "android.hardware.health@1.0-impl-helper",
-        "android.hardware.health@1.0-convert",
-        "libhealthd.default",
-    ],
-
-    shared_libs: [
-        "libhidlbase",
-        "libutils",
-        "android.hardware.health@1.0",
-    ],
-}
-
-cc_binary {
-    name: "android.hardware.health@1.0-service",
-    vendor: true,
-    relative_install_path: "hw",
-    init_rc: ["android.hardware.health@1.0-service.rc"],
-    srcs: ["HealthService.cpp"],
-
-    shared_libs: [
-        "liblog",
-        "libcutils",
-        "libdl",
-        "libbase",
-        "libutils",
-        "libhidlbase",
-        "android.hardware.health@1.0",
-    ],
-}
diff --git a/health/1.0/default/Health.cpp b/health/1.0/default/Health.cpp
deleted file mode 100644
index 1a02956..0000000
--- a/health/1.0/default/Health.cpp
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "health-hal"
-
-#include <Health.h>
-#include <include/hal_conversion.h>
-
-namespace android {
-namespace hardware {
-namespace health {
-namespace V1_0 {
-namespace implementation {
-
-using ::android::hardware::health::V1_0::hal_conversion::convertToHealthConfig;
-using ::android::hardware::health::V1_0::hal_conversion::convertFromHealthConfig;
-using ::android::hardware::health::V1_0::hal_conversion::convertToHealthInfo;
-using ::android::hardware::health::V1_0::hal_conversion::convertFromHealthInfo;
-
-// Methods from ::android::hardware::health::V1_0::IHealth follow.
-Return<void> Health::init(const HealthConfig& config, init_cb _hidl_cb)  {
-    struct healthd_config healthd_config = {};
-    HealthConfig configOut;
-
-    // To keep working with existing healthd static HALs,
-    // convert the new HealthConfig to the old healthd_config
-    // and back.
-
-    convertFromHealthConfig(config, &healthd_config);
-    healthd_board_init(&healthd_config);
-    mGetEnergyCounter = healthd_config.energyCounter;
-    convertToHealthConfig(&healthd_config, configOut);
-
-    _hidl_cb(configOut);
-
-    return Void();
-}
-
-Return<void> Health::update(const HealthInfo& info, update_cb _hidl_cb)  {
-    struct android::BatteryProperties p = {};
-    HealthInfo infoOut;
-
-    // To keep working with existing healthd static HALs,
-    // convert the new HealthInfo to android::Batteryproperties
-    // and back.
-
-    convertFromHealthInfo(info, &p);
-    int skipLogging = healthd_board_battery_update(&p);
-    convertToHealthInfo(&p, infoOut);
-
-    _hidl_cb(!!skipLogging, infoOut);
-
-    return Void();
-}
-
-Return<void> Health::energyCounter(energyCounter_cb _hidl_cb) {
-    int64_t energy = 0;
-    Result result = Result::NOT_SUPPORTED;
-
-    if (mGetEnergyCounter) {
-        int status = mGetEnergyCounter(&energy);
-        if (status == 0) {
-            result = Result::SUCCESS;
-        }
-    }
-
-    _hidl_cb(result, energy);
-
-   return Void();
-}
-
-IHealth* HIDL_FETCH_IHealth(const char* /* name */) {
-    return new Health();
-}
-
-} // namespace implementation
-}  // namespace V1_0
-}  // namespace health
-}  // namespace hardware
-}  // namespace android
diff --git a/health/1.0/default/Health.h b/health/1.0/default/Health.h
deleted file mode 100644
index ed364c1..0000000
--- a/health/1.0/default/Health.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#ifndef ANDROID_HARDWARE_HEALTH_V1_0_HEALTH_H
-#define ANDROID_HARDWARE_HEALTH_V1_0_HEALTH_H
-
-#include <android/hardware/health/1.0/IHealth.h>
-#include <hidl/Status.h>
-#include <hidl/MQDescriptor.h>
-#include <healthd/healthd.h>
-#include <utils/String8.h>
-
-namespace android {
-namespace hardware {
-namespace health {
-namespace V1_0 {
-namespace implementation {
-
-using ::android::hardware::health::V1_0::HealthInfo;
-using ::android::hardware::health::V1_0::HealthConfig;
-using ::android::hardware::health::V1_0::IHealth;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::hidl_string;
-using ::android::sp;
-
-struct Health : public IHealth {
-    // Methods from ::android::hardware::health::V1_0::IHealth follow.
-    Return<void> init(const HealthConfig& config, init_cb _hidl_cb)  override;
-    Return<void> update(const HealthInfo& info, update_cb _hidl_cb)  override;
-    Return<void> energyCounter(energyCounter_cb _hidl_cb) override;
-private:
-    std::function<int(int64_t *)> mGetEnergyCounter;
-};
-
-extern "C" IHealth* HIDL_FETCH_IHealth(const char* name);
-
-}  // namespace implementation
-}  // namespace V1_0
-}  // namespace health
-}  // namespace hardware
-}  // namespace android
-
-#endif  // ANDROID_HARDWARE_HEALTH_V1_0_HEALTH_H
diff --git a/health/1.0/default/HealthService.cpp b/health/1.0/default/HealthService.cpp
deleted file mode 100644
index 55848d2..0000000
--- a/health/1.0/default/HealthService.cpp
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "android.hardware.health@1.0-service"
-
-#include <android/hardware/health/1.0/IHealth.h>
-#include <hidl/LegacySupport.h>
-
-using android::hardware::health::V1_0::IHealth;
-using android::hardware::defaultPassthroughServiceImplementation;
-
-int main() {
-    return defaultPassthroughServiceImplementation<IHealth>();
-}
diff --git a/health/1.0/default/README.md b/health/1.0/default/README.md
deleted file mode 100644
index 1ded7de..0000000
--- a/health/1.0/default/README.md
+++ /dev/null
@@ -1,66 +0,0 @@
-# Implement the 2.1 HAL instead!
-
-It is strongly recommended that you implement the 2.1 HAL directly. See
-`hardware/interfaces/health/2.1/README.md` for more details.
-
-# Implement Health 1.0 HAL
-
-1. Install common binderized service. The binderized service `dlopen()`s
-   passthrough implementations on the device, so there is no need to write
-   your own.
-
-    ```mk
-    # Install default binderized implementation to vendor.
-    PRODUCT_PACKAGES += android.hardware.health@1.0-service
-    ```
-
-1. Add proper VINTF manifest entry to your device manifest. Example:
-
-    ```xml
-    <hal format="hidl">
-        <name>android.hardware.health</name>
-        <transport>hwbinder</transport>
-        <version>1.0</version>
-        <interface>
-            <name>IHealth</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-    ```
-
-1. Install the proper passthrough implemetation.
-
-    1. If you want to use the default implementation (with default `libhealthd`),
-       add the following to `device.mk`:
-
-        ```mk
-        PRODUCT_PACKAGES += \
-            android.hardware.health@1.0-impl
-        ```
-
-    1. Otherwise, if you have a customized `libhealthd.<board>`:
-
-        1. Define your passthrough implementation. Example (replace `<device>`
-           and `<board>` accordingly):
-
-            ```bp
-            cc_library_shared {
-                name: "android.hardware.health@1.0-impl-<device>",
-                vendor: true,
-                relative_install_path: "hw",
-
-                static_libs: [
-                    "android.hardware.health@1.0-impl-helper",
-                    "android.hardware.health@1.0-convert",
-                    "libhealthd.<board>",
-                ],
-            }
-            ```
-
-        1. Add to `device.mk`.
-
-            ```
-            PRODUCT_PACKAGES += android.hardware.health@1.0-impl-<device>
-            ```
-
-        1. Define appropriate SELinux permissions.
diff --git a/health/1.0/default/android.hardware.health@1.0-service.rc b/health/1.0/default/android.hardware.health@1.0-service.rc
deleted file mode 100644
index 569dc88..0000000
--- a/health/1.0/default/android.hardware.health@1.0-service.rc
+++ /dev/null
@@ -1,5 +0,0 @@
-service vendor.health-hal-1-0 /vendor/bin/hw/android.hardware.health@1.0-service
-    class hal
-    user system
-    group system
-    capabilities WAKE_ALARM BLOCK_SUSPEND
diff --git a/health/1.0/default/libhealthd/Android.bp b/health/1.0/default/libhealthd/Android.bp
deleted file mode 100644
index 43463eb..0000000
--- a/health/1.0/default/libhealthd/Android.bp
+++ /dev/null
@@ -1,11 +0,0 @@
-// Copyright 2016 The Android Open Source Project
-
-cc_library_static {
-    srcs: ["healthd_board_default.cpp"],
-    name: "libhealthd.default",
-    vendor_available: true,
-    recovery_available: true,
-    cflags: ["-Werror"],
-    include_dirs: ["system/libbase/include"],
-    header_libs: ["libhealthd_headers"],
-}
diff --git a/health/1.0/vts/functional/Android.bp b/health/1.0/vts/functional/Android.bp
deleted file mode 100644
index f4a04a7..0000000
--- a/health/1.0/vts/functional/Android.bp
+++ /dev/null
@@ -1,23 +0,0 @@
-//
-// Copyright (C) 2017 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-cc_test {
-    name: "VtsHalHealthV1_0TargetTest",
-    defaults: ["VtsHalTargetTestDefaults"],
-    srcs: ["VtsHalHealthV1_0TargetTest.cpp"],
-    static_libs: ["android.hardware.health@1.0"],
-    test_suites: ["general-tests", "vts"],
-}
diff --git a/health/1.0/vts/functional/VtsHalHealthV1_0TargetTest.cpp b/health/1.0/vts/functional/VtsHalHealthV1_0TargetTest.cpp
deleted file mode 100644
index 8b3dcc1..0000000
--- a/health/1.0/vts/functional/VtsHalHealthV1_0TargetTest.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "health_hidl_hal_test"
-
-#include <android/hardware/health/1.0/IHealth.h>
-#include <android/hardware/health/1.0/types.h>
-#include <gtest/gtest.h>
-#include <hidl/GtestPrinter.h>
-#include <hidl/ServiceManagement.h>
-#include <log/log.h>
-
-using HealthConfig = ::android::hardware::health::V1_0::HealthConfig;
-using HealthInfo = ::android::hardware::health::V1_0::HealthInfo;
-using IHealth = ::android::hardware::health::V1_0::IHealth;
-using Result = ::android::hardware::health::V1_0::Result;
-
-using ::android::sp;
-
-class HealthHidlTest : public ::testing::TestWithParam<std::string> {
-   public:
-    virtual void SetUp() override {
-        health = IHealth::getService(GetParam());
-        ASSERT_NE(health, nullptr);
-        health->init(config,
-                     [&](const auto& halConfigOut) { config = halConfigOut; });
-    }
-
-    sp<IHealth> health;
-    HealthConfig config;
-};
-
-/**
- * Ensure EnergyCounter call returns positive energy counter or NOT_SUPPORTED
- */
-TEST_P(HealthHidlTest, TestEnergyCounter) {
-    Result result;
-    int64_t energy = 0;
-    health->energyCounter([&](Result ret, int64_t energyOut) {
-        result = ret;
-        energy = energyOut;
-    });
-
-    ASSERT_TRUE(result == Result::SUCCESS || result == Result::NOT_SUPPORTED);
-    ASSERT_TRUE(result != Result::SUCCESS || energy > 0);
-}
-
-GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(HealthHidlTest);
-INSTANTIATE_TEST_SUITE_P(
-        PerInstance, HealthHidlTest,
-        testing::ValuesIn(android::hardware::getAllHalInstanceNames(IHealth::descriptor)),
-        android::hardware::PrintInstanceNameToString);
diff --git a/health/storage/1.0/default/Android.bp b/health/storage/1.0/default/Android.bp
index 3156dfe..3834244 100644
--- a/health/storage/1.0/default/Android.bp
+++ b/health/storage/1.0/default/Android.bp
@@ -38,6 +38,7 @@
     ],
 
     static_libs: [
+        "libhealth_storage_impl_common",
         "libfstab",
     ],
 
diff --git a/health/storage/1.0/default/Storage.cpp b/health/storage/1.0/default/Storage.cpp
index 561deaa..02b6a3d 100644
--- a/health/storage/1.0/default/Storage.cpp
+++ b/health/storage/1.0/default/Storage.cpp
@@ -18,11 +18,8 @@
 
 #include <sstream>
 
-#include <android-base/chrono_utils.h>
-#include <android-base/file.h>
 #include <android-base/logging.h>
-#include <android-base/strings.h>
-#include <fstab/fstab.h>
+#include <health-storage-impl/common.h>
 
 namespace android {
 namespace hardware {
@@ -31,69 +28,9 @@
 namespace V1_0 {
 namespace implementation {
 
-using base::ReadFileToString;
-using base::Timer;
-using base::Trim;
-using base::WriteStringToFd;
-using base::WriteStringToFile;
-using fs_mgr::Fstab;
-using fs_mgr::ReadDefaultFstab;
-
-std::string getGarbageCollectPath() {
-    Fstab fstab;
-    ReadDefaultFstab(&fstab);
-
-    for (const auto& entry : fstab) {
-        if (!entry.sysfs_path.empty()) {
-            return entry.sysfs_path + "/manual_gc";
-        }
-    }
-
-    return "";
-}
-
 Return<void> Storage::garbageCollect(uint64_t timeoutSeconds,
                                      const sp<IGarbageCollectCallback>& cb) {
-    Result result = Result::SUCCESS;
-    std::string path = getGarbageCollectPath();
-
-    if (path.empty()) {
-        LOG(WARNING) << "Cannot find Dev GC path";
-        result = Result::UNKNOWN_ERROR;
-    } else {
-        Timer timer;
-        LOG(INFO) << "Start Dev GC on " << path;
-        while (1) {
-            std::string require;
-            if (!ReadFileToString(path, &require)) {
-                PLOG(WARNING) << "Reading manual_gc failed in " << path;
-                result = Result::IO_ERROR;
-                break;
-            }
-            require = Trim(require);
-            if (require == "" || require == "off" || require == "disabled") {
-                LOG(DEBUG) << "No more to do Dev GC";
-                break;
-            }
-            LOG(DEBUG) << "Trigger Dev GC on " << path;
-            if (!WriteStringToFile("1", path)) {
-                PLOG(WARNING) << "Start Dev GC failed on " << path;
-                result = Result::IO_ERROR;
-                break;
-            }
-            if (timer.duration() >= std::chrono::seconds(timeoutSeconds)) {
-                LOG(WARNING) << "Dev GC timeout";
-                // Timeout is not treated as an error. Try next time.
-                break;
-            }
-            sleep(2);
-        }
-        LOG(INFO) << "Stop Dev GC on " << path;
-        if (!WriteStringToFile("0", path)) {
-            PLOG(WARNING) << "Stop Dev GC failed on " << path;
-            result = Result::IO_ERROR;
-        }
-    }
+    Result result = GarbageCollect(timeoutSeconds);
 
     if (cb != nullptr) {
         auto ret = cb->onFinish(result);
@@ -110,28 +47,7 @@
     }
 
     int fd = handle->data[0];
-    std::stringstream output;
-
-    std::string path = getGarbageCollectPath();
-    if (path.empty()) {
-        output << "Cannot find Dev GC path";
-    } else {
-        std::string require;
-
-        if (ReadFileToString(path, &require)) {
-            output << path << ":" << require << std::endl;
-        }
-
-        if (WriteStringToFile("0", path)) {
-            output << "stop success" << std::endl;
-        }
-    }
-
-    if (!WriteStringToFd(output.str(), fd)) {
-        PLOG(WARNING) << "debug: cannot write to fd";
-    }
-
-    fsync(fd);
+    DebugDump(fd);
 
     return Void();
 }
diff --git a/health/storage/1.0/vts/functional/Android.bp b/health/storage/1.0/vts/functional/Android.bp
index 2201031..731ad62 100644
--- a/health/storage/1.0/vts/functional/Android.bp
+++ b/health/storage/1.0/vts/functional/Android.bp
@@ -19,6 +19,9 @@
     defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalHealthStorageV1_0TargetTest.cpp"],
     static_libs: ["android.hardware.health.storage@1.0"],
+    header_libs: [
+        "libhealth_storage_test_common_headers",
+    ],
     shared_libs: [
         "libhidlbase",
     ],
diff --git a/health/storage/1.0/vts/functional/VtsHalHealthStorageV1_0TargetTest.cpp b/health/storage/1.0/vts/functional/VtsHalHealthStorageV1_0TargetTest.cpp
index 24ddc5d..ddb6b5a 100644
--- a/health/storage/1.0/vts/functional/VtsHalHealthStorageV1_0TargetTest.cpp
+++ b/health/storage/1.0/vts/functional/VtsHalHealthStorageV1_0TargetTest.cpp
@@ -14,14 +14,17 @@
  * limitations under the License.
  */
 
+#include <unistd.h>
+
+#include <thread>
+
 #include <android-base/logging.h>
 #include <android/hardware/health/storage/1.0/IStorage.h>
 #include <gtest/gtest.h>
+#include <health-storage-test/common.h>
 #include <hidl/GtestPrinter.h>
 #include <hidl/HidlTransportSupport.h>
 #include <hidl/ServiceManagement.h>
-#include <unistd.h>
-#include <thread>
 
 namespace android {
 namespace hardware {
@@ -29,61 +32,17 @@
 namespace storage {
 namespace V1_0 {
 
+using namespace ::android::hardware::health::storage::test;
 using ::std::literals::chrono_literals::operator""ms;
 
 #define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk()) << ret.description()
 
-// Dev GC timeout. This is the timeout used by vold.
-const uint64_t kDevGcTimeoutSec = 120;
-const std::chrono::seconds kDevGcTimeout{kDevGcTimeoutSec};
-// Dev GC timeout tolerance. The HAL may not immediately return after the
-// timeout, so include an acceptable tolerance.
-const std::chrono::seconds kDevGcTolerance{3};
-// Time accounted for RPC calls.
-const std::chrono::milliseconds kRpcTime{1000};
-
-template <typename R>
-std::string toString(std::chrono::duration<R, std::milli> time) {
-    return std::to_string(time.count()) + "ms";
-}
-
-/** An atomic boolean flag that indicates whether a task has finished. */
-class Flag {
-   public:
-    void onFinish() {
-        std::unique_lock<std::mutex> lock(mMutex);
-        onFinishLocked(&lock);
-    }
-    template <typename R, typename P>
-    bool wait(std::chrono::duration<R, P> duration) {
-        std::unique_lock<std::mutex> lock(mMutex);
-        return waitLocked(&lock, duration);
-    }
-
-   protected:
-    /** Will unlock. */
-    void onFinishLocked(std::unique_lock<std::mutex>* lock) {
-        mFinished = true;
-        lock->unlock();
-        mCv.notify_all();
-    }
-    template <typename R, typename P>
-    bool waitLocked(std::unique_lock<std::mutex>* lock, std::chrono::duration<R, P> duration) {
-        mCv.wait_for(*lock, duration, [this] { return mFinished; });
-        return mFinished;
-    }
-
-    bool mFinished{false};
-    std::mutex mMutex;
-    std::condition_variable mCv;
-};
-
 class GcCallback : public IGarbageCollectCallback, public Flag {
-   public:
+  public:
     Return<void> onFinish(Result result) override {
-        std::unique_lock<std::mutex> lock(mMutex);
-        mResult = result;
-        Flag::onFinishLocked(&lock);
+        std::unique_lock<std::mutex> lock(mutex_);
+        result_ = result;
+        Flag::OnFinishLocked(&lock);
         return Void();
     }
 
@@ -93,13 +52,13 @@
      */
     template <typename R, typename P>
     void waitForResult(std::chrono::duration<R, P> timeout, Result expected) {
-        std::unique_lock<std::mutex> lock(mMutex);
-        ASSERT_TRUE(waitLocked(&lock, timeout)) << "timeout after " << toString(timeout);
-        EXPECT_EQ(expected, mResult);
+        std::unique_lock<std::mutex> lock(mutex_);
+        ASSERT_TRUE(WaitLocked(&lock, timeout)) << "timeout after " << to_string(timeout);
+        EXPECT_EQ(expected, result_);
     }
 
-   private:
-    Result mResult{Result::UNKNOWN_ERROR};
+  private:
+    Result result_{Result::UNKNOWN_ERROR};
 };
 
 class HealthStorageHidlTest : public ::testing::TestWithParam<std::string> {
@@ -127,10 +86,10 @@
         auto pingFlag = std::make_shared<Flag>();
         std::thread([service, pingFlag] {
             service->ping();
-            pingFlag->onFinish();
+            pingFlag->OnFinish();
         })
             .detach();
-        return pingFlag->wait(timeout);
+        return pingFlag->Wait(timeout);
     }
 
     sp<IStorage> fs;
@@ -147,7 +106,7 @@
     // Hold test process because HAL can be single-threaded and doing GC.
     ASSERT_TRUE(ping(kDevGcTimeout + kDevGcTolerance + kRpcTime))
             << "Service must be available after "
-            << toString(kDevGcTimeout + kDevGcTolerance + kRpcTime);
+            << to_string(kDevGcTimeout + kDevGcTolerance + kRpcTime);
 }
 
 /**
diff --git a/health/storage/aidl/Android.bp b/health/storage/aidl/Android.bp
new file mode 100644
index 0000000..c39a46d
--- /dev/null
+++ b/health/storage/aidl/Android.bp
@@ -0,0 +1,33 @@
+// 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.
+
+aidl_interface {
+    name: "android.hardware.health.storage",
+    vendor_available: true,
+    srcs: ["android/hardware/health/storage/*.aidl"],
+    stability: "vintf",
+    backend: {
+        cpp: {
+            enabled: false,
+        },
+        java: {
+            enabled: false,
+        },
+        ndk: {
+            vndk: {
+                enabled: true,
+            },
+        },
+    },
+}
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Timestamp.aidl b/health/storage/aidl/aidl_api/android.hardware.health.storage/current/android/hardware/health/storage/IGarbageCollectCallback.aidl
similarity index 87%
copy from security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Timestamp.aidl
copy to health/storage/aidl/aidl_api/android.hardware.health.storage/current/android/hardware/health/storage/IGarbageCollectCallback.aidl
index 963e66e..0f382d7 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Timestamp.aidl
+++ b/health/storage/aidl/aidl_api/android.hardware.health.storage/current/android/hardware/health/storage/IGarbageCollectCallback.aidl
@@ -16,8 +16,8 @@
 // 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.security.keymint;
+package android.hardware.health.storage;
 @VintfStability
-parcelable Timestamp {
-  long milliSeconds;
+interface IGarbageCollectCallback {
+  oneway void onFinish(in android.hardware.health.storage.Result result);
 }
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Timestamp.aidl b/health/storage/aidl/aidl_api/android.hardware.health.storage/current/android/hardware/health/storage/IStorage.aidl
similarity index 84%
copy from security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Timestamp.aidl
copy to health/storage/aidl/aidl_api/android.hardware.health.storage/current/android/hardware/health/storage/IStorage.aidl
index 963e66e..61f838a 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Timestamp.aidl
+++ b/health/storage/aidl/aidl_api/android.hardware.health.storage/current/android/hardware/health/storage/IStorage.aidl
@@ -16,8 +16,8 @@
 // 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.security.keymint;
+package android.hardware.health.storage;
 @VintfStability
-parcelable Timestamp {
-  long milliSeconds;
+interface IStorage {
+  oneway void garbageCollect(in long timeoutSeconds, in android.hardware.health.storage.IGarbageCollectCallback callback);
 }
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Timestamp.aidl b/health/storage/aidl/aidl_api/android.hardware.health.storage/current/android/hardware/health/storage/Result.aidl
similarity index 87%
copy from security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Timestamp.aidl
copy to health/storage/aidl/aidl_api/android.hardware.health.storage/current/android/hardware/health/storage/Result.aidl
index 963e66e..a345808 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Timestamp.aidl
+++ b/health/storage/aidl/aidl_api/android.hardware.health.storage/current/android/hardware/health/storage/Result.aidl
@@ -16,8 +16,10 @@
 // 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.security.keymint;
-@VintfStability
-parcelable Timestamp {
-  long milliSeconds;
+package android.hardware.health.storage;
+@Backing(type="int") @VintfStability
+enum Result {
+  SUCCESS = 0,
+  IO_ERROR = 1,
+  UNKNOWN_ERROR = 2,
 }
diff --git a/health/storage/aidl/android/hardware/health/storage/IGarbageCollectCallback.aidl b/health/storage/aidl/android/hardware/health/storage/IGarbageCollectCallback.aidl
new file mode 100644
index 0000000..ccd1b44
--- /dev/null
+++ b/health/storage/aidl/android/hardware/health/storage/IGarbageCollectCallback.aidl
@@ -0,0 +1,34 @@
+/*
+ * 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.health.storage;
+
+import android.hardware.health.storage.Result;
+
+/**
+ * Callback interface to IStorage.garbageCollect.
+ */
+@VintfStability
+interface IGarbageCollectCallback {
+    /**
+     * When garbage collection has finished, the implementation must
+     * invoke this function to indicate the result of the garbage collection.
+     *
+     * @param out result Execution result. See documentation for Result for
+     *     details.
+     */
+    oneway void onFinish(in Result result);
+}
diff --git a/health/storage/aidl/android/hardware/health/storage/IStorage.aidl b/health/storage/aidl/android/hardware/health/storage/IStorage.aidl
new file mode 100644
index 0000000..78992a2
--- /dev/null
+++ b/health/storage/aidl/android/hardware/health/storage/IStorage.aidl
@@ -0,0 +1,49 @@
+/*
+ * 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.health.storage;
+
+import android.hardware.health.storage.IGarbageCollectCallback;
+
+/**
+ * IStorage is an interface that provides operations on underlying storage
+ * devices, including flash memory.
+ */
+@VintfStability
+interface IStorage {
+    /**
+     * Start garbage collection on the driver of storage devices.
+     *
+     * Garbage collection must be started at regular intervals when it is a good
+     * time for a longer-running cleanup tasks, roughly daily.
+     *
+     * When garbage collection finishes or encounters an error before the
+     * specified timeout, the implementation must call IGarbageCollect.finish
+     * immediately with appropriate result.
+     *
+     * If garbage collection does not finish within the specified timeout,
+     * the implementation must stop garbage collection, and must not call
+     * IGarbageCollect.finish.
+     *
+     * @param timeoutSeconds timeout in seconds. The implementation must
+     *     return after the timeout is reached.
+     *
+     * @param callback callback interface. Callback must be null if the client
+     *     does not need to receive any callbacks.
+     *
+     */
+    oneway void garbageCollect(in long timeoutSeconds, in IGarbageCollectCallback callback);
+}
diff --git a/health/storage/aidl/android/hardware/health/storage/Result.aidl b/health/storage/aidl/android/hardware/health/storage/Result.aidl
new file mode 100644
index 0000000..73bb779
--- /dev/null
+++ b/health/storage/aidl/android/hardware/health/storage/Result.aidl
@@ -0,0 +1,37 @@
+/*
+ * 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.health.storage;
+
+/**
+ * Status values for HAL methods.
+ */
+@VintfStability
+@Backing(type="int")
+enum Result {
+    /**
+     * Execution of the method is successful.
+     */
+    SUCCESS = 0,
+    /**
+     * An IO error is encountered when the HAL communicates with the device.
+     */
+    IO_ERROR,
+    /**
+     * An unknown error is encountered.
+     */
+    UNKNOWN_ERROR,
+}
diff --git a/health/storage/aidl/default/Android.bp b/health/storage/aidl/default/Android.bp
new file mode 100644
index 0000000..68a8ee2
--- /dev/null
+++ b/health/storage/aidl/default/Android.bp
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+
+cc_defaults {
+    name: "libhealth_storage_impl_defaults",
+    vendor: true,
+    shared_libs: [
+        "libbase",
+        "libbinder_ndk",
+        "android.hardware.health.storage-unstable-ndk_platform",
+    ],
+    static_libs: [
+        "libfstab",
+        "libhealth_storage_impl_common",
+    ],
+}
+
+cc_library_static {
+    name: "libhealth_storage_default_impl",
+    defaults: ["libhealth_storage_impl_defaults"],
+    srcs: [
+        "Storage.cpp",
+    ],
+    visibility: [
+        ":__subpackages__",
+        "//hardware/interfaces/tests/extension/health/storage:__subpackages__",
+    ],
+}
+
+cc_binary {
+    name: "android.hardware.health.storage-service.default",
+    defaults: ["libhealth_storage_impl_defaults"],
+    relative_install_path: "hw",
+    init_rc: ["health-storage-default.rc"],
+    vintf_fragments: ["health-storage-default.xml"],
+    srcs: ["main.cpp"],
+    static_libs: [
+        "libhealth_storage_default_impl",
+    ],
+}
diff --git a/health/storage/aidl/default/Storage.cpp b/health/storage/aidl/default/Storage.cpp
new file mode 100644
index 0000000..faa4ff6
--- /dev/null
+++ b/health/storage/aidl/default/Storage.cpp
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+#include "Storage.h"
+
+#include <sstream>
+
+#include <android-base/logging.h>
+#include <health-storage-impl/common.h>
+
+using ::android::hardware::health::storage::DebugDump;
+using ::android::hardware::health::storage::GarbageCollect;
+
+using HResult = android::hardware::health::storage::V1_0::Result;
+using AResult = aidl::android::hardware::health::storage::Result;
+// Ensure static_cast<AResult>(any HResult) works
+static_assert(static_cast<AResult>(HResult::SUCCESS) == AResult::SUCCESS);
+static_assert(static_cast<AResult>(HResult::IO_ERROR) == AResult::IO_ERROR);
+static_assert(static_cast<AResult>(HResult::UNKNOWN_ERROR) == AResult::UNKNOWN_ERROR);
+
+namespace aidl::android::hardware::health::storage {
+
+ndk::ScopedAStatus Storage::garbageCollect(
+        int64_t timeout_seconds, const std::shared_ptr<IGarbageCollectCallback>& callback) {
+    AResult result = static_cast<AResult>(GarbageCollect(static_cast<uint64_t>(timeout_seconds)));
+    if (callback != nullptr) {
+        auto status = callback->onFinish(result);
+        if (!status.isOk()) {
+            LOG(WARNING) << "Cannot return result " << toString(result)
+                         << " to callback: " << status.getDescription();
+        }
+    }
+    return ndk::ScopedAStatus::ok();
+}
+
+binder_status_t Storage::dump(int fd, const char**, uint32_t) {
+    DebugDump(fd);
+    return STATUS_OK;
+}
+
+}  // namespace aidl::android::hardware::health::storage
diff --git a/health/storage/aidl/default/Storage.h b/health/storage/aidl/default/Storage.h
new file mode 100644
index 0000000..049991b
--- /dev/null
+++ b/health/storage/aidl/default/Storage.h
@@ -0,0 +1,30 @@
+/*
+ * 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/health/storage/BnStorage.h>
+
+namespace aidl::android::hardware::health::storage {
+
+class Storage : public BnStorage {
+    ndk::ScopedAStatus garbageCollect(
+            int64_t timeout_seconds,
+            const std::shared_ptr<IGarbageCollectCallback>& callback) override;
+    binder_status_t dump(int fd, const char** args, uint32_t num_args) override;
+};
+
+}  // namespace aidl::android::hardware::health::storage
diff --git a/health/storage/aidl/default/health-storage-default.rc b/health/storage/aidl/default/health-storage-default.rc
new file mode 100644
index 0000000..fc1cc8b
--- /dev/null
+++ b/health/storage/aidl/default/health-storage-default.rc
@@ -0,0 +1,7 @@
+service vendor.health-storage-default /vendor/bin/hw/android.hardware.health.storage-service.default
+    interface aidl android.hardware.health.storage.IStorage/default
+    oneshot
+    disabled
+    class hal
+    user system
+    group system
diff --git a/health/storage/aidl/default/health-storage-default.xml b/health/storage/aidl/default/health-storage-default.xml
new file mode 100644
index 0000000..14d4901
--- /dev/null
+++ b/health/storage/aidl/default/health-storage-default.xml
@@ -0,0 +1,7 @@
+<manifest version="1.0" type="device">
+    <hal format="aidl">
+        <name>android.hardware.health.storage</name>
+        <version>1</version>
+        <fqname>IStorage/default</fqname>
+    </hal>
+</manifest>
diff --git a/health/storage/aidl/default/main.cpp b/health/storage/aidl/default/main.cpp
new file mode 100644
index 0000000..186b64c
--- /dev/null
+++ b/health/storage/aidl/default/main.cpp
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+#include "Storage.h"
+
+using aidl::android::hardware::health::storage::Storage;
+using std::string_literals::operator""s;
+
+int main() {
+    ABinderProcess_setThreadPoolMaxThreadCount(0);
+
+    // make a default storage service
+    auto storage = ndk::SharedRefBase::make<Storage>();
+    const std::string name = Storage::descriptor + "/default"s;
+    CHECK_EQ(STATUS_OK,
+             AServiceManager_registerLazyService(storage->asBinder().get(), name.c_str()));
+
+    ABinderProcess_joinThreadPool();
+    return EXIT_FAILURE;  // should not reach
+}
diff --git a/health/storage/aidl/vts/functional/Android.bp b/health/storage/aidl/vts/functional/Android.bp
new file mode 100644
index 0000000..86b72a7
--- /dev/null
+++ b/health/storage/aidl/vts/functional/Android.bp
@@ -0,0 +1,37 @@
+// 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.
+
+cc_test {
+    name: "VtsHalHealthStorageTargetTest",
+    defaults: [
+        "VtsHalTargetTestDefaults",
+        "use_libaidlvintf_gtest_helper_static",
+    ],
+    srcs: [
+        "VtsHalHealthStorageTargetTest.cpp",
+    ],
+    shared_libs: [
+        "libbinder_ndk",
+    ],
+    static_libs: [
+        "android.hardware.health.storage-ndk_platform",
+    ],
+    header_libs: [
+        "libhealth_storage_test_common_headers",
+    ],
+    test_suites: [
+        "vts",
+    ],
+    test_config: "VtsHalHealthStorageTargetTest.xml",
+}
diff --git a/health/storage/aidl/vts/functional/VtsHalHealthStorageTargetTest.cpp b/health/storage/aidl/vts/functional/VtsHalHealthStorageTargetTest.cpp
new file mode 100644
index 0000000..3b6b6b4
--- /dev/null
+++ b/health/storage/aidl/vts/functional/VtsHalHealthStorageTargetTest.cpp
@@ -0,0 +1,136 @@
+/*
+ * 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.
+ */
+
+#include <unistd.h>
+
+#include <chrono>
+#include <set>
+#include <string>
+#include <thread>
+
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/health/storage/BnGarbageCollectCallback.h>
+#include <aidl/android/hardware/health/storage/IStorage.h>
+#include <android-base/logging.h>
+#include <android/binder_ibinder.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <gtest/gtest.h>
+#include <health-storage-test/common.h>
+
+namespace aidl::android::hardware::health::storage {
+
+using namespace ::android::hardware::health::storage::test;
+using std::chrono_literals::operator""ms;
+
+#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk()) << ret.getDescription()
+#define EXPECT_OK(ret) EXPECT_TRUE(ret.isOk()) << ret.getDescription()
+
+class GcCallback : public BnGarbageCollectCallback, public Flag {
+  public:
+    ndk::ScopedAStatus onFinish(Result result) override {
+        std::unique_lock<std::mutex> lock(mutex_);
+        result_ = result;
+        OnFinishLocked(&lock);
+        return ndk::ScopedAStatus::ok();
+    }
+
+    /**
+     * Wait for a specific "timeout". If GC has finished, test that the result
+     * is equal to the "expected" value.
+     */
+    template <typename R, typename P>
+    void WaitForResult(std::chrono::duration<R, P> timeout, Result expected) {
+        std::unique_lock<std::mutex> lock(mutex_);
+        ASSERT_TRUE(WaitLocked(&lock, timeout)) << "timeout after " << to_string(timeout);
+        EXPECT_EQ(expected, result_);
+    }
+
+  private:
+    Result result_{Result::UNKNOWN_ERROR};
+};
+
+class HealthStorageAidl : public testing::TestWithParam<std::string> {
+  public:
+    virtual void SetUp() override {
+        std::string name = GetParam();
+        ASSERT_TRUE(AServiceManager_isDeclared(name.c_str())) << name;
+        ndk::SpAIBinder binder(AServiceManager_waitForService(name.c_str()));
+        ASSERT_NE(binder, nullptr);
+        storage_ = IStorage::fromBinder(binder);
+        ASSERT_NE(storage_, nullptr);
+    }
+
+    virtual void TearDown() override {
+        EXPECT_TRUE(ping(kRpcTime))
+                << "Service is not responsive; expect subsequent tests to fail.";
+    }
+
+    /**
+     * Ping the service and expect it to return after "timeout". Return true
+     * iff the service is responsive within "timeout".
+     */
+    template <typename R, typename P>
+    bool ping(std::chrono::duration<R, P> timeout) {
+        // Ensure the service is responsive after the test.
+        std::shared_ptr<IStorage> service = storage_;
+        auto ping_flag = std::make_shared<Flag>();
+        std::thread([service, ping_flag] {
+            EXPECT_EQ(STATUS_OK, AIBinder_ping(service->asBinder().get()));
+            ping_flag->OnFinish();
+        }).detach();
+        return ping_flag->Wait(timeout);
+    }
+
+    std::shared_ptr<IStorage> storage_;
+};
+
+/**
+ * Ensure garbage collection works on null callback.
+ */
+TEST_P(HealthStorageAidl, GcNullCallback) {
+    ASSERT_OK(storage_->garbageCollect(kDevGcTimeoutSec, nullptr));
+
+    // Hold test process because HAL can be single-threaded and doing GC.
+    ASSERT_TRUE(ping(kDevGcTimeout + kDevGcTolerance + kRpcTime))
+            << "Service must be available after "
+            << to_string(kDevGcTimeout + kDevGcTolerance + kRpcTime);
+}
+
+/**
+ * Ensure garbage collection works on non-null callback.
+ */
+TEST_P(HealthStorageAidl, GcNonNullCallback) {
+    std::shared_ptr<GcCallback> cb = ndk::SharedRefBase::make<GcCallback>();
+    ASSERT_OK(storage_->garbageCollect(kDevGcTimeoutSec, cb));
+    cb->WaitForResult(kDevGcTimeout + kDevGcTolerance + kRpcTime, Result::SUCCESS);
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(HealthStorageAidl);
+INSTANTIATE_TEST_SUITE_P(
+        HealthStorage, HealthStorageAidl,
+        testing::ValuesIn(::android::getAidlHalInstanceNames(IStorage::descriptor)),
+        ::android::PrintInstanceNameToString);
+
+}  // namespace aidl::android::hardware::health::storage
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    ABinderProcess_setThreadPoolMaxThreadCount(1);
+    ABinderProcess_startThreadPool();
+    return RUN_ALL_TESTS();
+}
diff --git a/health/storage/aidl/vts/functional/VtsHalHealthStorageTargetTest.xml b/health/storage/aidl/vts/functional/VtsHalHealthStorageTargetTest.xml
new file mode 100644
index 0000000..f8a1c87
--- /dev/null
+++ b/health/storage/aidl/vts/functional/VtsHalHealthStorageTargetTest.xml
@@ -0,0 +1,33 @@
+<?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.
+-->
+<configuration description="Runs VtsHalHealthStorageTargetTest.">
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-suite-tag" value="apct-native" />
+
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer">
+    </target_preparer>
+
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push" value="VtsHalHealthStorageTargetTest->/data/local/tmp/VtsHalHealthStorageTargetTest" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="VtsHalHealthStorageTargetTest" />
+        <option name="native-test-timeout" value="3m" />
+    </test>
+</configuration>
diff --git a/health/storage/impl_common/Android.bp b/health/storage/impl_common/Android.bp
new file mode 100644
index 0000000..e1149c0
--- /dev/null
+++ b/health/storage/impl_common/Android.bp
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+// Common implementation between HIDL and AIDL HAL.
+cc_library_static {
+    name: "libhealth_storage_impl_common",
+    vendor: true,
+    srcs: [
+        "impl_common.cpp",
+    ],
+    export_include_dirs: [
+        "include",
+    ],
+
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+
+    shared_libs: [
+        "libbase",
+        "libhidlbase",
+        "liblog",
+        "android.hardware.health.storage@1.0",
+    ],
+
+    static_libs: [
+        "libfstab",
+    ],
+
+    export_shared_lib_headers: [
+        "android.hardware.health.storage@1.0",
+    ],
+}
diff --git a/health/storage/impl_common/impl_common.cpp b/health/storage/impl_common/impl_common.cpp
new file mode 100644
index 0000000..6e753d4
--- /dev/null
+++ b/health/storage/impl_common/impl_common.cpp
@@ -0,0 +1,118 @@
+/*
+ * 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.
+ */
+#include <health-storage-impl/common.h>
+
+#include <android-base/chrono_utils.h>
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/strings.h>
+#include <fstab/fstab.h>
+
+using ::android::base::ReadFileToString;
+using ::android::base::Timer;
+using ::android::base::Trim;
+using ::android::base::WriteStringToFd;
+using ::android::base::WriteStringToFile;
+using ::android::fs_mgr::Fstab;
+using ::android::fs_mgr::ReadDefaultFstab;
+using ::android::hardware::health::storage::V1_0::Result;
+
+namespace android::hardware::health::storage {
+
+static std::string GetGarbageCollectPath() {
+    Fstab fstab;
+    ReadDefaultFstab(&fstab);
+
+    for (const auto& entry : fstab) {
+        if (!entry.sysfs_path.empty()) {
+            return entry.sysfs_path + "/manual_gc";
+        }
+    }
+
+    return "";
+}
+
+Result GarbageCollect(uint64_t timeout_seconds) {
+    std::string path = GetGarbageCollectPath();
+
+    if (path.empty()) {
+        LOG(WARNING) << "Cannot find Dev GC path";
+        return Result::UNKNOWN_ERROR;
+    }
+
+    Result result = Result::SUCCESS;
+    Timer timer;
+    LOG(INFO) << "Start Dev GC on " << path;
+    while (1) {
+        std::string require;
+        if (!ReadFileToString(path, &require)) {
+            PLOG(WARNING) << "Reading manual_gc failed in " << path;
+            result = Result::IO_ERROR;
+            break;
+        }
+        require = Trim(require);
+        if (require == "" || require == "off" || require == "disabled") {
+            LOG(DEBUG) << "No more to do Dev GC";
+            break;
+        }
+        LOG(DEBUG) << "Trigger Dev GC on " << path;
+        if (!WriteStringToFile("1", path)) {
+            PLOG(WARNING) << "Start Dev GC failed on " << path;
+            result = Result::IO_ERROR;
+            break;
+        }
+        if (timer.duration() >= std::chrono::seconds(timeout_seconds)) {
+            LOG(WARNING) << "Dev GC timeout";
+            // Timeout is not treated as an error. Try next time.
+            break;
+        }
+        sleep(2);
+    }
+    LOG(INFO) << "Stop Dev GC on " << path;
+    if (!WriteStringToFile("0", path)) {
+        PLOG(WARNING) << "Stop Dev GC failed on " << path;
+        result = Result::IO_ERROR;
+    }
+
+    return result;
+}
+
+void DebugDump(int fd) {
+    std::stringstream output;
+
+    std::string path = GetGarbageCollectPath();
+    if (path.empty()) {
+        output << "Cannot find Dev GC path";
+    } else {
+        std::string require;
+
+        if (ReadFileToString(path, &require)) {
+            output << path << ":" << require << std::endl;
+        }
+
+        if (WriteStringToFile("0", path)) {
+            output << "stop success" << std::endl;
+        }
+    }
+
+    if (!WriteStringToFd(output.str(), fd)) {
+        PLOG(WARNING) << "debug: cannot write to fd";
+    }
+
+    fsync(fd);
+}
+
+}  // namespace android::hardware::health::storage
diff --git a/health/storage/impl_common/include/health-storage-impl/common.h b/health/storage/impl_common/include/health-storage-impl/common.h
new file mode 100644
index 0000000..c84a6a9
--- /dev/null
+++ b/health/storage/impl_common/include/health-storage-impl/common.h
@@ -0,0 +1,31 @@
+/*
+ * 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 <android/hardware/health/storage/1.0/types.h>
+#include <string>
+
+namespace android::hardware::health::storage {
+
+// Run debug on fd
+void DebugDump(int fd);
+
+// Run garbage collection on GetGarbageCollectPath(). Blocks until garbage
+// collect finishes or |timeout_seconds| has reached.
+V1_0::Result GarbageCollect(uint64_t timeout_seconds);
+
+}  // namespace android::hardware::health::storage
diff --git a/health/1.0/default/libhealthd/healthd_board_default.cpp b/health/storage/test_common/Android.bp
similarity index 64%
rename from health/1.0/default/libhealthd/healthd_board_default.cpp
rename to health/storage/test_common/Android.bp
index 127f98e..7c6bef4 100644
--- a/health/1.0/default/libhealthd/healthd_board_default.cpp
+++ b/health/storage/test_common/Android.bp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 The Android Open Source Project
+ * 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.
@@ -14,15 +14,7 @@
  * limitations under the License.
  */
 
-#include <healthd/healthd.h>
-
-void healthd_board_init(struct healthd_config*)
-{
-    // use defaults
-}
-
-int healthd_board_battery_update(struct android::BatteryProperties*)
-{
-    // return 0 to log periodic polled battery status to kernel log
-    return 0;
+cc_library_headers {
+    name: "libhealth_storage_test_common_headers",
+    export_include_dirs: ["include"],
 }
diff --git a/health/storage/test_common/include/health-storage-test/common.h b/health/storage/test_common/include/health-storage-test/common.h
new file mode 100644
index 0000000..dfda830
--- /dev/null
+++ b/health/storage/test_common/include/health-storage-test/common.h
@@ -0,0 +1,69 @@
+/*
+ * 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 <chrono>
+#include <string>
+
+namespace android::hardware::health::storage::test {
+
+// Dev GC timeout. This is the timeout used by vold.
+const uint64_t kDevGcTimeoutSec = 120;
+const std::chrono::seconds kDevGcTimeout{kDevGcTimeoutSec};
+// Dev GC timeout tolerance. The HAL may not immediately return after the
+// timeout, so include an acceptable tolerance.
+const std::chrono::seconds kDevGcTolerance{3};
+// Time accounted for RPC calls.
+const std::chrono::milliseconds kRpcTime{1000};
+
+template <typename R>
+std::string to_string(std::chrono::duration<R, std::milli> time) {
+    return std::to_string(time.count()) + "ms";
+}
+
+/** An atomic boolean flag that indicates whether a task has finished. */
+class Flag {
+  public:
+    void OnFinish() {
+        std::unique_lock<std::mutex> lock(mutex_);
+        OnFinishLocked(&lock);
+    }
+    template <typename R, typename P>
+    bool Wait(std::chrono::duration<R, P> duration) {
+        std::unique_lock<std::mutex> lock(mutex_);
+        return WaitLocked(&lock, duration);
+    }
+
+  protected:
+    /** Will unlock. */
+    void OnFinishLocked(std::unique_lock<std::mutex>* lock) {
+        finished_ = true;
+        lock->unlock();
+        cv_.notify_all();
+    }
+    template <typename R, typename P>
+    bool WaitLocked(std::unique_lock<std::mutex>* lock, std::chrono::duration<R, P> duration) {
+        cv_.wait_for(*lock, duration, [this] { return finished_; });
+        return finished_;
+    }
+
+    bool finished_{false};
+    std::mutex mutex_;
+    std::condition_variable cv_;
+};
+
+}  // namespace android::hardware::health::storage::test
diff --git a/oemlock/aidl/vts/OWNERS b/oemlock/aidl/vts/OWNERS
new file mode 100644
index 0000000..40d95e4
--- /dev/null
+++ b/oemlock/aidl/vts/OWNERS
@@ -0,0 +1,2 @@
+chengyouho@google.com
+frankwoo@google.com
diff --git a/radio/1.5/vts/functional/radio_hidl_hal_api.cpp b/radio/1.5/vts/functional/radio_hidl_hal_api.cpp
index 7166654..0b49b36 100644
--- a/radio/1.5/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.5/vts/functional/radio_hidl_hal_api.cpp
@@ -236,7 +236,12 @@
 
     ALOGI("setSignalStrengthReportingCriteria_1_5_NGRAN_SSRSRP, rspInfo.error = %s\n",
           toString(radioRsp_v1_5->rspInfo.error).c_str());
-    ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error, {RadioError::NONE}));
+
+    // Allow REQUEST_NOT_SUPPORTED because some non-5G device may not support NGRAN for
+    // setSignalStrengthReportingCriteria_1_5()
+    ASSERT_TRUE(
+            CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error,
+                             {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
 }
 
 /*
@@ -261,7 +266,12 @@
 
     ALOGI("setSignalStrengthReportingCriteria_1_5_NGRAN_SSRSRQ, rspInfo.error = %s\n",
           toString(radioRsp_v1_5->rspInfo.error).c_str());
-    ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error, {RadioError::NONE}));
+
+    // Allow REQUEST_NOT_SUPPORTED because some non-5G device may not support NGRAN for
+    // setSignalStrengthReportingCriteria_1_5()
+    ASSERT_TRUE(
+            CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error,
+                             {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
 }
 
 /*
@@ -307,7 +317,12 @@
 
     ALOGI("setSignalStrengthReportingCriteria_1_5_NGRAN_SSSINR, rspInfo.error = %s\n",
           toString(radioRsp_v1_5->rspInfo.error).c_str());
-    ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error, {RadioError::NONE}));
+
+    // Allow REQUEST_NOT_SUPPORTED because some non-5G device may not support NGRAN for
+    // setSignalStrengthReportingCriteria_1_5()
+    ASSERT_TRUE(
+            CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error,
+                             {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
 }
 
 /*
diff --git a/security/keymint/aidl/Android.bp b/security/keymint/aidl/Android.bp
index b5adac9..5652827 100644
--- a/security/keymint/aidl/Android.bp
+++ b/security/keymint/aidl/Android.bp
@@ -4,6 +4,9 @@
     srcs: [
         "android/hardware/security/keymint/*.aidl",
     ],
+    imports: [
+        "android.hardware.security.secureclock",
+    ],
     stability: "vintf",
     backend: {
         java: {
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/HardwareAuthToken.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/HardwareAuthToken.aidl
index 0d43d8d..ad5bf39 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/HardwareAuthToken.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/HardwareAuthToken.aidl
@@ -23,6 +23,6 @@
   long userId;
   long authenticatorId;
   android.hardware.security.keymint.HardwareAuthenticatorType authenticatorType;
-  android.hardware.security.keymint.Timestamp timestamp;
+  android.hardware.security.secureclock.Timestamp timestamp;
   byte[] mac;
 }
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 07c2844..c95145d 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
@@ -20,7 +20,6 @@
 @VintfStability
 interface IKeyMintDevice {
   android.hardware.security.keymint.KeyMintHardwareInfo getHardwareInfo();
-  android.hardware.security.keymint.VerificationToken verifyAuthorization(in long challenge, in android.hardware.security.keymint.HardwareAuthToken token);
   void addRngEntropy(in byte[] data);
   android.hardware.security.keymint.KeyCreationResult generateKey(in android.hardware.security.keymint.KeyParameter[] keyParams);
   android.hardware.security.keymint.KeyCreationResult importKey(in android.hardware.security.keymint.KeyParameter[] keyParams, in android.hardware.security.keymint.KeyFormat keyFormat, in byte[] keyData);
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 08aa00a..e6ab4c8 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
@@ -19,7 +19,7 @@
 package android.hardware.security.keymint;
 @VintfStability
 interface IKeyMintOperation {
-  int update(in @nullable android.hardware.security.keymint.KeyParameterArray inParams, in @nullable byte[] input, in @nullable android.hardware.security.keymint.HardwareAuthToken inAuthToken, in @nullable android.hardware.security.keymint.VerificationToken inVerificationToken, out @nullable android.hardware.security.keymint.KeyParameterArray outParams, out @nullable android.hardware.security.keymint.ByteArray output);
-  byte[] finish(in @nullable android.hardware.security.keymint.KeyParameterArray inParams, in @nullable byte[] input, in @nullable byte[] inSignature, in @nullable android.hardware.security.keymint.HardwareAuthToken authToken, in @nullable android.hardware.security.keymint.VerificationToken inVerificationToken, out @nullable android.hardware.security.keymint.KeyParameterArray outParams);
+  int update(in @nullable android.hardware.security.keymint.KeyParameterArray inParams, in @nullable byte[] input, in @nullable android.hardware.security.keymint.HardwareAuthToken inAuthToken, in @nullable android.hardware.security.secureclock.TimeStampToken inTimeStampToken, out @nullable android.hardware.security.keymint.KeyParameterArray outParams, out @nullable android.hardware.security.keymint.ByteArray output);
+  byte[] finish(in @nullable android.hardware.security.keymint.KeyParameterArray inParams, in @nullable byte[] input, in @nullable byte[] inSignature, in @nullable android.hardware.security.keymint.HardwareAuthToken authToken, in @nullable android.hardware.security.secureclock.TimeStampToken inTimeStampToken, out @nullable android.hardware.security.keymint.KeyParameterArray outParams);
   void abort();
 }
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/VerificationToken.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/VerificationToken.aidl
deleted file mode 100644
index 7dc556c..0000000
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/VerificationToken.aidl
+++ /dev/null
@@ -1,26 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////
-// 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.security.keymint;
-@VintfStability
-parcelable VerificationToken {
-  long challenge;
-  android.hardware.security.keymint.Timestamp timestamp;
-  android.hardware.security.keymint.SecurityLevel securityLevel;
-  byte[] mac;
-}
diff --git a/security/keymint/aidl/android/hardware/security/keymint/HardwareAuthToken.aidl b/security/keymint/aidl/android/hardware/security/keymint/HardwareAuthToken.aidl
index 12d615f..1067540 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/HardwareAuthToken.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/HardwareAuthToken.aidl
@@ -16,7 +16,7 @@
 
 package android.hardware.security.keymint;
 
-import android.hardware.security.keymint.Timestamp;
+import android.hardware.security.secureclock.Timestamp;
 import android.hardware.security.keymint.HardwareAuthenticatorType;
 
 /**
diff --git a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
index 820e135..d5f7a1f 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
@@ -26,7 +26,7 @@
 import android.hardware.security.keymint.KeyMintHardwareInfo;
 import android.hardware.security.keymint.KeyPurpose;
 import android.hardware.security.keymint.SecurityLevel;
-import android.hardware.security.keymint.VerificationToken;
+import android.hardware.security.secureclock.TimeStampToken;
 
 /**
  * KeyMint device definition.
@@ -223,34 +223,6 @@
     KeyMintHardwareInfo getHardwareInfo();
 
     /**
-     * Verify authorizations for another IKeyMintDevice instance.
-     *
-     * On systems with both a StrongBox and a TEE IKeyMintDevice instance it is sometimes useful
-     * to ask the TEE KeyMintDevice to verify authorizations for a key hosted in StrongBox.
-     *
-     * For every StrongBox operation, Keystore is required to call this method on the TEE KeyMint,
-     * passing in the StrongBox key's hardwareEnforced authorization list and the challenge
-     * returned by StrongBox begin().  Keystore must then pass the VerificationToken to the
-     * subsequent invocations of StrongBox update() and finish().
-     *
-     * StrongBox implementations must return ErrorCode::UNIMPLEMENTED.
-     *
-     * @param the challenge returned by StrongBox's keyMint's begin().
-     *
-     * @param authToken A HardwareAuthToken if needed to authorize key usage.
-     *
-     * @return error ErrorCode::OK on success or ErrorCode::UNIMPLEMENTED if the KeyMintDevice is
-     *         a StrongBox.  If the IKeyMintDevice cannot verify one or more elements of
-     *         parametersToVerify it must not return an error code, but just omit the unverified
-     *         parameter from the VerificationToken.
-     *
-     * @return token the verification token.  See VerificationToken in VerificationToken.aidl for
-     *         details.
-     */
-    VerificationToken verifyAuthorization(in long challenge,
-                                          in HardwareAuthToken token);
-
-    /**
      * Adds entropy to the RNG used by KeyMint.  Entropy added through this method must not be the
      * only source of entropy used, and a secure mixing function must be used to mix the entropy
      * provided by this method with internally-generated entropy.  The mixing function must be
diff --git a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintOperation.aidl b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintOperation.aidl
index 24960cc..8c49602 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintOperation.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintOperation.aidl
@@ -20,7 +20,7 @@
 import android.hardware.security.keymint.HardwareAuthToken;
 import android.hardware.security.keymint.KeyParameter;
 import android.hardware.security.keymint.KeyParameterArray;
-import android.hardware.security.keymint.VerificationToken;
+import android.hardware.security.secureclock.TimeStampToken;
 
 @VintfStability
 interface IKeyMintOperation {
@@ -119,10 +119,9 @@
      * @param input Data to be processed.  Note that update() may or may not consume all of the data
      *        provided.  See return value.
      *
-     * @param verificationToken Verification token, used to prove that another IKeymasterDevice HAL
-     *        has verified some parameters, and to deliver the other HAL's current timestamp, if
-     *        needed.  If not provided, all fields must be initialized to zero and vectors must be
-     *        empty.
+     * @param inTimeStampToken timestamp token, certifies the freshness of an auth token in case
+     *        the security domain of this KeyMint instance has a different clock than the
+     *        authenticator issuing the auth token.
      *
      * @return error Returns ErrorCode encountered in keymint as service specific errors. See the
      *         ErrorCode enum in ErrorCode.aidl.
@@ -141,7 +140,7 @@
     int update(in @nullable KeyParameterArray inParams,
                in @nullable byte[] input,
                in @nullable HardwareAuthToken inAuthToken,
-               in @nullable VerificationToken inVerificationToken,
+               in @nullable TimeStampToken inTimeStampToken,
                out @nullable KeyParameterArray outParams,
                out @nullable ByteArray output);
 
@@ -241,9 +240,9 @@
      *
      * @param authToken Authentication token. Can be nullable if not provided.
      *
-     * @param verificationToken Verification token, used to prove that another IKeyMintDevice HAL
-     *        has verified some parameters, and to deliver the other HAL's current timestamp, if
-     *        needed. Can be nullable if not needed.
+     * @param inTimeStampToken timestamp token, certifies the freshness of an auth token in case
+     *        the security domain of this KeyMint instance has a different clock than the
+     *        authenticator issuing the auth token.
      *
      * @return outParams Any output parameters generated by finish().
      *
@@ -252,7 +251,7 @@
     byte[] finish(in @nullable KeyParameterArray inParams, in @nullable byte[] input,
                 in @nullable byte[] inSignature,
                 in @nullable HardwareAuthToken authToken,
-                in @nullable VerificationToken inVerificationToken,
+                in @nullable TimeStampToken inTimeStampToken,
                 out @nullable KeyParameterArray outParams);
 
     /**
diff --git a/security/keymint/aidl/android/hardware/security/keymint/VerificationToken.aidl b/security/keymint/aidl/android/hardware/security/keymint/VerificationToken.aidl
deleted file mode 100644
index f76e6a8..0000000
--- a/security/keymint/aidl/android/hardware/security/keymint/VerificationToken.aidl
+++ /dev/null
@@ -1,63 +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.security.keymint;
-
-import android.hardware.security.keymint.SecurityLevel;
-import android.hardware.security.keymint.Timestamp;
-
-/**
- * VerificationToken instances are used for secure environments to authenticate one another.
- *
- * This version of the parcelable currently don't use the parametersVerified field since it's not
- * needed for time-based verification. This can be added in a later version, if needed.
- */
-@VintfStability
-parcelable VerificationToken {
-    /**
-     * The operation handle, used to ensure freshness.
-     */
-    long challenge;
-
-    /**
-     * The current time of the secure environment that generates the VerificationToken.  This can be
-     * checked against auth tokens generated by the same secure environment, which avoids needing to
-     * synchronize clocks.
-     */
-    Timestamp timestamp;
-
-    /**
-     * SecurityLevel of the secure environment that generated the token.
-     */
-    SecurityLevel securityLevel;
-
-    /**
-     * 32-byte HMAC-SHA256 of the above values, computed as:
-     *
-     *    HMAC(H,
-     *         "Auth Verification" || challenge || timestamp || securityLevel)
-     *
-     * where:
-     *
-     *   ``HMAC'' is the shared HMAC key (see computeSharedHmac() in IKeyMint).
-     *
-     *   ``||'' represents concatenation
-     *
-     * The representation of challenge and timestamp is as 64-bit unsigned integers in big-endian
-     * order.  securityLevel is represented as a 32-bit unsigned integer in big-endian order.
-     */
-    byte[] mac;
-}
diff --git a/security/keymint/aidl/vts/functional/Android.bp b/security/keymint/aidl/vts/functional/Android.bp
index c7cc380..17a4613 100644
--- a/security/keymint/aidl/vts/functional/Android.bp
+++ b/security/keymint/aidl/vts/functional/Android.bp
@@ -22,7 +22,6 @@
     ],
     srcs: [
         "KeyMintTest.cpp",
-        "VerificationTokenTest.cpp",
     ],
     shared_libs: [
         "libbinder_ndk",
@@ -32,6 +31,7 @@
     ],
     static_libs: [
         "android.hardware.security.keymint-unstable-ndk_platform",
+        "android.hardware.security.secureclock-unstable-ndk_platform",
         "libcppbor_external",
         "libkeymint_vts_test_utils",
     ],
@@ -61,6 +61,7 @@
     ],
     static_libs: [
         "android.hardware.security.keymint-unstable-ndk_platform",
+        "android.hardware.security.secureclock-unstable-ndk_platform",
         "libcppbor",
     ],
 }
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
index 93a216f..766c02d 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
@@ -37,7 +37,7 @@
         os << "(Empty)" << ::std::endl;
     else {
         os << "\n";
-        for (size_t i = 0; i < set.size(); ++i) os << set[i] << ::std::endl;
+        for (auto& entry : set) os << entry << ::std::endl;
     }
     return os;
 }
@@ -131,6 +131,17 @@
         *key_blob = std::move(creationResult.keyBlob);
         *key_characteristics = std::move(creationResult.keyCharacteristics);
         cert_chain_ = std::move(creationResult.certificateChain);
+
+        auto algorithm = key_desc.GetTagValue(TAG_ALGORITHM);
+        EXPECT_TRUE(algorithm);
+        if (algorithm &&
+            (algorithm.value() == Algorithm::RSA || algorithm.value() == Algorithm::EC)) {
+            EXPECT_GE(cert_chain_.size(), 1);
+            if (key_desc.Contains(TAG_ATTESTATION_CHALLENGE)) EXPECT_GT(cert_chain_.size(), 1);
+        } else {
+            // For symmetric keys there should be no certificates.
+            EXPECT_EQ(cert_chain_.size(), 0);
+        }
     }
 
     return GetReturnErrorCode(result);
@@ -162,6 +173,17 @@
         *key_blob = std::move(creationResult.keyBlob);
         *key_characteristics = std::move(creationResult.keyCharacteristics);
         cert_chain_ = std::move(creationResult.certificateChain);
+
+        auto algorithm = key_desc.GetTagValue(TAG_ALGORITHM);
+        EXPECT_TRUE(algorithm);
+        if (algorithm &&
+            (algorithm.value() == Algorithm::RSA || algorithm.value() == Algorithm::EC)) {
+            EXPECT_GE(cert_chain_.size(), 1);
+            if (key_desc.Contains(TAG_ATTESTATION_CHALLENGE)) EXPECT_GT(cert_chain_.size(), 1);
+        } else {
+            // For symmetric keys there should be no certificates.
+            EXPECT_EQ(cert_chain_.size(), 0);
+        }
     }
 
     return GetReturnErrorCode(result);
@@ -195,6 +217,20 @@
         key_blob_ = std::move(creationResult.keyBlob);
         key_characteristics_ = std::move(creationResult.keyCharacteristics);
         cert_chain_ = std::move(creationResult.certificateChain);
+
+        AuthorizationSet allAuths;
+        for (auto& entry : key_characteristics_) {
+            allAuths.push_back(AuthorizationSet(entry.authorizations));
+        }
+        auto algorithm = allAuths.GetTagValue(TAG_ALGORITHM);
+        EXPECT_TRUE(algorithm);
+        if (algorithm &&
+            (algorithm.value() == Algorithm::RSA || algorithm.value() == Algorithm::EC)) {
+            EXPECT_GE(cert_chain_.size(), 1);
+        } else {
+            // For symmetric keys there should be no certificates.
+            EXPECT_EQ(cert_chain_.size(), 0);
+        }
     }
 
     return GetReturnErrorCode(result);
@@ -788,6 +824,24 @@
     return (found == key_characteristics.end()) ? kEmptyAuthList : found->authorizations;
 }
 
+const vector<KeyParameter>& KeyMintAidlTestBase::HwEnforcedAuthorizations(
+        const vector<KeyCharacteristics>& key_characteristics) {
+    auto found =
+            std::find_if(key_characteristics.begin(), key_characteristics.end(), [](auto& entry) {
+                return entry.securityLevel == SecurityLevel::STRONGBOX ||
+                       entry.securityLevel == SecurityLevel::TRUSTED_ENVIRONMENT;
+            });
+    return (found == key_characteristics.end()) ? kEmptyAuthList : found->authorizations;
+}
+
+const vector<KeyParameter>& KeyMintAidlTestBase::SwEnforcedAuthorizations(
+        const vector<KeyCharacteristics>& key_characteristics) {
+    auto found = std::find_if(
+            key_characteristics.begin(), key_characteristics.end(),
+            [](auto& entry) { return entry.securityLevel == SecurityLevel::SOFTWARE; });
+    return (found == key_characteristics.end()) ? kEmptyAuthList : found->authorizations;
+}
+
 }  // 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 f36c397..c1a1dd9 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
@@ -27,7 +27,11 @@
 
 #include <keymint_support/authorization_set.h>
 
-namespace aidl::android::hardware::security::keymint::test {
+namespace aidl::android::hardware::security::keymint {
+
+::std::ostream& operator<<(::std::ostream& os, const AuthorizationSet& set);
+
+namespace test {
 
 using ::android::sp;
 using Status = ::ndk::ScopedAStatus;
@@ -37,8 +41,6 @@
 
 constexpr uint64_t kOpHandleSentinel = 0xFFFFFFFFFFFFFFFF;
 
-::std::ostream& operator<<(::std::ostream& os, const AuthorizationSet& set);
-
 class KeyMintAidlTestBase : public ::testing::TestWithParam<string> {
   public:
     void SetUp() override;
@@ -173,6 +175,10 @@
     inline const vector<KeyParameter>& SecLevelAuthorizations() {
         return SecLevelAuthorizations(key_characteristics_);
     }
+    const vector<KeyParameter>& HwEnforcedAuthorizations(
+            const vector<KeyCharacteristics>& key_characteristics);
+    const vector<KeyParameter>& SwEnforcedAuthorizations(
+            const vector<KeyCharacteristics>& key_characteristics);
 
   private:
     std::shared_ptr<IKeyMintDevice> keymint_;
@@ -190,4 +196,6 @@
                              testing::ValuesIn(KeyMintAidlTestBase::build_params()), \
                              ::android::PrintInstanceNameToString)
 
-}  // namespace aidl::android::hardware::security::keymint::test
+}  // namespace test
+
+}  // namespace aidl::android::hardware::security::keymint
diff --git a/security/keymint/aidl/vts/functional/KeyMintTest.cpp b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
index bd36b8e..e7c94f3 100644
--- a/security/keymint/aidl/vts/functional/KeyMintTest.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
@@ -180,9 +180,280 @@
     void operator()(RSA* p) { RSA_free(p); }
 };
 
-/* TODO(seleneh) add attestation verification codes like verify_chain() and
- * attestation tests after we decided on the keymint 1 attestation changes.
- */
+char nibble2hex[16] = {'0', '1', '2', '3', '4', '5', '6', '7',
+                       '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
+
+string bin2hex(const vector<uint8_t>& data) {
+    string retval;
+    retval.reserve(data.size() * 2 + 1);
+    for (uint8_t byte : data) {
+        retval.push_back(nibble2hex[0x0F & (byte >> 4)]);
+        retval.push_back(nibble2hex[0x0F & byte]);
+    }
+    return retval;
+}
+
+X509* parse_cert_blob(const vector<uint8_t>& blob) {
+    const uint8_t* p = blob.data();
+    return d2i_X509(nullptr, &p, blob.size());
+}
+
+bool verify_chain(const vector<Certificate>& chain) {
+    for (size_t i = 0; i < chain.size(); ++i) {
+        X509_Ptr key_cert(parse_cert_blob(chain[i].encodedCertificate));
+        X509_Ptr signing_cert;
+        if (i < chain.size() - 1) {
+            signing_cert.reset(parse_cert_blob(chain[i + 1].encodedCertificate));
+        } else {
+            signing_cert.reset(parse_cert_blob(chain[i].encodedCertificate));
+        }
+        EXPECT_TRUE(!!key_cert.get() && !!signing_cert.get());
+        if (!key_cert.get() || !signing_cert.get()) return false;
+
+        EVP_PKEY_Ptr signing_pubkey(X509_get_pubkey(signing_cert.get()));
+        EXPECT_TRUE(!!signing_pubkey.get());
+        if (!signing_pubkey.get()) return false;
+
+        EXPECT_EQ(1, X509_verify(key_cert.get(), signing_pubkey.get()))
+                << "Verification of certificate " << i << " failed "
+                << "OpenSSL error string: " << ERR_error_string(ERR_get_error(), NULL);
+
+        char* cert_issuer =  //
+                X509_NAME_oneline(X509_get_issuer_name(key_cert.get()), nullptr, 0);
+        char* signer_subj =
+                X509_NAME_oneline(X509_get_subject_name(signing_cert.get()), nullptr, 0);
+        EXPECT_STREQ(cert_issuer, signer_subj) << "Cert " << i << " has wrong issuer.";
+        if (i == 0) {
+            char* cert_sub = X509_NAME_oneline(X509_get_subject_name(key_cert.get()), nullptr, 0);
+            EXPECT_STREQ("/CN=Android Keystore Key", cert_sub)
+                    << "Cert " << i << " has wrong subject.";
+            OPENSSL_free(cert_sub);
+        }
+
+        OPENSSL_free(cert_issuer);
+        OPENSSL_free(signer_subj);
+
+        if (dump_Attestations) std::cout << bin2hex(chain[i].encodedCertificate) << std::endl;
+    }
+
+    return true;
+}
+
+// Extract attestation record from cert. Returned object is still part of cert; don't free it
+// separately.
+ASN1_OCTET_STRING* get_attestation_record(X509* certificate) {
+    ASN1_OBJECT_Ptr oid(OBJ_txt2obj(kAttestionRecordOid, 1 /* dotted string format */));
+    EXPECT_TRUE(!!oid.get());
+    if (!oid.get()) return nullptr;
+
+    int location = X509_get_ext_by_OBJ(certificate, oid.get(), -1 /* search from beginning */);
+    EXPECT_NE(-1, location) << "Attestation extension not found in certificate";
+    if (location == -1) return nullptr;
+
+    X509_EXTENSION* attest_rec_ext = X509_get_ext(certificate, location);
+    EXPECT_TRUE(!!attest_rec_ext)
+            << "Found attestation extension but couldn't retrieve it?  Probably a BoringSSL bug.";
+    if (!attest_rec_ext) return nullptr;
+
+    ASN1_OCTET_STRING* attest_rec = X509_EXTENSION_get_data(attest_rec_ext);
+    EXPECT_TRUE(!!attest_rec) << "Attestation extension contained no data";
+    return attest_rec;
+}
+
+bool tag_in_list(const KeyParameter& entry) {
+    // Attestations don't contain everything in key authorization lists, so we need to filter
+    // the key lists to produce the lists that we expect to match the attestations.
+    auto tag_list = {
+            Tag::BLOB_USAGE_REQUIREMENTS,  //
+            Tag::CREATION_DATETIME,        //
+            Tag::EC_CURVE,
+            Tag::HARDWARE_TYPE,
+            Tag::INCLUDE_UNIQUE_ID,
+    };
+    return std::find(tag_list.begin(), tag_list.end(), entry.tag) != tag_list.end();
+}
+
+AuthorizationSet filtered_tags(const AuthorizationSet& set) {
+    AuthorizationSet filtered;
+    std::remove_copy_if(set.begin(), set.end(), std::back_inserter(filtered), tag_in_list);
+    return filtered;
+}
+
+bool avb_verification_enabled() {
+    char value[PROPERTY_VALUE_MAX];
+    return property_get("ro.boot.vbmeta.device_state", value, "") != 0;
+}
+
+bool verify_attestation_record(const string& challenge,                //
+                               const string& app_id,                   //
+                               AuthorizationSet expected_sw_enforced,  //
+                               AuthorizationSet expected_hw_enforced,  //
+                               SecurityLevel security_level,
+                               const vector<uint8_t>& attestation_cert) {
+    X509_Ptr cert(parse_cert_blob(attestation_cert));
+    EXPECT_TRUE(!!cert.get());
+    if (!cert.get()) return false;
+
+    ASN1_OCTET_STRING* attest_rec = get_attestation_record(cert.get());
+    EXPECT_TRUE(!!attest_rec);
+    if (!attest_rec) return false;
+
+    AuthorizationSet att_sw_enforced;
+    AuthorizationSet att_hw_enforced;
+    uint32_t att_attestation_version;
+    uint32_t att_keymaster_version;
+    SecurityLevel att_attestation_security_level;
+    SecurityLevel att_keymaster_security_level;
+    vector<uint8_t> att_challenge;
+    vector<uint8_t> att_unique_id;
+    vector<uint8_t> att_app_id;
+
+    auto error = parse_attestation_record(attest_rec->data,                 //
+                                          attest_rec->length,               //
+                                          &att_attestation_version,         //
+                                          &att_attestation_security_level,  //
+                                          &att_keymaster_version,           //
+                                          &att_keymaster_security_level,    //
+                                          &att_challenge,                   //
+                                          &att_sw_enforced,                 //
+                                          &att_hw_enforced,                 //
+                                          &att_unique_id);
+    EXPECT_EQ(ErrorCode::OK, error);
+    if (error != ErrorCode::OK) return false;
+
+    EXPECT_GE(att_attestation_version, 3U);
+
+    expected_sw_enforced.push_back(TAG_ATTESTATION_APPLICATION_ID,
+                                   vector<uint8_t>(app_id.begin(), app_id.end()));
+
+    EXPECT_GE(att_keymaster_version, 4U);
+    EXPECT_EQ(security_level, att_keymaster_security_level);
+    EXPECT_EQ(security_level, att_attestation_security_level);
+
+    EXPECT_EQ(challenge.length(), att_challenge.size());
+    EXPECT_EQ(0, memcmp(challenge.data(), att_challenge.data(), challenge.length()));
+
+    char property_value[PROPERTY_VALUE_MAX] = {};
+    // TODO(b/136282179): When running under VTS-on-GSI the TEE-backed
+    // keymaster implementation will report YYYYMM dates instead of YYYYMMDD
+    // for the BOOT_PATCH_LEVEL.
+    if (avb_verification_enabled()) {
+        for (int i = 0; i < att_hw_enforced.size(); i++) {
+            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>());
+                // strptime seems to require delimiters, but the tag value will
+                // be YYYYMMDD
+                date.insert(6, "-");
+                date.insert(4, "-");
+                EXPECT_EQ(date.size(), 10);
+                struct tm time;
+                strptime(date.c_str(), "%Y-%m-%d", &time);
+
+                // Day of the month (0-31)
+                EXPECT_GE(time.tm_mday, 0);
+                EXPECT_LT(time.tm_mday, 32);
+                // Months since Jan (0-11)
+                EXPECT_GE(time.tm_mon, 0);
+                EXPECT_LT(time.tm_mon, 12);
+                // Years since 1900
+                EXPECT_GT(time.tm_year, 110);
+                EXPECT_LT(time.tm_year, 200);
+            }
+        }
+    }
+
+    // Check to make sure boolean values are properly encoded. Presence of a boolean tag indicates
+    // true. A provided boolean tag that can be pulled back out of the certificate indicates correct
+    // encoding. No need to check if it's in both lists, since the AuthorizationSet compare below
+    // will handle mismatches of tags.
+    if (security_level == SecurityLevel::SOFTWARE) {
+        EXPECT_TRUE(expected_sw_enforced.Contains(TAG_NO_AUTH_REQUIRED));
+    } else {
+        EXPECT_TRUE(expected_hw_enforced.Contains(TAG_NO_AUTH_REQUIRED));
+    }
+
+    // Alternatively this checks the opposite - a false boolean tag (one that isn't provided in
+    // the authorization list during key generation) isn't being attested to in the certificate.
+    EXPECT_FALSE(expected_sw_enforced.Contains(TAG_TRUSTED_USER_PRESENCE_REQUIRED));
+    EXPECT_FALSE(att_sw_enforced.Contains(TAG_TRUSTED_USER_PRESENCE_REQUIRED));
+    EXPECT_FALSE(expected_hw_enforced.Contains(TAG_TRUSTED_USER_PRESENCE_REQUIRED));
+    EXPECT_FALSE(att_hw_enforced.Contains(TAG_TRUSTED_USER_PRESENCE_REQUIRED));
+
+    if (att_hw_enforced.Contains(TAG_ALGORITHM, Algorithm::EC)) {
+        // For ECDSA keys, either an EC_CURVE or a KEY_SIZE can be specified, but one must be.
+        EXPECT_TRUE(att_hw_enforced.Contains(TAG_EC_CURVE) ||
+                    att_hw_enforced.Contains(TAG_KEY_SIZE));
+    }
+
+    // Test root of trust elements
+    vector<uint8_t> verified_boot_key;
+    VerifiedBoot verified_boot_state;
+    bool device_locked;
+    vector<uint8_t> verified_boot_hash;
+    error = parse_root_of_trust(attest_rec->data, attest_rec->length, &verified_boot_key,
+                                &verified_boot_state, &device_locked, &verified_boot_hash);
+    EXPECT_EQ(ErrorCode::OK, error);
+
+    if (avb_verification_enabled()) {
+        EXPECT_NE(property_get("ro.boot.vbmeta.digest", property_value, ""), 0);
+        string prop_string(property_value);
+        EXPECT_EQ(prop_string.size(), 64);
+        EXPECT_EQ(prop_string, bin2hex(verified_boot_hash));
+
+        EXPECT_NE(property_get("ro.boot.vbmeta.device_state", property_value, ""), 0);
+        if (!strcmp(property_value, "unlocked")) {
+            EXPECT_FALSE(device_locked);
+        } else {
+            EXPECT_TRUE(device_locked);
+        }
+
+        // Check that the device is locked if not debuggable, e.g., user build
+        // images in CTS. For VTS, debuggable images are used to allow adb root
+        // and the device is unlocked.
+        if (!property_get_bool("ro.debuggable", false)) {
+            EXPECT_TRUE(device_locked);
+        } else {
+            EXPECT_FALSE(device_locked);
+        }
+    }
+
+    // Verified boot key should be all 0's if the boot state is not verified or self signed
+    std::string empty_boot_key(32, '\0');
+    std::string verified_boot_key_str((const char*)verified_boot_key.data(),
+                                      verified_boot_key.size());
+    EXPECT_NE(property_get("ro.boot.verifiedbootstate", property_value, ""), 0);
+    if (!strcmp(property_value, "green")) {
+        EXPECT_EQ(verified_boot_state, VerifiedBoot::VERIFIED);
+        EXPECT_NE(0, memcmp(verified_boot_key.data(), empty_boot_key.data(),
+                            verified_boot_key.size()));
+    } else if (!strcmp(property_value, "yellow")) {
+        EXPECT_EQ(verified_boot_state, VerifiedBoot::SELF_SIGNED);
+        EXPECT_NE(0, memcmp(verified_boot_key.data(), empty_boot_key.data(),
+                            verified_boot_key.size()));
+    } else if (!strcmp(property_value, "orange")) {
+        EXPECT_EQ(verified_boot_state, VerifiedBoot::UNVERIFIED);
+        EXPECT_EQ(0, memcmp(verified_boot_key.data(), empty_boot_key.data(),
+                            verified_boot_key.size()));
+    } else if (!strcmp(property_value, "red")) {
+        EXPECT_EQ(verified_boot_state, VerifiedBoot::FAILED);
+    } else {
+        EXPECT_EQ(verified_boot_state, VerifiedBoot::UNVERIFIED);
+        EXPECT_NE(0, memcmp(verified_boot_key.data(), empty_boot_key.data(),
+                            verified_boot_key.size()));
+    }
+
+    att_sw_enforced.Sort();
+    expected_sw_enforced.Sort();
+    EXPECT_EQ(filtered_tags(expected_sw_enforced), filtered_tags(att_sw_enforced));
+
+    att_hw_enforced.Sort();
+    expected_hw_enforced.Sort();
+    EXPECT_EQ(filtered_tags(expected_hw_enforced), filtered_tags(att_hw_enforced));
+
+    return true;
+}
 
 std::string make_string(const uint8_t* data, size_t length) {
     return std::string(reinterpret_cast<const char*>(data), length);
@@ -289,6 +560,51 @@
 }
 
 /*
+ * NewKeyGenerationTest.Rsa
+ *
+ * Verifies that keymint can generate all required RSA key sizes, and that the resulting keys
+ * have correct characteristics.
+ */
+TEST_P(NewKeyGenerationTest, RsaWithAttestation) {
+    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),
+                                             &key_blob, &key_characteristics));
+
+        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));
+
+        EXPECT_TRUE(verify_chain(cert_chain_));
+        ASSERT_GT(cert_chain_.size(), 0);
+
+        AuthorizationSet hw_enforced = HwEnforcedAuthorizations(key_characteristics);
+        AuthorizationSet sw_enforced = SwEnforcedAuthorizations(key_characteristics);
+        EXPECT_TRUE(verify_attestation_record(challenge, app_id,  //
+                                              sw_enforced, hw_enforced, SecLevel(),
+                                              cert_chain_[0].encodedCertificate));
+
+        CheckedDeleteKey(&key_blob);
+    }
+}
+
+/*
  * NewKeyGenerationTest.NoInvalidRsaSizes
  *
  * Verifies that keymint cannot generate any RSA key sizes that are designated as invalid.
@@ -3895,16 +4211,6 @@
 
 INSTANTIATE_KEYMINT_AIDL_TEST(AddEntropyTest);
 
-typedef KeyMintAidlTestBase AttestationTest;
-
-/*
- * AttestationTest.RsaAttestation
- *
- * Verifies that attesting to RSA keys works and generates the expected output.
- */
-// TODO(seleneh) add attestation tests back after decided on the new attestation
-// behavior under generateKey and importKey
-
 typedef KeyMintAidlTestBase KeyDeletionTest;
 
 /**
diff --git a/security/keymint/aidl/vts/functional/VerificationTokenTest.cpp b/security/keymint/aidl/vts/functional/VerificationTokenTest.cpp
deleted file mode 100644
index 0b1eccd..0000000
--- a/security/keymint/aidl/vts/functional/VerificationTokenTest.cpp
+++ /dev/null
@@ -1,168 +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.
- */
-
-#include "KeyMintAidlTestBase.h"
-
-namespace aidl::android::hardware::security::keymint::test {
-
-class VerificationTokenTest : public KeyMintAidlTestBase {
-  protected:
-    struct VerifyAuthorizationResult {
-        ErrorCode error;
-        VerificationToken token;
-    };
-
-    VerifyAuthorizationResult verifyAuthorization(uint64_t operationHandle,
-                                                  const HardwareAuthToken& authToken) {
-        VerifyAuthorizationResult result;
-
-        Status err;
-        err = keyMint().verifyAuthorization(operationHandle,  //
-                                            authToken,        //
-                                            &result.token);
-
-        result.error = GetReturnErrorCode(err);
-        return result;
-    }
-
-    uint64_t getTime() {
-        struct timespec timespec;
-        EXPECT_EQ(0, clock_gettime(CLOCK_BOOTTIME, &timespec));
-        return timespec.tv_sec * 1000 + timespec.tv_nsec / 1000000;
-    }
-
-    int sleep_ms(uint32_t milliseconds) {
-        struct timespec sleep_time = {static_cast<time_t>(milliseconds / 1000),
-                                      static_cast<long>(milliseconds % 1000) * 1000000};
-        while (sleep_time.tv_sec || sleep_time.tv_nsec) {
-            if (nanosleep(&sleep_time /* to wait */,
-                          &sleep_time /* remaining (on interrruption) */) == 0) {
-                sleep_time = {};
-            } else {
-                if (errno != EINTR) return errno;
-            }
-        }
-        return 0;
-    }
-};
-
-/*
- * VerificationTokens exist to facilitate cross-KeyMint verification of requirements.  As
- * such, the precise capabilities required will vary depending on the specific vendor
- * implementations. Essentially, VerificationTokens are a "hook" to enable vendor
- * implementations to communicate, so the precise usage is defined by those vendors.  The only
- * thing we really can test is that tokens can be created by TEE keyMints, and that the
- * timestamps increase as expected.
- */
-TEST_P(VerificationTokenTest, TestCreation) {
-    auto result1 = verifyAuthorization(1 /* operation handle */, HardwareAuthToken());
-    auto result1_time = getTime();
-
-    if (SecLevel() == SecurityLevel::STRONGBOX) {
-        // StrongBox should not implement verifyAuthorization.
-        EXPECT_EQ(ErrorCode::UNIMPLEMENTED, result1.error);
-        return;
-    }
-
-    ASSERT_EQ(ErrorCode::OK, result1.error);
-    EXPECT_EQ(1U, result1.token.challenge);
-    EXPECT_EQ(SecLevel(), result1.token.securityLevel);
-    EXPECT_GT(result1.token.timestamp.milliSeconds, 0U);
-
-    constexpr uint32_t time_to_sleep = 200;
-    sleep_ms(time_to_sleep);
-
-    auto result2 = verifyAuthorization(2 /* operation handle */, HardwareAuthToken());
-
-    auto result2_time = getTime();
-    ASSERT_EQ(ErrorCode::OK, result2.error);
-    EXPECT_EQ(2U, result2.token.challenge);
-    EXPECT_EQ(SecLevel(), result2.token.securityLevel);
-
-    auto host_time_delta = result2_time - result1_time;
-
-    EXPECT_GE(host_time_delta, time_to_sleep)
-            << "We slept for " << time_to_sleep << " ms, the clock must have advanced by that much";
-    EXPECT_LE(host_time_delta, time_to_sleep + 20)
-            << "The verifyAuthorization call took " << (host_time_delta - time_to_sleep)
-            << " ms?  That's awful!";
-
-    auto km_time_delta =
-            result2.token.timestamp.milliSeconds - result1.token.timestamp.milliSeconds;
-
-    // If not too much else is going on on the system, the time delta should be quite close.  Allow
-    // 2 ms of slop just to avoid test flakiness.
-    //
-    // TODO(swillden): see if we can output values so they can be gathered across many runs and
-    // report if times aren't nearly always <1ms apart.
-    EXPECT_LE(host_time_delta, km_time_delta + 2);
-    EXPECT_LE(km_time_delta, host_time_delta + 2);
-    ASSERT_EQ(result1.token.mac.size(), result2.token.mac.size());
-    ASSERT_NE(0,
-              memcmp(result1.token.mac.data(), result2.token.mac.data(), result1.token.mac.size()));
-}
-
-/*
- * Test that the mac changes when the time stamp changes. This is does not guarantee that the time
- * stamp is included in the mac but on failure we know that it is not. Other than in the test
- * case above we call verifyAuthorization with the exact same set of parameters.
- */
-TEST_P(VerificationTokenTest, MacChangesOnChangingTimestamp) {
-    auto result1 = verifyAuthorization(0 /* operation handle */, HardwareAuthToken());
-    auto result1_time = getTime();
-
-    if (SecLevel() == SecurityLevel::STRONGBOX) {
-        // StrongBox should not implement verifyAuthorization.
-        EXPECT_EQ(ErrorCode::UNIMPLEMENTED, result1.error);
-        return;
-    }
-
-    EXPECT_EQ(ErrorCode::OK, result1.error);
-    EXPECT_EQ(0U, result1.token.challenge);
-    EXPECT_EQ(SecLevel(), result1.token.securityLevel);
-    EXPECT_GT(result1.token.timestamp.milliSeconds, 0U);
-
-    constexpr uint32_t time_to_sleep = 200;
-    sleep_ms(time_to_sleep);
-
-    auto result2 = verifyAuthorization(0 /* operation handle */, HardwareAuthToken());
-    // ASSERT_TRUE(result2.callSuccessful);
-    auto result2_time = getTime();
-    EXPECT_EQ(ErrorCode::OK, result2.error);
-    EXPECT_EQ(0U, result2.token.challenge);
-    EXPECT_EQ(SecLevel(), result2.token.securityLevel);
-
-    auto host_time_delta = result2_time - result1_time;
-
-    EXPECT_GE(host_time_delta, time_to_sleep)
-            << "We slept for " << time_to_sleep << " ms, the clock must have advanced by that much";
-    EXPECT_LE(host_time_delta, time_to_sleep + 20)
-            << "The verifyAuthorization call took " << (host_time_delta - time_to_sleep)
-            << " ms?  That's awful!";
-
-    auto km_time_delta =
-            result2.token.timestamp.milliSeconds - result1.token.timestamp.milliSeconds;
-
-    EXPECT_LE(host_time_delta, km_time_delta + 2);
-    EXPECT_LE(km_time_delta, host_time_delta + 2);
-    ASSERT_EQ(result1.token.mac.size(), result2.token.mac.size());
-    ASSERT_NE(0,
-              memcmp(result1.token.mac.data(), result2.token.mac.data(), result1.token.mac.size()));
-}
-
-INSTANTIATE_KEYMINT_AIDL_TEST(VerificationTokenTest);
-
-}  // namespace aidl::android::hardware::security::keymint::test
diff --git a/security/keymint/support/include/keymint_support/authorization_set.h b/security/keymint/support/include/keymint_support/authorization_set.h
index 596bb89..1407c5f 100644
--- a/security/keymint/support/include/keymint_support/authorization_set.h
+++ b/security/keymint/support/include/keymint_support/authorization_set.h
@@ -259,6 +259,12 @@
                              size - 1);  // drop the terminating '\0'
     }
 
+    template <Tag tag>
+    AuthorizationSetBuilder& Authorization(TypedTag<TagType::BYTES, tag> ttag,
+                                           const std::string& data) {
+        return Authorization(ttag, reinterpret_cast<const uint8_t*>(data.data()), data.size());
+    }
+
     AuthorizationSetBuilder& Authorizations(const AuthorizationSet& set) {
         for (const auto& entry : set) {
             push_back(entry);
@@ -294,6 +300,20 @@
     AuthorizationSetBuilder& Digest(std::vector<Digest> digests);
     AuthorizationSetBuilder& Padding(std::initializer_list<PaddingMode> paddings);
 
+    AuthorizationSetBuilder& AttestationChallenge(const std::string& challenge) {
+        return Authorization(TAG_ATTESTATION_CHALLENGE, challenge);
+    }
+    AuthorizationSetBuilder& AttestationChallenge(std::vector<uint8_t> challenge) {
+        return Authorization(TAG_ATTESTATION_CHALLENGE, challenge);
+    }
+
+    AuthorizationSetBuilder& AttestationApplicationId(const std::string& id) {
+        return Authorization(TAG_ATTESTATION_APPLICATION_ID, id);
+    }
+    AuthorizationSetBuilder& AttestationApplicationId(std::vector<uint8_t> id) {
+        return Authorization(TAG_ATTESTATION_APPLICATION_ID, id);
+    }
+
     template <typename... T>
     AuthorizationSetBuilder& BlockMode(T&&... a) {
         return BlockMode({std::forward<T>(a)...});
diff --git a/security/secureclock/aidl/Android.bp b/security/secureclock/aidl/Android.bp
index 7d26a9b..5a6d7ae 100644
--- a/security/secureclock/aidl/Android.bp
+++ b/security/secureclock/aidl/Android.bp
@@ -5,9 +5,6 @@
         "android/hardware/security/secureclock/*.aidl",
     ],
     stability: "vintf",
-    imports: [
-        "android.hardware.security.keymint",
-    ],
     backend: {
         java: {
             sdk_version: "module_current",
diff --git a/security/secureclock/aidl/aidl_api/android.hardware.security.secureclock/current/android/hardware/security/secureclock/TimeStampToken.aidl b/security/secureclock/aidl/aidl_api/android.hardware.security.secureclock/current/android/hardware/security/secureclock/TimeStampToken.aidl
index c23ddca..51b1824 100644
--- a/security/secureclock/aidl/aidl_api/android.hardware.security.secureclock/current/android/hardware/security/secureclock/TimeStampToken.aidl
+++ b/security/secureclock/aidl/aidl_api/android.hardware.security.secureclock/current/android/hardware/security/secureclock/TimeStampToken.aidl
@@ -20,7 +20,6 @@
 @VintfStability
 parcelable TimeStampToken {
   long challenge;
-  android.hardware.security.keymint.Timestamp timestamp;
-  android.hardware.security.keymint.SecurityLevel securityLevel;
+  android.hardware.security.secureclock.Timestamp timestamp;
   byte[] mac;
 }
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Timestamp.aidl b/security/secureclock/aidl/aidl_api/android.hardware.security.secureclock/current/android/hardware/security/secureclock/Timestamp.aidl
similarity index 95%
rename from security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Timestamp.aidl
rename to security/secureclock/aidl/aidl_api/android.hardware.security.secureclock/current/android/hardware/security/secureclock/Timestamp.aidl
index 963e66e..50b8b9f 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Timestamp.aidl
+++ b/security/secureclock/aidl/aidl_api/android.hardware.security.secureclock/current/android/hardware/security/secureclock/Timestamp.aidl
@@ -16,7 +16,7 @@
 // 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.security.keymint;
+package android.hardware.security.secureclock;
 @VintfStability
 parcelable Timestamp {
   long milliSeconds;
diff --git a/security/secureclock/aidl/android/hardware/security/secureclock/TimeStampToken.aidl b/security/secureclock/aidl/android/hardware/security/secureclock/TimeStampToken.aidl
index 76a2d28..b24d335 100644
--- a/security/secureclock/aidl/android/hardware/security/secureclock/TimeStampToken.aidl
+++ b/security/secureclock/aidl/android/hardware/security/secureclock/TimeStampToken.aidl
@@ -16,8 +16,7 @@
 
 package android.hardware.security.secureclock;
 
-import android.hardware.security.keymint.SecurityLevel;
-import android.hardware.security.keymint.Timestamp;
+import android.hardware.security.secureclock.Timestamp;
 
 /**
  * TimeStampToken instances are used for secure environments that requires secure time information.
@@ -36,11 +35,6 @@
     Timestamp timestamp;
 
     /**
-     * SecurityLevel of the secure environment that generated the token.
-     */
-    SecurityLevel securityLevel;
-
-    /**
      * 32-byte HMAC-SHA256 of the above values, computed as:
      *
      *    HMAC(H,
diff --git a/security/keymint/aidl/android/hardware/security/keymint/Timestamp.aidl b/security/secureclock/aidl/android/hardware/security/secureclock/Timestamp.aidl
similarity index 95%
rename from security/keymint/aidl/android/hardware/security/keymint/Timestamp.aidl
rename to security/secureclock/aidl/android/hardware/security/secureclock/Timestamp.aidl
index ebb3684..7bd1f9e 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/Timestamp.aidl
+++ b/security/secureclock/aidl/android/hardware/security/secureclock/Timestamp.aidl
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.hardware.security.keymint;
+package android.hardware.security.secureclock;
 
 /**
  * Time in milliseconds since some arbitrary point in time.  Time must be monotonically increasing,
diff --git a/tv/tuner/1.0/vts/functional/DvrTests.cpp b/tv/tuner/1.0/vts/functional/DvrTests.cpp
index 0dfc032..ba21189 100644
--- a/tv/tuner/1.0/vts/functional/DvrTests.cpp
+++ b/tv/tuner/1.0/vts/functional/DvrTests.cpp
@@ -55,6 +55,7 @@
     uint8_t* buffer;
     ALOGW("[vts] playback thread loop start %s", mInputDataFile.c_str());
     if (fd < 0) {
+        EXPECT_TRUE(fd >= 0) << "Failed to open: " + mInputDataFile;
         mPlaybackThreadRunning = false;
         ALOGW("[vts] Error %s", strerror(errno));
     }
@@ -178,7 +179,7 @@
             // Our current implementation filter the data and write it into the filter FMQ
             // immediately after the DATA_READY from the VTS/framework
             if (!readRecordFMQ()) {
-                ALOGD("[vts] record data failed to be filtered. Ending thread");
+                ALOGW("[vts] record data failed to be filtered. Ending thread");
                 mRecordThreadRunning = false;
                 break;
             }
diff --git a/tv/tuner/1.0/vts/functional/FilterTests.cpp b/tv/tuner/1.0/vts/functional/FilterTests.cpp
index 5f5d108..240aa9f 100644
--- a/tv/tuner/1.0/vts/functional/FilterTests.cpp
+++ b/tv/tuner/1.0/vts/functional/FilterTests.cpp
@@ -70,6 +70,10 @@
 }
 
 bool FilterCallback::readFilterEventData() {
+    if (mFilterMQ == NULL) {
+        ALOGW("[vts] FMQ is not configured and does not need to be tested.");
+        return true;
+    }
     bool result = false;
     DemuxFilterEvent filterEvent = mFilterEvent;
     ALOGW("[vts] reading from filter FMQ or buffer %d", mFilterId);
@@ -223,7 +227,11 @@
     return AssertionResult(status == Result::SUCCESS);
 }
 
-AssertionResult FilterTests::getFilterMQDescriptor(uint32_t filterId) {
+AssertionResult FilterTests::getFilterMQDescriptor(uint32_t filterId, bool getMqDesc) {
+    if (!getMqDesc) {
+        ALOGE("[vts] Filter does not need FMQ.");
+        return success();
+    }
     Result status;
     EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
     EXPECT_TRUE(mFilterCallbacks[filterId]) << "Test with getNewlyOpenedFilterId first.";
@@ -284,16 +292,14 @@
 AssertionResult FilterTests::closeFilter(uint32_t filterId) {
     EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
     Result status = mFilters[filterId]->close();
-    if (status == Result::SUCCESS) {
-        for (int i = 0; i < mUsedFilterIds.size(); i++) {
-            if (mUsedFilterIds[i] == filterId) {
-                mUsedFilterIds.erase(mUsedFilterIds.begin() + i);
-                break;
-            }
+    for (int i = 0; i < mUsedFilterIds.size(); i++) {
+        if (mUsedFilterIds[i] == filterId) {
+            mUsedFilterIds.erase(mUsedFilterIds.begin() + i);
+            break;
         }
-        mFilterCallbacks.erase(filterId);
-        mFilters.erase(filterId);
     }
+    mFilterCallbacks.erase(filterId);
+    mFilters.erase(filterId);
     return AssertionResult(status == Result::SUCCESS);
 }
 
diff --git a/tv/tuner/1.0/vts/functional/FilterTests.h b/tv/tuner/1.0/vts/functional/FilterTests.h
index 8ac9c55..c61fa18 100644
--- a/tv/tuner/1.0/vts/functional/FilterTests.h
+++ b/tv/tuner/1.0/vts/functional/FilterTests.h
@@ -159,7 +159,7 @@
     AssertionResult getTimeStamp();
     AssertionResult getNewlyOpenedFilterId(uint32_t& filterId);
     AssertionResult configFilter(DemuxFilterSettings setting, uint32_t filterId);
-    AssertionResult getFilterMQDescriptor(uint32_t filterId);
+    AssertionResult getFilterMQDescriptor(uint32_t filterId, bool getMqDesc);
     AssertionResult setFilterDataSource(uint32_t sourceFilterId, uint32_t sinkFilterId);
     AssertionResult setFilterDataSourceToDemux(uint32_t filterId);
     AssertionResult startFilter(uint32_t filterId);
diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
index 078f5df..891619a 100644
--- a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
+++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
@@ -48,7 +48,7 @@
     ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.type, filterConf.bufferSize));
     ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(filterId));
     ASSERT_TRUE(mFilterTests.configFilter(filterConf.settings, filterId));
-    ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId));
+    ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId, filterConf.getMqDesc));
     ASSERT_TRUE(mFilterTests.startFilter(filterId));
     ASSERT_TRUE(mFilterTests.stopFilter(filterId));
     ASSERT_TRUE(mFilterTests.closeFilter(filterId));
@@ -75,6 +75,9 @@
 
 void TunerBroadcastHidlTest::broadcastSingleFilterTest(FilterConfig filterConf,
                                                        FrontendConfig frontendConf) {
+    if (!frontendConf.enable) {
+        return;
+    }
     uint32_t feId;
     uint32_t demuxId;
     sp<IDemux> demux;
@@ -99,7 +102,7 @@
     ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.type, filterConf.bufferSize));
     ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(filterId));
     ASSERT_TRUE(mFilterTests.configFilter(filterConf.settings, filterId));
-    ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId));
+    ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId, filterConf.getMqDesc));
     ASSERT_TRUE(mFilterTests.startFilter(filterId));
     // tune test
     ASSERT_TRUE(mFrontendTests.tuneFrontend(frontendConf, true /*testWithDemux*/));
@@ -145,7 +148,7 @@
     ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.type, filterConf.bufferSize));
     ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(filterId));
     ASSERT_TRUE(mFilterTests.configFilter(filterConf.settings, filterId));
-    ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId));
+    ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId, filterConf.getMqDesc));
     mDvrTests.startPlaybackInputThread(dvrConf.playbackInputFile, dvrConf.settings.playback());
     ASSERT_TRUE(mDvrTests.startDvrPlayback());
     ASSERT_TRUE(mFilterTests.startFilter(filterId));
@@ -160,6 +163,9 @@
 
 void TunerRecordHidlTest::recordSingleFilterTest(FilterConfig filterConf,
                                                  FrontendConfig frontendConf, DvrConfig dvrConf) {
+    if (!frontendConf.enable) {
+        return;
+    }
     uint32_t feId;
     uint32_t demuxId;
     sp<IDemux> demux;
@@ -184,7 +190,7 @@
     ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.type, filterConf.bufferSize));
     ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(filterId));
     ASSERT_TRUE(mFilterTests.configFilter(filterConf.settings, filterId));
-    ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId));
+    ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId, filterConf.getMqDesc));
     filter = mFilterTests.getFilterById(filterId);
     ASSERT_TRUE(filter != nullptr);
     mDvrTests.startRecordOutputThread(dvrConf.settings.record());
@@ -247,7 +253,7 @@
     ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.type, filterConf.bufferSize));
     ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(filterId));
     ASSERT_TRUE(mFilterTests.configFilter(filterConf.settings, filterId));
-    ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId));
+    ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId, filterConf.getMqDesc));
     filter = mFilterTests.getFilterById(filterId);
     ASSERT_TRUE(filter != nullptr);
     ASSERT_TRUE(mDvrTests.attachFilterToDvr(filter));
@@ -265,6 +271,9 @@
 void TunerDescramblerHidlTest::scrambledBroadcastTest(set<struct FilterConfig> mediaFilterConfs,
                                                       FrontendConfig frontendConf,
                                                       DescramblerConfig descConfig) {
+    if (!frontendConf.enable) {
+        return;
+    }
     uint32_t feId;
     uint32_t demuxId;
     sp<IDemux> demux;
@@ -328,17 +337,17 @@
 
 TEST_P(TunerFrontendHidlTest, TuneFrontend) {
     description("Tune one Frontend with specific setting and check Lock event");
-    mFrontendTests.tuneTest(frontendArray[DVBT]);
+    mFrontendTests.tuneTest(frontendArray[defaultFrontend]);
 }
 
 TEST_P(TunerFrontendHidlTest, AutoScanFrontend) {
     description("Run an auto frontend scan with specific setting and check lock scanMessage");
-    mFrontendTests.scanTest(frontendScanArray[SCAN_DVBT], FrontendScanType::SCAN_AUTO);
+    mFrontendTests.scanTest(frontendScanArray[defaultScanFrontend], FrontendScanType::SCAN_AUTO);
 }
 
 TEST_P(TunerFrontendHidlTest, BlindScanFrontend) {
     description("Run an blind frontend scan with specific setting and check lock scanMessage");
-    mFrontendTests.scanTest(frontendScanArray[SCAN_DVBT], FrontendScanType::SCAN_BLIND);
+    mFrontendTests.scanTest(frontendScanArray[defaultScanFrontend], FrontendScanType::SCAN_BLIND);
 }
 
 TEST_P(TunerLnbHidlTest, OpenLnbByName) {
@@ -374,7 +383,7 @@
     uint32_t feId;
     uint32_t demuxId;
     sp<IDemux> demux;
-    mFrontendTests.getFrontendIdByType(frontendArray[DVBT].type, feId);
+    mFrontendTests.getFrontendIdByType(frontendArray[defaultFrontend].type, feId);
     ASSERT_TRUE(feId != INVALID_ID);
     ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
     ASSERT_TRUE(mFrontendTests.setFrontendCallback());
@@ -394,7 +403,7 @@
     uint32_t avSyncHwId;
     sp<IFilter> mediaFilter;
 
-    mFrontendTests.getFrontendIdByType(frontendArray[DVBT].type, feId);
+    mFrontendTests.getFrontendIdByType(frontendArray[defaultFrontend].type, feId);
     ASSERT_TRUE(feId != INVALID_ID);
     ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
     ASSERT_TRUE(mFrontendTests.setFrontendCallback());
@@ -422,7 +431,7 @@
 TEST_P(TunerFilterHidlTest, StartFilterInDemux) {
     description("Open and start a filter in Demux.");
     // TODO use paramterized tests
-    configSingleFilterInDemuxTest(filterArray[TS_VIDEO0], frontendArray[DVBT]);
+    configSingleFilterInDemuxTest(filterArray[TS_VIDEO0], frontendArray[defaultFrontend]);
 }
 
 TEST_P(TunerFilterHidlTest, SetFilterLinkage) {
@@ -463,22 +472,22 @@
 
 TEST_P(TunerBroadcastHidlTest, BroadcastDataFlowVideoFilterTest) {
     description("Test Video Filter functionality in Broadcast use case.");
-    broadcastSingleFilterTest(filterArray[TS_VIDEO1], frontendArray[DVBT]);
+    broadcastSingleFilterTest(filterArray[TS_VIDEO1], frontendArray[defaultFrontend]);
 }
 
 TEST_P(TunerBroadcastHidlTest, BroadcastDataFlowAudioFilterTest) {
     description("Test Audio Filter functionality in Broadcast use case.");
-    broadcastSingleFilterTest(filterArray[TS_AUDIO0], frontendArray[DVBT]);
+    broadcastSingleFilterTest(filterArray[TS_AUDIO0], frontendArray[defaultFrontend]);
 }
 
 TEST_P(TunerBroadcastHidlTest, BroadcastDataFlowSectionFilterTest) {
     description("Test Section Filter functionality in Broadcast use case.");
-    broadcastSingleFilterTest(filterArray[TS_SECTION0], frontendArray[DVBT]);
+    broadcastSingleFilterTest(filterArray[TS_SECTION0], frontendArray[defaultFrontend]);
 }
 
 TEST_P(TunerBroadcastHidlTest, IonBufferTest) {
     description("Test the av filter data bufferring.");
-    broadcastSingleFilterTest(filterArray[TS_VIDEO0], frontendArray[DVBT]);
+    broadcastSingleFilterTest(filterArray[TS_VIDEO0], frontendArray[defaultFrontend]);
 }
 
 TEST_P(TunerBroadcastHidlTest, LnbBroadcastDataFlowVideoFilterTest) {
@@ -493,11 +502,11 @@
     sp<IDemux> demux;
     uint32_t filterId;
 
-    mFrontendTests.getFrontendIdByType(frontendArray[DVBT].type, feId);
+    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 DVBT frontend.
+        // or with manual ts installing and use defaultFrontend frontend.
         return;
     }
     ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
@@ -510,13 +519,13 @@
                                                filterArray[TS_AUDIO1].bufferSize));
     ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(filterId));
     ASSERT_TRUE(mFilterTests.configFilter(filterArray[TS_AUDIO1].settings, filterId));
-    ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(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));
+    ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId, filterArray[TS_VIDEO1].getMqDesc));
     ASSERT_TRUE(mFilterTests.startFilter(filterId));
     // tune test
     PlaybackSettings playbackSettings{
@@ -533,7 +542,8 @@
     };
     dvrConfig.settings.playback(playbackSettings);
     mFrontendTests.setSoftwareFrontendDvrConfig(dvrConfig);
-    ASSERT_TRUE(mFrontendTests.tuneFrontend(frontendArray[DVBT], true /*testWithDemux*/));
+    ASSERT_TRUE(
+            mFrontendTests.tuneFrontend(frontendArray[defaultFrontend], true /*testWithDemux*/));
     ASSERT_TRUE(filterDataOutputTest(goldenOutputFiles));
     ASSERT_TRUE(mFrontendTests.stopTuneFrontend(true /*testWithDemux*/));
     ASSERT_TRUE(mFilterTests.stopFilter(filterId));
@@ -550,13 +560,14 @@
 TEST_P(TunerRecordHidlTest, AttachFiltersToRecordTest) {
     description("Attach a single filter to the record dvr test.");
     // TODO use paramterized tests
-    attachSingleFilterToRecordDvrTest(filterArray[TS_RECORD0], frontendArray[DVBT],
+    attachSingleFilterToRecordDvrTest(filterArray[TS_RECORD0], frontendArray[defaultFrontend],
                                       dvrArray[DVR_RECORD0]);
 }
 
 TEST_P(TunerRecordHidlTest, RecordDataFlowWithTsRecordFilterTest) {
     description("Feed ts data from frontend to recording and test with ts record filter");
-    recordSingleFilterTest(filterArray[TS_RECORD0], frontendArray[DVBT], dvrArray[DVR_RECORD0]);
+    recordSingleFilterTest(filterArray[TS_RECORD0], frontendArray[defaultFrontend],
+                           dvrArray[DVR_RECORD0]);
 }
 
 TEST_P(TunerRecordHidlTest, LnbRecordDataFlowWithTsRecordFilterTest) {
@@ -569,7 +580,7 @@
     uint32_t feId;
     uint32_t demuxId;
     sp<IDemux> demux;
-    mFrontendTests.getFrontendIdByType(frontendArray[DVBT].type, feId);
+    mFrontendTests.getFrontendIdByType(frontendArray[defaultFrontend].type, feId);
     ASSERT_TRUE(feId != INVALID_ID);
     ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
     ASSERT_TRUE(mFrontendTests.setFrontendCallback());
@@ -586,7 +597,7 @@
     set<FilterConfig> filterConfs;
     filterConfs.insert(filterArray[TS_AUDIO0]);
     filterConfs.insert(filterArray[TS_VIDEO1]);
-    scrambledBroadcastTest(filterConfs, frontendArray[DVBT], descramblerArray[DESC_0]);
+    scrambledBroadcastTest(filterConfs, frontendArray[defaultFrontend], descramblerArray[DESC_0]);
 }
 
 INSTANTIATE_TEST_SUITE_P(
diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h
index 27c6593..b0a9c03 100644
--- a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h
+++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h
@@ -55,6 +55,7 @@
 
 using namespace std;
 
+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;
@@ -134,6 +135,7 @@
     uint32_t bufferSize;
     DemuxFilterType type;
     DemuxFilterSettings settings;
+    bool getMqDesc;
 
     bool operator<(const FilterConfig& /*c*/) const { return false; }
 };
@@ -144,6 +146,7 @@
 };
 
 struct FrontendConfig {
+    bool enable;
     bool isSoftwareFe;
     FrontendType type;
     FrontendSettings settings;
@@ -191,6 +194,8 @@
 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 */
 inline void initFrontendConfig() {
@@ -216,7 +221,9 @@
     frontendArray[DVBT].tuneStatusTypes = types;
     frontendArray[DVBT].expectTuneStatuses = statuses;
     frontendArray[DVBT].isSoftwareFe = true;
+    frontendArray[DVBS].enable = true;
     frontendArray[DVBS].type = FrontendType::DVBS;
+    frontendArray[DVBS].enable = true;
     frontendArray[DVBS].isSoftwareFe = true;
 };
 
@@ -288,6 +295,7 @@
             .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);
@@ -308,6 +316,7 @@
     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);