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