/* * Copyright (C) 2016 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_V2_0_VehicleDebugUtils_H_ #define android_hardware_automotive_vehicle_V2_0_VehicleDebugUtils_H_ #include #include #include #include "vhal_v2_0/VehicleUtils.h" namespace android { namespace hardware { namespace automotive { namespace vehicle { namespace V2_0 { constexpr int32_t kCustomComplexProperty = 0xbeef | VehiclePropertyGroup::VENDOR | VehiclePropertyType::COMPLEX | VehicleArea::GLOBAL; const VehiclePropConfig kVehicleProperties[] = { { .prop = toInt(VehicleProperty::INFO_MAKE), .access = VehiclePropertyAccess::READ, .changeMode = VehiclePropertyChangeMode::STATIC, .configString = "Some=config,options=if,you=have_any", }, { .prop = toInt(VehicleProperty::HVAC_FAN_SPEED), .access = VehiclePropertyAccess::READ_WRITE, .changeMode = VehiclePropertyChangeMode::ON_CHANGE, .supportedAreas = static_cast( VehicleAreaZone::ROW_1_LEFT | VehicleAreaZone::ROW_1_RIGHT), .areaConfigs = { VehicleAreaConfig { .areaId = toInt(VehicleAreaZone::ROW_1_LEFT), .minInt32Value = 1, .maxInt32Value = 7}, VehicleAreaConfig { .areaId = toInt(VehicleAreaZone::ROW_1_RIGHT), .minInt32Value = 1, .maxInt32Value = 5, } } }, // Write-only property { .prop = toInt(VehicleProperty::HVAC_SEAT_TEMPERATURE), .access = VehiclePropertyAccess::WRITE, .changeMode = VehiclePropertyChangeMode::ON_SET, .supportedAreas = static_cast( VehicleAreaZone::ROW_1_LEFT | VehicleAreaZone::ROW_1_RIGHT), .areaConfigs = { VehicleAreaConfig { .areaId = toInt(VehicleAreaZone::ROW_1_LEFT), .minInt32Value = 64, .maxInt32Value = 80}, VehicleAreaConfig { .areaId = toInt(VehicleAreaZone::ROW_1_RIGHT), .minInt32Value = 64, .maxInt32Value = 80, } } }, { .prop = toInt(VehicleProperty::INFO_FUEL_CAPACITY), .access = VehiclePropertyAccess::READ, .changeMode = VehiclePropertyChangeMode::ON_CHANGE, .areaConfigs = { VehicleAreaConfig { .minFloatValue = 0, .maxFloatValue = 1.0 } } }, { .prop = toInt(VehicleProperty::DISPLAY_BRIGHTNESS), .access = VehiclePropertyAccess::READ_WRITE, .changeMode = VehiclePropertyChangeMode::ON_CHANGE, .areaConfigs = { VehicleAreaConfig { .minInt32Value = 0, .maxInt32Value = 10 } } }, { .prop = toInt(VehicleProperty::MIRROR_FOLD), .access = VehiclePropertyAccess::READ_WRITE, .changeMode = VehiclePropertyChangeMode::ON_CHANGE, }, // Complex data type. { .prop = kCustomComplexProperty, .access = VehiclePropertyAccess::READ_WRITE, .changeMode = VehiclePropertyChangeMode::ON_CHANGE } }; constexpr auto kTimeout = std::chrono::milliseconds(500); class MockedVehicleCallback : public IVehicleCallback { private: using MuxGuard = std::lock_guard; using HidlVecOfValues = hidl_vec; public: // Methods from ::android::hardware::automotive::vehicle::V2_0::IVehicleCallback follow. Return onPropertyEvent( const hidl_vec& values) override { { MuxGuard g(mLock); mReceivedEvents.push_back(values); } mEventCond.notify_one(); return Return(); } Return onPropertySet(const VehiclePropValue& /* value */) override { return Return(); } Return onPropertySetError(StatusCode /* errorCode */, int32_t /* propId */, int32_t /* areaId */) override { return Return(); } bool waitForExpectedEvents(size_t expectedEvents) { std::unique_lock g(mLock); if (expectedEvents == 0 && mReceivedEvents.size() == 0) { // No events expected, let's sleep a little bit to make sure // nothing will show up. return mEventCond.wait_for(g, kTimeout) == std::cv_status::timeout; } while (expectedEvents != mReceivedEvents.size()) { if (mEventCond.wait_for(g, kTimeout) == std::cv_status::timeout) { return false; } } return true; } void reset() { mReceivedEvents.clear(); } const std::vector& getReceivedEvents() { return mReceivedEvents; } private: std::mutex mLock; std::condition_variable mEventCond; std::vector mReceivedEvents; }; template inline std::string hexString(T value) { std::stringstream ss; ss << std::showbase << std::hex << value; return ss.str(); } template inline void assertAllExistsAnyOrder( std::initializer_list expected, const Collection& actual, const char* msg) { std::set expectedSet = expected; for (auto a: actual) { ASSERT_EQ(1u, expectedSet.erase(a)) << msg << "\nContains not unexpected value.\n"; } ASSERT_EQ(0u, expectedSet.size()) << msg << "\nDoesn't contain expected value."; } #define ASSERT_ALL_EXISTS(...) \ assertAllExistsAnyOrder(__VA_ARGS__, (std::string("Called from: ") + \ std::string(__FILE__) + std::string(":") + \ std::to_string(__LINE__)).c_str()); \ template inline std::string enumToHexString(T value) { return hexString(toInt(value)); } template inline std::string vecToString(const hidl_vec& vec) { std::stringstream ss("["); for (size_t i = 0; i < vec.size(); i++) { if (i != 0) ss << ","; ss << vec[i]; } ss << "]"; return ss.str(); } inline std::string toString(const VehiclePropValue &v) { std::stringstream ss; ss << "VehiclePropValue {n" << " prop: " << hexString(v.prop) << ",\n" << " areaId: " << hexString(v.areaId) << ",\n" << " timestamp: " << v.timestamp << ",\n" << " value {\n" << " int32Values: " << vecToString(v.value.int32Values) << ",\n" << " floatValues: " << vecToString(v.value.floatValues) << ",\n" << " int64Values: " << vecToString(v.value.int64Values) << ",\n" << " bytes: " << vecToString(v.value.bytes) << ",\n" << " string: " << v.value.stringValue.c_str() << ",\n" << " }\n" << "}\n"; return ss.str(); } inline std::string toString(const VehiclePropConfig &config) { std::stringstream ss; ss << "VehiclePropConfig {\n" << " prop: " << hexString(config.prop) << ",\n" << " supportedAreas: " << hexString(config.supportedAreas) << ",\n" << " access: " << enumToHexString(config.access) << ",\n" << " changeMode: " << enumToHexString(config.changeMode) << ",\n" << " configFlags: " << hexString(config.configFlags) << ",\n" << " minSampleRate: " << config.minSampleRate << ",\n" << " maxSampleRate: " << config.maxSampleRate << ",\n" << " configString: " << config.configString.c_str() << ",\n"; ss << " areaConfigs {\n"; for (size_t i = 0; i < config.areaConfigs.size(); i++) { const auto &area = config.areaConfigs[i]; ss << " areaId: " << hexString(area.areaId) << ",\n" << " minFloatValue: " << area.minFloatValue << ",\n" << " minFloatValue: " << area.maxFloatValue << ",\n" << " minInt32Value: " << area.minInt32Value << ",\n" << " minInt32Value: " << area.maxInt32Value << ",\n" << " minInt64Value: " << area.minInt64Value << ",\n" << " minInt64Value: " << area.maxInt64Value << ",\n"; } ss << " }\n" << "}\n"; return ss.str(); } } // namespace V2_0 } // namespace vehicle } // namespace automotive } // namespace hardware } // namespace android #endif //android_hardware_automotive_vehicle_V2_0_VehicleDebugUtils_H_