Loading automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp +1 −188 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ #include "ConnectedClient.h" #include "DefaultVehicleHal.h" #include "MockVehicleCallback.h" #include "MockVehicleHardware.h" #include <IVehicleHardware.h> #include <LargeParcelableBase.h> Loading Loading @@ -76,199 +77,11 @@ constexpr int32_t INVALID_PROP_ID = 0; // VehiclePropertyGroup:SYSTEM,VehicleArea:WINDOW,VehiclePropertyType:INT32 constexpr int32_t INT32_WINDOW_PROP = 10001 + 0x10000000 + 0x03000000 + 0x00400000; template <class T> std::optional<T> pop(std::list<T>& items) { if (items.size() > 0) { auto item = std::move(items.front()); items.pop_front(); return item; } return std::nullopt; } int32_t testInt32VecProp(size_t i) { // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32_VEC return static_cast<int32_t>(i) + 0x10000000 + 0x01000000 + 0x00410000; } class MockVehicleHardware final : public IVehicleHardware { public: ~MockVehicleHardware() { std::scoped_lock<std::mutex> lockGuard(mLock); for (auto& thread : mThreads) { thread.join(); } } std::vector<VehiclePropConfig> getAllPropertyConfigs() const override { std::scoped_lock<std::mutex> lockGuard(mLock); return mPropertyConfigs; } StatusCode setValues(std::shared_ptr<const SetValuesCallback> callback, const std::vector<SetValueRequest>& requests) override { std::scoped_lock<std::mutex> lockGuard(mLock); return handleRequests(__func__, callback, requests, &mSetValueRequests, &mSetValueResponses); } StatusCode getValues(std::shared_ptr<const GetValuesCallback> callback, const std::vector<GetValueRequest>& requests) const override { std::scoped_lock<std::mutex> lockGuard(mLock); return handleRequests(__func__, callback, requests, &mGetValueRequests, &mGetValueResponses); } DumpResult dump(const std::vector<std::string>&) override { // TODO(b/200737967): mock this. return DumpResult{}; } StatusCode checkHealth() override { // TODO(b/200737967): mock this. return StatusCode::OK; } void registerOnPropertyChangeEvent(std::unique_ptr<const PropertyChangeCallback>) override { // TODO(b/200737967): mock this. } void registerOnPropertySetErrorEvent(std::unique_ptr<const PropertySetErrorCallback>) override { // TODO(b/200737967): mock this. } // Test functions. void setPropertyConfigs(const std::vector<VehiclePropConfig>& configs) { std::scoped_lock<std::mutex> lockGuard(mLock); mPropertyConfigs = configs; } void addGetValueResponses(const std::vector<GetValueResult>& responses) { std::scoped_lock<std::mutex> lockGuard(mLock); mGetValueResponses.push_back(responses); } void addSetValueResponses(const std::vector<SetValueResult>& responses) { std::scoped_lock<std::mutex> lockGuard(mLock); mSetValueResponses.push_back(responses); } std::vector<GetValueRequest> nextGetValueRequests() { std::scoped_lock<std::mutex> lockGuard(mLock); std::optional<std::vector<GetValueRequest>> request = pop(mGetValueRequests); if (!request.has_value()) { return std::vector<GetValueRequest>(); } return std::move(request.value()); } std::vector<SetValueRequest> nextSetValueRequests() { std::scoped_lock<std::mutex> lockGuard(mLock); std::optional<std::vector<SetValueRequest>> request = pop(mSetValueRequests); if (!request.has_value()) { return std::vector<SetValueRequest>(); } return std::move(request.value()); } void setStatus(const char* functionName, StatusCode status) { std::scoped_lock<std::mutex> lockGuard(mLock); mStatusByFunctions[functionName] = status; } void setSleepTime(int64_t timeInNano) { std::scoped_lock<std::mutex> lockGuard(mLock); mSleepTime = timeInNano; } private: mutable std::mutex mLock; std::vector<VehiclePropConfig> mPropertyConfigs GUARDED_BY(mLock); mutable std::list<std::vector<GetValueRequest>> mGetValueRequests GUARDED_BY(mLock); mutable std::list<std::vector<GetValueResult>> mGetValueResponses GUARDED_BY(mLock); mutable std::list<std::vector<SetValueRequest>> mSetValueRequests GUARDED_BY(mLock); mutable std::list<std::vector<SetValueResult>> mSetValueResponses GUARDED_BY(mLock); std::unordered_map<const char*, StatusCode> mStatusByFunctions GUARDED_BY(mLock); int64_t mSleepTime GUARDED_BY(mLock) = 0; mutable std::vector<std::thread> mThreads GUARDED_BY(mLock); template <class ResultType> StatusCode returnResponse( std::shared_ptr<const std::function<void(std::vector<ResultType>)>> callback, std::list<std::vector<ResultType>>* storedResponses) const; template <class RequestType, class ResultType> StatusCode handleRequests( const char* functionName, std::shared_ptr<const std::function<void(std::vector<ResultType>)>> callback, const std::vector<RequestType>& requests, std::list<std::vector<RequestType>>* storedRequests, std::list<std::vector<ResultType>>* storedResponses) const REQUIRES(mLock); }; template <class ResultType> StatusCode MockVehicleHardware::returnResponse( std::shared_ptr<const std::function<void(std::vector<ResultType>)>> callback, std::list<std::vector<ResultType>>* storedResponses) const { if (storedResponses->size() > 0) { (*callback)(std::move(storedResponses->front())); storedResponses->pop_front(); return StatusCode::OK; } else { ALOGE("no more response"); return StatusCode::INTERNAL_ERROR; } } template StatusCode MockVehicleHardware::returnResponse<GetValueResult>( std::shared_ptr<const std::function<void(std::vector<GetValueResult>)>> callback, std::list<std::vector<GetValueResult>>* storedResponses) const; template StatusCode MockVehicleHardware::returnResponse<SetValueResult>( std::shared_ptr<const std::function<void(std::vector<SetValueResult>)>> callback, std::list<std::vector<SetValueResult>>* storedResponses) const; template <class RequestType, class ResultType> StatusCode MockVehicleHardware::handleRequests( const char* functionName, std::shared_ptr<const std::function<void(std::vector<ResultType>)>> callback, const std::vector<RequestType>& requests, std::list<std::vector<RequestType>>* storedRequests, std::list<std::vector<ResultType>>* storedResponses) const { storedRequests->push_back(requests); if (auto it = mStatusByFunctions.find(functionName); it != mStatusByFunctions.end()) { if (StatusCode status = it->second; status != StatusCode::OK) { return status; } } if (mSleepTime != 0) { int64_t sleepTime = mSleepTime; mThreads.emplace_back([this, callback, sleepTime, storedResponses]() { std::this_thread::sleep_for(std::chrono::nanoseconds(sleepTime)); returnResponse(callback, storedResponses); }); return StatusCode::OK; } else { return returnResponse(callback, storedResponses); } } template StatusCode MockVehicleHardware::handleRequests<GetValueRequest, GetValueResult>( const char* functionName, std::shared_ptr<const std::function<void(std::vector<GetValueResult>)>> callback, const std::vector<GetValueRequest>& requests, std::list<std::vector<GetValueRequest>>* storedRequests, std::list<std::vector<GetValueResult>>* storedResponses) const; template StatusCode MockVehicleHardware::handleRequests<SetValueRequest, SetValueResult>( const char* functionName, std::shared_ptr<const std::function<void(std::vector<SetValueResult>)>> callback, const std::vector<SetValueRequest>& requests, std::list<std::vector<SetValueRequest>>* storedRequests, std::list<std::vector<SetValueResult>>* storedResponses) const; struct PropConfigCmp { bool operator()(const VehiclePropConfig& a, const VehiclePropConfig& b) const { return (a.prop < b.prop); Loading automotive/vehicle/aidl/impl/vhal/test/MockVehicleCallback.cpp +11 −12 Original line number Diff line number Diff line Loading @@ -30,16 +30,6 @@ using ::aidl::android::hardware::automotive::vehicle::VehiclePropValues; using ::ndk::ScopedAStatus; using ::ndk::ScopedFileDescriptor; template <class T> std::optional<T> pop(std::list<T>& items) { if (items.size() > 0) { auto item = std::move(items.front()); items.pop_front(); return item; } return std::nullopt; } template <class T> static ScopedAStatus storeResults(const T& results, std::list<T>* storedResults) { T resultsCopy{ Loading @@ -65,8 +55,12 @@ ScopedAStatus MockVehicleCallback::onSetValues(const SetValueResults& results) { return storeResults(results, &mSetValueResults); } ScopedAStatus MockVehicleCallback::onPropertyEvent(const VehiclePropValues&, int32_t) { return ScopedAStatus::ok(); ScopedAStatus MockVehicleCallback::onPropertyEvent(const VehiclePropValues& results, int32_t sharedMemoryFileCount) { std::scoped_lock<std::mutex> lockGuard(mLock); mSharedMemoryFileCount = sharedMemoryFileCount; return storeResults(results, &mOnPropertyEventResults); } ScopedAStatus MockVehicleCallback::onPropertySetError(const VehiclePropErrors&) { Loading @@ -83,6 +77,11 @@ std::optional<SetValueResults> MockVehicleCallback::nextSetValueResults() { return pop(mSetValueResults); } std::optional<VehiclePropValues> MockVehicleCallback::nextOnPropertyEventResults() { std::scoped_lock<std::mutex> lockGuard(mLock); return pop(mOnPropertyEventResults); } } // namespace vehicle } // namespace automotive } // namespace hardware Loading automotive/vehicle/aidl/impl/vhal/test/MockVehicleCallback.h +15 −0 Original line number Diff line number Diff line Loading @@ -31,6 +31,16 @@ namespace hardware { namespace automotive { namespace vehicle { template <class T> std::optional<T> pop(std::list<T>& items) { if (items.size() > 0) { auto item = std::move(items.front()); items.pop_front(); return item; } return std::nullopt; } // MockVehicleCallback is a mock VehicleCallback implementation that simply stores the results. class MockVehicleCallback final : public ::aidl::android::hardware::automotive::vehicle::BnVehicleCallback { Loading @@ -52,6 +62,8 @@ class MockVehicleCallback final nextGetValueResults(); std::optional<::aidl::android::hardware::automotive::vehicle::SetValueResults> nextSetValueResults(); std::optional<::aidl::android::hardware::automotive::vehicle::VehiclePropValues> nextOnPropertyEventResults(); private: std::mutex mLock; Loading @@ -59,6 +71,9 @@ class MockVehicleCallback final GUARDED_BY(mLock); std::list<::aidl::android::hardware::automotive::vehicle::SetValueResults> mSetValueResults GUARDED_BY(mLock); std::list<::aidl::android::hardware::automotive::vehicle::VehiclePropValues> mOnPropertyEventResults GUARDED_BY(mLock); int32_t mSharedMemoryFileCount GUARDED_BY(mLock); }; } // namespace vehicle Loading automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.cpp 0 → 100644 +207 −0 Original line number Diff line number Diff line /* * 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 "MockVehicleHardware.h" #include "MockVehicleCallback.h" #include <utils/Log.h> namespace android { namespace hardware { namespace automotive { namespace vehicle { using ::aidl::android::hardware::automotive::vehicle::GetValueRequest; using ::aidl::android::hardware::automotive::vehicle::GetValueResult; using ::aidl::android::hardware::automotive::vehicle::SetValueRequest; using ::aidl::android::hardware::automotive::vehicle::SetValueResult; using ::aidl::android::hardware::automotive::vehicle::StatusCode; using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig; using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue; MockVehicleHardware::~MockVehicleHardware() { std::unique_lock<std::mutex> lk(mLock); mCv.wait(lk, [this] { return mThreadCount == 0; }); } std::vector<VehiclePropConfig> MockVehicleHardware::getAllPropertyConfigs() const { std::scoped_lock<std::mutex> lockGuard(mLock); return mPropertyConfigs; } StatusCode MockVehicleHardware::setValues(std::shared_ptr<const SetValuesCallback> callback, const std::vector<SetValueRequest>& requests) { std::scoped_lock<std::mutex> lockGuard(mLock); if (StatusCode status = handleRequestsLocked(__func__, callback, requests, &mSetValueRequests, &mSetValueResponses); status != StatusCode::OK) { return status; } if (mPropertyChangeCallback == nullptr) { return StatusCode::OK; } std::vector<VehiclePropValue> values; for (auto& request : requests) { values.push_back(request.value); } (*mPropertyChangeCallback)(values); return StatusCode::OK; } StatusCode MockVehicleHardware::getValues(std::shared_ptr<const GetValuesCallback> callback, const std::vector<GetValueRequest>& requests) const { std::scoped_lock<std::mutex> lockGuard(mLock); return handleRequestsLocked(__func__, callback, requests, &mGetValueRequests, &mGetValueResponses); } DumpResult MockVehicleHardware::dump(const std::vector<std::string>&) { // TODO(b/200737967): mock this. return DumpResult{}; } StatusCode MockVehicleHardware::checkHealth() { // TODO(b/200737967): mock this. return StatusCode::OK; } void MockVehicleHardware::registerOnPropertyChangeEvent( std::unique_ptr<const PropertyChangeCallback> callback) { std::scoped_lock<std::mutex> lockGuard(mLock); mPropertyChangeCallback = std::move(callback); } void MockVehicleHardware::registerOnPropertySetErrorEvent( std::unique_ptr<const PropertySetErrorCallback>) { // TODO(b/200737967): mock this. } void MockVehicleHardware::setPropertyConfigs(const std::vector<VehiclePropConfig>& configs) { std::scoped_lock<std::mutex> lockGuard(mLock); mPropertyConfigs = configs; } void MockVehicleHardware::addGetValueResponses(const std::vector<GetValueResult>& responses) { std::scoped_lock<std::mutex> lockGuard(mLock); mGetValueResponses.push_back(responses); } void MockVehicleHardware::addSetValueResponses(const std::vector<SetValueResult>& responses) { std::scoped_lock<std::mutex> lockGuard(mLock); mSetValueResponses.push_back(responses); } std::vector<GetValueRequest> MockVehicleHardware::nextGetValueRequests() { std::scoped_lock<std::mutex> lockGuard(mLock); std::optional<std::vector<GetValueRequest>> request = pop(mGetValueRequests); if (!request.has_value()) { return std::vector<GetValueRequest>(); } return std::move(request.value()); } std::vector<SetValueRequest> MockVehicleHardware::nextSetValueRequests() { std::scoped_lock<std::mutex> lockGuard(mLock); std::optional<std::vector<SetValueRequest>> request = pop(mSetValueRequests); if (!request.has_value()) { return std::vector<SetValueRequest>(); } return std::move(request.value()); } void MockVehicleHardware::setStatus(const char* functionName, StatusCode status) { std::scoped_lock<std::mutex> lockGuard(mLock); mStatusByFunctions[functionName] = status; } void MockVehicleHardware::setSleepTime(int64_t timeInNano) { std::scoped_lock<std::mutex> lockGuard(mLock); mSleepTime = timeInNano; } template <class ResultType> StatusCode MockVehicleHardware::returnResponse( std::shared_ptr<const std::function<void(std::vector<ResultType>)>> callback, std::list<std::vector<ResultType>>* storedResponses) const { if (storedResponses->size() > 0) { (*callback)(std::move(storedResponses->front())); storedResponses->pop_front(); return StatusCode::OK; } else { ALOGE("no more response"); return StatusCode::INTERNAL_ERROR; } } template StatusCode MockVehicleHardware::returnResponse<GetValueResult>( std::shared_ptr<const std::function<void(std::vector<GetValueResult>)>> callback, std::list<std::vector<GetValueResult>>* storedResponses) const; template StatusCode MockVehicleHardware::returnResponse<SetValueResult>( std::shared_ptr<const std::function<void(std::vector<SetValueResult>)>> callback, std::list<std::vector<SetValueResult>>* storedResponses) const; template <class RequestType, class ResultType> StatusCode MockVehicleHardware::handleRequestsLocked( const char* functionName, std::shared_ptr<const std::function<void(std::vector<ResultType>)>> callback, const std::vector<RequestType>& requests, std::list<std::vector<RequestType>>* storedRequests, std::list<std::vector<ResultType>>* storedResponses) const { storedRequests->push_back(requests); if (auto it = mStatusByFunctions.find(functionName); it != mStatusByFunctions.end()) { if (StatusCode status = it->second; status != StatusCode::OK) { return status; } } if (mSleepTime != 0) { int64_t sleepTime = mSleepTime; mThreadCount++; std::thread t([this, callback, sleepTime, storedResponses]() { std::this_thread::sleep_for(std::chrono::nanoseconds(sleepTime)); returnResponse(callback, storedResponses); mThreadCount--; mCv.notify_one(); }); // Detach the thread here so we do not have to maintain the thread object. mThreadCount // and mCv make sure we wait for all threads to end before we exit. t.detach(); return StatusCode::OK; } else { return returnResponse(callback, storedResponses); } } template StatusCode MockVehicleHardware::handleRequestsLocked<GetValueRequest, GetValueResult>( const char* functionName, std::shared_ptr<const std::function<void(std::vector<GetValueResult>)>> callback, const std::vector<GetValueRequest>& requests, std::list<std::vector<GetValueRequest>>* storedRequests, std::list<std::vector<GetValueResult>>* storedResponses) const; template StatusCode MockVehicleHardware::handleRequestsLocked<SetValueRequest, SetValueResult>( const char* functionName, std::shared_ptr<const std::function<void(std::vector<SetValueResult>)>> callback, const std::vector<SetValueRequest>& requests, std::list<std::vector<SetValueRequest>>* storedRequests, std::list<std::vector<SetValueResult>>* storedResponses) const; } // namespace vehicle } // namespace automotive } // namespace hardware } // namespace android automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.h 0 → 100644 +114 −0 Original line number Diff line number Diff line /* * 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_MockVehicleHardware_H_ #define android_hardware_automotive_vehicle_aidl_impl_vhal_test_MockVehicleHardware_H_ #include <IVehicleHardware.h> #include <VehicleHalTypes.h> #include <android-base/thread_annotations.h> #include <atomic> #include <condition_variable> #include <list> #include <memory> #include <mutex> #include <thread> #include <unordered_map> #include <vector> namespace android { namespace hardware { namespace automotive { namespace vehicle { class MockVehicleHardware final : public IVehicleHardware { public: ~MockVehicleHardware(); std::vector<::aidl::android::hardware::automotive::vehicle::VehiclePropConfig> getAllPropertyConfigs() const override; ::aidl::android::hardware::automotive::vehicle::StatusCode setValues( std::shared_ptr<const SetValuesCallback> callback, const std::vector<::aidl::android::hardware::automotive::vehicle::SetValueRequest>& requests) override; ::aidl::android::hardware::automotive::vehicle::StatusCode getValues( std::shared_ptr<const GetValuesCallback> callback, const std::vector<::aidl::android::hardware::automotive::vehicle::GetValueRequest>& requests) const override; DumpResult dump(const std::vector<std::string>&) override; ::aidl::android::hardware::automotive::vehicle::StatusCode checkHealth() override; void registerOnPropertyChangeEvent( std::unique_ptr<const PropertyChangeCallback> callback) override; void registerOnPropertySetErrorEvent(std::unique_ptr<const PropertySetErrorCallback>) override; // Test functions. void setPropertyConfigs( const std::vector<::aidl::android::hardware::automotive::vehicle::VehiclePropConfig>& configs); void addGetValueResponses( const std::vector<::aidl::android::hardware::automotive::vehicle::GetValueResult>& responses); void addSetValueResponses( const std::vector<::aidl::android::hardware::automotive::vehicle::SetValueResult>& responses); std::vector<::aidl::android::hardware::automotive::vehicle::GetValueRequest> nextGetValueRequests(); std::vector<::aidl::android::hardware::automotive::vehicle::SetValueRequest> nextSetValueRequests(); void setStatus(const char* functionName, ::aidl::android::hardware::automotive::vehicle::StatusCode status); void setSleepTime(int64_t timeInNano); private: mutable std::mutex mLock; mutable std::condition_variable mCv; mutable std::atomic<int> mThreadCount; std::vector<::aidl::android::hardware::automotive::vehicle::VehiclePropConfig> mPropertyConfigs GUARDED_BY(mLock); mutable std::list<std::vector<::aidl::android::hardware::automotive::vehicle::GetValueRequest>> mGetValueRequests GUARDED_BY(mLock); mutable std::list<std::vector<::aidl::android::hardware::automotive::vehicle::GetValueResult>> mGetValueResponses GUARDED_BY(mLock); mutable std::list<std::vector<::aidl::android::hardware::automotive::vehicle::SetValueRequest>> mSetValueRequests GUARDED_BY(mLock); mutable std::list<std::vector<::aidl::android::hardware::automotive::vehicle::SetValueResult>> mSetValueResponses GUARDED_BY(mLock); std::unordered_map<const char*, ::aidl::android::hardware::automotive::vehicle::StatusCode> mStatusByFunctions GUARDED_BY(mLock); int64_t mSleepTime GUARDED_BY(mLock) = 0; std::unique_ptr<const PropertyChangeCallback> mPropertyChangeCallback GUARDED_BY(mLock); template <class ResultType> ::aidl::android::hardware::automotive::vehicle::StatusCode returnResponse( std::shared_ptr<const std::function<void(std::vector<ResultType>)>> callback, std::list<std::vector<ResultType>>* storedResponses) const; template <class RequestType, class ResultType> ::aidl::android::hardware::automotive::vehicle::StatusCode handleRequestsLocked( const char* functionName, std::shared_ptr<const std::function<void(std::vector<ResultType>)>> callback, const std::vector<RequestType>& requests, std::list<std::vector<RequestType>>* storedRequests, std::list<std::vector<ResultType>>* storedResponses) const REQUIRES(mLock); }; } // namespace vehicle } // namespace automotive } // namespace hardware } // namespace android #endif // android_hardware_automotive_vehicle_aidl_impl_vhal_test_MockVehicleHardware_H_ Loading
automotive/vehicle/aidl/impl/vhal/test/DefaultVehicleHalTest.cpp +1 −188 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ #include "ConnectedClient.h" #include "DefaultVehicleHal.h" #include "MockVehicleCallback.h" #include "MockVehicleHardware.h" #include <IVehicleHardware.h> #include <LargeParcelableBase.h> Loading Loading @@ -76,199 +77,11 @@ constexpr int32_t INVALID_PROP_ID = 0; // VehiclePropertyGroup:SYSTEM,VehicleArea:WINDOW,VehiclePropertyType:INT32 constexpr int32_t INT32_WINDOW_PROP = 10001 + 0x10000000 + 0x03000000 + 0x00400000; template <class T> std::optional<T> pop(std::list<T>& items) { if (items.size() > 0) { auto item = std::move(items.front()); items.pop_front(); return item; } return std::nullopt; } int32_t testInt32VecProp(size_t i) { // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32_VEC return static_cast<int32_t>(i) + 0x10000000 + 0x01000000 + 0x00410000; } class MockVehicleHardware final : public IVehicleHardware { public: ~MockVehicleHardware() { std::scoped_lock<std::mutex> lockGuard(mLock); for (auto& thread : mThreads) { thread.join(); } } std::vector<VehiclePropConfig> getAllPropertyConfigs() const override { std::scoped_lock<std::mutex> lockGuard(mLock); return mPropertyConfigs; } StatusCode setValues(std::shared_ptr<const SetValuesCallback> callback, const std::vector<SetValueRequest>& requests) override { std::scoped_lock<std::mutex> lockGuard(mLock); return handleRequests(__func__, callback, requests, &mSetValueRequests, &mSetValueResponses); } StatusCode getValues(std::shared_ptr<const GetValuesCallback> callback, const std::vector<GetValueRequest>& requests) const override { std::scoped_lock<std::mutex> lockGuard(mLock); return handleRequests(__func__, callback, requests, &mGetValueRequests, &mGetValueResponses); } DumpResult dump(const std::vector<std::string>&) override { // TODO(b/200737967): mock this. return DumpResult{}; } StatusCode checkHealth() override { // TODO(b/200737967): mock this. return StatusCode::OK; } void registerOnPropertyChangeEvent(std::unique_ptr<const PropertyChangeCallback>) override { // TODO(b/200737967): mock this. } void registerOnPropertySetErrorEvent(std::unique_ptr<const PropertySetErrorCallback>) override { // TODO(b/200737967): mock this. } // Test functions. void setPropertyConfigs(const std::vector<VehiclePropConfig>& configs) { std::scoped_lock<std::mutex> lockGuard(mLock); mPropertyConfigs = configs; } void addGetValueResponses(const std::vector<GetValueResult>& responses) { std::scoped_lock<std::mutex> lockGuard(mLock); mGetValueResponses.push_back(responses); } void addSetValueResponses(const std::vector<SetValueResult>& responses) { std::scoped_lock<std::mutex> lockGuard(mLock); mSetValueResponses.push_back(responses); } std::vector<GetValueRequest> nextGetValueRequests() { std::scoped_lock<std::mutex> lockGuard(mLock); std::optional<std::vector<GetValueRequest>> request = pop(mGetValueRequests); if (!request.has_value()) { return std::vector<GetValueRequest>(); } return std::move(request.value()); } std::vector<SetValueRequest> nextSetValueRequests() { std::scoped_lock<std::mutex> lockGuard(mLock); std::optional<std::vector<SetValueRequest>> request = pop(mSetValueRequests); if (!request.has_value()) { return std::vector<SetValueRequest>(); } return std::move(request.value()); } void setStatus(const char* functionName, StatusCode status) { std::scoped_lock<std::mutex> lockGuard(mLock); mStatusByFunctions[functionName] = status; } void setSleepTime(int64_t timeInNano) { std::scoped_lock<std::mutex> lockGuard(mLock); mSleepTime = timeInNano; } private: mutable std::mutex mLock; std::vector<VehiclePropConfig> mPropertyConfigs GUARDED_BY(mLock); mutable std::list<std::vector<GetValueRequest>> mGetValueRequests GUARDED_BY(mLock); mutable std::list<std::vector<GetValueResult>> mGetValueResponses GUARDED_BY(mLock); mutable std::list<std::vector<SetValueRequest>> mSetValueRequests GUARDED_BY(mLock); mutable std::list<std::vector<SetValueResult>> mSetValueResponses GUARDED_BY(mLock); std::unordered_map<const char*, StatusCode> mStatusByFunctions GUARDED_BY(mLock); int64_t mSleepTime GUARDED_BY(mLock) = 0; mutable std::vector<std::thread> mThreads GUARDED_BY(mLock); template <class ResultType> StatusCode returnResponse( std::shared_ptr<const std::function<void(std::vector<ResultType>)>> callback, std::list<std::vector<ResultType>>* storedResponses) const; template <class RequestType, class ResultType> StatusCode handleRequests( const char* functionName, std::shared_ptr<const std::function<void(std::vector<ResultType>)>> callback, const std::vector<RequestType>& requests, std::list<std::vector<RequestType>>* storedRequests, std::list<std::vector<ResultType>>* storedResponses) const REQUIRES(mLock); }; template <class ResultType> StatusCode MockVehicleHardware::returnResponse( std::shared_ptr<const std::function<void(std::vector<ResultType>)>> callback, std::list<std::vector<ResultType>>* storedResponses) const { if (storedResponses->size() > 0) { (*callback)(std::move(storedResponses->front())); storedResponses->pop_front(); return StatusCode::OK; } else { ALOGE("no more response"); return StatusCode::INTERNAL_ERROR; } } template StatusCode MockVehicleHardware::returnResponse<GetValueResult>( std::shared_ptr<const std::function<void(std::vector<GetValueResult>)>> callback, std::list<std::vector<GetValueResult>>* storedResponses) const; template StatusCode MockVehicleHardware::returnResponse<SetValueResult>( std::shared_ptr<const std::function<void(std::vector<SetValueResult>)>> callback, std::list<std::vector<SetValueResult>>* storedResponses) const; template <class RequestType, class ResultType> StatusCode MockVehicleHardware::handleRequests( const char* functionName, std::shared_ptr<const std::function<void(std::vector<ResultType>)>> callback, const std::vector<RequestType>& requests, std::list<std::vector<RequestType>>* storedRequests, std::list<std::vector<ResultType>>* storedResponses) const { storedRequests->push_back(requests); if (auto it = mStatusByFunctions.find(functionName); it != mStatusByFunctions.end()) { if (StatusCode status = it->second; status != StatusCode::OK) { return status; } } if (mSleepTime != 0) { int64_t sleepTime = mSleepTime; mThreads.emplace_back([this, callback, sleepTime, storedResponses]() { std::this_thread::sleep_for(std::chrono::nanoseconds(sleepTime)); returnResponse(callback, storedResponses); }); return StatusCode::OK; } else { return returnResponse(callback, storedResponses); } } template StatusCode MockVehicleHardware::handleRequests<GetValueRequest, GetValueResult>( const char* functionName, std::shared_ptr<const std::function<void(std::vector<GetValueResult>)>> callback, const std::vector<GetValueRequest>& requests, std::list<std::vector<GetValueRequest>>* storedRequests, std::list<std::vector<GetValueResult>>* storedResponses) const; template StatusCode MockVehicleHardware::handleRequests<SetValueRequest, SetValueResult>( const char* functionName, std::shared_ptr<const std::function<void(std::vector<SetValueResult>)>> callback, const std::vector<SetValueRequest>& requests, std::list<std::vector<SetValueRequest>>* storedRequests, std::list<std::vector<SetValueResult>>* storedResponses) const; struct PropConfigCmp { bool operator()(const VehiclePropConfig& a, const VehiclePropConfig& b) const { return (a.prop < b.prop); Loading
automotive/vehicle/aidl/impl/vhal/test/MockVehicleCallback.cpp +11 −12 Original line number Diff line number Diff line Loading @@ -30,16 +30,6 @@ using ::aidl::android::hardware::automotive::vehicle::VehiclePropValues; using ::ndk::ScopedAStatus; using ::ndk::ScopedFileDescriptor; template <class T> std::optional<T> pop(std::list<T>& items) { if (items.size() > 0) { auto item = std::move(items.front()); items.pop_front(); return item; } return std::nullopt; } template <class T> static ScopedAStatus storeResults(const T& results, std::list<T>* storedResults) { T resultsCopy{ Loading @@ -65,8 +55,12 @@ ScopedAStatus MockVehicleCallback::onSetValues(const SetValueResults& results) { return storeResults(results, &mSetValueResults); } ScopedAStatus MockVehicleCallback::onPropertyEvent(const VehiclePropValues&, int32_t) { return ScopedAStatus::ok(); ScopedAStatus MockVehicleCallback::onPropertyEvent(const VehiclePropValues& results, int32_t sharedMemoryFileCount) { std::scoped_lock<std::mutex> lockGuard(mLock); mSharedMemoryFileCount = sharedMemoryFileCount; return storeResults(results, &mOnPropertyEventResults); } ScopedAStatus MockVehicleCallback::onPropertySetError(const VehiclePropErrors&) { Loading @@ -83,6 +77,11 @@ std::optional<SetValueResults> MockVehicleCallback::nextSetValueResults() { return pop(mSetValueResults); } std::optional<VehiclePropValues> MockVehicleCallback::nextOnPropertyEventResults() { std::scoped_lock<std::mutex> lockGuard(mLock); return pop(mOnPropertyEventResults); } } // namespace vehicle } // namespace automotive } // namespace hardware Loading
automotive/vehicle/aidl/impl/vhal/test/MockVehicleCallback.h +15 −0 Original line number Diff line number Diff line Loading @@ -31,6 +31,16 @@ namespace hardware { namespace automotive { namespace vehicle { template <class T> std::optional<T> pop(std::list<T>& items) { if (items.size() > 0) { auto item = std::move(items.front()); items.pop_front(); return item; } return std::nullopt; } // MockVehicleCallback is a mock VehicleCallback implementation that simply stores the results. class MockVehicleCallback final : public ::aidl::android::hardware::automotive::vehicle::BnVehicleCallback { Loading @@ -52,6 +62,8 @@ class MockVehicleCallback final nextGetValueResults(); std::optional<::aidl::android::hardware::automotive::vehicle::SetValueResults> nextSetValueResults(); std::optional<::aidl::android::hardware::automotive::vehicle::VehiclePropValues> nextOnPropertyEventResults(); private: std::mutex mLock; Loading @@ -59,6 +71,9 @@ class MockVehicleCallback final GUARDED_BY(mLock); std::list<::aidl::android::hardware::automotive::vehicle::SetValueResults> mSetValueResults GUARDED_BY(mLock); std::list<::aidl::android::hardware::automotive::vehicle::VehiclePropValues> mOnPropertyEventResults GUARDED_BY(mLock); int32_t mSharedMemoryFileCount GUARDED_BY(mLock); }; } // namespace vehicle Loading
automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.cpp 0 → 100644 +207 −0 Original line number Diff line number Diff line /* * 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 "MockVehicleHardware.h" #include "MockVehicleCallback.h" #include <utils/Log.h> namespace android { namespace hardware { namespace automotive { namespace vehicle { using ::aidl::android::hardware::automotive::vehicle::GetValueRequest; using ::aidl::android::hardware::automotive::vehicle::GetValueResult; using ::aidl::android::hardware::automotive::vehicle::SetValueRequest; using ::aidl::android::hardware::automotive::vehicle::SetValueResult; using ::aidl::android::hardware::automotive::vehicle::StatusCode; using ::aidl::android::hardware::automotive::vehicle::VehiclePropConfig; using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue; MockVehicleHardware::~MockVehicleHardware() { std::unique_lock<std::mutex> lk(mLock); mCv.wait(lk, [this] { return mThreadCount == 0; }); } std::vector<VehiclePropConfig> MockVehicleHardware::getAllPropertyConfigs() const { std::scoped_lock<std::mutex> lockGuard(mLock); return mPropertyConfigs; } StatusCode MockVehicleHardware::setValues(std::shared_ptr<const SetValuesCallback> callback, const std::vector<SetValueRequest>& requests) { std::scoped_lock<std::mutex> lockGuard(mLock); if (StatusCode status = handleRequestsLocked(__func__, callback, requests, &mSetValueRequests, &mSetValueResponses); status != StatusCode::OK) { return status; } if (mPropertyChangeCallback == nullptr) { return StatusCode::OK; } std::vector<VehiclePropValue> values; for (auto& request : requests) { values.push_back(request.value); } (*mPropertyChangeCallback)(values); return StatusCode::OK; } StatusCode MockVehicleHardware::getValues(std::shared_ptr<const GetValuesCallback> callback, const std::vector<GetValueRequest>& requests) const { std::scoped_lock<std::mutex> lockGuard(mLock); return handleRequestsLocked(__func__, callback, requests, &mGetValueRequests, &mGetValueResponses); } DumpResult MockVehicleHardware::dump(const std::vector<std::string>&) { // TODO(b/200737967): mock this. return DumpResult{}; } StatusCode MockVehicleHardware::checkHealth() { // TODO(b/200737967): mock this. return StatusCode::OK; } void MockVehicleHardware::registerOnPropertyChangeEvent( std::unique_ptr<const PropertyChangeCallback> callback) { std::scoped_lock<std::mutex> lockGuard(mLock); mPropertyChangeCallback = std::move(callback); } void MockVehicleHardware::registerOnPropertySetErrorEvent( std::unique_ptr<const PropertySetErrorCallback>) { // TODO(b/200737967): mock this. } void MockVehicleHardware::setPropertyConfigs(const std::vector<VehiclePropConfig>& configs) { std::scoped_lock<std::mutex> lockGuard(mLock); mPropertyConfigs = configs; } void MockVehicleHardware::addGetValueResponses(const std::vector<GetValueResult>& responses) { std::scoped_lock<std::mutex> lockGuard(mLock); mGetValueResponses.push_back(responses); } void MockVehicleHardware::addSetValueResponses(const std::vector<SetValueResult>& responses) { std::scoped_lock<std::mutex> lockGuard(mLock); mSetValueResponses.push_back(responses); } std::vector<GetValueRequest> MockVehicleHardware::nextGetValueRequests() { std::scoped_lock<std::mutex> lockGuard(mLock); std::optional<std::vector<GetValueRequest>> request = pop(mGetValueRequests); if (!request.has_value()) { return std::vector<GetValueRequest>(); } return std::move(request.value()); } std::vector<SetValueRequest> MockVehicleHardware::nextSetValueRequests() { std::scoped_lock<std::mutex> lockGuard(mLock); std::optional<std::vector<SetValueRequest>> request = pop(mSetValueRequests); if (!request.has_value()) { return std::vector<SetValueRequest>(); } return std::move(request.value()); } void MockVehicleHardware::setStatus(const char* functionName, StatusCode status) { std::scoped_lock<std::mutex> lockGuard(mLock); mStatusByFunctions[functionName] = status; } void MockVehicleHardware::setSleepTime(int64_t timeInNano) { std::scoped_lock<std::mutex> lockGuard(mLock); mSleepTime = timeInNano; } template <class ResultType> StatusCode MockVehicleHardware::returnResponse( std::shared_ptr<const std::function<void(std::vector<ResultType>)>> callback, std::list<std::vector<ResultType>>* storedResponses) const { if (storedResponses->size() > 0) { (*callback)(std::move(storedResponses->front())); storedResponses->pop_front(); return StatusCode::OK; } else { ALOGE("no more response"); return StatusCode::INTERNAL_ERROR; } } template StatusCode MockVehicleHardware::returnResponse<GetValueResult>( std::shared_ptr<const std::function<void(std::vector<GetValueResult>)>> callback, std::list<std::vector<GetValueResult>>* storedResponses) const; template StatusCode MockVehicleHardware::returnResponse<SetValueResult>( std::shared_ptr<const std::function<void(std::vector<SetValueResult>)>> callback, std::list<std::vector<SetValueResult>>* storedResponses) const; template <class RequestType, class ResultType> StatusCode MockVehicleHardware::handleRequestsLocked( const char* functionName, std::shared_ptr<const std::function<void(std::vector<ResultType>)>> callback, const std::vector<RequestType>& requests, std::list<std::vector<RequestType>>* storedRequests, std::list<std::vector<ResultType>>* storedResponses) const { storedRequests->push_back(requests); if (auto it = mStatusByFunctions.find(functionName); it != mStatusByFunctions.end()) { if (StatusCode status = it->second; status != StatusCode::OK) { return status; } } if (mSleepTime != 0) { int64_t sleepTime = mSleepTime; mThreadCount++; std::thread t([this, callback, sleepTime, storedResponses]() { std::this_thread::sleep_for(std::chrono::nanoseconds(sleepTime)); returnResponse(callback, storedResponses); mThreadCount--; mCv.notify_one(); }); // Detach the thread here so we do not have to maintain the thread object. mThreadCount // and mCv make sure we wait for all threads to end before we exit. t.detach(); return StatusCode::OK; } else { return returnResponse(callback, storedResponses); } } template StatusCode MockVehicleHardware::handleRequestsLocked<GetValueRequest, GetValueResult>( const char* functionName, std::shared_ptr<const std::function<void(std::vector<GetValueResult>)>> callback, const std::vector<GetValueRequest>& requests, std::list<std::vector<GetValueRequest>>* storedRequests, std::list<std::vector<GetValueResult>>* storedResponses) const; template StatusCode MockVehicleHardware::handleRequestsLocked<SetValueRequest, SetValueResult>( const char* functionName, std::shared_ptr<const std::function<void(std::vector<SetValueResult>)>> callback, const std::vector<SetValueRequest>& requests, std::list<std::vector<SetValueRequest>>* storedRequests, std::list<std::vector<SetValueResult>>* storedResponses) const; } // namespace vehicle } // namespace automotive } // namespace hardware } // namespace android
automotive/vehicle/aidl/impl/vhal/test/MockVehicleHardware.h 0 → 100644 +114 −0 Original line number Diff line number Diff line /* * 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_MockVehicleHardware_H_ #define android_hardware_automotive_vehicle_aidl_impl_vhal_test_MockVehicleHardware_H_ #include <IVehicleHardware.h> #include <VehicleHalTypes.h> #include <android-base/thread_annotations.h> #include <atomic> #include <condition_variable> #include <list> #include <memory> #include <mutex> #include <thread> #include <unordered_map> #include <vector> namespace android { namespace hardware { namespace automotive { namespace vehicle { class MockVehicleHardware final : public IVehicleHardware { public: ~MockVehicleHardware(); std::vector<::aidl::android::hardware::automotive::vehicle::VehiclePropConfig> getAllPropertyConfigs() const override; ::aidl::android::hardware::automotive::vehicle::StatusCode setValues( std::shared_ptr<const SetValuesCallback> callback, const std::vector<::aidl::android::hardware::automotive::vehicle::SetValueRequest>& requests) override; ::aidl::android::hardware::automotive::vehicle::StatusCode getValues( std::shared_ptr<const GetValuesCallback> callback, const std::vector<::aidl::android::hardware::automotive::vehicle::GetValueRequest>& requests) const override; DumpResult dump(const std::vector<std::string>&) override; ::aidl::android::hardware::automotive::vehicle::StatusCode checkHealth() override; void registerOnPropertyChangeEvent( std::unique_ptr<const PropertyChangeCallback> callback) override; void registerOnPropertySetErrorEvent(std::unique_ptr<const PropertySetErrorCallback>) override; // Test functions. void setPropertyConfigs( const std::vector<::aidl::android::hardware::automotive::vehicle::VehiclePropConfig>& configs); void addGetValueResponses( const std::vector<::aidl::android::hardware::automotive::vehicle::GetValueResult>& responses); void addSetValueResponses( const std::vector<::aidl::android::hardware::automotive::vehicle::SetValueResult>& responses); std::vector<::aidl::android::hardware::automotive::vehicle::GetValueRequest> nextGetValueRequests(); std::vector<::aidl::android::hardware::automotive::vehicle::SetValueRequest> nextSetValueRequests(); void setStatus(const char* functionName, ::aidl::android::hardware::automotive::vehicle::StatusCode status); void setSleepTime(int64_t timeInNano); private: mutable std::mutex mLock; mutable std::condition_variable mCv; mutable std::atomic<int> mThreadCount; std::vector<::aidl::android::hardware::automotive::vehicle::VehiclePropConfig> mPropertyConfigs GUARDED_BY(mLock); mutable std::list<std::vector<::aidl::android::hardware::automotive::vehicle::GetValueRequest>> mGetValueRequests GUARDED_BY(mLock); mutable std::list<std::vector<::aidl::android::hardware::automotive::vehicle::GetValueResult>> mGetValueResponses GUARDED_BY(mLock); mutable std::list<std::vector<::aidl::android::hardware::automotive::vehicle::SetValueRequest>> mSetValueRequests GUARDED_BY(mLock); mutable std::list<std::vector<::aidl::android::hardware::automotive::vehicle::SetValueResult>> mSetValueResponses GUARDED_BY(mLock); std::unordered_map<const char*, ::aidl::android::hardware::automotive::vehicle::StatusCode> mStatusByFunctions GUARDED_BY(mLock); int64_t mSleepTime GUARDED_BY(mLock) = 0; std::unique_ptr<const PropertyChangeCallback> mPropertyChangeCallback GUARDED_BY(mLock); template <class ResultType> ::aidl::android::hardware::automotive::vehicle::StatusCode returnResponse( std::shared_ptr<const std::function<void(std::vector<ResultType>)>> callback, std::list<std::vector<ResultType>>* storedResponses) const; template <class RequestType, class ResultType> ::aidl::android::hardware::automotive::vehicle::StatusCode handleRequestsLocked( const char* functionName, std::shared_ptr<const std::function<void(std::vector<ResultType>)>> callback, const std::vector<RequestType>& requests, std::list<std::vector<RequestType>>* storedRequests, std::list<std::vector<ResultType>>* storedResponses) const REQUIRES(mLock); }; } // namespace vehicle } // namespace automotive } // namespace hardware } // namespace android #endif // android_hardware_automotive_vehicle_aidl_impl_vhal_test_MockVehicleHardware_H_