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