Merge changes from topic "weaver-vts-fix" into main

* changes:
  Don't overwrite in-use Weaver slots during VTS
  Simplify Weaver VTS test
  Remove redundant HIDL Weaver VTS test
  Move VtsHalWeaverTargetTest to common directory
  Make VtsHalWeaverTargetTest test both HIDL and AIDL services
  Clarify the Weaver documentation
  Update weaver AIDL default to use V2
  Add WeaverReadStatus to WeaverReadResponse
diff --git a/compatibility_matrices/compatibility_matrix.9.xml b/compatibility_matrices/compatibility_matrix.9.xml
index ed03f7c..580cb93 100644
--- a/compatibility_matrices/compatibility_matrix.9.xml
+++ b/compatibility_matrices/compatibility_matrix.9.xml
@@ -739,7 +739,7 @@
     </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.weaver</name>
-        <version>1</version>
+        <version>2</version>
         <interface>
             <name>IWeaver</name>
             <instance>default</instance>
diff --git a/weaver/1.0/vts/functional/Android.bp b/weaver/1.0/vts/functional/Android.bp
deleted file mode 100644
index cc1d284..0000000
--- a/weaver/1.0/vts/functional/Android.bp
+++ /dev/null
@@ -1,32 +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.
-//
-
-package {
-    // See: http://go/android-license-faq
-    // A large-scale-change added 'default_applicable_licenses' to import
-    // all of the 'license_kinds' from "hardware_interfaces_license"
-    // to get the below license kinds:
-    //   SPDX-license-identifier-Apache-2.0
-    default_applicable_licenses: ["hardware_interfaces_license"],
-}
-
-cc_test {
-    name: "VtsHalWeaverV1_0TargetTest",
-    defaults: ["VtsHalTargetTestDefaults"],
-    srcs: ["VtsHalWeaverV1_0TargetTest.cpp"],
-    static_libs: ["android.hardware.weaver@1.0"],
-    test_suites: ["general-tests", "vts"],
-}
diff --git a/weaver/1.0/vts/functional/VtsHalWeaverV1_0TargetTest.cpp b/weaver/1.0/vts/functional/VtsHalWeaverV1_0TargetTest.cpp
deleted file mode 100644
index 66465a9..0000000
--- a/weaver/1.0/vts/functional/VtsHalWeaverV1_0TargetTest.cpp
+++ /dev/null
@@ -1,343 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <android/hardware/weaver/1.0/IWeaver.h>
-#include <gtest/gtest.h>
-#include <hidl/GtestPrinter.h>
-#include <hidl/ServiceManagement.h>
-
-#include <limits>
-
-using ::android::hardware::weaver::V1_0::IWeaver;
-using ::android::hardware::weaver::V1_0::WeaverConfig;
-using ::android::hardware::weaver::V1_0::WeaverReadStatus;
-using ::android::hardware::weaver::V1_0::WeaverReadResponse;
-using ::android::hardware::weaver::V1_0::WeaverStatus;
-using ::android::hardware::Return;
-using ::android::sp;
-
-const std::vector<uint8_t> KEY{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
-const std::vector<uint8_t> WRONG_KEY{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-const std::vector<uint8_t> VALUE{16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
-const std::vector<uint8_t> OTHER_VALUE{0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 255, 255};
-
-struct WeaverHidlTest : public ::testing::TestWithParam<std::string> {
-    virtual void SetUp() override {
-        weaver = IWeaver::getService(GetParam());
-        ASSERT_NE(weaver, nullptr);
-    }
-
-    virtual void TearDown() override {}
-
-    sp<IWeaver> weaver;
-};
-
-/*
- * Checks config values are suitably large
- */
-TEST_P(WeaverHidlTest, GetConfig) {
-    WeaverStatus status;
-    WeaverConfig config;
-
-    bool callbackCalled = false;
-    auto ret = weaver->getConfig([&](WeaverStatus s, WeaverConfig c) {
-        callbackCalled = true;
-        status = s;
-        config = c;
-    });
-    ASSERT_TRUE(ret.isOk());
-    ASSERT_TRUE(callbackCalled);
-    ASSERT_EQ(status, WeaverStatus::OK);
-
-    EXPECT_GE(config.slots, 16u);
-    EXPECT_GE(config.keySize, 16u);
-    EXPECT_GE(config.valueSize, 16u);
-}
-
-/*
- * Gets the config twice and checks they are the same
- */
-TEST_P(WeaverHidlTest, GettingConfigMultipleTimesGivesSameResult) {
-    WeaverConfig config1;
-    WeaverConfig config2;
-
-    WeaverStatus status;
-    bool callbackCalled = false;
-    auto ret = weaver->getConfig([&](WeaverStatus s, WeaverConfig c) {
-        callbackCalled = true;
-        status = s;
-        config1 = c;
-    });
-    ASSERT_TRUE(ret.isOk());
-    ASSERT_TRUE(callbackCalled);
-    ASSERT_EQ(status, WeaverStatus::OK);
-
-    callbackCalled = false;
-    ret = weaver->getConfig([&](WeaverStatus s, WeaverConfig c) {
-        callbackCalled = true;
-        status = s;
-        config2 = c;
-    });
-    ASSERT_TRUE(ret.isOk());
-    ASSERT_TRUE(callbackCalled);
-    ASSERT_EQ(status, WeaverStatus::OK);
-
-    EXPECT_EQ(config1, config2);
-}
-
-/*
- * Gets the number of slots from the config and writes a key and value to the last one
- */
-TEST_P(WeaverHidlTest, WriteToLastSlot) {
-    WeaverStatus status;
-    WeaverConfig config;
-    const auto configRet = weaver->getConfig([&](WeaverStatus s, WeaverConfig c) {
-        status = s;
-        config = c;
-    });
-    ASSERT_TRUE(configRet.isOk());
-    ASSERT_EQ(status, WeaverStatus::OK);
-
-    const uint32_t lastSlot = config.slots - 1;
-    const auto writeRet = weaver->write(lastSlot, KEY, VALUE);
-    ASSERT_TRUE(writeRet.isOk());
-    ASSERT_EQ(writeRet, WeaverStatus::OK);
-}
-
-/*
- * Writes a key and value to a slot
- * Reads the slot with the same key and receives the value that was previously written
- */
-TEST_P(WeaverHidlTest, WriteFollowedByReadGivesTheSameValue) {
-    constexpr uint32_t slotId = 0;
-    const auto ret = weaver->write(slotId, KEY, VALUE);
-    ASSERT_TRUE(ret.isOk());
-    ASSERT_EQ(ret, WeaverStatus::OK);
-
-    bool callbackCalled = false;
-    WeaverReadStatus status;
-    std::vector<uint8_t> readValue;
-    uint32_t timeout;
-    const auto readRet = weaver->read(slotId, KEY, [&](WeaverReadStatus s, WeaverReadResponse r) {
-        callbackCalled = true;
-        status = s;
-        readValue = r.value;
-        timeout = r.timeout;
-    });
-    ASSERT_TRUE(readRet.isOk());
-    ASSERT_TRUE(callbackCalled);
-    ASSERT_EQ(status, WeaverReadStatus::OK);
-    EXPECT_EQ(readValue, VALUE);
-    EXPECT_EQ(timeout, 0u);
-}
-
-/*
- * Writes a key and value to a slot
- * Overwrites the slot with a new key and value
- * Reads the slot with the new key and receives the new value
- */
-TEST_P(WeaverHidlTest, OverwritingSlotUpdatesTheValue) {
-    constexpr uint32_t slotId = 0;
-    const auto initialWriteRet = weaver->write(slotId, WRONG_KEY, VALUE);
-    ASSERT_TRUE(initialWriteRet.isOk());
-    ASSERT_EQ(initialWriteRet, WeaverStatus::OK);
-
-    const auto overwriteRet = weaver->write(slotId, KEY, OTHER_VALUE);
-    ASSERT_TRUE(overwriteRet.isOk());
-    ASSERT_EQ(overwriteRet, WeaverStatus::OK);
-
-    bool callbackCalled = false;
-    WeaverReadStatus status;
-    std::vector<uint8_t> readValue;
-    uint32_t timeout;
-    const auto readRet = weaver->read(slotId, KEY, [&](WeaverReadStatus s, WeaverReadResponse r) {
-        callbackCalled = true;
-        status = s;
-        readValue = r.value;
-        timeout = r.timeout;
-    });
-    ASSERT_TRUE(readRet.isOk());
-    ASSERT_TRUE(callbackCalled);
-    ASSERT_EQ(status, WeaverReadStatus::OK);
-    EXPECT_EQ(readValue, OTHER_VALUE);
-    EXPECT_EQ(timeout, 0u);
-}
-
-/*
- * Writes a key and value to a slot
- * Reads the slot with a different key so does not receive the value
- */
-TEST_P(WeaverHidlTest, WriteFollowedByReadWithWrongKeyDoesNotGiveTheValue) {
-    constexpr uint32_t slotId = 0;
-    const auto ret = weaver->write(slotId, KEY, VALUE);
-    ASSERT_TRUE(ret.isOk());
-    ASSERT_EQ(ret, WeaverStatus::OK);
-
-    bool callbackCalled = false;
-    WeaverReadStatus status;
-    std::vector<uint8_t> readValue;
-    const auto readRet =
-        weaver->read(slotId, WRONG_KEY, [&](WeaverReadStatus s, WeaverReadResponse r) {
-            callbackCalled = true;
-            status = s;
-            readValue = r.value;
-        });
-    ASSERT_TRUE(callbackCalled);
-    ASSERT_TRUE(readRet.isOk());
-    ASSERT_EQ(status, WeaverReadStatus::INCORRECT_KEY);
-    EXPECT_TRUE(readValue.empty());
-}
-
-/*
- * Writing to an invalid slot fails
- */
-TEST_P(WeaverHidlTest, WritingToInvalidSlotFails) {
-    WeaverStatus status;
-    WeaverConfig config;
-    const auto configRet = weaver->getConfig([&](WeaverStatus s, WeaverConfig c) {
-        status = s;
-        config = c;
-    });
-    ASSERT_TRUE(configRet.isOk());
-    ASSERT_EQ(status, WeaverStatus::OK);
-
-    if (config.slots == std::numeric_limits<uint32_t>::max()) {
-        // If there are no invalid slots then pass
-        return;
-    }
-
-    const auto writeRet = weaver->write(config.slots, KEY, VALUE);
-    ASSERT_TRUE(writeRet.isOk());
-    ASSERT_EQ(writeRet, WeaverStatus::FAILED);
-}
-
-/*
- * Reading from an invalid slot fails rather than incorrect key
- */
-TEST_P(WeaverHidlTest, ReadingFromInvalidSlotFails) {
-    WeaverStatus status;
-    WeaverConfig config;
-    const auto configRet = weaver->getConfig([&](WeaverStatus s, WeaverConfig c) {
-        status = s;
-        config = c;
-    });
-    ASSERT_TRUE(configRet.isOk());
-    ASSERT_EQ(status, WeaverStatus::OK);
-
-    if (config.slots == std::numeric_limits<uint32_t>::max()) {
-        // If there are no invalid slots then pass
-        return;
-    }
-
-    bool callbackCalled = false;
-    WeaverReadStatus readStatus;
-    std::vector<uint8_t> readValue;
-    uint32_t timeout;
-    const auto readRet =
-        weaver->read(config.slots, KEY, [&](WeaverReadStatus s, WeaverReadResponse r) {
-            callbackCalled = true;
-            readStatus = s;
-            readValue = r.value;
-            timeout = r.timeout;
-        });
-    ASSERT_TRUE(callbackCalled);
-    ASSERT_TRUE(readRet.isOk());
-    ASSERT_EQ(readStatus, WeaverReadStatus::FAILED);
-    EXPECT_TRUE(readValue.empty());
-    EXPECT_EQ(timeout, 0u);
-}
-
-/*
- * Writing a key that is too large fails
- */
-TEST_P(WeaverHidlTest, WriteWithTooLargeKeyFails) {
-    WeaverStatus status;
-    WeaverConfig config;
-    const auto configRet = weaver->getConfig([&](WeaverStatus s, WeaverConfig c) {
-        status = s;
-        config = c;
-    });
-    ASSERT_TRUE(configRet.isOk());
-    ASSERT_EQ(status, WeaverStatus::OK);
-
-    std::vector<uint8_t> bigKey(config.keySize + 1);
-
-    constexpr uint32_t slotId = 0;
-    const auto writeRet = weaver->write(slotId, bigKey, VALUE);
-    ASSERT_TRUE(writeRet.isOk());
-    ASSERT_EQ(writeRet, WeaverStatus::FAILED);
-}
-
-/*
- * Writing a value that is too large fails
- */
-TEST_P(WeaverHidlTest, WriteWithTooLargeValueFails) {
-    WeaverStatus status;
-    WeaverConfig config;
-    const auto configRet = weaver->getConfig([&](WeaverStatus s, WeaverConfig c) {
-        status = s;
-        config = c;
-    });
-    ASSERT_TRUE(configRet.isOk());
-    ASSERT_EQ(status, WeaverStatus::OK);
-
-    std::vector<uint8_t> bigValue(config.valueSize + 1);
-
-    constexpr uint32_t slotId = 0;
-    const auto writeRet = weaver->write(slotId, KEY, bigValue);
-    ASSERT_TRUE(writeRet.isOk());
-    ASSERT_EQ(writeRet, WeaverStatus::FAILED);
-}
-
-/*
- * Reading with a key that is loo large fails
- */
-TEST_P(WeaverHidlTest, ReadWithTooLargeKeyFails) {
-    WeaverStatus status;
-    WeaverConfig config;
-    const auto configRet = weaver->getConfig([&](WeaverStatus s, WeaverConfig c) {
-        status = s;
-        config = c;
-    });
-    ASSERT_TRUE(configRet.isOk());
-    ASSERT_EQ(status, WeaverStatus::OK);
-
-    std::vector<uint8_t> bigKey(config.keySize + 1);
-
-    constexpr uint32_t slotId = 0;
-    bool callbackCalled = false;
-    WeaverReadStatus readStatus;
-    std::vector<uint8_t> readValue;
-    uint32_t timeout;
-    const auto readRet =
-        weaver->read(slotId, bigKey, [&](WeaverReadStatus s, WeaverReadResponse r) {
-            callbackCalled = true;
-            readStatus = s;
-            readValue = r.value;
-            timeout = r.timeout;
-        });
-    ASSERT_TRUE(callbackCalled);
-    ASSERT_TRUE(readRet.isOk());
-    ASSERT_EQ(readStatus, WeaverReadStatus::FAILED);
-    EXPECT_TRUE(readValue.empty());
-    EXPECT_EQ(timeout, 0u);
-}
-
-GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WeaverHidlTest);
-INSTANTIATE_TEST_SUITE_P(
-        PerInstance, WeaverHidlTest,
-        testing::ValuesIn(android::hardware::getAllHalInstanceNames(IWeaver::descriptor)),
-        android::hardware::PrintInstanceNameToString);
diff --git a/weaver/aidl/Android.bp b/weaver/aidl/Android.bp
index caa92aa..74cec99 100644
--- a/weaver/aidl/Android.bp
+++ b/weaver/aidl/Android.bp
@@ -17,5 +17,10 @@
             platform_apis: true,
         },
     },
