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