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