-    versions: ["1"],
+    versions_with_info: [
+        {
+            version: "1",
+            imports: [],
+        },
+    ],
 }
diff --git a/weaver/aidl/aidl_api/android.hardware.weaver/current/android/hardware/weaver/WeaverReadResponse.aidl b/weaver/aidl/aidl_api/android.hardware.weaver/current/android/hardware/weaver/WeaverReadResponse.aidl
index 47ee4c8..96e528f 100644
--- a/weaver/aidl/aidl_api/android.hardware.weaver/current/android/hardware/weaver/WeaverReadResponse.aidl
+++ b/weaver/aidl/aidl_api/android.hardware.weaver/current/android/hardware/weaver/WeaverReadResponse.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright 2020 The Android Open Source Project
+ * Copyright 2022 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.
@@ -36,4 +36,5 @@
 parcelable WeaverReadResponse {
   long timeout;
   byte[] value;
+  android.hardware.weaver.WeaverReadStatus status = android.hardware.weaver.WeaverReadStatus.FAILED;
 }
diff --git a/weaver/aidl/aidl_api/android.hardware.weaver/current/android/hardware/weaver/WeaverReadStatus.aidl b/weaver/aidl/aidl_api/android.hardware.weaver/current/android/hardware/weaver/WeaverReadStatus.aidl
new file mode 100644
index 0000000..fce9758
--- /dev/null
+++ b/weaver/aidl/aidl_api/android.hardware.weaver/current/android/hardware/weaver/WeaverReadStatus.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE.                          //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+//     the interface (from the latest frozen version), the build system will
+//     prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.weaver;
+@Backing(type="int") @VintfStability
+enum WeaverReadStatus {
+  OK = 0,
+  FAILED = 1,
+  INCORRECT_KEY = 2,
+  THROTTLE = 3,
+}
diff --git a/weaver/aidl/android/hardware/weaver/IWeaver.aidl b/weaver/aidl/android/hardware/weaver/IWeaver.aidl
index f51034a..ae816ef 100644
--- a/weaver/aidl/android/hardware/weaver/IWeaver.aidl
+++ b/weaver/aidl/android/hardware/weaver/IWeaver.aidl
@@ -20,8 +20,8 @@
 import android.hardware.weaver.WeaverReadResponse;
 
 /**
- * Weaver provides secure storage of secret values that may only be read if the
- * corresponding key has been presented.
+ * Weaver provides secure persistent storage of secret values that may only be
+ * read if the corresponding key has been presented.
  *
  * The storage must be secure as the device's user authentication and encryption
  * relies on the security of these values. The cardinality of the domains of the
@@ -76,7 +76,8 @@
     WeaverReadResponse read(in int slotId, in byte[] key);
 
     /**
-     * Overwrites the identified slot with the provided key and value.
+     * Overwrites the identified slot with the provided key and value, rendering
+     * the previous contents of the slot permanently unrecoverable.
      *
      * The new values are written regardless of the current state of the slot in
      * order to remain idempotent.
diff --git a/weaver/aidl/android/hardware/weaver/WeaverReadResponse.aidl b/weaver/aidl/android/hardware/weaver/WeaverReadResponse.aidl
index ec006e8..17ea718 100644
--- a/weaver/aidl/android/hardware/weaver/WeaverReadResponse.aidl
+++ b/weaver/aidl/android/hardware/weaver/WeaverReadResponse.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright 2020 The Android Open Source Project
+ * Copyright 2022 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.
@@ -16,15 +16,22 @@
 
 package android.hardware.weaver;
 
+import android.hardware.weaver.WeaverReadStatus;
+
 @VintfStability
 parcelable WeaverReadResponse {
     /**
-     * The time to wait, in milliseconds, before making the next request.
+     * The time to wait, in milliseconds, before making the next request,
+     * must be greater than or equal to zero and less than INT_MAX.
      */
     long timeout;
     /**
      * The value read from the slot or empty if the value was not read.
      */
     byte[] value;
