diff --git a/compatibility_matrices/compatibility_matrix.9.xml b/compatibility_matrices/compatibility_matrix.9.xml index ed03f7c912..580cb933a5 100644 --- a/compatibility_matrices/compatibility_matrix.9.xml +++ b/compatibility_matrices/compatibility_matrix.9.xml @@ -739,7 +739,7 @@ android.hardware.weaver - 1 + 2 IWeaver default diff --git a/weaver/1.0/vts/functional/Android.bp b/weaver/1.0/vts/functional/Android.bp deleted file mode 100644 index cc1d28465d..0000000000 --- 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 66465a9798..0000000000 --- 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 -#include -#include -#include - -#include - -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 KEY{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; -const std::vector WRONG_KEY{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; -const std::vector VALUE{16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}; -const std::vector OTHER_VALUE{0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 255, 255}; - -struct WeaverHidlTest : public ::testing::TestWithParam { - virtual void SetUp() override { - weaver = IWeaver::getService(GetParam()); - ASSERT_NE(weaver, nullptr); - } - - virtual void TearDown() override {} - - sp 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 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 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 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::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::max()) { - // If there are no invalid slots then pass - return; - } - - bool callbackCalled = false; - WeaverReadStatus readStatus; - std::vector 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 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 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 bigKey(config.keySize + 1); - - constexpr uint32_t slotId = 0; - bool callbackCalled = false; - WeaverReadStatus readStatus; - std::vector 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 caa92aa9b4..74cec99f7d 100644 --- a/weaver/aidl/Android.bp +++ b/weaver/aidl/Android.bp @@ -17,5 +17,10 @@ aidl_interface { 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 47ee4c8a13..96e528fa30 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 @@ package android.hardware.weaver; 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 0000000000..fce9758f5c --- /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 -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 f51034a387..ae816ef3f4 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.WeaverConfig; 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 @@ interface IWeaver { 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 ec006e8c45..17ea718089 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 0000000000..36e731fabe --- /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 70d91718de..494cb1bf4a 100644 --- a/weaver/aidl/default/Android.bp +++ b/weaver/aidl/default/Android.bp @@ -34,7 +34,7 @@ cc_binary { "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 6b77924be7..c9ffe85594 100644 --- a/weaver/aidl/default/Weaver.cpp +++ b/weaver/aidl/default/Weaver.cpp @@ -37,18 +37,19 @@ std::array slot_array; } ::ndk::ScopedAStatus Weaver::read(int32_t in_slotId, const std::vector& 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 ed291cdf60..bfe43966ab 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 @@ android.hardware.weaver - 1 + 2 IWeaver default diff --git a/weaver/aidl/vts/VtsHalWeaverTargetTest.cpp b/weaver/aidl/vts/VtsHalWeaverTargetTest.cpp deleted file mode 100644 index 878c76203f..0000000000 --- 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 -#include - -#include -#include -#include - -#include - -using ::aidl::android::hardware::weaver::IWeaver; -using ::aidl::android::hardware::weaver::WeaverConfig; -using ::aidl::android::hardware::weaver::WeaverReadResponse; - -using ::ndk::SpAIBinder; - -const std::vector KEY{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; -const std::vector WRONG_KEY{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; -const std::vector VALUE{16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}; -const std::vector OTHER_VALUE{0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 255, 255}; - -struct WeaverAidlTest : public ::testing::TestWithParam { - virtual void SetUp() override { - weaver = IWeaver::fromBinder( - SpAIBinder(AServiceManager_waitForService(GetParam().c_str()))); - ASSERT_NE(weaver, nullptr); - } - - virtual void TearDown() override {} - - std::shared_ptr 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 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 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 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::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::max()) { - // If there are no invalid slots then pass - return; - } - - WeaverReadResponse response; - std::vector 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 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 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 bigKey(config.keySize + 1); - - constexpr uint32_t slotId = 0; - WeaverReadResponse response; - std::vector 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 cf1661ce1e..ee03b28136 100644 --- a/weaver/aidl/vts/Android.bp +++ b/weaver/vts/Android.bp @@ -34,7 +34,10 @@ cc_test { "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 0000000000..9ee6d93cf0 --- /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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +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 KEY{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; +const std::vector WRONG_KEY{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +const std::vector VALUE{16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}; +const std::vector 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& in_key, + WeaverReadResponse* _aidl_return) = 0; + virtual ::ndk::ScopedAStatus write(int32_t in_slotId, const std::vector& in_key, + const std::vector& 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& 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& in_key, + const std::vector& in_value) { + return aidl_weaver_->write(in_slotId, in_key, in_value); + } + + private: + std::shared_ptr 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& in_key, + WeaverReadResponse* _aidl_return) { + bool callbackCalled = false; + HidlWeaverReadStatus status; + std::vector 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(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& in_key, + const std::vector& 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 hidl_weaver_; +}; + +class WeaverTest : public ::testing::TestWithParam> { + protected: + void SetUp() override; + void TearDown() override {} + void FindFreeSlots(); + + std::unique_ptr 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 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::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::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 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 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 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>& info) { + return android::hardware::PrintInstanceNameToString( + testing::TestParamInfo{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>& 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::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(); +}