• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
getGenerator()33 GeneratorHub* VehicleHalServer::getGenerator() {
34     return &mGeneratorHub;
35 }
36 
getValuePool() const37 VehiclePropValuePool* VehicleHalServer::getValuePool() const {
38     if (!mValuePool) {
39         LOG(WARNING) << __func__ << ": Value pool not set!";
40     }
41     return mValuePool;
42 }
43 
setValuePool(VehiclePropValuePool * valuePool)44 void VehicleHalServer::setValuePool(VehiclePropValuePool* valuePool) {
45     if (!valuePool) {
46         LOG(WARNING) << __func__ << ": Setting value pool to nullptr!";
47     }
48     mValuePool = valuePool;
49 }
50 
onFakeValueGenerated(const VehiclePropValue & value)51 void VehicleHalServer::onFakeValueGenerated(const VehiclePropValue& value) {
52     constexpr bool updateStatus = true;
53     LOG(DEBUG) << __func__ << ": " << toString(value);
54     auto updatedPropValue = getValuePool()->obtain(value);
55     if (updatedPropValue) {
56         updatedPropValue->timestamp = value.timestamp;
57         updatedPropValue->status = VehiclePropertyStatus::AVAILABLE;
58         onPropertyValueFromCar(*updatedPropValue, updateStatus);
59     }
60 }
61 
onGetAllPropertyConfig() const62 std::vector<VehiclePropConfig> VehicleHalServer::onGetAllPropertyConfig() const {
63     std::vector<VehiclePropConfig> vehiclePropConfigs;
64     constexpr size_t numOfVehiclePropConfigs =
65             sizeof(kVehicleProperties) / sizeof(kVehicleProperties[0]);
66     vehiclePropConfigs.reserve(numOfVehiclePropConfigs);
67     for (auto& it : kVehicleProperties) {
68         vehiclePropConfigs.emplace_back(it.config);
69     }
70     return vehiclePropConfigs;
71 }
72 
handleGenerateFakeDataRequest(const VehiclePropValue & request)73 StatusCode VehicleHalServer::handleGenerateFakeDataRequest(const VehiclePropValue& request) {
74     constexpr bool updateStatus = true;
75 
76     LOG(INFO) << __func__;
77     const auto& v = request.value;
78     if (!v.int32Values.size()) {
79         LOG(ERROR) << __func__ << ": expected at least \"command\" field in int32Values";
80         return StatusCode::INVALID_ARG;
81     }
82 
83     FakeDataCommand command = static_cast<FakeDataCommand>(v.int32Values[0]);
84 
85     switch (command) {
86         case FakeDataCommand::StartLinear: {
87             LOG(INFO) << __func__ << ", FakeDataCommand::StartLinear";
88             if (v.int32Values.size() < 2) {
89                 LOG(ERROR) << __func__ << ": expected property ID in int32Values";
90                 return StatusCode::INVALID_ARG;
91             }
92             if (!v.int64Values.size()) {
93                 LOG(ERROR) << __func__ << ": interval is not provided in int64Values";
94                 return StatusCode::INVALID_ARG;
95             }
96             if (v.floatValues.size() < 3) {
97                 LOG(ERROR) << __func__ << ": expected at least 3 elements in floatValues, got: "
98                            << v.floatValues.size();
99                 return StatusCode::INVALID_ARG;
100             }
101             int32_t cookie = v.int32Values[1];
102             getGenerator()->registerGenerator(cookie,
103                                               std::make_unique<LinearFakeValueGenerator>(request));
104             break;
105         }
106         case FakeDataCommand::StartJson: {
107             LOG(INFO) << __func__ << ", FakeDataCommand::StartJson";
108             if (v.stringValue.empty()) {
109                 LOG(ERROR) << __func__ << ": path to JSON file is missing";
110                 return StatusCode::INVALID_ARG;
111             }
112             int32_t cookie = std::hash<std::string>()(v.stringValue);
113             getGenerator()->registerGenerator(cookie,
114                                               std::make_unique<JsonFakeValueGenerator>(request));
115             break;
116         }
117         case FakeDataCommand::StopLinear: {
118             LOG(INFO) << __func__ << ", FakeDataCommand::StopLinear";
119             if (v.int32Values.size() < 2) {
120                 LOG(ERROR) << __func__ << ": expected property ID in int32Values";
121                 return StatusCode::INVALID_ARG;
122             }
123             int32_t cookie = v.int32Values[1];
124             getGenerator()->unregisterGenerator(cookie);
125             break;
126         }
127         case FakeDataCommand::StopJson: {
128             LOG(INFO) << __func__ << ", FakeDataCommand::StopJson";
129             if (v.stringValue.empty()) {
130                 LOG(ERROR) << __func__ << ": path to JSON file is missing";
131                 return StatusCode::INVALID_ARG;
132             }
133             int32_t cookie = std::hash<std::string>()(v.stringValue);
134             getGenerator()->unregisterGenerator(cookie);
135             break;
136         }
137         case FakeDataCommand::KeyPress: {
138             LOG(INFO) << __func__ << ", FakeDataCommand::KeyPress";
139             int32_t keyCode = request.value.int32Values[2];
140             int32_t display = request.value.int32Values[3];
141             // Send back to HAL
142             onPropertyValueFromCar(
143                     *createHwInputKeyProp(VehicleHwKeyInputAction::ACTION_DOWN, keyCode, display),
144                     updateStatus);
145             onPropertyValueFromCar(
146                     *createHwInputKeyProp(VehicleHwKeyInputAction::ACTION_UP, keyCode, display),
147                     updateStatus);
148             break;
149         }
150         default: {
151             LOG(ERROR) << __func__ << ": unexpected command: " << toInt(command);
152             return StatusCode::INVALID_ARG;
153         }
154     }
155     return StatusCode::OK;
156 }
157 
createApPowerStateReq(VehicleApPowerStateReq state,int32_t param)158 VehicleHalServer::VehiclePropValuePtr VehicleHalServer::createApPowerStateReq(
159         VehicleApPowerStateReq state, int32_t param) {
160     auto req = getValuePool()->obtain(VehiclePropertyType::INT32_VEC, 2);
161     req->prop = toInt(VehicleProperty::AP_POWER_STATE_REQ);
162     req->areaId = 0;
163     req->timestamp = elapsedRealtimeNano();
164     req->status = VehiclePropertyStatus::AVAILABLE;
165     req->value.int32Values[0] = toInt(state);
166     req->value.int32Values[1] = param;
167     return req;
168 }
169 
createHwInputKeyProp(VehicleHwKeyInputAction action,int32_t keyCode,int32_t targetDisplay)170 VehicleHalServer::VehiclePropValuePtr VehicleHalServer::createHwInputKeyProp(
171         VehicleHwKeyInputAction action, int32_t keyCode, int32_t targetDisplay) {
172     auto keyEvent = getValuePool()->obtain(VehiclePropertyType::INT32_VEC, 3);
173     keyEvent->prop = toInt(VehicleProperty::HW_KEY_INPUT);
174     keyEvent->areaId = 0;
175     keyEvent->timestamp = elapsedRealtimeNano();
176     keyEvent->status = VehiclePropertyStatus::AVAILABLE;
177     keyEvent->value.int32Values[0] = toInt(action);
178     keyEvent->value.int32Values[1] = keyCode;
179     keyEvent->value.int32Values[2] = targetDisplay;
180     return keyEvent;
181 }
182 
onSetProperty(const VehiclePropValue & value,bool updateStatus)183 StatusCode VehicleHalServer::onSetProperty(const VehiclePropValue& value, bool updateStatus) {
184     LOG(DEBUG) << "onSetProperty(" << value.prop << ")";
185 
186     // Some properties need to be treated non-trivially
187     switch (value.prop) {
188         case kGenerateFakeDataControllingProperty:
189             return handleGenerateFakeDataRequest(value);
190 
191         // set the value from vehicle side, used in end to end test.
192         case kSetIntPropertyFromVehicleForTest: {
193             auto updatedPropValue = createVehiclePropValue(VehiclePropertyType::INT32, 1);
194             updatedPropValue->prop = value.value.int32Values[0];
195             updatedPropValue->value.int32Values[0] = value.value.int32Values[1];
196             updatedPropValue->timestamp = value.value.int64Values[0];
197             updatedPropValue->areaId = value.areaId;
198             onPropertyValueFromCar(*updatedPropValue, updateStatus);
199             return StatusCode::OK;
200         }
201         case kSetFloatPropertyFromVehicleForTest: {
202             auto updatedPropValue = createVehiclePropValue(VehiclePropertyType::FLOAT, 1);
203             updatedPropValue->prop = value.value.int32Values[0];
204             updatedPropValue->value.floatValues[0] = value.value.floatValues[0];
205             updatedPropValue->timestamp = value.value.int64Values[0];
206             updatedPropValue->areaId = value.areaId;
207             onPropertyValueFromCar(*updatedPropValue, updateStatus);
208             return StatusCode::OK;
209         }
210         case kSetBooleanPropertyFromVehicleForTest: {
211             auto updatedPropValue = createVehiclePropValue(VehiclePropertyType::BOOLEAN, 1);
212             updatedPropValue->prop = value.value.int32Values[1];
213             updatedPropValue->value.int32Values[0] = value.value.int32Values[0];
214             updatedPropValue->timestamp = value.value.int64Values[0];
215             updatedPropValue->areaId = value.areaId;
216             onPropertyValueFromCar(*updatedPropValue, updateStatus);
217             return StatusCode::OK;
218         }
219 
220         case AP_POWER_STATE_REPORT:
221             switch (value.value.int32Values[0]) {
222                 case toInt(VehicleApPowerStateReport::DEEP_SLEEP_EXIT):
223                 case toInt(VehicleApPowerStateReport::SHUTDOWN_CANCELLED):
224                 case toInt(VehicleApPowerStateReport::WAIT_FOR_VHAL):
225                     // CPMS is in WAIT_FOR_VHAL state, simply move to ON
226                     // Send back to HAL
227                     // ALWAYS update status for generated property value
228                     onPropertyValueFromCar(*createApPowerStateReq(VehicleApPowerStateReq::ON, 0),
229                                            true /* updateStatus */);
230                     break;
231                 case toInt(VehicleApPowerStateReport::DEEP_SLEEP_ENTRY):
232                 case toInt(VehicleApPowerStateReport::SHUTDOWN_START):
233                     // CPMS is in WAIT_FOR_FINISH state, send the FINISHED command
234                     // Send back to HAL
235                     // ALWAYS update status for generated property value
236                     onPropertyValueFromCar(
237                             *createApPowerStateReq(VehicleApPowerStateReq::FINISHED, 0),
238                             true /* updateStatus */);
239                     break;
240                 case toInt(VehicleApPowerStateReport::ON):
241                 case toInt(VehicleApPowerStateReport::SHUTDOWN_POSTPONE):
242                 case toInt(VehicleApPowerStateReport::SHUTDOWN_PREPARE):
243                     // Do nothing
244                     break;
245                 default:
246                     // Unknown state
247                     break;
248             }
249             break;
250         default:
251             break;
252     }
253 
254     // In the real vhal, the value will be sent to Car ECU.
255     // We just pretend it is done here and send back to HAL
256     auto updatedPropValue = getValuePool()->obtain(value);
257     updatedPropValue->timestamp = elapsedRealtimeNano();
258 
259     onPropertyValueFromCar(*updatedPropValue, updateStatus);
260     return StatusCode::OK;
261 }
262 
263 }  // namespace android::hardware::automotive::vehicle::V2_0::impl
264