+    /**
+     * Status from WeaverReadStatus
+     */
+    WeaverReadStatus status = WeaverReadStatus.FAILED;
 }
 
diff --git a/weaver/aidl/android/hardware/weaver/WeaverReadStatus.aidl b/weaver/aidl/android/hardware/weaver/WeaverReadStatus.aidl
new file mode 100644
index 0000000..36e731f
--- /dev/null
+++ b/weaver/aidl/android/hardware/weaver/WeaverReadStatus.aidl
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2022 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.weaver;
+
+@VintfStability
+@Backing(type="int")
+enum WeaverReadStatus {
+    OK,
+    FAILED,
+    INCORRECT_KEY,
+    THROTTLE,
+}
diff --git a/weaver/aidl/default/Android.bp b/weaver/aidl/default/Android.bp
index 70d9171..494cb1b 100644
--- a/weaver/aidl/default/Android.bp
+++ b/weaver/aidl/default/Android.bp
@@ -34,7 +34,7 @@
         "Weaver.cpp",
     ],
     shared_libs: [
-        "android.hardware.weaver-V1-ndk",
+        "android.hardware.weaver-V2-ndk",
         "libbase",
         "libbinder_ndk",
     ],
diff --git a/weaver/aidl/default/Weaver.cpp b/weaver/aidl/default/Weaver.cpp
index 6b77924..c9ffe85 100644
--- a/weaver/aidl/default/Weaver.cpp
+++ b/weaver/aidl/default/Weaver.cpp
@@ -37,18 +37,19 @@
 }
 
 ::ndk::ScopedAStatus Weaver::read(int32_t in_slotId, const std::vector<uint8_t>& in_key, WeaverReadResponse* out_response) {
+    using ::aidl::android::hardware::weaver::WeaverReadStatus;
 
     if (in_slotId > 15 || in_key.size() > 16) {
-        *out_response = {0, {}};
-        return ndk::ScopedAStatus(AStatus_fromServiceSpecificError(Weaver::STATUS_FAILED));
+        *out_response = {0, {}, WeaverReadStatus::FAILED};
+        return ndk::ScopedAStatus::ok();
     }
 
     if (slot_array[in_slotId].key != in_key) {
-        *out_response = {0, {}};
-        return ndk::ScopedAStatus(AStatus_fromServiceSpecificError(Weaver::STATUS_INCORRECT_KEY));
+        *out_response = {0, {}, WeaverReadStatus::INCORRECT_KEY};
+        return ndk::ScopedAStatus::ok();
     }
 
-    *out_response = {0, slot_array[in_slotId].value};
+    *out_response = {0, slot_array[in_slotId].value, WeaverReadStatus::OK};
 
     return ::ndk::ScopedAStatus::ok();
 }
