xref: /aosp_15_r20/hardware/interfaces/automotive/vehicle/2.0/default/impl/vhal_v2_0/JsonFakeValueGenerator.cpp (revision 4d7e907c777eeecc4c5bd7cf640a754fac206ff7)
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 #include <type_traits>
21 #include <typeinfo>
22 
23 #include <log/log.h>
24 #include <vhal_v2_0/VehicleUtils.h>
25 
26 #include "JsonFakeValueGenerator.h"
27 
28 namespace android {
29 namespace hardware {
30 namespace automotive {
31 namespace vehicle {
32 namespace V2_0 {
33 
34 namespace impl {
35 
JsonFakeValueGenerator(const std::string & path,int32_t repetition)36 JsonFakeValueGenerator::JsonFakeValueGenerator(const std::string& path, int32_t repetition) {
37     const char* file = path.c_str();
38     std::ifstream ifs(file);
39     if (!ifs) {
40         ALOGE("%s: couldn't open %s for parsing.", __func__, file);
41         mGenCfg = {
42                 .index = 0,
43                 .events = {},
44         };
45         mNumOfIterations = 0;
46         return;
47     }
48     mGenCfg = {
49             .index = 0,
50             .events = parseFakeValueJson(ifs),
51     };
52     mNumOfIterations = repetition;
53 }
54 
JsonFakeValueGenerator(const VehiclePropValue & request)55 JsonFakeValueGenerator::JsonFakeValueGenerator(const VehiclePropValue& request) {
56     const auto& v = request.value;
57     const char* file = v.stringValue.c_str();
58     std::ifstream ifs(file);
59     if (!ifs) {
60         ALOGE("%s: couldn't open %s for parsing.", __func__, file);
61         mGenCfg = {
62                 .index = 0,
63                 .events = {},
64         };
65         mNumOfIterations = 0;
66         return;
67     }
68     mGenCfg = {
69         .index = 0,
70         .events = parseFakeValueJson(ifs),
71     };
72     // Iterate infinitely if repetition number is not provided
73     mNumOfIterations = v.int32Values.size() < 2 ? -1 : v.int32Values[1];
74 }
75 
JsonFakeValueGenerator(const std::string & path)76 JsonFakeValueGenerator::JsonFakeValueGenerator(const std::string& path) {
77     std::ifstream ifs(path);
78     if (!ifs) {
79         ALOGE("%s: couldn't open %s for parsing.", __func__, path.c_str());
80         mGenCfg = {
81                 .index = 0,
82                 .events = {},
83         };
84         mNumOfIterations = 0;
85         return;
86     }
87     mGenCfg = {
88         .index = 0,
89         .events = parseFakeValueJson(ifs),
90     };
91     mNumOfIterations = mGenCfg.events.size();
92 }
93 
getAllEvents()94 std::vector<VehiclePropValue> JsonFakeValueGenerator::getAllEvents() {
95     return mGenCfg.events;
96 }
97 
nextEvent()98 VehiclePropValue JsonFakeValueGenerator::nextEvent() {
99     VehiclePropValue generatedValue;
100     if (!hasNext()) {
101         return generatedValue;
102     }
103     TimePoint eventTime = Clock::now();
104     if (mGenCfg.index != 0) {
105         // All events (start from 2nd one) are supposed to happen in the future with a delay
106         // equals to the duration between previous and current event.
107         eventTime += Nanos(mGenCfg.events[mGenCfg.index].timestamp -
108                            mGenCfg.events[mGenCfg.index - 1].timestamp);
109     }
110     generatedValue = mGenCfg.events[mGenCfg.index];
111     generatedValue.timestamp = eventTime.time_since_epoch().count();
112 
113     mGenCfg.index++;
114     if (mGenCfg.index == mGenCfg.events.size()) {
115         mGenCfg.index = 0;
116         if (mNumOfIterations > 0) {
117             mNumOfIterations--;
118         }
119     }
120     return generatedValue;
121 }
122 
hasNext()123 bool JsonFakeValueGenerator::hasNext() {
124     return mNumOfIterations != 0 && mGenCfg.events.size() > 0;
125 }
126 
parseFakeValueJson(std::istream & is)127 std::vector<VehiclePropValue> JsonFakeValueGenerator::parseFakeValueJson(std::istream& is) {
128     std::vector<VehiclePropValue> fakeVhalEvents;
129 
130     Json::CharReaderBuilder builder;
131     Json::Value rawEvents;
132     std::string errorMessage;
133     if (!Json::parseFromStream(builder, is, &rawEvents, &errorMessage)) {
134         ALOGE("%s: Failed to parse fake data JSON file. Error: %s", __func__,
135               errorMessage.c_str());
136         return fakeVhalEvents;
137     }
138 
139     for (Json::Value::ArrayIndex i = 0; i < rawEvents.size(); i++) {
140         Json::Value rawEvent = rawEvents[i];
141         if (!rawEvent.isObject()) {
142             ALOGE("%s: VHAL JSON event should be an object, %s", __func__,
143                   rawEvent.toStyledString().c_str());
144             continue;
145         }
146         if (rawEvent["prop"].empty() || rawEvent["areaId"].empty() || rawEvent["value"].empty() ||
147             rawEvent["timestamp"].empty()) {
148             ALOGE("%s: VHAL JSON event has missing fields, skip it, %s", __func__,
149                   rawEvent.toStyledString().c_str());
150             continue;
151         }
152         VehiclePropValue event = {
153                 .timestamp = rawEvent["timestamp"].asInt64(),
154                 .areaId = rawEvent["areaId"].asInt(),
155                 .prop = rawEvent["prop"].asInt(),
156         };
157 
158         Json::Value rawEventValue = rawEvent["value"];
159         auto& value = event.value;
160         int32_t count;
161         switch (getPropType(event.prop)) {
162             case VehiclePropertyType::BOOLEAN:
163             case VehiclePropertyType::INT32:
164                 value.int32Values.resize(1);
165                 value.int32Values[0] = rawEventValue.asInt();
166                 break;
167             case VehiclePropertyType::INT64:
168                 value.int64Values.resize(1);
169                 value.int64Values[0] = rawEventValue.asInt64();
170                 break;
171             case VehiclePropertyType::FLOAT:
172                 value.floatValues.resize(1);
173                 value.floatValues[0] = rawEventValue.asFloat();
174                 break;
175             case VehiclePropertyType::STRING:
176                 value.stringValue = rawEventValue.asString();
177                 break;
178             case VehiclePropertyType::INT32_VEC:
179                 value.int32Values.resize(rawEventValue.size());
180                 count = 0;
181                 for (auto& it : rawEventValue) {
182                     value.int32Values[count++] = it.asInt();
183                 }
184                 break;
185             case VehiclePropertyType::MIXED:
186                 copyMixedValueJson(value, rawEventValue);
187                 if (isDiagnosticProperty(event.prop)) {
188                     value.bytes = generateDiagnosticBytes(value);
189                 }
190                 break;
191             default:
192                 ALOGE("%s: unsupported type for property: 0x%x", __func__, event.prop);
193                 continue;
194         }
195         fakeVhalEvents.push_back(event);
196     }
197     return fakeVhalEvents;
198 }
199 
copyMixedValueJson(VehiclePropValue::RawValue & dest,const Json::Value & jsonValue)200 void JsonFakeValueGenerator::copyMixedValueJson(VehiclePropValue::RawValue& dest,
201                                                 const Json::Value& jsonValue) {
202     copyJsonArray(dest.int32Values, jsonValue["int32Values"]);
203     copyJsonArray(dest.int64Values, jsonValue["int64Values"]);
204     copyJsonArray(dest.floatValues, jsonValue["floatValues"]);
205     dest.stringValue = jsonValue["stringValue"].asString();
206 }
207 
208 template <typename T>
copyJsonArray(hidl_vec<T> & dest,const Json::Value & jsonArray)209 void JsonFakeValueGenerator::copyJsonArray(hidl_vec<T>& dest, const Json::Value& jsonArray) {
210     dest.resize(jsonArray.size());
211     for (Json::Value::ArrayIndex i = 0; i < jsonArray.size(); i++) {
212         if (std::is_same<T, int32_t>::value) {
213             dest[i] = jsonArray[i].asInt();
214         } else if (std::is_same<T, int64_t>::value) {
215             dest[i] = jsonArray[i].asInt64();
216         } else if (std::is_same<T, float>::value) {
217             dest[i] = jsonArray[i].asFloat();
218         }
219     }
220 }
221 
isDiagnosticProperty(int32_t prop)222 bool JsonFakeValueGenerator::isDiagnosticProperty(int32_t prop) {
223     return prop == (int32_t)VehicleProperty::OBD2_LIVE_FRAME ||
224            prop == (int32_t)VehicleProperty::OBD2_FREEZE_FRAME;
225 }
226 
generateDiagnosticBytes(const VehiclePropValue::RawValue & diagnosticValue)227 hidl_vec<uint8_t> JsonFakeValueGenerator::generateDiagnosticBytes(
228     const VehiclePropValue::RawValue& diagnosticValue) {
229     size_t byteSize = ((size_t)DiagnosticIntegerSensorIndex::LAST_SYSTEM_INDEX +
230                        (size_t)DiagnosticFloatSensorIndex::LAST_SYSTEM_INDEX + 2);
231     hidl_vec<uint8_t> bytes(byteSize % 8 == 0 ? byteSize / 8 : byteSize / 8 + 1);
232 
233     auto& int32Values = diagnosticValue.int32Values;
234     for (size_t i = 0; i < int32Values.size(); i++) {
235         if (int32Values[i] != 0) {
236             setBit(bytes, i);
237         }
238     }
239 
240     auto& floatValues = diagnosticValue.floatValues;
241     for (size_t i = 0; i < floatValues.size(); i++) {
242         if (floatValues[i] != 0.0) {
243             setBit(bytes, i + (size_t)DiagnosticIntegerSensorIndex::LAST_SYSTEM_INDEX + 1);
244         }
245     }
246     return bytes;
247 }
248 
setBit(hidl_vec<uint8_t> & bytes,size_t idx)249 void JsonFakeValueGenerator::setBit(hidl_vec<uint8_t>& bytes, size_t idx) {
250     uint8_t mask = 1 << (idx % 8);
251     bytes[idx / 8] |= mask;
252 }
253 
254 }  // namespace impl
255 
256 }  // namespace V2_0
257 }  // namespace vehicle
258 }  // namespace automotive
259 }  // namespace hardware
260 }  // namespace android
261