1 /* 2 * Copyright (C) 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef android_hardware_automotive_vehicle_V2_0_impl_FakeHalEventGenerator_H_ 18 #define android_hardware_automotive_vehicle_V2_0_impl_FakeHalEventGenerator_H_ 19 20 #include <chrono> 21 22 #include <android/hardware/automotive/vehicle/2.0/types.h> 23 24 #include <vhal_v2_0/RecurrentTimer.h> 25 26 namespace android { 27 namespace hardware { 28 namespace automotive { 29 namespace vehicle { 30 namespace V2_0 { 31 32 namespace impl { 33 34 class FakeValueGenerator { 35 private: 36 // In every timer tick we may want to generate new value based on initial value for debug 37 // purpose. It's better to have sequential values to see if events gets delivered in order 38 // to the client. 39 40 struct GeneratorCfg { 41 float initialValue; // 42 float currentValue; // Should be in range (initialValue +/- dispersion). 43 float dispersion; // Defines minimum and maximum value based on initial value. 44 float increment; // Value that we will be added to currentValue with each timer tick. 45 }; 46 47 public: 48 using OnHalEvent = std::function<void(int32_t propId, float value)>; 49 50 FakeValueGenerator(const OnHalEvent& onHalEvent) : 51 mOnHalEvent(onHalEvent), 52 mRecurrentTimer(std::bind(&FakeValueGenerator::onTimer, this, 53 std::placeholders::_1)) 54 {} 55 56 ~FakeValueGenerator() = default; 57 58 59 void startGeneratingHalEvents(std::chrono::nanoseconds interval, int propId, float initialValue, 60 float dispersion, float increment) { 61 MuxGuard g(mLock); 62 63 removeLocked(propId); 64 65 mGenCfg.insert({propId, GeneratorCfg { 66 .initialValue = initialValue, 67 .currentValue = initialValue, 68 .dispersion = dispersion, 69 .increment = increment, 70 }}); 71 72 mRecurrentTimer.registerRecurrentEvent(interval, propId); 73 } 74 75 void stopGeneratingHalEvents(int propId) { 76 MuxGuard g(mLock); 77 if (propId == 0) { 78 // Remove all. 79 for (auto&& it : mGenCfg) { 80 removeLocked(it.first); 81 } 82 } else { 83 removeLocked(propId); 84 } 85 } 86 87 private: 88 void removeLocked(int propId) { 89 if (mGenCfg.erase(propId)) { 90 mRecurrentTimer.unregisterRecurrentEvent(propId); 91 } 92 } 93 94 void onTimer(const std::vector<int32_t>& properties) { 95 MuxGuard g(mLock); 96 97 for (int32_t propId : properties) { 98 auto& cfg = mGenCfg[propId]; 99 cfg.currentValue += cfg.increment; 100 if (cfg.currentValue > cfg.initialValue + cfg.dispersion) { 101 cfg.currentValue = cfg.initialValue - cfg.dispersion; 102 } 103 mOnHalEvent(propId, cfg.currentValue); 104 } 105 } 106 107 private: 108 using MuxGuard = std::lock_guard<std::mutex>; 109 110 mutable std::mutex mLock; 111 OnHalEvent mOnHalEvent; 112 RecurrentTimer mRecurrentTimer; 113 std::unordered_map<int32_t, GeneratorCfg> mGenCfg; 114 }; 115 116 117 } // impl 118 119 } // namespace V2_0 120 } // namespace vehicle 121 } // namespace automotive 122 } // namespace hardware 123 } // namespace android 124 125 126 127 #endif //android_hardware_automotive_vehicle_V2_0_impl_FakeHalEventGenerator_H_ 128