diff --git a/weaver/aidl/default/android.hardware.weaver-service.example.xml b/weaver/aidl/default/android.hardware.weaver-service.example.xml
index ed291cd..bfe4396 100644
--- a/weaver/aidl/default/android.hardware.weaver-service.example.xml
+++ b/weaver/aidl/default/android.hardware.weaver-service.example.xml
@@ -1,7 +1,7 @@
 <manifest version="1.0" type="device">
     <hal format="aidl">
         <name>android.hardware.weaver</name>
-        <version>1</version>
+        <version>2</version>
         <interface>
             <name>IWeaver</name>
             <instance>default</instance>
diff --git a/weaver/aidl/vts/VtsHalWeaverTargetTest.cpp b/weaver/aidl/vts/VtsHalWeaverTargetTest.cpp
deleted file mode 100644
index 878c762..0000000
--- a/weaver/aidl/vts/VtsHalWeaverTargetTest.cpp
+++ /dev/null
@@ -1,277 +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 <aidl/Gtest.h>
-#include <aidl/Vintf.h>
-
-#include <aidl/android/hardware/weaver/IWeaver.h>
-#include <android/binder_manager.h>
-#include <android/binder_process.h>
-
-#include <limits>
-
-using ::aidl::android::hardware::weaver::IWeaver;
-using ::aidl::android::hardware::weaver::WeaverConfig;
-using ::aidl::android::hardware::weaver::WeaverReadResponse;
-
-using ::ndk::SpAIBinder;
-
-const std::vector<uint8_t> KEY{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
-const std::vector<uint8_t> WRONG_KEY{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-const std::vector<uint8_t> VALUE{16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
-const std::vector<uint8_t> OTHER_VALUE{0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 255, 255};
-
-struct WeaverAidlTest : public ::testing::TestWithParam<std::string> {
-    virtual void SetUp() override {
-        weaver = IWeaver::fromBinder(
-            SpAIBinder(AServiceManager_waitForService(GetParam().c_str())));
-        ASSERT_NE(weaver, nullptr);
-    }
-
-    virtual void TearDown() override {}
-
-    std::shared_ptr<IWeaver> weaver;
-};
-
-/*
- * Checks config values are suitably large
- */
-TEST_P(WeaverAidlTest, GetConfig) {
-    WeaverConfig config;
-
-    auto ret = weaver->getConfig(&config);
-
-    ASSERT_TRUE(ret.isOk());
-
-    EXPECT_GE(config.slots, 16u);
-    EXPECT_GE(config.keySize, 16u);
-    EXPECT_GE(config.valueSize, 16u);
-}
-
-/*
- * Gets the config twice and checks they are the same
- */
-TEST_P(WeaverAidlTest, GettingConfigMultipleTimesGivesSameResult) {
-    WeaverConfig config1;
-    WeaverConfig config2;
-
-    auto ret = weaver->getConfig(&config1);
-    ASSERT_TRUE(ret.isOk());
-
-    ret = weaver->getConfig(&config2);
-    ASSERT_TRUE(ret.isOk());
-
-    EXPECT_EQ(config1, config2);
-}
-
-/*
- * Gets the number of slots from the config and writes a key and value to the last one
- */
-TEST_P(WeaverAidlTest, WriteToLastSlot) {
-    WeaverConfig config;
-    const auto configRet = weaver->getConfig(&config);
-
-    ASSERT_TRUE(configRet.isOk());
-
-    const uint32_t lastSlot = config.slots - 1;
-    const auto writeRet = weaver->write(lastSlot, KEY, VALUE);
-    ASSERT_TRUE(writeRet.isOk());
-}
-
-/*
- * Writes a key and value to a slot
- * Reads the slot with the same key and receives the value that was previously written
- */
-TEST_P(WeaverAidlTest, WriteFollowedByReadGivesTheSameValue) {
-    constexpr uint32_t slotId = 0;
-    const auto ret = weaver->write(slotId, KEY, VALUE);
-    ASSERT_TRUE(ret.isOk());
-
-    WeaverReadResponse response;
-    std::vector<uint8_t> readValue;
-    uint32_t timeout;
-    const auto readRet = weaver->read(slotId, KEY, &response);
-
-    readValue = response.value;
-    timeout = response.timeout;
-
-    ASSERT_TRUE(readRet.isOk());
-    EXPECT_EQ(readValue, VALUE);
-    EXPECT_EQ(timeout, 0u);
-}
-
-/*
- * Writes a key and value to a slot
- * Overwrites the slot with a new key and value
- * Reads the slot with the new key and receives the new value
- */
-TEST_P(WeaverAidlTest, OverwritingSlotUpdatesTheValue) {
-    constexpr uint32_t slotId = 0;
-    const auto initialWriteRet = weaver->write(slotId, WRONG_KEY, VALUE);
-    ASSERT_TRUE(initialWriteRet.isOk());
-
-    const auto overwriteRet = weaver->write(slotId, KEY, OTHER_VALUE);
-    ASSERT_TRUE(overwriteRet.isOk());
-
-    WeaverReadResponse response;
-    std::vector<uint8_t> readValue;
-    uint32_t timeout;
-    const auto readRet = weaver->read(slotId, KEY, &response);
-
-    readValue = response.value;
-    timeout = response.timeout;
-
-    ASSERT_TRUE(readRet.isOk());
-    EXPECT_EQ(readValue, OTHER_VALUE);
-    EXPECT_EQ(timeout, 0u);
-}
-
-/*
- * Writes a key and value to a slot
- * Reads the slot with a different key so does not receive the value
- */
-TEST_P(WeaverAidlTest, WriteFollowedByReadWithWrongKeyDoesNotGiveTheValue) {
-    constexpr uint32_t slotId = 0;
-    const auto ret = weaver->write(slotId, KEY, VALUE);
-    ASSERT_TRUE(ret.isOk());
-
-    WeaverReadResponse response;
-    std::vector<uint8_t> readValue;
-    const auto readRet =
-        weaver->read(slotId, WRONG_KEY, &response);
-
-    readValue = response.value;
-
-    ASSERT_FALSE(readRet.isOk());
-    ASSERT_EQ(EX_SERVICE_SPECIFIC, readRet.getExceptionCode());
-    ASSERT_EQ(IWeaver::STATUS_INCORRECT_KEY, readRet.getServiceSpecificError());
-    EXPECT_TRUE(readValue.empty());
-}
-
-/*
- * Writing to an invalid slot fails
- */
-TEST_P(WeaverAidlTest, WritingToInvalidSlotFails) {
-    WeaverConfig config;
-    const auto configRet = weaver->getConfig(&config);
-    ASSERT_TRUE(configRet.isOk());
-
-    if (config.slots == std::numeric_limits<uint32_t>::max()) {
-        // If there are no invalid slots then pass
-        return;
-    }
-
-    const auto writeRet = weaver->write(config.slots, KEY, VALUE);
-    ASSERT_FALSE(writeRet.isOk());
-}
-
-/*
- * Reading from an invalid slot fails rather than incorrect key
- */
-TEST_P(WeaverAidlTest, ReadingFromInvalidSlotFails) {
-    WeaverConfig config;
-    const auto configRet = weaver->getConfig(&config);
-    ASSERT_TRUE(configRet.isOk());
-
-    if (config.slots == std::numeric_limits<uint32_t>::max()) {
-        // If there are no invalid slots then pass
-        return;
-    }
-
-    WeaverReadResponse response;
-    std::vector<uint8_t> readValue;
-    uint32_t timeout;
-    const auto readRet =
-        weaver->read(config.slots, KEY, &response);
-
-    readValue = response.value;
-    timeout = response.timeout;
-
-    ASSERT_FALSE(readRet.isOk());
-    ASSERT_EQ(EX_SERVICE_SPECIFIC, readRet.getExceptionCode());
-    ASSERT_EQ(IWeaver::STATUS_FAILED, readRet.getServiceSpecificError());
-    EXPECT_TRUE(readValue.empty());
-    EXPECT_EQ(timeout, 0u);
-}
-
-/*
- * Writing a key that is too large fails
- */
-TEST_P(WeaverAidlTest, WriteWithTooLargeKeyFails) {
-    WeaverConfig config;
-    const auto configRet = weaver->getConfig(&config);
-    ASSERT_TRUE(configRet.isOk());
-
-    std::vector<uint8_t> bigKey(config.keySize + 1);
-
-    constexpr uint32_t slotId = 0;
-    const auto writeRet = weaver->write(slotId, bigKey, VALUE);
-    ASSERT_FALSE(writeRet.isOk());
-}
-
-/*
- * Writing a value that is too large fails
- */
-TEST_P(WeaverAidlTest, WriteWithTooLargeValueFails) {
-    WeaverConfig config;
-    const auto configRet = weaver->getConfig(&config);
-    ASSERT_TRUE(configRet.isOk());
-
-    std::vector<uint8_t> bigValue(config.valueSize + 1);
-
-    constexpr uint32_t slotId = 0;
-    const auto writeRet = weaver->write(slotId, KEY, bigValue);
-    ASSERT_FALSE(writeRet.isOk());
-}
-
-/*
- * Reading with a key that is loo large fails
- */
-TEST_P(WeaverAidlTest, ReadWithTooLargeKeyFails) {
-    WeaverConfig config;
-    const auto configRet = weaver->getConfig(&config);
-    ASSERT_TRUE(configRet.isOk());
-
-    std::vector<uint8_t> bigKey(config.keySize + 1);
-
-    constexpr uint32_t slotId = 0;
-    WeaverReadResponse response;
-    std::vector<uint8_t> readValue;
-    uint32_t timeout;
-    const auto readRet =
-        weaver->read(slotId, bigKey, &response);
-
-    readValue = response.value;
-    timeout = response.timeout;
-
-    ASSERT_FALSE(readRet.isOk());
-    ASSERT_EQ(EX_SERVICE_SPECIFIC, readRet.getExceptionCode());
-    ASSERT_EQ(IWeaver::STATUS_FAILED, readRet.getServiceSpecificError());
-    EXPECT_TRUE(readValue.empty());
-    EXPECT_EQ(timeout, 0u);
-}
-
-GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WeaverAidlTest);
-INSTANTIATE_TEST_SUITE_P(
-        PerInstance, WeaverAidlTest,
-        testing::ValuesIn(android::getAidlHalInstanceNames(IWeaver::descriptor)),
-        android::PrintInstanceNameToString);
-
-int main(int argc, char** argv) {
-    ::testing::InitGoogleTest(&argc, argv);
-    ABinderProcess_setThreadPoolMaxThreadCount(1);
-    ABinderProcess_startThreadPool();
-    return RUN_ALL_TESTS();
-}
diff --git a/weaver/aidl/vts/Android.bp b/weaver/vts/Android.bp
similarity index 92%
rename from weaver/aidl/vts/Android.bp
rename to weaver/vts/Android.bp
index cf1661c..ee03b28 100644
--- a/weaver/aidl/vts/Android.bp
+++ b/weaver/vts/Android.bp
@@ -34,7 +34,10 @@
         "libbinder_ndk",
         "libbase",
     ],
-    static_libs: ["android.hardware.weaver-V1-ndk"],
+    static_libs: [
+        "android.hardware.weaver-V2-ndk",
+        "android.hardware.weaver@1.0",
+    ],
     test_suites: [
         "general-tests",
         "vts",
diff --git a/weaver/vts/VtsHalWeaverTargetTest.cpp b/weaver/vts/VtsHalWeaverTargetTest.cpp
new file mode 100644
index 0000000..9ee6d93
--- /dev/null
+++ b/weaver/vts/VtsHalWeaverTargetTest.cpp
@@ -0,0 +1,425 @@
+/*
+ * 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 <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+
+#include <aidl/android/hardware/weaver/IWeaver.h>
+#include <android-base/file.h>
+#include <android-base/parseint.h>
+#include <android-base/strings.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <android/hardware/weaver/1.0/IWeaver.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
+
+#include <limits>
+
+using ::aidl::android::hardware::weaver::IWeaver;
+using ::aidl::android::hardware::weaver::WeaverConfig;
+using ::aidl::android::hardware::weaver::WeaverReadResponse;
+using ::aidl::android::hardware::weaver::WeaverReadStatus;
+
+using HidlIWeaver = ::android::hardware::weaver::V1_0::IWeaver;
+using HidlWeaverConfig = ::android::hardware::weaver::V1_0::WeaverConfig;
+using HidlWeaverReadStatus = ::android::hardware::weaver::V1_0::WeaverReadStatus;
+using HidlWeaverReadResponse = ::android::hardware::weaver::V1_0::WeaverReadResponse;
+using HidlWeaverStatus = ::android::hardware::weaver::V1_0::WeaverStatus;
+
+const std::string kSlotMapFile = "/metadata/password_slots/slot_map";
+const std::vector<uint8_t> KEY{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
+const std::vector<uint8_t> WRONG_KEY{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+const std::vector<uint8_t> VALUE{16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
+const std::vector<uint8_t> OTHER_VALUE{0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 255, 255};
+
+class WeaverAdapter {
+  public:
+    virtual ~WeaverAdapter() {}
+    virtual bool isReady() = 0;
+    virtual ::ndk::ScopedAStatus getConfig(WeaverConfig* _aidl_return) = 0;
+    virtual ::ndk::ScopedAStatus read(int32_t in_slotId, const std::vector<uint8_t>& in_key,
+                                      WeaverReadResponse* _aidl_return) = 0;
+    virtual ::ndk::ScopedAStatus write(int32_t in_slotId, const std::vector<uint8_t>& in_key,
+                                       const std::vector<uint8_t>& in_value) = 0;
+};
+
+class WeaverAidlAdapter : public WeaverAdapter {
+  public:
+    WeaverAidlAdapter(const std::string& param)
+        : aidl_weaver_(IWeaver::fromBinder(
+                  ::ndk::SpAIBinder(AServiceManager_waitForService(param.c_str())))) {}
+    ~WeaverAidlAdapter() {}
+
+    bool isReady() { return aidl_weaver_ != nullptr; }
+
+    ::ndk::ScopedAStatus getConfig(WeaverConfig* _aidl_return) {
+        return aidl_weaver_->getConfig(_aidl_return);
+    }
+
+    ::ndk::ScopedAStatus read(int32_t in_slotId, const std::vector<uint8_t>& in_key,
+                              WeaverReadResponse* _aidl_return) {
+        return aidl_weaver_->read(in_slotId, in_key, _aidl_return);
+    }
+
+    ::ndk::ScopedAStatus write(int32_t in_slotId, const std::vector<uint8_t>& in_key,
+                               const std::vector<uint8_t>& in_value) {
+        return aidl_weaver_->write(in_slotId, in_key, in_value);
+    }
+
+  private:
+    std::shared_ptr<IWeaver> aidl_weaver_;
+};
+
+class WeaverHidlAdapter : public WeaverAdapter {
+  public:
+    WeaverHidlAdapter(const std::string& param) : hidl_weaver_(HidlIWeaver::getService(param)) {}
+    ~WeaverHidlAdapter() {}
+
+    bool isReady() { return hidl_weaver_ != nullptr; }
+
+    ::ndk::ScopedAStatus getConfig(WeaverConfig* _aidl_return) {
+        bool callbackCalled = false;
+        HidlWeaverStatus status;
+        HidlWeaverConfig config;
+        auto ret = hidl_weaver_->getConfig([&](HidlWeaverStatus s, HidlWeaverConfig c) {
+            callbackCalled = true;
+            status = s;
+            config = c;
+        });
+        if (!ret.isOk() || !callbackCalled || status != HidlWeaverStatus::OK) {
+            return ::ndk::ScopedAStatus::fromStatus(STATUS_FAILED_TRANSACTION);
+        }
+        _aidl_return->slots = config.slots;
+        _aidl_return->keySize = config.keySize;
+        _aidl_return->valueSize = config.valueSize;
+        return ::ndk::ScopedAStatus::ok();
+    }
+
+    ::ndk::ScopedAStatus read(int32_t in_slotId, const std::vector<uint8_t>& in_key,
+                              WeaverReadResponse* _aidl_return) {
+        bool callbackCalled = false;
+        HidlWeaverReadStatus status;
+        std::vector<uint8_t> value;
+        uint32_t timeout;
+        auto ret = hidl_weaver_->read(in_slotId, in_key,
+                                      [&](HidlWeaverReadStatus s, HidlWeaverReadResponse r) {
+                                          callbackCalled = true;
+                                          status = s;
+                                          value = r.value;
+                                          timeout = r.timeout;
+                                      });
+        if (!ret.isOk() || !callbackCalled) {
+            return ::ndk::ScopedAStatus::fromStatus(STATUS_FAILED_TRANSACTION);
+        }
+        switch (status) {
+            case HidlWeaverReadStatus::OK:
+                _aidl_return->status = WeaverReadStatus::OK;
+                break;
+            case HidlWeaverReadStatus::FAILED:
+                _aidl_return->status = WeaverReadStatus::FAILED;
+                break;
+            case HidlWeaverReadStatus::INCORRECT_KEY:
+                _aidl_return->status = WeaverReadStatus::INCORRECT_KEY;
+                break;
+            case HidlWeaverReadStatus::THROTTLE:
+                _aidl_return->status = WeaverReadStatus::THROTTLE;
+                break;
+            default:
+                ADD_FAILURE() << "Unknown HIDL read status: " << static_cast<uint32_t>(status);
+                _aidl_return->status = WeaverReadStatus::FAILED;
+                break;
+        }
+        _aidl_return->value = value;
+        _aidl_return->timeout = timeout;
+        return ::ndk::ScopedAStatus::ok();
+    }
+
+    ::ndk::ScopedAStatus write(int32_t in_slotId, const std::vector<uint8_t>& in_key,
+                               const std::vector<uint8_t>& in_value) {
+        auto status = hidl_weaver_->write(in_slotId, in_key, in_value);
+        switch (status) {
+            case HidlWeaverStatus::OK:
+                return ::ndk::ScopedAStatus::ok();
+            case HidlWeaverStatus::FAILED:
+                return ::ndk::ScopedAStatus::fromStatus(STATUS_FAILED_TRANSACTION);
+            default:
+                ADD_FAILURE() << "Unknown HIDL write status: " << status.description();
+                return ::ndk::ScopedAStatus::fromStatus(STATUS_FAILED_TRANSACTION);
+        }
+    }
+
+  private:
+    android::sp<HidlIWeaver> hidl_weaver_;
+};
+
+class WeaverTest : public ::testing::TestWithParam<std::tuple<std::string, std::string>> {
+  protected:
+    void SetUp() override;
+    void TearDown() override {}
+    void FindFreeSlots();
+
+    std::unique_ptr<WeaverAdapter> weaver_;
+    WeaverConfig config_;
+    uint32_t first_free_slot_;
+    uint32_t last_free_slot_;
+};
+
+void WeaverTest::SetUp() {
+    std::string api, instance_name;
+    std::tie(api, instance_name) = GetParam();
+    if (api == "hidl") {
+        weaver_.reset(new WeaverHidlAdapter(instance_name));
+    } else if (api == "aidl") {
+        weaver_.reset(new WeaverAidlAdapter(instance_name));
+    } else {
+        FAIL() << "Bad test parameterization";
+    }
+    ASSERT_TRUE(weaver_->isReady());
+
+    auto ret = weaver_->getConfig(&config_);
+    ASSERT_TRUE(ret.isOk());
+    ASSERT_GT(config_.slots, 0);
+    GTEST_LOG_(INFO) << "WeaverConfig: slots=" << config_.slots << ", keySize=" << config_.keySize
+                     << ", valueSize=" << config_.valueSize;
+
+    FindFreeSlots();
+    GTEST_LOG_(INFO) << "First free slot is " << first_free_slot_ << ", last free slot is "
+                     << last_free_slot_;
+}
+
+void WeaverTest::FindFreeSlots() {
+    // Determine which Weaver slots are in use by the system. These slots can't be used by the test.
+    std::set<uint32_t> used_slots;
+    if (access(kSlotMapFile.c_str(), F_OK) == 0) {
+        std::string contents;
+        ASSERT_TRUE(android::base::ReadFileToString(kSlotMapFile, &contents))
+                << "Failed to read " << kSlotMapFile;
+        for (const auto& line : android::base::Split(contents, "\n")) {
+            auto trimmed_line = android::base::Trim(line);
+            if (trimmed_line[0] == '#' || trimmed_line[0] == '\0') continue;
+            auto slot_and_user = android::base::Split(trimmed_line, "=");
+            uint32_t slot;
+            ASSERT_TRUE(slot_and_user.size() == 2 &&
+                        android::base::ParseUint(slot_and_user[0], &slot))
+                    << "Error parsing " << kSlotMapFile << " at \"" << line << "\"";
+            GTEST_LOG_(INFO) << "Slot " << slot << " is in use by " << slot_and_user[1];
+            ASSERT_LT(slot, config_.slots);
+            used_slots.insert(slot);
+        }
+    }
+    // Starting in Android 14, the system will always use at least one Weaver slot if Weaver is
+    // supported at all.  Make sure we saw at least one.
+    // TODO: uncomment after Android 14 is merged into AOSP
+    // ASSERT_FALSE(used_slots.empty())
+    //<< "Could not determine which Weaver slots are in use by the system";
+
+    // Find the first free slot.
+    int found = 0;
+    for (uint32_t i = 0; i < config_.slots; i++) {
+        if (used_slots.find(i) == used_slots.end()) {
+            first_free_slot_ = i;
+            found++;
+            break;
+        }
+    }
+    // Find the last free slot.
+    for (uint32_t i = config_.slots; i > 0; i--) {
+        if (used_slots.find(i - 1) == used_slots.end()) {
+            last_free_slot_ = i - 1;
+            found++;
+            break;
+        }
+    }
+    ASSERT_EQ(found, 2) << "All Weaver slots are already in use by the system";
+}
+
+/*
+ * Checks config values are suitably large
+ */
+TEST_P(WeaverTest, GetConfig) {
+    EXPECT_GE(config_.slots, 16u);
+    EXPECT_GE(config_.keySize, 16u);
+    EXPECT_GE(config_.valueSize, 16u);
+}
+
+/*
+ * Gets the config twice and checks they are the same
+ */
+TEST_P(WeaverTest, GettingConfigMultipleTimesGivesSameResult) {
+    WeaverConfig config2;
+
+    auto ret = weaver_->getConfig(&config2);
+    ASSERT_TRUE(ret.isOk());
+
+    EXPECT_EQ(config_, config2);
+}
+
+/*
+ * Writes a key and value to the last free slot
+ */
+TEST_P(WeaverTest, WriteToLastSlot) {
+    const auto writeRet = weaver_->write(last_free_slot_, KEY, VALUE);
+    ASSERT_TRUE(writeRet.isOk());
+}
+
+/*
+ * Writes a key and value to a slot
+ * Reads the slot with the same key and receives the value that was previously written
+ */
+TEST_P(WeaverTest, WriteFollowedByReadGivesTheSameValue) {
+    const uint32_t slotId = first_free_slot_;
+    const auto ret = weaver_->write(slotId, KEY, VALUE);
+    ASSERT_TRUE(ret.isOk());
+
+    WeaverReadResponse response;
+    const auto readRet = weaver_->read(slotId, KEY, &response);
+    ASSERT_TRUE(readRet.isOk());
+    EXPECT_EQ(response.value, VALUE);
+    EXPECT_EQ(response.timeout, 0u);
+    EXPECT_EQ(response.status, WeaverReadStatus::OK);
+}
+
+/*
+ * Writes a key and value to a slot
+ * Overwrites the slot with a new key and value
+ * Reads the slot with the new key and receives the new value
+ */
+TEST_P(WeaverTest, OverwritingSlotUpdatesTheValue) {
+    const uint32_t slotId = first_free_slot_;
+    const auto initialWriteRet = weaver_->write(slotId, WRONG_KEY, VALUE);
+    ASSERT_TRUE(initialWriteRet.isOk());
+
+    const auto overwriteRet = weaver_->write(slotId, KEY, OTHER_VALUE);
+    ASSERT_TRUE(overwriteRet.isOk());
+
+    WeaverReadResponse response;
+    const auto readRet = weaver_->read(slotId, KEY, &response);
+    ASSERT_TRUE(readRet.isOk());
+    EXPECT_EQ(response.value, OTHER_VALUE);
+    EXPECT_EQ(response.timeout, 0u);
+    EXPECT_EQ(response.status, WeaverReadStatus::OK);
+}
+
+/*
+ * Writes a key and value to a slot
+ * Reads the slot with a different key so does not receive the value
+ */
+TEST_P(WeaverTest, WriteFollowedByReadWithWrongKeyDoesNotGiveTheValue) {
+    const uint32_t slotId = first_free_slot_;
+    const auto writeRet = weaver_->write(slotId, KEY, VALUE);
+    ASSERT_TRUE(writeRet.isOk());
+
+    WeaverReadResponse response;
+    const auto readRet = weaver_->read(slotId, WRONG_KEY, &response);
+    ASSERT_TRUE(readRet.isOk());
+    EXPECT_TRUE(response.value.empty());
+    EXPECT_EQ(response.status, WeaverReadStatus::INCORRECT_KEY);
+}
+
+/*
+ * Writing to an invalid slot fails
+ */
+TEST_P(WeaverTest, WritingToInvalidSlotFails) {
+    if (config_.slots == std::numeric_limits<uint32_t>::max()) {
+        // If there are no invalid slots then pass
+        return;
+    }
+
+    const auto writeRet = weaver_->write(config_.slots, KEY, VALUE);
+    ASSERT_FALSE(writeRet.isOk());
+}
+
+/*
+ * Reading from an invalid slot fails rather than incorrect key
+ */
+TEST_P(WeaverTest, ReadingFromInvalidSlotFails) {
+    if (config_.slots == std::numeric_limits<uint32_t>::max()) {
+        // If there are no invalid slots then pass
+        return;
+    }
+
+    WeaverReadResponse response;
+    const auto readRet = weaver_->read(config_.slots, KEY, &response);
+    ASSERT_TRUE(readRet.isOk());
+    EXPECT_TRUE(response.value.empty());
+    EXPECT_EQ(response.timeout, 0u);
+    EXPECT_EQ(response.status, WeaverReadStatus::FAILED);
+}
+
+/*
+ * Writing a key that is too large fails
+ */
+TEST_P(WeaverTest, WriteWithTooLargeKeyFails) {
+    std::vector<uint8_t> bigKey(config_.keySize + 1);
+
+    const auto writeRet = weaver_->write(first_free_slot_, bigKey, VALUE);
+    ASSERT_FALSE(writeRet.isOk());
+}
+
+/*
+ * Writing a value that is too large fails
+ */
+TEST_P(WeaverTest, WriteWithTooLargeValueFails) {
+    std::vector<uint8_t> bigValue(config_.valueSize + 1);
+
+    const auto writeRet = weaver_->write(first_free_slot_, KEY, bigValue);
+    ASSERT_FALSE(writeRet.isOk());
+}
+
+/*
+ * Reading with a key that is too large fails
+ */
+TEST_P(WeaverTest, ReadWithTooLargeKeyFails) {
+    std::vector<uint8_t> bigKey(config_.keySize + 1);
+
+    WeaverReadResponse response;
+    const auto readRet = weaver_->read(first_free_slot_, bigKey, &response);
+    ASSERT_TRUE(readRet.isOk());
+    EXPECT_TRUE(response.value.empty());
+    EXPECT_EQ(response.timeout, 0u);
+    EXPECT_EQ(response.status, WeaverReadStatus::FAILED);
+}
+
+// Instantiate the test for each HIDL Weaver service.
+INSTANTIATE_TEST_SUITE_P(
+        PerHidlInstance, WeaverTest,
+        testing::Combine(testing::Values("hidl"),
+                         testing::ValuesIn(android::hardware::getAllHalInstanceNames(
+                                 HidlIWeaver::descriptor))),
+        [](const testing::TestParamInfo<std::tuple<std::string, std::string>>& info) {
+            return android::hardware::PrintInstanceNameToString(
+                    testing::TestParamInfo<std::string>{std::get<1>(info.param), info.index});
+        });
+
+// Instantiate the test for each AIDL Weaver service.
+INSTANTIATE_TEST_SUITE_P(
+        PerAidlInstance, WeaverTest,
+        testing::Combine(testing::Values("aidl"),
+                         testing::ValuesIn(android::getAidlHalInstanceNames(IWeaver::descriptor))),
+        [](const testing::TestParamInfo<std::tuple<std::string, std::string>>& info) {
+            // This name_generator makes the instance name be included in the test case names, e.g.
+            // "PerAidlInstance/WeaverTest#GetConfig/0_android_hardware_weaver_IWeaver_default"
+            // instead of "PerAidlInstance/WeaverTest#GetConfig/0".
+            return android::PrintInstanceNameToString(
+                    testing::TestParamInfo<std::string>{std::get<1>(info.param), info.index});
+        });
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    ABinderProcess_setThreadPoolMaxThreadCount(1);
+    ABinderProcess_startThreadPool();
+    return RUN_ALL_TESTS();
+}