diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml index d371f7c982..96124f93c1 100644 --- a/compatibility_matrices/compatibility_matrix.current.xml +++ b/compatibility_matrices/compatibility_matrix.current.xml @@ -569,6 +569,14 @@ default + + android.hardware.weaver + 1 + + IWeaver + default + + android.hardware.wifi 1.3-4 diff --git a/weaver/aidl/Android.bp b/weaver/aidl/Android.bp new file mode 100644 index 0000000000..5637e0a248 --- /dev/null +++ b/weaver/aidl/Android.bp @@ -0,0 +1,16 @@ +aidl_interface { + name: "android.hardware.weaver", + vendor_available: true, + srcs: ["android/hardware/weaver/*.aidl"], + stability: "vintf", + backend: { + java: { + platform_apis: true, + }, + ndk: { + vndk: { + enabled: true, + }, + }, + }, +} diff --git a/weaver/aidl/aidl_api/android.hardware.weaver/current/android/hardware/weaver/IWeaver.aidl b/weaver/aidl/aidl_api/android.hardware.weaver/current/android/hardware/weaver/IWeaver.aidl new file mode 100644 index 0000000000..29bd9a9213 --- /dev/null +++ b/weaver/aidl/aidl_api/android.hardware.weaver/current/android/hardware/weaver/IWeaver.aidl @@ -0,0 +1,42 @@ +/* + * Copyright 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. + *//////////////////////////////////////////////////////////////////////////////// +// 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; +@VintfStability +interface IWeaver { + android.hardware.weaver.WeaverConfig getConfig(); + android.hardware.weaver.WeaverReadResponse read(in int slotId, in byte[] key); + void write(in int slotId, in byte[] key, in byte[] value); + const int STATUS_FAILED = 1; + const int INCORRECT_KEY = 2; + const int THROTTLE = 3; +} diff --git a/weaver/aidl/aidl_api/android.hardware.weaver/current/android/hardware/weaver/WeaverConfig.aidl b/weaver/aidl/aidl_api/android.hardware.weaver/current/android/hardware/weaver/WeaverConfig.aidl new file mode 100644 index 0000000000..239cdac00b --- /dev/null +++ b/weaver/aidl/aidl_api/android.hardware.weaver/current/android/hardware/weaver/WeaverConfig.aidl @@ -0,0 +1,39 @@ +/* + * Copyright 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. + *//////////////////////////////////////////////////////////////////////////////// +// 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; +@VintfStability +parcelable WeaverConfig { + long slots; + long keySize; + long valueSize; +} diff --git a/weaver/aidl/aidl_api/android.hardware.weaver/current/android/hardware/weaver/WeaverReadResponse.aidl b/weaver/aidl/aidl_api/android.hardware.weaver/current/android/hardware/weaver/WeaverReadResponse.aidl new file mode 100644 index 0000000000..7e5db59f9a --- /dev/null +++ b/weaver/aidl/aidl_api/android.hardware.weaver/current/android/hardware/weaver/WeaverReadResponse.aidl @@ -0,0 +1,38 @@ +/* + * Copyright 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. + *//////////////////////////////////////////////////////////////////////////////// +// 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; +@VintfStability +parcelable WeaverReadResponse { + long timeout; + byte[] value; +} diff --git a/weaver/aidl/android/hardware/weaver/IWeaver.aidl b/weaver/aidl/android/hardware/weaver/IWeaver.aidl new file mode 100644 index 0000000000..ebbfabe62a --- /dev/null +++ b/weaver/aidl/android/hardware/weaver/IWeaver.aidl @@ -0,0 +1,94 @@ +/* + * Copyright 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.weaver; + +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. + * + * 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 + * key and value must be suitably large such that they cannot be easily guessed. + * + * Weaver is structured as an array of slots, each containing a key-value pair. + * Slots are uniquely identified by an ID in the range [0, `getConfig().slots`). + */ +@VintfStability +interface IWeaver { + /** + * Retrieves the config information for this implementation of Weaver. + * + * The config is static i.e. every invocation returns the same information. + * + * @return config data for this implementation of Weaver if status is OK, + * otherwise undefined. + */ + WeaverConfig getConfig(); + + /** + * Read binder calls may return a ServiceSpecificException with the following error codes. + */ + const int STATUS_FAILED = 1; + const int INCORRECT_KEY = 2; + const int THROTTLE = 3; + + /** + * Attempts to retrieve the value stored in the identified slot. + * + * The value is only returned if the provided key matches the key stored in + * the slot. The value is never returned if the wrong key is provided. + * + * Throttling must be used to limit the frequency of failed read attempts. + * The value is only returned when throttling is not active, even if the + * correct key is provided. If called when throttling is active, the time + * until the next attempt can be made is returned. + * + * Service status return: + * + * OK if the value was successfully read from slot. + * INCORRECT_KEY if the key does not match the key in the slot. + * THROTTLE if throttling is active. + * STATUS_FAILED if the read was unsuccessful for another reason. + * + * @param slotId of the slot to read from, this must be positive to be valid. + * @param key that is stored in the slot. + * @return The WeaverReadResponse for this read request. If the status is OK, + * value is set to the value in the slot and timeout is 0. Otherwise, value is + * empty and timeout is set accordingly. + */ + WeaverReadResponse read(in int slotId, in byte[] key); + + /** + * Overwrites the identified slot with the provided key and value. + * + * The new values are written regardless of the current state of the slot in + * order to remain idempotent. + * + * Service status return: + * + * OK if the write was successfully completed. + * FAILED if the write was unsuccessful. + * + * @param slotId of the slot to write to. + * @param key to write to the slot. + * @param value to write to slot. + */ + void write(in int slotId, in byte[] key, in byte[] value); +} diff --git a/weaver/aidl/android/hardware/weaver/WeaverConfig.aidl b/weaver/aidl/android/hardware/weaver/WeaverConfig.aidl new file mode 100644 index 0000000000..75d961e851 --- /dev/null +++ b/weaver/aidl/android/hardware/weaver/WeaverConfig.aidl @@ -0,0 +1,34 @@ +/* + * Copyright 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.weaver; + +@VintfStability +parcelable WeaverConfig { + /** + * The number of slots available. + */ + long slots; + /** + * The number of bytes used for a key. + */ + long keySize; + /** + * The number of bytes used for a value. + */ + long valueSize; +} + diff --git a/weaver/aidl/android/hardware/weaver/WeaverReadResponse.aidl b/weaver/aidl/android/hardware/weaver/WeaverReadResponse.aidl new file mode 100644 index 0000000000..ec006e8c45 --- /dev/null +++ b/weaver/aidl/android/hardware/weaver/WeaverReadResponse.aidl @@ -0,0 +1,30 @@ +/* + * Copyright 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.weaver; + +@VintfStability +parcelable WeaverReadResponse { + /** + * The time to wait, in milliseconds, before making the next request. + */ + long timeout; + /** + * The value read from the slot or empty if the value was not read. + */ + byte[] value; +} + diff --git a/weaver/aidl/default/Android.bp b/weaver/aidl/default/Android.bp new file mode 100644 index 0000000000..d93682828f --- /dev/null +++ b/weaver/aidl/default/Android.bp @@ -0,0 +1,32 @@ +// +// 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. +// + +cc_binary { + name: "android.hardware.weaver-service.example", + relative_install_path: "hw", + init_rc: ["android.hardware.weaver-service.example.rc"], + vintf_fragments: ["android.hardware.weaver-service.example.xml"], + vendor: true, + srcs: [ + "service.cpp", + "Weaver.cpp", + ], + shared_libs: [ + "android.hardware.weaver-ndk_platform", + "libbase", + "libbinder_ndk", + ], +} diff --git a/weaver/aidl/default/Weaver.cpp b/weaver/aidl/default/Weaver.cpp new file mode 100644 index 0000000000..56d9c4da8b --- /dev/null +++ b/weaver/aidl/default/Weaver.cpp @@ -0,0 +1,48 @@ +/* + * 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 "Weaver.h" + +namespace aidl { +namespace android { +namespace hardware { +namespace weaver { + +// Methods from ::android::hardware::weaver::IWeaver follow. + +::ndk::ScopedAStatus Weaver::getConfig(WeaverConfig* out_config) { + (void)out_config; + return ::ndk::ScopedAStatus::ok(); +} + +::ndk::ScopedAStatus Weaver::read(int32_t in_slotId, const std::vector& in_key, WeaverReadResponse* out_response) { + (void)in_slotId; + (void)in_key; + (void)out_response; + return ::ndk::ScopedAStatus::ok(); +} + +::ndk::ScopedAStatus Weaver::write(int32_t in_slotId, const std::vector& in_key, const std::vector& in_value) { + (void)in_slotId; + (void)in_key; + (void)in_value; + return ::ndk::ScopedAStatus::ok(); +} + +} //namespace weaver +} //namespace hardware +} //namespace android +} //namespace aidl diff --git a/weaver/aidl/default/Weaver.h b/weaver/aidl/default/Weaver.h new file mode 100644 index 0000000000..b50018e94a --- /dev/null +++ b/weaver/aidl/default/Weaver.h @@ -0,0 +1,42 @@ +/* + * 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. + */ + +#pragma once + +#include + +namespace aidl { +namespace android { +namespace hardware { +namespace weaver { + +using ::aidl::android::hardware::weaver::WeaverConfig; +using ::aidl::android::hardware::weaver::WeaverReadResponse; + +struct Weaver : public BnWeaver { +public: + Weaver() = default; + + // Methods from ::android::hardware::weaver::IWeaver follow. + ::ndk::ScopedAStatus getConfig(WeaverConfig* _aidl_return) override; + ::ndk::ScopedAStatus read(int32_t in_slotId, const std::vector& in_key, WeaverReadResponse* _aidl_return) override; + ::ndk::ScopedAStatus write(int32_t in_slotId, const std::vector& in_key, const std::vector& in_value) override; +}; + +} // namespace weaver +} // namespace hardware +} // namespace android +} // namespace aidl diff --git a/weaver/aidl/default/android.hardware.weaver-service.example.rc b/weaver/aidl/default/android.hardware.weaver-service.example.rc new file mode 100644 index 0000000000..ec777748b2 --- /dev/null +++ b/weaver/aidl/default/android.hardware.weaver-service.example.rc @@ -0,0 +1,4 @@ +service vendor.weaver_default /vendor/bin/hw/android.hardware.weaver-service.example + class hal + user hsm + group hsm diff --git a/weaver/aidl/default/android.hardware.weaver-service.example.xml b/weaver/aidl/default/android.hardware.weaver-service.example.xml new file mode 100644 index 0000000000..ed291cdf60 --- /dev/null +++ b/weaver/aidl/default/android.hardware.weaver-service.example.xml @@ -0,0 +1,10 @@ + + + android.hardware.weaver + 1 + + IWeaver + default + + + diff --git a/weaver/aidl/default/service.cpp b/weaver/aidl/default/service.cpp new file mode 100644 index 0000000000..1495bc9201 --- /dev/null +++ b/weaver/aidl/default/service.cpp @@ -0,0 +1,35 @@ +/* + * 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 "Weaver.h" + +using ::aidl::android::hardware::weaver::Weaver; + +int main() { + ABinderProcess_setThreadPoolMaxThreadCount(0); + std::shared_ptr weaver = ndk::SharedRefBase::make(); + + const std::string instance = std::string() + Weaver::descriptor + "/default"; + binder_status_t status = AServiceManager_addService(weaver->asBinder().get(), instance.c_str()); + CHECK(status == STATUS_OK); + + ABinderProcess_joinThreadPool(); + return -1; // Should never be reached +} diff --git a/weaver/aidl/vts/Android.bp b/weaver/aidl/vts/Android.bp new file mode 100644 index 0000000000..d7e3ab7a6e --- /dev/null +++ b/weaver/aidl/vts/Android.bp @@ -0,0 +1,33 @@ +// +// 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. +// + +cc_test { + name: "VtsHalWeaverTargetTest", + defaults: [ + "VtsHalTargetTestDefaults", + "use_libaidlvintf_gtest_helper_static", + ], + srcs: ["VtsHalWeaverTargetTest.cpp"], + shared_libs: [ + "libbinder_ndk", + "libbase", + ], + static_libs: ["android.hardware.weaver-ndk_platform"], + test_suites: [ + "general-tests", + "vts", + ], +} diff --git a/weaver/aidl/vts/OWNERS b/weaver/aidl/vts/OWNERS new file mode 100644 index 0000000000..40d95e4bf0 --- /dev/null +++ b/weaver/aidl/vts/OWNERS @@ -0,0 +1,2 @@ +chengyouho@google.com +frankwoo@google.com diff --git a/weaver/aidl/vts/VtsHalWeaverTargetTest.cpp b/weaver/aidl/vts/VtsHalWeaverTargetTest.cpp new file mode 100644 index 0000000000..7d8daa2464 --- /dev/null +++ b/weaver/aidl/vts/VtsHalWeaverTargetTest.cpp @@ -0,0 +1,277 @@ +/* + * 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::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(); +}