diff --git a/automotive/vehicle/aidl/impl/utils/common/include/VehicleHalTypes.h b/automotive/vehicle/aidl/impl/utils/common/include/VehicleHalTypes.h index 2b36c72bb1..013d1773c8 100644 --- a/automotive/vehicle/aidl/impl/utils/common/include/VehicleHalTypes.h +++ b/automotive/vehicle/aidl/impl/utils/common/include/VehicleHalTypes.h @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -34,6 +35,7 @@ #include #include #include +#include #include #include #include diff --git a/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h b/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h index dfc7cbf748..63eb747965 100644 --- a/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h +++ b/automotive/vehicle/aidl/impl/utils/common/include/VehicleUtils.h @@ -19,6 +19,7 @@ #include +#include #include #include @@ -208,6 +209,37 @@ std::string getErrorMsg(const ::android::base::Result& result) { return result.error().message(); } +template +::ndk::ScopedAStatus toScopedAStatus( + const ::android::base::Result& result, + ::aidl::android::hardware::automotive::vehicle::StatusCode status, + std::string additionalErrorMsg) { + if (result.ok()) { + return ::ndk::ScopedAStatus::ok(); + } + return ::ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage( + toInt(status), + fmt::format("{}, error: {}", additionalErrorMsg, getErrorMsg(result)).c_str()); +} + +template +::ndk::ScopedAStatus toScopedAStatus( + const ::android::base::Result& result, + ::aidl::android::hardware::automotive::vehicle::StatusCode status) { + return toScopedAStatus(result, status, ""); +} + +template +::ndk::ScopedAStatus toScopedAStatus(const ::android::base::Result& result) { + return toScopedAStatus(result, getErrorCode(result)); +} + +template +::ndk::ScopedAStatus toScopedAStatus(const ::android::base::Result& result, + std::string additionalErrorMsg) { + return toScopedAStatus(result, getErrorCode(result), additionalErrorMsg); +} + } // namespace vehicle } // namespace automotive } // namespace hardware diff --git a/automotive/vehicle/aidl/impl/vhal/Android.bp b/automotive/vehicle/aidl/impl/vhal/Android.bp index ef1d0f18ef..79d3ebd82e 100644 --- a/automotive/vehicle/aidl/impl/vhal/Android.bp +++ b/automotive/vehicle/aidl/impl/vhal/Android.bp @@ -53,7 +53,10 @@ cc_library { ], local_include_dirs: ["include"], export_include_dirs: ["include"], - srcs: ["src/DefaultVehicleHal.cpp"], + srcs: [ + "src/ConnectedClient.cpp", + "src/DefaultVehicleHal.cpp", + ], static_libs: [ "VehicleHalUtils", "android-automotive-large-parcelable-vendor-lib", diff --git a/automotive/vehicle/aidl/impl/vhal/include/ConnectedClient.h b/automotive/vehicle/aidl/impl/vhal/include/ConnectedClient.h new file mode 100644 index 0000000000..43a96036cb --- /dev/null +++ b/automotive/vehicle/aidl/impl/vhal/include/ConnectedClient.h @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef android_hardware_automotive_vehicle_aidl_impl_vhal_include_ConnectedClient_H_ +#define android_hardware_automotive_vehicle_aidl_impl_vhal_include_ConnectedClient_H_ + +#include + +#include +#include + +#include +#include +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { + +// A class to represent a binder client with a callback interface. Each callback function, e.g. +// GetValues or SetValues for a specific binder client is a separate {@code ConnectedClient}. +// For one {@code ConnectedClient}, we use one pending request pool to manage all pending requests, +// so the request IDs must be unique for one client. We also manage a set of callback functions +// for one client, e.g. timeoutCallback which could be passed to hardware. +// This class is thread-safe. +class ConnectedClient { + public: + ConnectedClient( + std::shared_ptr<::aidl::android::hardware::automotive::vehicle::IVehicleCallback> + callback); + + virtual ~ConnectedClient() = default; + + protected: + const std::shared_ptr<::aidl::android::hardware::automotive::vehicle::IVehicleCallback> + mCallback; +}; + +// A class to represent a client that calls {@code IVehicle.setValues} or {@code +// IVehicle.getValues}. +template +class GetSetValuesClient final : public ConnectedClient { + public: + GetSetValuesClient( + std::shared_ptr<::aidl::android::hardware::automotive::vehicle::IVehicleCallback> + callback); + + // Sends the results to this client. + void sendResults(const std::vector& results); + + // Sends each result separately to this client. Each result would be sent through one callback + // invocation. + void sendResultsSeparately(const std::vector& results); + + // Gets the callback to be called when the request for this client has finished. + std::shared_ptr)>> getResultCallback(); + + private: + // The following members are only initialized during construction. + std::shared_ptr)>> mResultCallback; +}; + +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android + +#endif // android_hardware_automotive_vehicle_aidl_impl_vhal_include_ConnectedClient_H_ diff --git a/automotive/vehicle/aidl/impl/vhal/include/ParcelableUtils.h b/automotive/vehicle/aidl/impl/vhal/include/ParcelableUtils.h new file mode 100644 index 0000000000..dcb15b9c63 --- /dev/null +++ b/automotive/vehicle/aidl/impl/vhal/include/ParcelableUtils.h @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef android_hardware_automotive_vehicle_aidl_impl_vhal_include_ParcelableUtils_H_ +#define android_hardware_automotive_vehicle_aidl_impl_vhal_include_ParcelableUtils_H_ + +#include +#include +#include + +#include +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { + +template +::ndk::ScopedAStatus vectorToStableLargeParcelable(std::vector&& values, T2* output) { + auto result = ::android::automotive::car_binder_lib::LargeParcelableBase:: + parcelableVectorToStableLargeParcelable(values); + if (!result.ok()) { + return toScopedAStatus( + result, ::aidl::android::hardware::automotive::vehicle::StatusCode::INTERNAL_ERROR); + } + auto& fd = result.value(); + if (fd == nullptr) { + // If we no longer needs values, move it inside the payloads to avoid copying. + output->payloads = std::move(values); + } else { + // Move the returned ScopedFileDescriptor pointer to ScopedFileDescriptor value in + // 'sharedMemoryFd' field. + output->sharedMemoryFd = std::move(*fd); + } + return ::ndk::ScopedAStatus::ok(); +} + +template +::ndk::ScopedAStatus vectorToStableLargeParcelable(const std::vector& values, T2* output) { + // Because 'values' is passed in as const reference, we have to do a copy here. + std::vector valuesCopy = values; + + return vectorToStableLargeParcelable(std::move(valuesCopy), output); +} + +template +::android::base::expected, ::ndk::ScopedAStatus> stableLargeParcelableToVector( + const T2& largeParcelable) { + ::android::base::Result>> result = + ::android::automotive::car_binder_lib::LargeParcelableBase:: + stableLargeParcelableToParcelableVector(largeParcelable.sharedMemoryFd); + + if (!result.ok()) { + return ::android::base::unexpected(toScopedAStatus( + result, ::aidl::android::hardware::automotive::vehicle::StatusCode::INVALID_ARG, + "failed to parse large parcelable")); + } + + if (!result.value().has_value()) { + return ::android::base::unexpected( + ::ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage( + toInt(::aidl::android::hardware::automotive::vehicle::StatusCode:: + INVALID_ARG), + "empty request")); + } + + return std::move(result.value().value()); +} + +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android + +#endif // android_hardware_automotive_vehicle_aidl_impl_vhal_include_ParcelableUtils_H_ diff --git a/automotive/vehicle/aidl/impl/vhal/src/ConnectedClient.cpp b/automotive/vehicle/aidl/impl/vhal/src/ConnectedClient.cpp new file mode 100644 index 0000000000..656dfaf579 --- /dev/null +++ b/automotive/vehicle/aidl/impl/vhal/src/ConnectedClient.cpp @@ -0,0 +1,160 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ConnectedClient.h" +#include "ParcelableUtils.h" + +#include + +#include + +#include +#include +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { + +namespace { + +using ::aidl::android::hardware::automotive::vehicle::GetValueResult; +using ::aidl::android::hardware::automotive::vehicle::GetValueResults; +using ::aidl::android::hardware::automotive::vehicle::IVehicleCallback; +using ::aidl::android::hardware::automotive::vehicle::SetValueResult; +using ::aidl::android::hardware::automotive::vehicle::SetValueResults; +using ::aidl::android::hardware::automotive::vehicle::StatusCode; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropValues; +using ::android::base::Result; +using ::ndk::ScopedAStatus; + +// A function to call the specific callback based on results type. +template +ScopedAStatus callCallback(std::shared_ptr callback, const T& results); + +template <> +ScopedAStatus callCallback(std::shared_ptr callback, + const GetValueResults& results) { + return callback->onGetValues(results); +} + +template <> +ScopedAStatus callCallback(std::shared_ptr callback, + const SetValueResults& results) { + return callback->onSetValues(results); +} + +// Send a single GetValue/SetValue result through the callback. +template +void sendGetOrSetValueResult(std::shared_ptr callback, const ResultType& result) { + ResultsType parcelableResults; + parcelableResults.payloads.resize(1); + parcelableResults.payloads[0] = result; + if (ScopedAStatus callbackStatus = callCallback(callback, parcelableResults); + !callbackStatus.isOk()) { + ALOGE("failed to call callback, error: %s, code: %d", callbackStatus.getMessage(), + callbackStatus.getServiceSpecificError()); + } +} + +// Send all the GetValue/SetValue results through callback, one result in each callback invocation. +template +void sendGetOrSetValueResultsSeparately(std::shared_ptr callback, + const std::vector& results) { + for (const auto& result : results) { + sendGetOrSetValueResult(callback, result); + } +} + +// Send all the GetValue/SetValue results through callback in a single callback invocation. +template +void sendGetOrSetValueResults(std::shared_ptr callback, + const std::vector& results) { + ResultsType parcelableResults; + ScopedAStatus status = vectorToStableLargeParcelable(results, &parcelableResults); + if (status.isOk()) { + if (ScopedAStatus callbackStatus = callCallback(callback, parcelableResults); + !callbackStatus.isOk()) { + ALOGE("failed to call callback, error: %s, code: %d", status.getMessage(), + status.getServiceSpecificError()); + } + return; + } + int statusCode = status.getServiceSpecificError(); + ALOGE("failed to marshal result into large parcelable, error: " + "%s, code: %d", + status.getMessage(), statusCode); + sendGetOrSetValueResultsSeparately(callback, results); +} + +// Specify the functions for GetValues and SetValues types. +template void sendGetOrSetValueResult( + std::shared_ptr callback, const GetValueResult& result); +template void sendGetOrSetValueResult( + std::shared_ptr callback, const SetValueResult& result); + +template void sendGetOrSetValueResults( + std::shared_ptr callback, const std::vector& results); +template void sendGetOrSetValueResults( + std::shared_ptr callback, const std::vector& results); + +template void sendGetOrSetValueResultsSeparately( + std::shared_ptr callback, const std::vector& results); +template void sendGetOrSetValueResultsSeparately( + std::shared_ptr callback, const std::vector& results); + +} // namespace + +ConnectedClient::ConnectedClient(std::shared_ptr callback) + : mCallback(callback) {} + +template +GetSetValuesClient::GetSetValuesClient( + std::shared_ptr callback) + : ConnectedClient(callback) { + mResultCallback = std::make_shared)>>( + [callback](std::vector results) { + return sendGetOrSetValueResults(callback, results); + }); +} + +template +std::shared_ptr)>> +GetSetValuesClient::getResultCallback() { + return mResultCallback; +} + +template +void GetSetValuesClient::sendResults( + const std::vector& results) { + return sendGetOrSetValueResults(mCallback, results); +} + +template +void GetSetValuesClient::sendResultsSeparately( + const std::vector& results) { + return sendGetOrSetValueResultsSeparately(mCallback, results); +} + +template class GetSetValuesClient; +template class GetSetValuesClient; + +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android diff --git a/automotive/vehicle/aidl/impl/vhal/test/ConnectedClientTest.cpp b/automotive/vehicle/aidl/impl/vhal/test/ConnectedClientTest.cpp new file mode 100644 index 0000000000..ddd0c65ec5 --- /dev/null +++ b/automotive/vehicle/aidl/impl/vhal/test/ConnectedClientTest.cpp @@ -0,0 +1,208 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ConnectedClient.h" +#include "MockVehicleCallback.h" + +#include + +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { + +using ::aidl::android::hardware::automotive::vehicle::GetValueResult; +using ::aidl::android::hardware::automotive::vehicle::GetValueResults; +using ::aidl::android::hardware::automotive::vehicle::IVehicleCallback; +using ::aidl::android::hardware::automotive::vehicle::SetValueResult; +using ::aidl::android::hardware::automotive::vehicle::SetValueResults; +using ::aidl::android::hardware::automotive::vehicle::StatusCode; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue; + +class ConnectedClientTest : public ::testing::Test { + public: + void SetUp() override { + mCallback = ndk::SharedRefBase::make(); + mCallbackClient = IVehicleCallback::fromBinder(mCallback->asBinder()); + } + + std::shared_ptr getCallbackClient() { return mCallbackClient; } + + MockVehicleCallback* getCallback() { return mCallback.get(); } + + protected: + using GetValuesClient = GetSetValuesClient; + using SetValuesClient = GetSetValuesClient; + + private: + std::shared_ptr mCallback; + std::shared_ptr mCallbackClient; +}; + +TEST_F(ConnectedClientTest, testSendGetValueResults) { + std::vector results = {{ + .requestId = 0, + .status = StatusCode::OK, + .prop = + VehiclePropValue{ + .prop = 0, + }, + }, + { + .requestId = 1, + .status = StatusCode::OK, + .prop = + VehiclePropValue{ + .prop = 1, + }, + }}; + + GetValuesClient client(getCallbackClient()); + + client.sendResults(results); + + auto maybeGetValueResults = getCallback()->nextGetValueResults(); + ASSERT_TRUE(maybeGetValueResults.has_value()); + ASSERT_EQ(maybeGetValueResults.value().payloads, results); +} + +TEST_F(ConnectedClientTest, testSendGetValueResultsSeparately) { + std::vector results = {{ + .requestId = 0, + .status = StatusCode::OK, + .prop = + VehiclePropValue{ + .prop = 0, + }, + }, + { + .requestId = 1, + .status = StatusCode::OK, + .prop = + VehiclePropValue{ + .prop = 1, + }, + }}; + + GetValuesClient client(getCallbackClient()); + + client.sendResultsSeparately(results); + + for (auto& result : results) { + auto maybeGetValueResults = getCallback()->nextGetValueResults(); + EXPECT_TRUE(maybeGetValueResults.has_value()); + if (!maybeGetValueResults.has_value()) { + continue; + } + EXPECT_EQ(maybeGetValueResults.value().payloads, std::vector({result})); + } +} + +TEST_F(ConnectedClientTest, testGetValuesGnResultCallback) { + std::vector results = {{ + .requestId = 0, + .status = StatusCode::OK, + .prop = + VehiclePropValue{ + .prop = 0, + }, + }, + { + .requestId = 1, + .status = StatusCode::OK, + .prop = + VehiclePropValue{ + .prop = 1, + }, + }}; + + GetValuesClient client(getCallbackClient()); + + (*(client.getResultCallback()))(results); + + auto maybeGetValueResults = getCallback()->nextGetValueResults(); + ASSERT_TRUE(maybeGetValueResults.has_value()); + ASSERT_EQ(maybeGetValueResults.value().payloads, results); +} + +TEST_F(ConnectedClientTest, testSendSetValueResults) { + std::vector results = {{ + .requestId = 0, + .status = StatusCode::OK, + }, + { + .requestId = 1, + .status = StatusCode::OK, + }}; + + SetValuesClient client(getCallbackClient()); + + client.sendResults(results); + + auto maybeSetValueResults = getCallback()->nextSetValueResults(); + ASSERT_TRUE(maybeSetValueResults.has_value()); + ASSERT_EQ(maybeSetValueResults.value().payloads, results); +} + +TEST_F(ConnectedClientTest, testSendSetValueResultsSeparately) { + std::vector results = {{ + .requestId = 0, + .status = StatusCode::OK, + }, + { + .requestId = 1, + .status = StatusCode::OK, + }}; + + SetValuesClient client(getCallbackClient()); + + client.sendResultsSeparately(results); + + for (auto& result : results) { + auto maybeSetValueResults = getCallback()->nextSetValueResults(); + EXPECT_TRUE(maybeSetValueResults.has_value()); + if (!maybeSetValueResults.has_value()) { + continue; + } + EXPECT_EQ(maybeSetValueResults.value().payloads, std::vector({result})); + } +} + +TEST_F(ConnectedClientTest, testSetValuesGetResultCallback) { + std::vector results = {{ + .requestId = 0, + .status = StatusCode::OK, + }, + { + .requestId = 1, + .status = StatusCode::OK, + }}; + + SetValuesClient client(getCallbackClient()); + + (*(client.getResultCallback()))(results); + + auto maybeSetValueResults = getCallback()->nextSetValueResults(); + ASSERT_TRUE(maybeSetValueResults.has_value()); + ASSERT_EQ(maybeSetValueResults.value().payloads, results); +} + +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android diff --git a/automotive/vehicle/aidl/impl/vhal/test/MockVehicleCallback.cpp b/automotive/vehicle/aidl/impl/vhal/test/MockVehicleCallback.cpp new file mode 100644 index 0000000000..ca366cd746 --- /dev/null +++ b/automotive/vehicle/aidl/impl/vhal/test/MockVehicleCallback.cpp @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "MockVehicleCallback.h" + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { + +namespace { + +using ::aidl::android::hardware::automotive::vehicle::GetValueResults; +using ::aidl::android::hardware::automotive::vehicle::SetValueResults; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropErrors; +using ::aidl::android::hardware::automotive::vehicle::VehiclePropValues; +using ::ndk::ScopedAStatus; +using ::ndk::ScopedFileDescriptor; + +template +std::optional pop(std::list& items) { + if (items.size() > 0) { + auto item = std::move(items.front()); + items.pop_front(); + return item; + } + return std::nullopt; +} + +template +static ScopedAStatus storeResults(const T& results, std::list* storedResults) { + T resultsCopy{ + .payloads = results.payloads, + }; + int fd = results.sharedMemoryFd.get(); + if (fd != -1) { + resultsCopy.sharedMemoryFd = ScopedFileDescriptor(dup(fd)); + } + storedResults->push_back(std::move(resultsCopy)); + return ScopedAStatus::ok(); +} + +} // namespace + +ScopedAStatus MockVehicleCallback::onGetValues(const GetValueResults& results) { + std::scoped_lock lockGuard(mLock); + return storeResults(results, &mGetValueResults); +} + +ScopedAStatus MockVehicleCallback::onSetValues(const SetValueResults& results) { + std::scoped_lock lockGuard(mLock); + return storeResults(results, &mSetValueResults); +} + +ScopedAStatus MockVehicleCallback::onPropertyEvent(const VehiclePropValues&, int32_t) { + return ScopedAStatus::ok(); +} + +ScopedAStatus MockVehicleCallback::onPropertySetError(const VehiclePropErrors&) { + return ScopedAStatus::ok(); +} + +std::optional MockVehicleCallback::nextGetValueResults() { + std::scoped_lock lockGuard(mLock); + return pop(mGetValueResults); +} + +std::optional MockVehicleCallback::nextSetValueResults() { + std::scoped_lock lockGuard(mLock); + return pop(mSetValueResults); +} + +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android diff --git a/automotive/vehicle/aidl/impl/vhal/test/MockVehicleCallback.h b/automotive/vehicle/aidl/impl/vhal/test/MockVehicleCallback.h new file mode 100644 index 0000000000..916575abdc --- /dev/null +++ b/automotive/vehicle/aidl/impl/vhal/test/MockVehicleCallback.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef android_hardware_automotive_vehicle_aidl_impl_vhal_test_MockVehicleCallback_H_ +#define android_hardware_automotive_vehicle_aidl_impl_vhal_test_MockVehicleCallback_H_ + +#include + +#include +#include + +#include +#include +#include + +namespace android { +namespace hardware { +namespace automotive { +namespace vehicle { + +// MockVehicleCallback is a mock VehicleCallback implementation that simply stores the results. +class MockVehicleCallback final + : public ::aidl::android::hardware::automotive::vehicle::BnVehicleCallback { + public: + ::ndk::ScopedAStatus onGetValues( + const ::aidl::android::hardware::automotive::vehicle::GetValueResults& results) + override; + ::ndk::ScopedAStatus onSetValues( + const ::aidl::android::hardware::automotive::vehicle::SetValueResults& results) + override; + ::ndk::ScopedAStatus onPropertyEvent( + const ::aidl::android::hardware::automotive::vehicle::VehiclePropValues&, + int32_t) override; + ::ndk::ScopedAStatus onPropertySetError( + const ::aidl::android::hardware::automotive::vehicle::VehiclePropErrors&) override; + + // Test functions + std::optional<::aidl::android::hardware::automotive::vehicle::GetValueResults> + nextGetValueResults(); + std::optional<::aidl::android::hardware::automotive::vehicle::SetValueResults> + nextSetValueResults(); + + private: + std::mutex mLock; + std::list<::aidl::android::hardware::automotive::vehicle::GetValueResults> mGetValueResults + GUARDED_BY(mLock); + std::list<::aidl::android::hardware::automotive::vehicle::SetValueResults> mSetValueResults + GUARDED_BY(mLock); +}; + +} // namespace vehicle +} // namespace automotive +} // namespace hardware +} // namespace android + +#endif // android_hardware_automotive_vehicle_aidl_impl_vhal_test_MockVehicleCallback_H_