1 /* 2 * Copyright (C) 2018 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 #define LOG_TAG "JsonFakeValueGenerator" 18 19 #include <fstream> 20 21 #include <log/log.h> 22 #include <vhal_v2_0/VehicleUtils.h> 23 24 #include "JsonFakeValueGenerator.h" 25 26 namespace android { 27 namespace hardware { 28 namespace automotive { 29 namespace vehicle { 30 namespace V2_0 { 31 32 namespace impl { 33 34 JsonFakeValueGenerator::JsonFakeValueGenerator(const OnHalEvent& onHalEvent) 35 : mOnHalEvent(onHalEvent), mThread(&JsonFakeValueGenerator::loop, this) {} 36 37 JsonFakeValueGenerator::~JsonFakeValueGenerator() { 38 mStopRequested = true; 39 { 40 MuxGuard g(mLock); 41 mGenCfg.index = 0; 42 mGenCfg.events.clear(); 43 } 44 mCond.notify_one(); 45 if (mThread.joinable()) { 46 mThread.join(); 47 } 48 } 49 50 StatusCode JsonFakeValueGenerator::start(const VehiclePropValue& request) { 51 const auto& v = request.value; 52 if (v.stringValue.empty()) { 53 ALOGE("%s: path to JSON file is missing", __func__); 54 return StatusCode::INVALID_ARG; 55 } 56 const char* file = v.stringValue.c_str(); 57 std::ifstream ifs(file); 58 if (!ifs) { 59 ALOGE("%s: couldn't open %s for parsing.", __func__, file); 60 return StatusCode::INTERNAL_ERROR; 61 } 62 std::vector<VehiclePropValue> fakeVhalEvents = parseFakeValueJson(ifs); 63 64 { 65 MuxGuard g(mLock); 66 mGenCfg = {0, fakeVhalEvents}; 67 } 68 mCond.notify_one(); 69 return StatusCode::OK; 70 } 71 72 StatusCode JsonFakeValueGenerator::stop(const VehiclePropValue& request) { 73 const auto& v = request.value; 74 if (!v.stringValue.empty()) { 75 ALOGI("%s: %s", __func__, v.stringValue.c_str()); 76 } 77 78 { 79 MuxGuard g(mLock); 80 mGenCfg.index = 0; 81 mGenCfg.events.clear(); 82 } 83 mCond.notify_one(); 84 return StatusCode::OK; 85 } 86 87 std::vector<VehiclePropValue> JsonFakeValueGenerator::parseFakeValueJson(std::istream& is) { 88 std::vector<VehiclePropValue> fakeVhalEvents; 89 90 Json::Reader reader; 91 Json::Value rawEvents; 92 if (!reader.parse(is, rawEvents)) { 93 ALOGE("%s: Failed to parse fake data JSON file. Error: %s", __func__, 94 reader.getFormattedErrorMessages().c_str()); 95 return fakeVhalEvents; 96 } 97 98 for (Json::Value::ArrayIndex i = 0; i < rawEvents.size(); i++) { 99 Json::Value rawEvent = rawEvents[i]; 100 if (!rawEvent.isObject()) { 101 ALOGE("%s: VHAL JSON event should be an object, %s", __func__, 102 rawEvent.toStyledString().c_str()); 103 continue; 104 } 105 if (rawEvent["prop"].empty() || rawEvent["areaId"].empty() || rawEvent["value"].empty() || 106 rawEvent["timestamp"].empty()) { 107 ALOGE("%s: VHAL JSON event has missing fields, skip it, %s", __func__, 108 rawEvent.toStyledString().c_str()); 109 continue; 110 } 111 VehiclePropValue event = {.prop = rawEvent["prop"].asInt(), 112 .areaId = rawEvent["areaId"].asInt(), 113 .timestamp = rawEvent["timestamp"].asInt64()}; 114 115 Json::Value rawEventValue = rawEvent["value"]; 116 auto& value = event.value; 117 switch (getPropType(event.prop)) { 118 case VehiclePropertyType::BOOLEAN: 119 case VehiclePropertyType::INT32: 120 value.int32Values.resize(1); 121 value.int32Values[0] = rawEventValue.asInt(); 122 break; 123 case VehiclePropertyType::INT64: 124 value.int64Values.resize(1); 125 value.int64Values[0] = rawEventValue.asInt64(); 126 break; 127 case VehiclePropertyType::FLOAT: 128 value.floatValues.resize(1); 129 value.floatValues[0] = rawEventValue.asFloat(); 130 break; 131 case VehiclePropertyType::STRING: 132 value.stringValue = rawEventValue.asString(); 133 break; 134 default: 135 ALOGE("%s: unsupported type for property: 0x%x with value: %s", __func__, 136 event.prop, rawEventValue.asString().c_str()); 137 continue; 138 } 139 fakeVhalEvents.push_back(event); 140 } 141 return fakeVhalEvents; 142 } 143 144 void JsonFakeValueGenerator::loop() { 145 static constexpr auto kInvalidTime = TimePoint(Nanos::max()); 146 147 while (!mStopRequested) { 148 auto nextEventTime = kInvalidTime; 149 { 150 MuxGuard g(mLock); 151 if (mGenCfg.index < mGenCfg.events.size()) { 152 mOnHalEvent(mGenCfg.events[mGenCfg.index]); 153 } 154 if (!mGenCfg.events.empty() && mGenCfg.index < mGenCfg.events.size() - 1) { 155 Nanos intervalNano = 156 static_cast<Nanos>(mGenCfg.events[mGenCfg.index + 1].timestamp - 157 mGenCfg.events[mGenCfg.index].timestamp); 158 nextEventTime = Clock::now() + intervalNano; 159 } 160 mGenCfg.index++; 161 } 162 163 std::unique_lock<std::mutex> g(mLock); 164 mCond.wait_until(g, nextEventTime); 165 } 166 } 167 168 } // namespace impl 169 170 } // namespace V2_0 171 } // namespace vehicle 172 } // namespace automotive 173 } // namespace hardware 174 } // namespace android 175