1 /*
2  * Copyright (C) 2020 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 "VehicleHalServer"
18 
19 #include "VehicleHalServer.h"
20 
21 #include <fstream>
22 
23 #include <android-base/logging.h>
24 #include <utils/SystemClock.h>
25 
26 #include "DefaultConfig.h"
27 #include "JsonFakeValueGenerator.h"
28 #include "LinearFakeValueGenerator.h"
29 #include "Obd2SensorStore.h"
30 
31 namespace android::hardware::automotive::vehicle::V2_0::impl {
32 
isDiagnosticProperty(VehiclePropConfig propConfig)33 static bool isDiagnosticProperty(VehiclePropConfig propConfig) {
34     switch (propConfig.prop) {
35         case OBD2_LIVE_FRAME:
36         case OBD2_FREEZE_FRAME:
37         case OBD2_FREEZE_FRAME_CLEAR:
38         case OBD2_FREEZE_FRAME_INFO:
39             return true;
40     }
41     return false;
42 }
43 
VehicleHalServer()44 VehicleHalServer::VehicleHalServer() {
45     constexpr bool shouldUpdateStatus = true;
46 
47     for (auto& it : kVehicleProperties) {
48         VehiclePropConfig cfg = it.config;
49 
50         mServerSidePropStore.registerProperty(cfg);
51 
52         if (isDiagnosticProperty(cfg)) {
53             continue;
54         }
55 
56         // A global property will have only a single area
57         int32_t numAreas = isGlobalProp(cfg.prop) ? 1 : cfg.areaConfigs.size();
58 
59         for (int i = 0; i < numAreas; i++) {
60             int32_t curArea = isGlobalProp(cfg.prop) ? 0 : cfg.areaConfigs[i].areaId;
61 
62             // Create a separate instance for each individual zone
63             VehiclePropValue prop = {
64                     .areaId = curArea,
65                     .prop = cfg.prop,
66             };
67 
68             if (it.initialAreaValues.empty()) {
69                 prop.value = it.initialValue;
70             } else if (auto valueForAreaIt = it.initialAreaValues.find(curArea);
71                        valueForAreaIt != it.initialAreaValues.end()) {
72                 prop.value = valueForAreaIt->second;
73             } else {
74                 LOG(WARNING) << __func__ << " failed to get default value for"
75                              << " prop 0x" << std::hex << cfg.prop << " area 0x" << std::hex
76                              << curArea;
77                 prop.status = VehiclePropertyStatus::UNAVAILABLE;
78             }
79 
80             mServerSidePropStore.writeValue(prop, shouldUpdateStatus);
81         }
82     }
83 }
84 
sendAllValuesToClient()85 void VehicleHalServer::sendAllValuesToClient() {
86     constexpr bool update_status = true;
87     auto values = mServerSidePropStore.readAllValues();
88     for (const auto& value : values) {
89         onPropertyValueFromCar(value, update_status);
90     }
91 }
92 
getGenerator()93 GeneratorHub* VehicleHalServer::getGenerator() {
94     return &mGeneratorHub;
95 }
96 
getValuePool() const97 VehiclePropValuePool* VehicleHalServer::getValuePool() const {
98     if (!mValuePool) {
99         LOG(WARNING) << __func__ << ": Value pool not set!";
100     }
101     return mValuePool;
102 }
103 
setValuePool(VehiclePropValuePool * valuePool)104 void VehicleHalServer::setValuePool(VehiclePropValuePool* valuePool) {
105     if (!valuePool) {
106         LOG(WARNING) << __func__ << ": Setting value pool to nullptr!";
107     }
108     mValuePool = valuePool;
109 }
110 
onFakeValueGenerated(const VehiclePropValue & value)111 void VehicleHalServer::onFakeValueGenerated(const VehiclePropValue& value) {
112     constexpr bool updateStatus = true;
113     LOG(DEBUG) << __func__ << ": " << toString(value);
114     auto updatedPropValue = getValuePool()->obtain(value);
115     if (updatedPropValue) {
116         updatedPropValue->timestamp = value.timestamp;
117         updatedPropValue->status = VehiclePropertyStatus::AVAILABLE;
118         mServerSidePropStore.writeValue(*updatedPropValue, updateStatus);
119         onPropertyValueFromCar(*updatedPropValue, updateStatus);
120     }
121 }
122 
onGetAllPropertyConfig() const123 std::vector<VehiclePropConfig> VehicleHalServer::onGetAllPropertyConfig() const {
124     return mServerSidePropStore.getAllConfigs();
125 }
126 
handleGenerateFakeDataRequest(const VehiclePropValue & request)127 StatusCode VehicleHalServer::handleGenerateFakeDataRequest(const VehiclePropValue& request) {
128     constexpr bool updateStatus = true;
129 
130     LOG(INFO) << __func__;
131     const auto& v = request.value;
132     if (!v.int32Values.size()) {
133         LOG(ERROR) << __func__ << ": expected at least \"command\" field in int32Values";
134         return StatusCode::INVALID_ARG;
135     }
136 
137     FakeDataCommand command = static_cast<FakeDataCommand>(v.int32Values[0]);
138 
139     switch (command) {
140         case FakeDataCommand::StartLinear: {
141             LOG(INFO) << __func__ << ", FakeDataCommand::StartLinear";
142             if (v.int32Values.size() < 2) {
143                 LOG(ERROR) << __func__ << ": expected property ID in int32Values";
144                 return StatusCode::INVALID_ARG;
145             }
146             if (!v.int64Values.size()) {
147                 LOG(ERROR) << __func__ << ": interval is not provided in int64Values";
148                 return StatusCode::INVALID_ARG;
149             }
150             if (v.floatValues.size() < 3) {
151                 LOG(ERROR) << __func__ << ": expected at least 3 elements in floatValues, got: "
152                            << v.floatValues.size();
153                 return StatusCode::INVALID_ARG;
154             }
155             int32_t cookie = v.int32Values[1];
156             getGenerator()->registerGenerator(cookie,
157                                               std::make_unique<LinearFakeValueGenerator>(request));
158             break;
159         }
160         case FakeDataCommand::StartJson: {
161             LOG(INFO) << __func__ << ", FakeDataCommand::StartJson";
162             if (v.stringValue.empty()) {
163                 LOG(ERROR) << __func__ << ": path to JSON file is missing";
164                 return StatusCode::INVALID_ARG;
165             }
166             int32_t cookie = std::hash<std::string>()(v.stringValue);
167             getGenerator()->registerGenerator(cookie,
168                                               std::make_unique<JsonFakeValueGenerator>(request));
169             break;
170         }
171         case FakeDataCommand::StopLinear: {
172             LOG(INFO) << __func__ << ", FakeDataCommand::StopLinear";
173             if (v.int32Values.size() < 2) {
174                 LOG(ERROR) << __func__ << ": expected property ID in int32Values";
175                 return StatusCode::INVALID_ARG;
176             }
177             int32_t cookie = v.int32Values[1];
178             getGenerator()->unregisterGenerator(cookie);
179             break;
180         }
181         case FakeDataCommand::StopJson: {
182             LOG(INFO) << __func__ << ", FakeDataCommand::StopJson";
183             if (v.stringValue.empty()) {
184                 LOG(ERROR) << __func__ << ": path to JSON file is missing";
185                 return StatusCode::INVALID_ARG;
186             }
187             int32_t cookie = std::hash<std::string>()(v.stringValue);
188             getGenerator()->unregisterGenerator(cookie);
189             break;
190         }
191         case FakeDataCommand::KeyPress: {
192             LOG(INFO) << __func__ << ", FakeDataCommand::KeyPress";
193             int32_t keyCode = request.value.int32Values[2];
194             int32_t display = request.value.int32Values[3];
195             // Send back to HAL
196             onPropertyValueFromCar(
197                     *createHwInputKeyProp(VehicleHwKeyInputAction::ACTION_DOWN, keyCode, display),
198                     updateStatus);
199             onPropertyValueFromCar(
200                     *createHwInputKeyProp(VehicleHwKeyInputAction::ACTION_UP, keyCode, display),
201                     updateStatus);
202             break;
203         }
204         default: {
205             LOG(ERROR) << __func__ << ": unexpected command: " << toInt(command);
206             return StatusCode::INVALID_ARG;
207         }
208     }
209     return StatusCode::OK;
210 }
211 
createApPowerStateReq(VehicleApPowerStateReq state,int32_t param)212 VehicleHalServer::VehiclePropValuePtr VehicleHalServer::createApPowerStateReq(
213         VehicleApPowerStateReq state, int32_t param) {
214     auto req = getValuePool()->obtain(VehiclePropertyType::INT32_VEC, 2);
215     req->prop = toInt(VehicleProperty::AP_POWER_STATE_REQ);
216     req->areaId = 0;
217     req->timestamp = elapsedRealtimeNano();
218     req->status = VehiclePropertyStatus::AVAILABLE;
219     req->value.int32Values[0] = toInt(state);
220     req->value.int32Values[1] = param;
221     return req;
222 }
223 
createHwInputKeyProp(VehicleHwKeyInputAction action,int32_t keyCode,int32_t targetDisplay)224 VehicleHalServer::VehiclePropValuePtr VehicleHalServer::createHwInputKeyProp(
225         VehicleHwKeyInputAction action, int32_t keyCode, int32_t targetDisplay) {
226     auto keyEvent = getValuePool()->obtain(VehiclePropertyType::INT32_VEC, 3);
227     keyEvent->prop = toInt(VehicleProperty::HW_KEY_INPUT);
228     keyEvent->areaId = 0;
229     keyEvent->timestamp = elapsedRealtimeNano();
230     keyEvent->status = VehiclePropertyStatus::AVAILABLE;
231     keyEvent->value.int32Values[0] = toInt(action);
232     keyEvent->value.int32Values[1] = keyCode;
233     keyEvent->value.int32Values[2] = targetDisplay;
234     return keyEvent;
235 }
236 
onSetProperty(const VehiclePropValue & value,bool updateStatus)237 StatusCode VehicleHalServer::onSetProperty(const VehiclePropValue& value, bool updateStatus) {
238     LOG(DEBUG) << "onSetProperty(" << value.prop << ")";
239 
240     // Some properties need to be treated non-trivially
241     switch (value.prop) {
242         case kGenerateFakeDataControllingProperty:
243             return handleGenerateFakeDataRequest(value);
244 
245         // set the value from vehicle side, used in end to end test.
246         case kSetIntPropertyFromVehicleForTest: {
247             auto updatedPropValue = createVehiclePropValue(VehiclePropertyType::INT32, 1);
248             updatedPropValue->prop = value.value.int32Values[0];
249             updatedPropValue->value.int32Values[0] = value.value.int32Values[1];
250             updatedPropValue->timestamp = value.value.int64Values[0];
251             updatedPropValue->areaId = value.areaId;
252             onPropertyValueFromCar(*updatedPropValue, updateStatus);
253             return StatusCode::OK;
254         }
255         case kSetFloatPropertyFromVehicleForTest: {
256             auto updatedPropValue = createVehiclePropValue(VehiclePropertyType::FLOAT, 1);
257             updatedPropValue->prop = value.value.int32Values[0];
258             updatedPropValue->value.floatValues[0] = value.value.floatValues[0];
259             updatedPropValue->timestamp = value.value.int64Values[0];
260             updatedPropValue->areaId = value.areaId;
261             onPropertyValueFromCar(*updatedPropValue, updateStatus);
262             return StatusCode::OK;
263         }
264         case kSetBooleanPropertyFromVehicleForTest: {
265             auto updatedPropValue = createVehiclePropValue(VehiclePropertyType::BOOLEAN, 1);
266             updatedPropValue->prop = value.value.int32Values[1];
267             updatedPropValue->value.int32Values[0] = value.value.int32Values[0];
268             updatedPropValue->timestamp = value.value.int64Values[0];
269             updatedPropValue->areaId = value.areaId;
270             onPropertyValueFromCar(*updatedPropValue, updateStatus);
271             return StatusCode::OK;
272         }
273 
274         case AP_POWER_STATE_REPORT:
275             switch (value.value.int32Values[0]) {
276                 case toInt(VehicleApPowerStateReport::DEEP_SLEEP_EXIT):
277                 case toInt(VehicleApPowerStateReport::SHUTDOWN_CANCELLED):
278                 case toInt(VehicleApPowerStateReport::WAIT_FOR_VHAL):
279                     // CPMS is in WAIT_FOR_VHAL state, simply move to ON
280                     // Send back to HAL
281                     // ALWAYS update status for generated property value
282                     onPropertyValueFromCar(*createApPowerStateReq(VehicleApPowerStateReq::ON, 0),
283                                            true /* updateStatus */);
284                     break;
285                 case toInt(VehicleApPowerStateReport::DEEP_SLEEP_ENTRY):
286                 case toInt(VehicleApPowerStateReport::SHUTDOWN_START):
287                     // CPMS is in WAIT_FOR_FINISH state, send the FINISHED command
288                     // Send back to HAL
289                     // ALWAYS update status for generated property value
290                     onPropertyValueFromCar(
291                             *createApPowerStateReq(VehicleApPowerStateReq::FINISHED, 0),
292                             true /* updateStatus */);
293                     break;
294                 case toInt(VehicleApPowerStateReport::ON):
295                 case toInt(VehicleApPowerStateReport::SHUTDOWN_POSTPONE):
296                 case toInt(VehicleApPowerStateReport::SHUTDOWN_PREPARE):
297                     // Do nothing
298                     break;
299                 default:
300                     // Unknown state
301                     break;
302             }
303             break;
304 
305 #ifdef ENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING
306         case toInt(VehicleProperty::CLUSTER_REPORT_STATE):
307         case toInt(VehicleProperty::CLUSTER_REQUEST_DISPLAY):
308         case toInt(VehicleProperty::CLUSTER_NAVIGATION_STATE):
309         case VENDOR_CLUSTER_SWITCH_UI:
310         case VENDOR_CLUSTER_DISPLAY_STATE: {
311             auto updatedPropValue = createVehiclePropValue(getPropType(value.prop), 0);
312             updatedPropValue->prop = value.prop & ~toInt(VehiclePropertyGroup::MASK);
313             if (isSystemProperty(value.prop)) {
314                 updatedPropValue->prop |= toInt(VehiclePropertyGroup::VENDOR);
315             } else {
316                 updatedPropValue->prop |= toInt(VehiclePropertyGroup::SYSTEM);
317             }
318             updatedPropValue->value = value.value;
319             updatedPropValue->timestamp = elapsedRealtimeNano();
320             updatedPropValue->areaId = value.areaId;
321             onPropertyValueFromCar(*updatedPropValue, updateStatus);
322             return StatusCode::OK;
323         }
324 #endif  // ENABLE_VENDOR_CLUSTER_PROPERTY_FOR_TESTING
325 
326         default:
327             break;
328     }
329 
330     // In the real vhal, the value will be sent to Car ECU.
331     // We just pretend it is done here and send back to HAL
332     auto updatedPropValue = getValuePool()->obtain(value);
333     updatedPropValue->timestamp = elapsedRealtimeNano();
334 
335     mServerSidePropStore.writeValue(*updatedPropValue, updateStatus);
336     onPropertyValueFromCar(*updatedPropValue, updateStatus);
337     return StatusCode::OK;
338 }
339 
340 }  // namespace android::hardware::automotive::vehicle::V2_0::impl
341