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