blob: 33b39482da2d1db986783afef4d45f99f78e7f33 [file] [log] [blame]
Lakshman Annadoraib33e2ab2020-07-27 10:42:32 -07001/*
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#define LOG_TAG "UserHalHelper"
17
18#include "UserHalHelper.h"
19
20#include <log/log.h>
21#include <utils/SystemClock.h>
22
23namespace android {
24namespace hardware {
25namespace automotive {
26namespace vehicle {
27namespace V2_0 {
28
29namespace user_hal_helper {
30namespace {
31
32using android::base::Error;
33using android::base::Result;
34
35static constexpr const char* kSeparator = "||";
36static const size_t kNumFieldsPerUserInfo = 2;
37static const size_t kNumFieldsPerSetAssociation = 2;
38
39template <typename T>
40Result<T> verifyAndCast(int32_t value) {
41 T castValue = static_cast<T>(value);
42 const auto iter = hidl_enum_range<T>();
43 if (castValue < *iter.begin() || castValue > *std::prev(iter.end())) {
44 return Error() << "Value " << value << " not in range [" << toString(*iter.begin()) << ", "
45 << toString(*std::prev(iter.end())) << "]";
46 }
47 for (const auto& v : hidl_enum_range<T>()) {
48 if (castValue == v) {
49 return castValue;
50 }
51 }
52 return Error() << "Value " << value << " not in enum values";
53}
54
55Result<void> verifyPropValue(const VehiclePropValue& propValue, VehicleProperty vehicleProperty,
56 size_t minInt32Values) {
57 auto prop = verifyAndCast<VehicleProperty>(propValue.prop);
58 if (!prop.ok()) {
59 return Error() << "Invalid vehicle property: " << prop.error();
60 }
61 if (*prop != vehicleProperty) {
62 return Error() << "Mismatching " << toString(vehicleProperty) << " request, received "
63 << toString(*prop) << " property";
64 }
65 if (propValue.value.int32Values.size() < minInt32Values) {
66 return Error() << "Int32Values must have at least " << minInt32Values
67 << " values, received " << propValue.value.int32Values.size();
68 }
69 return {};
70}
71
72Result<void> parseUserInfo(const hidl_vec<int32_t>& int32Values, size_t startPos,
73 UserInfo* userInfo) {
74 if (int32Values.size() < startPos + kNumFieldsPerUserInfo) {
75 return Error() << "Int32Values must have at least " << startPos + 2 << " values, received "
76 << int32Values.size();
77 }
78 userInfo->userId = int32Values[startPos];
79 auto userFlags = verifyAndCast<UserFlags>(int32Values[startPos + 1]);
80 if (!userFlags.ok()) {
81 return Error() << "Invalid user flags: " << userFlags.error();
82 }
83 userInfo->flags = *userFlags;
84 return {};
85}
86
87Result<void> parseUsersInfo(const hidl_vec<int32_t>& int32Values, size_t startPos,
88 UsersInfo* usersInfo) {
89 if (int32Values.size() < startPos + 3) {
90 return Error() << "Int32Values must have at least " << startPos + 3 << " values, received "
91 << int32Values.size();
92 }
93 auto ret = parseUserInfo(int32Values, startPos, &usersInfo->currentUser);
94 if (!ret.ok()) {
95 return ret;
96 }
97 usersInfo->numberUsers = int32Values[startPos + 2];
98 usersInfo->existingUsers.resize(usersInfo->numberUsers);
99 for (size_t i = 0; i < static_cast<size_t>(usersInfo->numberUsers); ++i) {
100 ret = parseUserInfo(int32Values, startPos + 3 + (kNumFieldsPerUserInfo * i),
101 &usersInfo->existingUsers[i]);
102 if (!ret.ok()) {
103 return Error() << "Failed to parse existing user '" << i << "' info: " << ret.error();
104 }
105 }
106 return {};
107}
108
109Result<void> parseUserAssociationTypes(
110 const hidl_vec<int32_t>& int32Values, size_t startPos, size_t numberAssociationTypes,
111 hidl_vec<UserIdentificationAssociationType>* associationTypes) {
112 size_t minInt32Values = startPos + numberAssociationTypes;
113 if (int32Values.size() < minInt32Values) {
114 return Error() << "Int32Values must have at least " << minInt32Values
115 << " values, received " << int32Values.size();
116 }
117 associationTypes->resize(numberAssociationTypes);
118 for (size_t i = 0; i < static_cast<size_t>(numberAssociationTypes); ++i) {
119 size_t pos = startPos + i;
120 auto type = verifyAndCast<UserIdentificationAssociationType>(int32Values[pos]);
121 if (!type.ok()) {
122 return Error() << "Invalid association type in query '" << i << "': " << type.error();
123 }
124 (*associationTypes)[i] = *type;
125 }
126 return {};
127}
128
129Result<void> parseUserAssociations(const hidl_vec<int32_t>& int32Values, size_t startPos,
130 size_t numberAssociations,
131 hidl_vec<UserIdentificationSetAssociation>* associations) {
132 size_t minInt32Values = startPos + (numberAssociations * kNumFieldsPerSetAssociation);
133 if (int32Values.size() < minInt32Values) {
134 return Error() << "Int32Values must have at least " << minInt32Values
135 << " values, received " << int32Values.size();
136 }
137 associations->resize(numberAssociations);
138 for (size_t i = 0; i < static_cast<size_t>(numberAssociations); ++i) {
139 size_t pos = startPos + (kNumFieldsPerSetAssociation * i);
140 auto type = verifyAndCast<UserIdentificationAssociationType>(int32Values[pos]);
141 if (!type.ok()) {
142 return Error() << "Invalid association type in request '" << i << "': " << type.error();
143 }
144 (*associations)[i].type = *type;
145 auto value = verifyAndCast<UserIdentificationAssociationSetValue>(int32Values[pos + 1]);
146 if (!value.ok()) {
147 return Error() << "Invalid association set value in request '" << i
148 << "': " << value.error();
149 }
150 (*associations)[i].value = *value;
151 }
152 return {};
153}
154
155} // namespace
156
157Result<InitialUserInfoRequest> toInitialUserInfoRequest(const VehiclePropValue& propValue) {
158 auto ret = verifyPropValue(propValue, VehicleProperty::INITIAL_USER_INFO, 2);
159 if (!ret.ok()) {
160 return ret.error();
161 }
162 InitialUserInfoRequest request;
163 request.requestId = propValue.value.int32Values[0];
164 auto requestType = verifyAndCast<InitialUserInfoRequestType>(propValue.value.int32Values[1]);
165 if (!requestType.ok()) {
166 return Error() << "Invalid InitialUserInfoRequestType: " << requestType.error();
167 }
168 request.requestType = *requestType;
169 ret = parseUsersInfo(propValue.value.int32Values, 2, &request.usersInfo);
170 if (!ret.ok()) {
171 return Error() << "Failed to parse users info: " << ret.error();
172 }
173 return request;
174}
175
176Result<SwitchUserRequest> toSwitchUserRequest(const VehiclePropValue& propValue) {
177 auto ret = verifyPropValue(propValue, VehicleProperty::SWITCH_USER, 2);
178 if (!ret.ok()) {
179 return ret.error();
180 }
181 SwitchUserRequest request;
182 auto messageType = verifyAndCast<SwitchUserMessageType>(propValue.value.int32Values[1]);
183 if (!messageType.ok()) {
184 return Error() << "Invalid SwitchUserMessageType: " << messageType.error();
185 }
186 if (*messageType != SwitchUserMessageType::LEGACY_ANDROID_SWITCH &&
187 *messageType != SwitchUserMessageType::ANDROID_SWITCH &&
188 *messageType != SwitchUserMessageType::ANDROID_POST_SWITCH) {
189 return Error() << "Invalid " << toString(*messageType) << " from Android System";
190 }
191 request.requestId = propValue.value.int32Values[0];
192 request.messageType = *messageType;
193 ret = parseUserInfo(propValue.value.int32Values, 2, &request.targetUser);
194 if (!ret.ok()) {
195 return Error() << "Failed to parse target user info: " << ret.error();
196 }
197 ret = parseUsersInfo(propValue.value.int32Values, 4, &request.usersInfo);
198 if (!ret.ok()) {
199 return Error() << "Failed to parse users info: " << ret.error();
200 }
201 return request;
202}
203
204Result<CreateUserRequest> toCreateUserRequest(const VehiclePropValue& propValue) {
205 auto ret = verifyPropValue(propValue, VehicleProperty::CREATE_USER, 1);
206 if (!ret.ok()) {
207 return ret.error();
208 }
209 CreateUserRequest request;
210 request.requestId = propValue.value.int32Values[0];
211 ret = parseUserInfo(propValue.value.int32Values, 1, &request.newUserInfo);
212 if (!ret.ok()) {
213 return Error() << "Failed to parse new user info: " << ret.error();
214 }
215 request.newUserName = propValue.value.stringValue;
216 ret = parseUsersInfo(propValue.value.int32Values, 3, &request.usersInfo);
217 if (!ret.ok()) {
218 return Error() << "Failed to parse users info: " << ret.error();
219 }
220 return request;
221}
222
223Result<RemoveUserRequest> toRemoveUserRequest(const VehiclePropValue& propValue) {
224 auto ret = verifyPropValue(propValue, VehicleProperty::REMOVE_USER, 1);
225 if (!ret.ok()) {
226 return ret.error();
227 }
228 RemoveUserRequest request;
229 request.requestId = propValue.value.int32Values[0];
230 ret = parseUserInfo(propValue.value.int32Values, 1, &request.removedUserInfo);
231 if (!ret.ok()) {
232 return Error() << "Failed to parse removed user info: " << ret.error();
233 }
234 ret = parseUsersInfo(propValue.value.int32Values, 3, &request.usersInfo);
235 if (!ret.ok()) {
236 return Error() << "Failed to parse users info: " << ret.error();
237 }
238 return request;
239}
240
241Result<UserIdentificationGetRequest> toUserIdentificationGetRequest(
242 const VehiclePropValue& propValue) {
243 auto ret = verifyPropValue(propValue, VehicleProperty::USER_IDENTIFICATION_ASSOCIATION, 4);
244 if (!ret.ok()) {
245 return ret.error();
246 }
247 UserIdentificationGetRequest request;
248 request.requestId = propValue.value.int32Values[0];
249 ret = parseUserInfo(propValue.value.int32Values, 1, &request.userInfo);
250 if (!ret.ok()) {
251 return Error() << "Failed to parse user info: " << ret.error();
252 }
253 request.numberAssociationTypes = propValue.value.int32Values[3];
254 ret = parseUserAssociationTypes(propValue.value.int32Values, 4, request.numberAssociationTypes,
255 &request.associationTypes);
256 if (!ret.ok()) {
257 return Error() << "Failed to parse UserIdentificationAssociationType: " << ret.error();
258 }
259 return request;
260}
261
262Result<UserIdentificationSetRequest> toUserIdentificationSetRequest(
263 const VehiclePropValue& propValue) {
264 auto ret = verifyPropValue(propValue, VehicleProperty::USER_IDENTIFICATION_ASSOCIATION, 4);
265 if (!ret.ok()) {
266 return ret.error();
267 }
268 UserIdentificationSetRequest request;
269 request.requestId = propValue.value.int32Values[0];
270 ret = parseUserInfo(propValue.value.int32Values, 1, &request.userInfo);
271 if (!ret.ok()) {
272 return Error() << "Failed to parse user info: " << ret.error();
273 }
274 request.numberAssociations = propValue.value.int32Values[3];
275 ret = parseUserAssociations(propValue.value.int32Values, 4, request.numberAssociations,
276 &request.associations);
277 if (!ret.ok()) {
278 return Error() << "Failed to parse UserIdentificationSetAssociation: " << ret.error();
279 }
280 return request;
281}
282
283std::unique_ptr<VehiclePropValue> toVehiclePropValue(const SwitchUserRequest& request) {
284 if (request.messageType != SwitchUserMessageType::VEHICLE_REQUEST) {
285 ALOGE("Invalid %s message type %s from HAL", toString(VehicleProperty::SWITCH_USER).c_str(),
286 toString(request.messageType).c_str());
287 return nullptr;
288 }
289 auto propValue = std::unique_ptr<VehiclePropValue>(new VehiclePropValue());
290 propValue->prop = static_cast<int32_t>(VehicleProperty::SWITCH_USER);
291 propValue->timestamp = elapsedRealtimeNano();
292 propValue->value.int32Values.resize(3);
293 propValue->value.int32Values[0] = static_cast<int32_t>(request.requestId);
294 propValue->value.int32Values[1] = static_cast<int32_t>(request.messageType);
295 propValue->value.int32Values[2] = static_cast<int32_t>(request.targetUser.userId);
296 return propValue;
297}
298
299std::unique_ptr<VehiclePropValue> toVehiclePropValue(const InitialUserInfoResponse& response) {
300 auto propValue = std::unique_ptr<VehiclePropValue>(new VehiclePropValue());
301 propValue->prop = static_cast<int32_t>(VehicleProperty::INITIAL_USER_INFO);
302 propValue->timestamp = elapsedRealtimeNano();
303 propValue->value.int32Values.resize(4);
304 propValue->value.int32Values[0] = static_cast<int32_t>(response.requestId);
305 propValue->value.int32Values[1] = static_cast<int32_t>(response.action);
306 propValue->value.int32Values[2] = static_cast<int32_t>(response.userToSwitchOrCreate.userId);
307 propValue->value.int32Values[3] = static_cast<int32_t>(response.userToSwitchOrCreate.flags);
308 propValue->value.stringValue = std::string(response.userLocales) + std::string(kSeparator) +
309 std::string(response.userNameToCreate);
310 return propValue;
311}
312
313std::unique_ptr<VehiclePropValue> toVehiclePropValue(const SwitchUserResponse& response) {
314 auto propValue = std::unique_ptr<VehiclePropValue>(new VehiclePropValue());
315 propValue->prop = static_cast<int32_t>(VehicleProperty::SWITCH_USER);
316 propValue->timestamp = elapsedRealtimeNano();
317 propValue->value.int32Values.resize(3);
318 propValue->value.int32Values[0] = static_cast<int32_t>(response.requestId);
319 propValue->value.int32Values[1] = static_cast<int32_t>(response.messageType);
320 propValue->value.int32Values[2] = static_cast<int32_t>(response.status);
321 if (response.status == SwitchUserStatus::FAILURE) {
322 propValue->value.stringValue = response.errorMessage;
323 }
324 return propValue;
325}
326
327std::unique_ptr<VehiclePropValue> toVehiclePropValue(const CreateUserResponse& response) {
328 auto propValue = std::unique_ptr<VehiclePropValue>(new VehiclePropValue());
329 propValue->prop = static_cast<int32_t>(VehicleProperty::CREATE_USER);
330 propValue->timestamp = elapsedRealtimeNano();
331 propValue->value.int32Values.resize(2);
332 propValue->value.int32Values[0] = static_cast<int32_t>(response.requestId);
333 propValue->value.int32Values[1] = static_cast<int32_t>(response.status);
334 if (response.status == CreateUserStatus::FAILURE) {
335 propValue->value.stringValue = response.errorMessage;
336 }
337 return propValue;
338}
339
340std::unique_ptr<VehiclePropValue> toVehiclePropValue(const UserIdentificationResponse& response) {
341 auto propValue = std::unique_ptr<VehiclePropValue>(new VehiclePropValue());
342 propValue->prop = static_cast<int32_t>(VehicleProperty::USER_IDENTIFICATION_ASSOCIATION);
343 propValue->timestamp = elapsedRealtimeNano();
344 propValue->value.int32Values.resize(2 + (response.numberAssociation * 2));
345 propValue->value.int32Values[0] = static_cast<int32_t>(response.requestId);
346 propValue->value.int32Values[1] = static_cast<int32_t>(response.numberAssociation);
347 for (size_t i = 0; i < static_cast<size_t>(response.numberAssociation); ++i) {
348 size_t int32ValuesPos = 2 + (2 * i);
349 propValue->value.int32Values[int32ValuesPos] =
350 static_cast<int32_t>(response.associations[i].type);
351 propValue->value.int32Values[int32ValuesPos + 1] =
352 static_cast<int32_t>(response.associations[i].value);
353 }
354 if (!response.errorMessage.empty()) {
355 propValue->value.stringValue = response.errorMessage;
356 }
357 return propValue;
358}
359
360} // namespace user_hal_helper
361
362} // namespace V2_0
363} // namespace vehicle
364} // namespace automotive
365} // namespace hardware
366} // namespace android