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 package android.car.userlib;
18 
19 import static android.car.test.mocks.AndroidMockitoHelper.mockAmGetCurrentUser;
20 import static android.car.test.mocks.AndroidMockitoHelper.mockUmGetUsers;
21 import static android.car.userlib.UserHalHelper.CREATE_USER_PROPERTY;
22 import static android.car.userlib.UserHalHelper.REMOVE_USER_PROPERTY;
23 import static android.car.userlib.UserHalHelper.SWITCH_USER_PROPERTY;
24 import static android.car.userlib.UserHalHelper.USER_IDENTIFICATION_ASSOCIATION_PROPERTY;
25 import static android.hardware.automotive.vehicle.V2_0.UserIdentificationAssociationSetValue.ASSOCIATE_CURRENT_USER;
26 import static android.hardware.automotive.vehicle.V2_0.UserIdentificationAssociationSetValue.DISASSOCIATE_ALL_USERS;
27 import static android.hardware.automotive.vehicle.V2_0.UserIdentificationAssociationSetValue.DISASSOCIATE_CURRENT_USER;
28 import static android.hardware.automotive.vehicle.V2_0.UserIdentificationAssociationType.CUSTOM_1;
29 import static android.hardware.automotive.vehicle.V2_0.UserIdentificationAssociationType.CUSTOM_2;
30 import static android.hardware.automotive.vehicle.V2_0.UserIdentificationAssociationType.CUSTOM_3;
31 import static android.hardware.automotive.vehicle.V2_0.UserIdentificationAssociationType.CUSTOM_4;
32 import static android.hardware.automotive.vehicle.V2_0.UserIdentificationAssociationType.KEY_FOB;
33 import static android.hardware.automotive.vehicle.V2_0.UserIdentificationAssociationValue.ASSOCIATED_ANOTHER_USER;
34 import static android.hardware.automotive.vehicle.V2_0.UserIdentificationAssociationValue.ASSOCIATED_CURRENT_USER;
35 import static android.hardware.automotive.vehicle.V2_0.UserIdentificationAssociationValue.NOT_ASSOCIATED_ANY_USER;
36 import static android.hardware.automotive.vehicle.V2_0.UserIdentificationAssociationValue.UNKNOWN;
37 
38 import static com.google.common.truth.Truth.assertThat;
39 import static com.google.common.truth.Truth.assertWithMessage;
40 
41 import static org.junit.Assert.fail;
42 import static org.mockito.Mockito.when;
43 import static org.testng.Assert.assertThrows;
44 
45 import android.annotation.NonNull;
46 import android.app.ActivityManager;
47 import android.car.test.mocks.AbstractExtendedMockitoTestCase;
48 import android.car.test.mocks.AbstractExtendedMockitoTestCase.CustomMockitoSessionBuilder;
49 import android.car.test.util.UserTestingHelper.UserInfoBuilder;
50 import android.content.pm.UserInfo;
51 import android.hardware.automotive.vehicle.V2_0.CreateUserRequest;
52 import android.hardware.automotive.vehicle.V2_0.InitialUserInfoRequestType;
53 import android.hardware.automotive.vehicle.V2_0.InitialUserInfoResponse;
54 import android.hardware.automotive.vehicle.V2_0.InitialUserInfoResponseAction;
55 import android.hardware.automotive.vehicle.V2_0.RemoveUserRequest;
56 import android.hardware.automotive.vehicle.V2_0.SwitchUserMessageType;
57 import android.hardware.automotive.vehicle.V2_0.SwitchUserRequest;
58 import android.hardware.automotive.vehicle.V2_0.UserFlags;
59 import android.hardware.automotive.vehicle.V2_0.UserIdentificationAssociation;
60 import android.hardware.automotive.vehicle.V2_0.UserIdentificationAssociationType;
61 import android.hardware.automotive.vehicle.V2_0.UserIdentificationAssociationValue;
62 import android.hardware.automotive.vehicle.V2_0.UserIdentificationGetRequest;
63 import android.hardware.automotive.vehicle.V2_0.UserIdentificationResponse;
64 import android.hardware.automotive.vehicle.V2_0.UserIdentificationSetAssociation;
65 import android.hardware.automotive.vehicle.V2_0.UserIdentificationSetRequest;
66 import android.hardware.automotive.vehicle.V2_0.UsersInfo;
67 import android.hardware.automotive.vehicle.V2_0.VehiclePropValue;
68 import android.os.SystemClock;
69 import android.os.UserHandle;
70 import android.os.UserManager;
71 
72 import com.google.common.collect.Range;
73 
74 import org.junit.Test;
75 import org.mockito.Mock;
76 
77 import java.util.Arrays;
78 
79 public final class UserHalHelperTest extends AbstractExtendedMockitoTestCase {
80 
81     @Mock
82     private UserManager mUm;
83 
84     @Override
onSessionBuilder(CustomMockitoSessionBuilder session)85     protected void onSessionBuilder(CustomMockitoSessionBuilder session) {
86         session.spyStatic(ActivityManager.class);
87     }
88 
89     @Test
testHalCallbackStatusToString()90     public void testHalCallbackStatusToString() {
91         assertThat(UserHalHelper.halCallbackStatusToString(-666)).isNotNull();
92     }
93 
94     @Test
testParseInitialUserInfoRequestType_valid()95     public void testParseInitialUserInfoRequestType_valid() {
96         assertThat(UserHalHelper.parseInitialUserInfoRequestType("FIRST_BOOT"))
97                 .isEqualTo(InitialUserInfoRequestType.FIRST_BOOT);
98         assertThat(UserHalHelper.parseInitialUserInfoRequestType("COLD_BOOT"))
99             .isEqualTo(InitialUserInfoRequestType.COLD_BOOT);
100         assertThat(UserHalHelper.parseInitialUserInfoRequestType("FIRST_BOOT_AFTER_OTA"))
101             .isEqualTo(InitialUserInfoRequestType.FIRST_BOOT_AFTER_OTA);
102         assertThat(UserHalHelper.parseInitialUserInfoRequestType("RESUME"))
103             .isEqualTo(InitialUserInfoRequestType.RESUME);
104     }
105 
106     @Test
testParseInitialUserInfoRequestType_unknown()107     public void testParseInitialUserInfoRequestType_unknown() {
108         assertThat(UserHalHelper.parseInitialUserInfoRequestType("666")).isEqualTo(666);
109     }
110 
111     @Test
testParseInitialUserInfoRequestType_invalid()112     public void testParseInitialUserInfoRequestType_invalid() {
113         assertThrows(IllegalArgumentException.class,
114                 () -> UserHalHelper.parseInitialUserInfoRequestType("NumberNotIAm"));
115     }
116 
117     @Test
testConvertFlags_nullUser()118     public void testConvertFlags_nullUser() {
119         assertThrows(IllegalArgumentException.class, () -> UserHalHelper.convertFlags(null));
120     }
121 
122     @Test
testConvertFlags()123     public void testConvertFlags() {
124         UserInfo user = new UserInfo();
125 
126         user.id = UserHandle.USER_SYSTEM;
127         assertConvertFlags(UserFlags.SYSTEM, user);
128 
129         user.id = 10;
130         assertConvertFlags(UserFlags.NONE, user);
131 
132         user.flags = UserInfo.FLAG_ADMIN;
133         assertThat(user.isAdmin()).isTrue(); // Confidence check
134         assertConvertFlags(UserFlags.ADMIN, user);
135 
136         user.flags = UserInfo.FLAG_EPHEMERAL;
137         assertThat(user.isEphemeral()).isTrue(); // Confidence check
138         assertConvertFlags(UserFlags.EPHEMERAL, user);
139 
140         user.userType = UserManager.USER_TYPE_FULL_GUEST;
141         assertThat(user.isEphemeral()).isTrue(); // Confidence check
142         assertThat(user.isGuest()).isTrue(); // Confidence check
143         assertConvertFlags(UserFlags.GUEST | UserFlags.EPHEMERAL, user);
144     }
145 
146     @Test
testGetFlags_nullUserManager()147     public void testGetFlags_nullUserManager() {
148         assertThrows(IllegalArgumentException.class, () -> UserHalHelper.getFlags(null, 10));
149     }
150 
151     @Test
testGetFlags_noUser()152     public void testGetFlags_noUser() {
153         // No need to set anythin as mUm call will return null
154         assertThrows(IllegalArgumentException.class, () -> UserHalHelper.getFlags(mUm, 10));
155     }
156 
157     @Test
testGetFlags_ok()158     public void testGetFlags_ok() {
159         UserInfo user = new UserInfo();
160 
161         user.id = UserHandle.USER_SYSTEM;
162         assertGetFlags(UserFlags.SYSTEM, user);
163 
164         user.id = 10;
165         assertGetFlags(UserFlags.NONE, user);
166 
167         user.flags = UserInfo.FLAG_ADMIN;
168         assertThat(user.isAdmin()).isTrue(); // Confidence check
169         assertGetFlags(UserFlags.ADMIN, user);
170 
171         user.flags = UserInfo.FLAG_EPHEMERAL;
172         assertThat(user.isEphemeral()).isTrue(); // Confidence check
173         assertGetFlags(UserFlags.EPHEMERAL, user);
174 
175         user.userType = UserManager.USER_TYPE_FULL_GUEST;
176         assertThat(user.isEphemeral()).isTrue(); // Confidence check
177         assertThat(user.isGuest()).isTrue(); // Confidence check
178         assertGetFlags(UserFlags.GUEST | UserFlags.EPHEMERAL, user);
179     }
180 
181     @Test
testIsSystem()182     public void testIsSystem() {
183         assertThat(UserHalHelper.isSystem(UserFlags.SYSTEM)).isTrue();
184         assertThat(UserHalHelper.isSystem(UserFlags.SYSTEM | 666)).isTrue();
185         assertThat(UserHalHelper.isSystem(UserFlags.GUEST)).isFalse();
186     }
187 
188     @Test
testIsGuest()189     public void testIsGuest() {
190         assertThat(UserHalHelper.isGuest(UserFlags.GUEST)).isTrue();
191         assertThat(UserHalHelper.isGuest(UserFlags.GUEST | 666)).isTrue();
192         assertThat(UserHalHelper.isGuest(UserFlags.SYSTEM)).isFalse();
193     }
194 
195     @Test
testIsEphemeral()196     public void testIsEphemeral() {
197         assertThat(UserHalHelper.isEphemeral(UserFlags.EPHEMERAL)).isTrue();
198         assertThat(UserHalHelper.isEphemeral(UserFlags.EPHEMERAL | 666)).isTrue();
199         assertThat(UserHalHelper.isEphemeral(UserFlags.GUEST)).isFalse();
200     }
201 
202     @Test
testIsAdmin()203     public void testIsAdmin() {
204         assertThat(UserHalHelper.isAdmin(UserFlags.ADMIN)).isTrue();
205         assertThat(UserHalHelper.isAdmin(UserFlags.ADMIN | 666)).isTrue();
206         assertThat(UserHalHelper.isAdmin(UserFlags.GUEST)).isFalse();
207     }
208 
209     @Test
testIsDisabled()210     public void testIsDisabled() {
211         assertThat(UserHalHelper.isDisabled(UserFlags.DISABLED)).isTrue();
212         assertThat(UserHalHelper.isDisabled(UserFlags.DISABLED | 666)).isTrue();
213         assertThat(UserHalHelper.isDisabled(UserFlags.GUEST)).isFalse();
214     }
215 
216     @Test
testIsProfile()217     public void testIsProfile() {
218         assertThat(UserHalHelper.isProfile(UserFlags.PROFILE)).isTrue();
219         assertThat(UserHalHelper.isProfile(UserFlags.PROFILE | 666)).isTrue();
220         assertThat(UserHalHelper.isProfile(UserFlags.GUEST)).isFalse();
221     }
222 
223     @Test
testToUserInfoFlags()224     public void testToUserInfoFlags() {
225         assertThat(UserHalHelper.toUserInfoFlags(UserFlags.NONE)).isEqualTo(0);
226         assertThat(UserHalHelper.toUserInfoFlags(UserFlags.EPHEMERAL))
227                 .isEqualTo(UserInfo.FLAG_EPHEMERAL);
228         assertThat(UserHalHelper.toUserInfoFlags(UserFlags.ADMIN))
229                 .isEqualTo(UserInfo.FLAG_ADMIN);
230         assertThat(UserHalHelper.toUserInfoFlags(UserFlags.EPHEMERAL | UserFlags.ADMIN))
231                 .isEqualTo(UserInfo.FLAG_EPHEMERAL | UserInfo.FLAG_ADMIN);
232 
233         // test flags that should be ignored
234         assertThat(UserHalHelper.toUserInfoFlags(UserFlags.SYSTEM)).isEqualTo(0);
235         assertThat(UserHalHelper.toUserInfoFlags(UserFlags.GUEST)).isEqualTo(0);
236         assertThat(UserHalHelper.toUserInfoFlags(1024)).isEqualTo(0);
237     }
238 
assertConvertFlags(int expectedFlags, @NonNull UserInfo user)239     private void assertConvertFlags(int expectedFlags, @NonNull UserInfo user) {
240         assertWithMessage("flags mismatch: user=%s, flags=%s",
241                 user.toFullString(), UserHalHelper.userFlagsToString(expectedFlags))
242                         .that(UserHalHelper.convertFlags(user)).isEqualTo(expectedFlags);
243     }
244 
assertGetFlags(int expectedFlags, @NonNull UserInfo user)245     private void assertGetFlags(int expectedFlags, @NonNull UserInfo user) {
246         when(mUm.getUserInfo(user.id)).thenReturn(user);
247         assertWithMessage("flags mismatch: user=%s, flags=%s",
248                 user.toFullString(), UserHalHelper.userFlagsToString(expectedFlags))
249                         .that(UserHalHelper.getFlags(mUm, user.id)).isEqualTo(expectedFlags);
250     }
251 
252     @Test
testUserFlagsToString()253     public void testUserFlagsToString() {
254         assertThat(UserHalHelper.userFlagsToString(-666)).isNotNull();
255     }
256 
257     @Test
testCreatePropRequest_withType()258     public void testCreatePropRequest_withType() {
259         int prop = 1;
260         int requestId = 2;
261         int requestType = 3;
262         long before = SystemClock.elapsedRealtime();
263         VehiclePropValue propRequest = UserHalHelper.createPropRequest(prop, requestId,
264                 requestType);
265         long after = SystemClock.elapsedRealtime();
266 
267         assertThat(propRequest.value.int32Values)
268                 .containsExactly(requestId, requestType)
269                 .inOrder();
270         assertThat(propRequest.prop).isEqualTo(prop);
271         assertThat(propRequest.timestamp).isIn(Range.closed(before, after));
272     }
273 
274     @Test
testCreatePropRequest()275     public void testCreatePropRequest() {
276         int prop = 1;
277         int requestId = 2;
278         long before = SystemClock.elapsedRealtime();
279         VehiclePropValue propRequest = UserHalHelper.createPropRequest(prop, requestId);
280         long after = SystemClock.elapsedRealtime();
281 
282         assertThat(propRequest.value.int32Values)
283                 .containsExactly(requestId)
284                 .inOrder();
285         assertThat(propRequest.prop).isEqualTo(prop);
286         assertThat(propRequest.timestamp).isIn(Range.closed(before, after));
287     }
288 
289     @Test
testAddUsersInfo_nullProp()290     public void testAddUsersInfo_nullProp() {
291         UsersInfo infos = new UsersInfo();
292 
293         assertThrows(NullPointerException.class, () -> UserHalHelper.addUsersInfo(null, infos));
294     }
295 
296     @Test
testAddUsersInfo_nullCurrentUser()297     public void testAddUsersInfo_nullCurrentUser() {
298         VehiclePropValue propRequest = new VehiclePropValue();
299 
300         UsersInfo infos = new UsersInfo();
301         infos.currentUser = null;
302         assertThrows(NullPointerException.class, () ->
303                 UserHalHelper.addUsersInfo(propRequest, infos));
304     }
305 
306     @Test
testAddUsersInfo_mismatchNumberUsers()307     public void testAddUsersInfo_mismatchNumberUsers() {
308         VehiclePropValue propRequest = new VehiclePropValue();
309 
310         UsersInfo infos = new UsersInfo();
311         infos.currentUser.userId = 42;
312         infos.currentUser.flags = 1;
313         infos.numberUsers = 1;
314         assertThat(infos.existingUsers).isEmpty();
315         assertThrows(IllegalArgumentException.class, () ->
316                 UserHalHelper.addUsersInfo(propRequest, infos));
317     }
318 
319     @Test
testAddUsersInfo_success()320     public void testAddUsersInfo_success() {
321         VehiclePropValue propRequest = new VehiclePropValue();
322         propRequest.value.int32Values.add(99);
323 
324         UsersInfo infos = new UsersInfo();
325         infos.currentUser.userId = 42;
326         infos.currentUser.flags = 1;
327         infos.numberUsers = 1;
328 
329         android.hardware.automotive.vehicle.V2_0.UserInfo userInfo =
330                 new android.hardware.automotive.vehicle.V2_0.UserInfo();
331         userInfo.userId = 43;
332         userInfo.flags = 1;
333         infos.existingUsers.add(userInfo);
334         UserHalHelper.addUsersInfo(propRequest, infos);
335 
336         assertThat(propRequest.value.int32Values)
337                 .containsExactly(99, 42, 1, 1, 43, 1)
338                 .inOrder();
339     }
340 
341     @Test
testAddUserInfo_nullProp()342     public void testAddUserInfo_nullProp() {
343         android.hardware.automotive.vehicle.V2_0.UserInfo userInfo =
344                 new android.hardware.automotive.vehicle.V2_0.UserInfo();
345 
346         assertThrows(NullPointerException.class, () -> UserHalHelper.addUserInfo(null, userInfo));
347     }
348 
349     @Test
testAddUserInfo_nullCurrentUser()350     public void testAddUserInfo_nullCurrentUser() {
351         VehiclePropValue prop = new VehiclePropValue();
352 
353         assertThrows(NullPointerException.class, () -> UserHalHelper.addUserInfo(prop, null));
354     }
355 
356     @Test
testAddUserInfo_success()357     public void testAddUserInfo_success() {
358         VehiclePropValue propRequest = new VehiclePropValue();
359         propRequest.value.int32Values.add(99);
360 
361         android.hardware.automotive.vehicle.V2_0.UserInfo userInfo =
362                 new android.hardware.automotive.vehicle.V2_0.UserInfo();
363         userInfo.userId = 42;
364         userInfo.flags = 1;
365 
366         UserHalHelper.addUserInfo(propRequest, userInfo);
367 
368         assertThat(propRequest.value.int32Values)
369                 .containsExactly(99, 42, 1)
370                 .inOrder();
371     }
372 
373     @Test
testIsValidUserIdentificationAssociationType_valid()374     public void testIsValidUserIdentificationAssociationType_valid() {
375         assertThat(UserHalHelper.isValidUserIdentificationAssociationType(KEY_FOB)).isTrue();
376         assertThat(UserHalHelper.isValidUserIdentificationAssociationType(CUSTOM_1)).isTrue();
377         assertThat(UserHalHelper.isValidUserIdentificationAssociationType(CUSTOM_2)).isTrue();
378         assertThat(UserHalHelper.isValidUserIdentificationAssociationType(CUSTOM_3)).isTrue();
379         assertThat(UserHalHelper.isValidUserIdentificationAssociationType(CUSTOM_4)).isTrue();
380     }
381 
382     @Test
testIsValidUserIdentificationAssociationType_invalid()383     public void testIsValidUserIdentificationAssociationType_invalid() {
384         assertThat(UserHalHelper.isValidUserIdentificationAssociationType(CUSTOM_4 + 1)).isFalse();
385     }
386 
387     @Test
testIsValidUserIdentificationAssociationValue_valid()388     public void testIsValidUserIdentificationAssociationValue_valid() {
389         assertThat(UserHalHelper.isValidUserIdentificationAssociationValue(ASSOCIATED_ANOTHER_USER))
390                 .isTrue();
391         assertThat(UserHalHelper.isValidUserIdentificationAssociationValue(ASSOCIATED_CURRENT_USER))
392                 .isTrue();
393         assertThat(UserHalHelper.isValidUserIdentificationAssociationValue(NOT_ASSOCIATED_ANY_USER))
394                 .isTrue();
395         assertThat(UserHalHelper.isValidUserIdentificationAssociationValue(UNKNOWN)).isTrue();
396     }
397 
398     @Test
testIsValidUserIdentificationAssociationValue_invalid()399     public void testIsValidUserIdentificationAssociationValue_invalid() {
400         assertThat(UserHalHelper.isValidUserIdentificationAssociationValue(0)).isFalse();
401     }
402 
403     @Test
testIsValidUserIdentificationAssociationSetValue_valid()404     public void testIsValidUserIdentificationAssociationSetValue_valid() {
405         assertThat(UserHalHelper
406                 .isValidUserIdentificationAssociationSetValue(ASSOCIATE_CURRENT_USER)).isTrue();
407         assertThat(UserHalHelper
408                 .isValidUserIdentificationAssociationSetValue(DISASSOCIATE_CURRENT_USER)).isTrue();
409         assertThat(UserHalHelper
410                 .isValidUserIdentificationAssociationSetValue(DISASSOCIATE_ALL_USERS)).isTrue();
411     }
412 
413     @Test
testIsValidUserIdentificationAssociationSetValue_invalid()414     public void testIsValidUserIdentificationAssociationSetValue_invalid() {
415         assertThat(UserHalHelper.isValidUserIdentificationAssociationSetValue(0)).isFalse();
416     }
417 
418     @Test
testUserIdentificationGetRequestToVehiclePropValue_null()419     public void testUserIdentificationGetRequestToVehiclePropValue_null() {
420         assertThrows(NullPointerException.class,
421                 () -> UserHalHelper.toVehiclePropValue((UserIdentificationGetRequest) null));
422     }
423 
424     @Test
testUserIdentificationGetRequestToVehiclePropValue_emptyRequest()425     public void testUserIdentificationGetRequestToVehiclePropValue_emptyRequest() {
426         UserIdentificationGetRequest request = new UserIdentificationGetRequest();
427 
428         assertThrows(IllegalArgumentException.class,
429                 () -> UserHalHelper.toVehiclePropValue(request));
430     }
431 
432     @Test
testUserIdentificationGetRequestToVehiclePropValue_wrongNumberOfAssociations()433     public void testUserIdentificationGetRequestToVehiclePropValue_wrongNumberOfAssociations() {
434         UserIdentificationGetRequest request = new UserIdentificationGetRequest();
435         request.numberAssociationTypes = 1;
436 
437         assertThrows(IllegalArgumentException.class,
438                 () -> UserHalHelper.toVehiclePropValue(request));
439     }
440 
441     @Test
testUserIdentificationGetRequestToVehiclePropValue_invalidType()442     public void testUserIdentificationGetRequestToVehiclePropValue_invalidType() {
443         UserIdentificationGetRequest request = new UserIdentificationGetRequest();
444         request.numberAssociationTypes = 1;
445         request.associationTypes.add(CUSTOM_4 + 1);
446 
447         assertThrows(IllegalArgumentException.class,
448                 () -> UserHalHelper.toVehiclePropValue(request));
449     }
450 
451     @Test
testUserIdentificationGetRequestToVehiclePropValue_missingRequestId()452     public void testUserIdentificationGetRequestToVehiclePropValue_missingRequestId() {
453         UserIdentificationGetRequest request = new UserIdentificationGetRequest();
454         request.userInfo.userId = 42;
455         request.userInfo.flags = 108;
456         request.numberAssociationTypes = 1;
457         request.associationTypes.add(KEY_FOB);
458 
459         assertThrows(IllegalArgumentException.class,
460                 () -> UserHalHelper.toVehiclePropValue(request));
461     }
462 
463     @Test
testUserIdentificationGetRequestToVehiclePropValue_ok()464     public void testUserIdentificationGetRequestToVehiclePropValue_ok() {
465         UserIdentificationGetRequest request = new UserIdentificationGetRequest();
466         request.requestId = 1;
467         request.userInfo.userId = 42;
468         request.userInfo.flags = 108;
469         request.numberAssociationTypes = 2;
470         request.associationTypes.add(KEY_FOB);
471         request.associationTypes.add(CUSTOM_1);
472 
473         VehiclePropValue propValue = UserHalHelper.toVehiclePropValue(request);
474         assertWithMessage("wrong prop on %s", propValue).that(propValue.prop)
475                 .isEqualTo(USER_IDENTIFICATION_ASSOCIATION_PROPERTY);
476         assertWithMessage("wrong int32values on %s", propValue).that(propValue.value.int32Values)
477                 .containsExactly(1, 42, 108, 2, KEY_FOB, CUSTOM_1).inOrder();
478     }
479 
480     @Test
testToUserIdentificationResponse_null()481     public void testToUserIdentificationResponse_null() {
482         assertThrows(NullPointerException.class,
483                 () -> UserHalHelper.toUserIdentificationResponse(null));
484     }
485 
486     @Test
testToUserIdentificationResponse_invalidPropType()487     public void testToUserIdentificationResponse_invalidPropType() {
488         VehiclePropValue prop = new VehiclePropValue();
489 
490         assertThrows(IllegalArgumentException.class,
491                 () -> UserHalHelper.toUserIdentificationResponse(prop));
492     }
493 
494     @Test
testToUserIdentificationResponse_invalidSize()495     public void testToUserIdentificationResponse_invalidSize() {
496         VehiclePropValue prop = new VehiclePropValue();
497         prop.prop = UserHalHelper.USER_IDENTIFICATION_ASSOCIATION_PROPERTY;
498         // need at least 4: request_id, number associations, type1, value1
499         prop.value.int32Values.add(1);
500         prop.value.int32Values.add(2);
501         prop.value.int32Values.add(3);
502 
503         assertThrows(IllegalArgumentException.class,
504                 () -> UserHalHelper.toUserIdentificationResponse(prop));
505     }
506 
507     @Test
testToUserIdentificationResponse_invalidRequest()508     public void testToUserIdentificationResponse_invalidRequest() {
509         VehiclePropValue prop = new VehiclePropValue();
510         prop.prop = UserHalHelper.USER_IDENTIFICATION_ASSOCIATION_PROPERTY;
511         prop.value.int32Values.add(0);
512 
513         assertThrows(IllegalArgumentException.class,
514                 () -> UserHalHelper.toUserIdentificationResponse(prop));
515     }
516 
517     @Test
testToUserIdentificationResponse_invalidType()518     public void testToUserIdentificationResponse_invalidType() {
519         VehiclePropValue prop = new VehiclePropValue();
520         prop.prop = UserHalHelper.USER_IDENTIFICATION_ASSOCIATION_PROPERTY;
521         prop.value.int32Values.add(42); // request id
522         prop.value.int32Values.add(1); // number of associations
523         prop.value.int32Values.add(CUSTOM_4 + 1);
524         prop.value.int32Values.add(ASSOCIATED_ANOTHER_USER);
525 
526         assertThrows(IllegalArgumentException.class,
527                 () -> UserHalHelper.toUserIdentificationResponse(prop));
528     }
529 
530     @Test
testToUserIdentificationResponse_invalidValue()531     public void testToUserIdentificationResponse_invalidValue() {
532         VehiclePropValue prop = new VehiclePropValue();
533         prop.prop = UserHalHelper.USER_IDENTIFICATION_ASSOCIATION_PROPERTY;
534         prop.value.int32Values.add(42); // request id
535         prop.value.int32Values.add(1); // number of associations
536         prop.value.int32Values.add(KEY_FOB);
537         prop.value.int32Values.add(0);
538 
539         assertThrows(IllegalArgumentException.class,
540                 () -> UserHalHelper.toUserIdentificationResponse(prop));
541     }
542 
543     @Test
testToUserIdentificationResponse_ok()544     public void testToUserIdentificationResponse_ok() {
545         VehiclePropValue prop = new VehiclePropValue();
546         prop.prop = UserHalHelper.USER_IDENTIFICATION_ASSOCIATION_PROPERTY;
547         prop.value.int32Values.add(42); // request id
548         prop.value.int32Values.add(3); // number of associations
549         prop.value.int32Values.add(KEY_FOB);
550         prop.value.int32Values.add(ASSOCIATED_ANOTHER_USER);
551         prop.value.int32Values.add(CUSTOM_1);
552         prop.value.int32Values.add(ASSOCIATED_CURRENT_USER);
553         prop.value.int32Values.add(CUSTOM_2);
554         prop.value.int32Values.add(NOT_ASSOCIATED_ANY_USER);
555         prop.value.stringValue = "D'OH!";
556 
557         UserIdentificationResponse response = UserHalHelper.toUserIdentificationResponse(prop);
558 
559         assertWithMessage("Wrong request id on %s", response)
560             .that(response.requestId).isEqualTo(42);
561         assertWithMessage("Wrong number of associations on %s", response)
562             .that(response.numberAssociation).isEqualTo(3);
563         assertAssociation(response, 0, KEY_FOB, ASSOCIATED_ANOTHER_USER);
564         assertAssociation(response, 1, CUSTOM_1, ASSOCIATED_CURRENT_USER);
565         assertAssociation(response, 2, CUSTOM_2, NOT_ASSOCIATED_ANY_USER);
566         assertWithMessage("Wrong error message on %s", response)
567             .that(response.errorMessage).isEqualTo("D'OH!");
568     }
569 
570     @Test
testToInitialUserInfoResponse_null()571     public void testToInitialUserInfoResponse_null() {
572         assertThrows(NullPointerException.class,
573                 () -> UserHalHelper.toInitialUserInfoResponse(null));
574     }
575 
576     @Test
testToInitialUserInfoResponse_invalidPropType()577     public void testToInitialUserInfoResponse_invalidPropType() {
578         VehiclePropValue prop = new VehiclePropValue();
579 
580         assertThrows(IllegalArgumentException.class,
581                 () -> UserHalHelper.toInitialUserInfoResponse(prop));
582     }
583 
584     @Test
testToInitialUserInfoResponse_invalidSize()585     public void testToInitialUserInfoResponse_invalidSize() {
586         VehiclePropValue prop = new VehiclePropValue();
587         prop.prop = UserHalHelper.INITIAL_USER_INFO_PROPERTY;
588         //      need at least 2: request_id, action_type
589         prop.value.int32Values.add(42);
590 
591         assertThrows(IllegalArgumentException.class,
592                 () -> UserHalHelper.toInitialUserInfoResponse(prop));
593     }
594 
595     @Test
testToInitialUserInfoResponse_invalidRequest()596     public void testToInitialUserInfoResponse_invalidRequest() {
597         VehiclePropValue prop = new VehiclePropValue();
598         prop.prop = UserHalHelper.INITIAL_USER_INFO_PROPERTY;
599         prop.value.int32Values.add(0);
600 
601         assertThrows(IllegalArgumentException.class,
602                 () -> UserHalHelper.toInitialUserInfoResponse(prop));
603     }
604 
605     @Test
testToInitialUserInfoResponse_invalidAction()606     public void testToInitialUserInfoResponse_invalidAction() {
607         VehiclePropValue prop = new VehiclePropValue();
608         prop.prop = UserHalHelper.INITIAL_USER_INFO_PROPERTY;
609         prop.value.int32Values.add(42); // request id
610         prop.value.int32Values.add(-1); // InitialUserInfoResponseAction
611 
612         assertThrows(IllegalArgumentException.class,
613                 () -> UserHalHelper.toInitialUserInfoResponse(prop));
614     }
615 
616     @Test
testToInitialUserInfoResponse_default_ok_noStringValue()617     public void testToInitialUserInfoResponse_default_ok_noStringValue() {
618         VehiclePropValue prop = new VehiclePropValue();
619         prop.prop = UserHalHelper.INITIAL_USER_INFO_PROPERTY;
620         prop.value.int32Values.add(42); // request id
621         prop.value.int32Values.add(InitialUserInfoResponseAction.DEFAULT);
622 
623         InitialUserInfoResponse response = UserHalHelper.toInitialUserInfoResponse(prop);
624 
625         assertThat(response).isNotNull();
626         assertThat(response.requestId).isEqualTo(42);
627         assertThat(response.action).isEqualTo(InitialUserInfoResponseAction.DEFAULT);
628         assertThat(response.userNameToCreate).isEmpty();
629         assertThat(response.userToSwitchOrCreate.userId).isEqualTo(UserHandle.USER_NULL);
630         assertThat(response.userToSwitchOrCreate.flags).isEqualTo(UserFlags.NONE);
631         assertThat(response.userLocales).isEmpty();
632     }
633 
634     @Test
testToInitialUserInfoResponse_default_ok_stringValueWithJustSeparator()635     public void testToInitialUserInfoResponse_default_ok_stringValueWithJustSeparator() {
636         VehiclePropValue prop = new VehiclePropValue();
637         prop.prop = UserHalHelper.INITIAL_USER_INFO_PROPERTY;
638         prop.value.int32Values.add(42); // request id
639         prop.value.int32Values.add(InitialUserInfoResponseAction.DEFAULT);
640         prop.value.stringValue = "||";
641 
642         InitialUserInfoResponse response = UserHalHelper.toInitialUserInfoResponse(prop);
643 
644         assertThat(response).isNotNull();
645         assertThat(response.requestId).isEqualTo(42);
646         assertThat(response.action).isEqualTo(InitialUserInfoResponseAction.DEFAULT);
647         assertThat(response.userNameToCreate).isEmpty();
648         assertThat(response.userToSwitchOrCreate.userId).isEqualTo(UserHandle.USER_NULL);
649         assertThat(response.userToSwitchOrCreate.flags).isEqualTo(UserFlags.NONE);
650         assertThat(response.userLocales).isEmpty();
651     }
652 
653     @Test
testToInitialUserInfoResponse_default_ok_stringValueWithLocale()654     public void testToInitialUserInfoResponse_default_ok_stringValueWithLocale() {
655         VehiclePropValue prop = new VehiclePropValue();
656         prop.prop = UserHalHelper.INITIAL_USER_INFO_PROPERTY;
657         prop.value.int32Values.add(42); // request id
658         prop.value.int32Values.add(InitialUserInfoResponseAction.DEFAULT);
659         prop.value.stringValue = "esperanto,klingon";
660 
661         InitialUserInfoResponse response = UserHalHelper.toInitialUserInfoResponse(prop);
662 
663         assertThat(response).isNotNull();
664         assertThat(response.requestId).isEqualTo(42);
665         assertThat(response.action).isEqualTo(InitialUserInfoResponseAction.DEFAULT);
666         assertThat(response.userNameToCreate).isEmpty();
667         assertThat(response.userToSwitchOrCreate.userId).isEqualTo(UserHandle.USER_NULL);
668         assertThat(response.userToSwitchOrCreate.flags).isEqualTo(UserFlags.NONE);
669         assertThat(response.userLocales).isEqualTo("esperanto,klingon");
670     }
671 
672     @Test
testToInitialUserInfoResponse_default_ok_stringValueWithLocaleWithHalfSeparator()673     public void testToInitialUserInfoResponse_default_ok_stringValueWithLocaleWithHalfSeparator() {
674         VehiclePropValue prop = new VehiclePropValue();
675         prop.prop = UserHalHelper.INITIAL_USER_INFO_PROPERTY;
676         prop.value.int32Values.add(42); // request id
677         prop.value.int32Values.add(InitialUserInfoResponseAction.DEFAULT);
678         prop.value.stringValue = "esperanto|klingon";
679 
680         InitialUserInfoResponse response = UserHalHelper.toInitialUserInfoResponse(prop);
681 
682         assertThat(response).isNotNull();
683         assertThat(response.requestId).isEqualTo(42);
684         assertThat(response.action).isEqualTo(InitialUserInfoResponseAction.DEFAULT);
685         assertThat(response.userNameToCreate).isEmpty();
686         assertThat(response.userToSwitchOrCreate.userId).isEqualTo(UserHandle.USER_NULL);
687         assertThat(response.userToSwitchOrCreate.flags).isEqualTo(UserFlags.NONE);
688         assertThat(response.userLocales).isEqualTo("esperanto|klingon");
689     }
690 
691     @Test
testToInitialUserInfoResponse_switch_missingUserId()692     public void testToInitialUserInfoResponse_switch_missingUserId() {
693         VehiclePropValue prop = new VehiclePropValue();
694         prop.prop = UserHalHelper.INITIAL_USER_INFO_PROPERTY;
695         prop.value.int32Values.add(42); // request id
696         prop.value.int32Values.add(InitialUserInfoResponseAction.SWITCH);
697 
698         assertThrows(IllegalArgumentException.class,
699                 () -> UserHalHelper.toInitialUserInfoResponse(prop));
700     }
701 
702     @Test
testToInitialUserInfoResponse_switch_ok_noLocale()703     public void testToInitialUserInfoResponse_switch_ok_noLocale() {
704         VehiclePropValue prop = new VehiclePropValue();
705         prop.prop = UserHalHelper.INITIAL_USER_INFO_PROPERTY;
706         prop.value.int32Values.add(42); // request id
707         prop.value.int32Values.add(InitialUserInfoResponseAction.SWITCH);
708         prop.value.int32Values.add(108); // user id
709         prop.value.int32Values.add(666); // flags - should be ignored
710 
711         InitialUserInfoResponse response = UserHalHelper.toInitialUserInfoResponse(prop);
712 
713         assertThat(response).isNotNull();
714         assertThat(response.requestId).isEqualTo(42);
715         assertThat(response.action).isEqualTo(InitialUserInfoResponseAction.SWITCH);
716         assertThat(response.userNameToCreate).isEmpty();
717         assertThat(response.userToSwitchOrCreate.userId).isEqualTo(108);
718         assertThat(response.userToSwitchOrCreate.flags).isEqualTo(UserFlags.NONE);
719         assertThat(response.userLocales).isEmpty();
720     }
721 
722     @Test
testToInitialUserInfoResponse_switch_ok_withLocale()723     public void testToInitialUserInfoResponse_switch_ok_withLocale() {
724         VehiclePropValue prop = new VehiclePropValue();
725         prop.prop = UserHalHelper.INITIAL_USER_INFO_PROPERTY;
726         prop.value.int32Values.add(42); // request id
727         prop.value.int32Values.add(InitialUserInfoResponseAction.SWITCH);
728         prop.value.int32Values.add(108); // user id
729         prop.value.int32Values.add(666); // flags - should be ignored
730         // add some extra | to make sure they're ignored
731         prop.value.stringValue = "esperanto,klingon|||";
732         InitialUserInfoResponse response = UserHalHelper.toInitialUserInfoResponse(prop);
733 
734         assertThat(response).isNotNull();
735         assertThat(response.requestId).isEqualTo(42);
736         assertThat(response.action).isEqualTo(InitialUserInfoResponseAction.SWITCH);
737         assertThat(response.userNameToCreate).isEmpty();
738         assertThat(response.userToSwitchOrCreate.userId).isEqualTo(108);
739         assertThat(response.userToSwitchOrCreate.flags).isEqualTo(UserFlags.NONE);
740         assertThat(response.userLocales).isEqualTo("esperanto,klingon");
741     }
742 
743     @Test
testToInitialUserInfoResponse_create_missingUserId()744     public void testToInitialUserInfoResponse_create_missingUserId() {
745         VehiclePropValue prop = new VehiclePropValue();
746         prop.prop = UserHalHelper.INITIAL_USER_INFO_PROPERTY;
747         prop.value.int32Values.add(42); // request id
748         prop.value.int32Values.add(InitialUserInfoResponseAction.CREATE);
749 
750         assertThrows(IllegalArgumentException.class,
751                 () -> UserHalHelper.toInitialUserInfoResponse(prop));
752     }
753 
754     @Test
testToInitialUserInfoResponse_create_missingFlags()755     public void testToInitialUserInfoResponse_create_missingFlags() {
756         VehiclePropValue prop = new VehiclePropValue();
757         prop.prop = UserHalHelper.INITIAL_USER_INFO_PROPERTY;
758         prop.value.int32Values.add(42); // request id
759         prop.value.int32Values.add(InitialUserInfoResponseAction.CREATE);
760         prop.value.int32Values.add(108); // user id
761 
762         assertThrows(IllegalArgumentException.class,
763                 () -> UserHalHelper.toInitialUserInfoResponse(prop));
764     }
765 
766     @Test
testToInitialUserInfoResponse_create_ok_noLocale()767     public void testToInitialUserInfoResponse_create_ok_noLocale() {
768         VehiclePropValue prop = new VehiclePropValue();
769         prop.prop = UserHalHelper.INITIAL_USER_INFO_PROPERTY;
770         prop.value.int32Values.add(42); // request id
771         prop.value.int32Values.add(InitialUserInfoResponseAction.CREATE);
772         prop.value.int32Values.add(666); // user id - not used
773         prop.value.int32Values.add(UserFlags.GUEST);
774         prop.value.stringValue = "||ElGuesto";
775 
776         InitialUserInfoResponse response = UserHalHelper.toInitialUserInfoResponse(prop);
777 
778         assertThat(response).isNotNull();
779         assertThat(response.requestId).isEqualTo(42);
780         assertThat(response.action).isEqualTo(InitialUserInfoResponseAction.CREATE);
781         assertThat(response.userNameToCreate).isEqualTo("ElGuesto");
782         assertThat(response.userToSwitchOrCreate.userId).isEqualTo(UserHandle.USER_NULL);
783         assertThat(response.userToSwitchOrCreate.flags).isEqualTo(UserFlags.GUEST);
784         assertThat(response.userLocales).isEmpty();
785     }
786 
787     @Test
testToInitialUserInfoResponse_create_ok_withLocale()788     public void testToInitialUserInfoResponse_create_ok_withLocale() {
789         VehiclePropValue prop = new VehiclePropValue();
790         prop.prop = UserHalHelper.INITIAL_USER_INFO_PROPERTY;
791         prop.value.int32Values.add(42); // request id
792         prop.value.int32Values.add(InitialUserInfoResponseAction.CREATE);
793         prop.value.int32Values.add(666); // user id - not used
794         prop.value.int32Values.add(UserFlags.GUEST);
795         prop.value.stringValue = "esperanto,klingon||ElGuesto";
796 
797         InitialUserInfoResponse response = UserHalHelper.toInitialUserInfoResponse(prop);
798 
799         assertThat(response).isNotNull();
800         assertThat(response.requestId).isEqualTo(42);
801         assertThat(response.action).isEqualTo(InitialUserInfoResponseAction.CREATE);
802         assertThat(response.userNameToCreate).isEqualTo("ElGuesto");
803         assertThat(response.userToSwitchOrCreate.userId).isEqualTo(UserHandle.USER_NULL);
804         assertThat(response.userToSwitchOrCreate.flags).isEqualTo(UserFlags.GUEST);
805         assertThat(response.userLocales).isEqualTo("esperanto,klingon");
806     }
807 
808     @Test
testToInitialUserInfoResponse_create_ok_nameAndLocaleWithHalfDelimiter()809     public void testToInitialUserInfoResponse_create_ok_nameAndLocaleWithHalfDelimiter() {
810         VehiclePropValue prop = new VehiclePropValue();
811         prop.prop = UserHalHelper.INITIAL_USER_INFO_PROPERTY;
812         prop.value.int32Values.add(42); // request id
813         prop.value.int32Values.add(InitialUserInfoResponseAction.CREATE);
814         prop.value.int32Values.add(666); // user id - not used
815         prop.value.int32Values.add(UserFlags.GUEST);
816         prop.value.stringValue = "esperanto|klingon||El|Guesto";
817 
818         InitialUserInfoResponse response = UserHalHelper.toInitialUserInfoResponse(prop);
819 
820         assertThat(response).isNotNull();
821         assertThat(response.requestId).isEqualTo(42);
822         assertThat(response.action).isEqualTo(InitialUserInfoResponseAction.CREATE);
823         assertThat(response.userNameToCreate).isEqualTo("El|Guesto");
824         assertThat(response.userToSwitchOrCreate.userId).isEqualTo(UserHandle.USER_NULL);
825         assertThat(response.userToSwitchOrCreate.flags).isEqualTo(UserFlags.GUEST);
826         assertThat(response.userLocales).isEqualTo("esperanto|klingon");
827     }
828 
829     @Test
testUserIdentificationSetRequestToVehiclePropValue_null()830     public void testUserIdentificationSetRequestToVehiclePropValue_null() {
831         assertThrows(NullPointerException.class,
832                 () -> UserHalHelper.toVehiclePropValue((UserIdentificationSetRequest) null));
833     }
834 
835     @Test
testUserIdentificationSetRequestToVehiclePropValue_emptyRequest()836     public void testUserIdentificationSetRequestToVehiclePropValue_emptyRequest() {
837         UserIdentificationSetRequest request = new UserIdentificationSetRequest();
838 
839         assertThrows(IllegalArgumentException.class,
840                 () -> UserHalHelper.toVehiclePropValue(request));
841     }
842 
843     @Test
testUserIdentificationSetRequestToVehiclePropValue_wrongNumberOfAssociations()844     public void testUserIdentificationSetRequestToVehiclePropValue_wrongNumberOfAssociations() {
845         UserIdentificationSetRequest request = new UserIdentificationSetRequest();
846         request.numberAssociations = 1;
847 
848         assertThrows(IllegalArgumentException.class,
849                 () -> UserHalHelper.toVehiclePropValue(request));
850     }
851 
852     @Test
testUserIdentificationSetRequestToVehiclePropValue_invalidType()853     public void testUserIdentificationSetRequestToVehiclePropValue_invalidType() {
854         UserIdentificationSetRequest request = new UserIdentificationSetRequest();
855         request.numberAssociations = 1;
856         UserIdentificationSetAssociation association1 = new UserIdentificationSetAssociation();
857         request.associations.add(association1);
858         association1.type = CUSTOM_4 + 1;
859         association1.value = ASSOCIATE_CURRENT_USER;
860 
861         assertThrows(IllegalArgumentException.class,
862                 () -> UserHalHelper.toVehiclePropValue(request));
863     }
864 
865     @Test
testUserIdentificationSetRequestToVehiclePropValue_invalidValue()866     public void testUserIdentificationSetRequestToVehiclePropValue_invalidValue() {
867         UserIdentificationSetRequest request = new UserIdentificationSetRequest();
868         request.numberAssociations = 1;
869         UserIdentificationSetAssociation association1 = new UserIdentificationSetAssociation();
870         request.associations.add(association1);
871         association1.type = KEY_FOB;
872         association1.value = -1;
873 
874         assertThrows(IllegalArgumentException.class,
875                 () -> UserHalHelper.toVehiclePropValue(request));
876     }
877 
878     @Test
testUserIdentificationSetRequestToVehiclePropValue_missingRequestId()879     public void testUserIdentificationSetRequestToVehiclePropValue_missingRequestId() {
880         UserIdentificationSetRequest request = new UserIdentificationSetRequest();
881         request.userInfo.userId = 42;
882         request.userInfo.flags = 108;
883         request.numberAssociations = 1;
884         UserIdentificationSetAssociation association1 = new UserIdentificationSetAssociation();
885         association1.type = KEY_FOB;
886         association1.value = ASSOCIATE_CURRENT_USER;
887         request.associations.add(association1);
888 
889         assertThrows(IllegalArgumentException.class,
890                 () -> UserHalHelper.toVehiclePropValue(request));
891     }
892 
893     @Test
testUserIdentificationSetRequestToVehiclePropValue_ok()894     public void testUserIdentificationSetRequestToVehiclePropValue_ok() {
895         UserIdentificationSetRequest request = new UserIdentificationSetRequest();
896         request.requestId = 1;
897         request.userInfo.userId = 42;
898         request.userInfo.flags = 108;
899         request.numberAssociations = 2;
900         UserIdentificationSetAssociation association1 = new UserIdentificationSetAssociation();
901         association1.type = KEY_FOB;
902         association1.value = ASSOCIATE_CURRENT_USER;
903         request.associations.add(association1);
904         UserIdentificationSetAssociation association2 = new UserIdentificationSetAssociation();
905         association2.type = CUSTOM_1;
906         association2.value = DISASSOCIATE_CURRENT_USER;
907         request.associations.add(association2);
908 
909         VehiclePropValue propValue = UserHalHelper.toVehiclePropValue(request);
910         assertWithMessage("wrong prop on %s", propValue).that(propValue.prop)
911                 .isEqualTo(USER_IDENTIFICATION_ASSOCIATION_PROPERTY);
912         assertWithMessage("wrong int32values on %s", propValue).that(propValue.value.int32Values)
913                 .containsExactly(1, 42, 108, 2,
914                         KEY_FOB, ASSOCIATE_CURRENT_USER,
915                         CUSTOM_1, DISASSOCIATE_CURRENT_USER)
916                 .inOrder();
917     }
918 
919     @Test
testRemoveUserRequestToVehiclePropValue_null()920     public void testRemoveUserRequestToVehiclePropValue_null() {
921         assertThrows(NullPointerException.class,
922                 () -> UserHalHelper.toVehiclePropValue((RemoveUserRequest) null));
923     }
924 
925     @Test
testRemoveUserRequestToVehiclePropValue_emptyRequest()926     public void testRemoveUserRequestToVehiclePropValue_emptyRequest() {
927         RemoveUserRequest request = new RemoveUserRequest();
928 
929         assertThrows(IllegalArgumentException.class,
930                 () -> UserHalHelper.toVehiclePropValue(request));
931     }
932 
933     @Test
testRemoveUserRequestToVehiclePropValue_missingRequestId()934     public void testRemoveUserRequestToVehiclePropValue_missingRequestId() {
935         RemoveUserRequest request = new RemoveUserRequest();
936         request.removedUserInfo.userId = 11;
937         request.usersInfo.existingUsers.add(request.removedUserInfo);
938 
939         assertThrows(IllegalArgumentException.class,
940                 () -> UserHalHelper.toVehiclePropValue(request));
941     }
942 
943     @Test
testRemoveUserRequestToVehiclePropValue_ok()944     public void testRemoveUserRequestToVehiclePropValue_ok() {
945         RemoveUserRequest request = new RemoveUserRequest();
946         request.requestId = 42;
947 
948         android.hardware.automotive.vehicle.V2_0.UserInfo user10 =
949                 new android.hardware.automotive.vehicle.V2_0.UserInfo();
950         user10.userId = 10;
951         user10.flags = UserFlags.ADMIN;
952 
953         // existing users
954         request.usersInfo.numberUsers = 1;
955         request.usersInfo.existingUsers.add(user10);
956 
957         // current user
958         request.usersInfo.currentUser = user10;
959         // user to remove
960         request.removedUserInfo = user10;
961 
962         VehiclePropValue propValue = UserHalHelper.toVehiclePropValue(request);
963 
964         assertWithMessage("wrong prop on %s", propValue).that(propValue.prop)
965                 .isEqualTo(REMOVE_USER_PROPERTY);
966         assertWithMessage("wrong int32values on %s", propValue).that(propValue.value.int32Values)
967                 .containsExactly(42, // request id
968                         10, UserFlags.ADMIN, // user to remove
969                         10, UserFlags.ADMIN, // current user
970                         1, // number of users
971                         10, UserFlags.ADMIN  // existing user 1
972                         ).inOrder();
973     }
974 
975     @Test
testCreateUserRequestToVehiclePropValue_null()976     public void testCreateUserRequestToVehiclePropValue_null() {
977         assertThrows(NullPointerException.class,
978                 () -> UserHalHelper.toVehiclePropValue((CreateUserRequest) null));
979     }
980 
981     @Test
testCreateUserRequestToVehiclePropValue_emptyRequest()982     public void testCreateUserRequestToVehiclePropValue_emptyRequest() {
983         CreateUserRequest request = new CreateUserRequest();
984 
985         assertThrows(IllegalArgumentException.class,
986                 () -> UserHalHelper.toVehiclePropValue(request));
987     }
988 
989     @Test
testCreateUserRequestToVehiclePropValue_missingRequestId()990     public void testCreateUserRequestToVehiclePropValue_missingRequestId() {
991         CreateUserRequest request = new CreateUserRequest();
992         request.newUserInfo.userId = 10;
993         request.usersInfo.existingUsers.add(request.newUserInfo);
994 
995         assertThrows(IllegalArgumentException.class,
996                 () -> UserHalHelper.toVehiclePropValue(request));
997     }
998 
999     @Test
testCreateUserRequestToVehiclePropValue_nullNewUserName()1000     public void testCreateUserRequestToVehiclePropValue_nullNewUserName() {
1001         CreateUserRequest request = new CreateUserRequest();
1002         request.requestId = 42;
1003 
1004         request.newUserInfo.userId = 10;
1005         request.newUserInfo.flags = UserFlags.ADMIN;
1006         request.newUserName = null;
1007 
1008         request.usersInfo.numberUsers = 1;
1009         request.usersInfo.currentUser.userId = request.newUserInfo.userId;
1010         request.usersInfo.currentUser.flags = request.newUserInfo.flags;
1011         request.usersInfo.existingUsers.add(request.usersInfo.currentUser);
1012 
1013         assertThrows(IllegalArgumentException.class,
1014                 () -> UserHalHelper.toVehiclePropValue(request));
1015     }
1016 
1017     @Test
testCreateUserRequestToVehiclePropValue_usersInfoDoesNotContainNewUser()1018     public void testCreateUserRequestToVehiclePropValue_usersInfoDoesNotContainNewUser() {
1019         CreateUserRequest request = new CreateUserRequest();
1020         request.requestId = 42;
1021         request.newUserInfo.userId = 10;
1022         android.hardware.automotive.vehicle.V2_0.UserInfo user =
1023                 new android.hardware.automotive.vehicle.V2_0.UserInfo();
1024         user.userId = 11;
1025         request.usersInfo.existingUsers.add(user);
1026 
1027         assertThrows(IllegalArgumentException.class,
1028                 () -> UserHalHelper.toVehiclePropValue(request));
1029     }
1030 
1031     @Test
testCreateUserRequestToVehiclePropValue_newUserFlagsMismatch()1032     public void testCreateUserRequestToVehiclePropValue_newUserFlagsMismatch() {
1033         CreateUserRequest request = new CreateUserRequest();
1034         request.requestId = 42;
1035         request.newUserInfo.userId = 10;
1036         request.newUserInfo.flags = UserFlags.ADMIN;
1037         android.hardware.automotive.vehicle.V2_0.UserInfo user =
1038                 new android.hardware.automotive.vehicle.V2_0.UserInfo();
1039         user.userId = 10;
1040         request.newUserInfo.flags = UserFlags.SYSTEM;
1041         request.usersInfo.existingUsers.add(user);
1042 
1043         assertThrows(IllegalArgumentException.class,
1044                 () -> UserHalHelper.toVehiclePropValue(request));
1045     }
1046 
1047     @Test
testCreateUserRequestToVehiclePropValue_ok()1048     public void testCreateUserRequestToVehiclePropValue_ok() {
1049         CreateUserRequest request = new CreateUserRequest();
1050         request.requestId = 42;
1051 
1052         android.hardware.automotive.vehicle.V2_0.UserInfo user10 =
1053                 new android.hardware.automotive.vehicle.V2_0.UserInfo();
1054         user10.userId = 10;
1055         user10.flags = UserFlags.ADMIN;
1056         android.hardware.automotive.vehicle.V2_0.UserInfo user11 =
1057                 new android.hardware.automotive.vehicle.V2_0.UserInfo();
1058         user11.userId = 11;
1059         user11.flags = UserFlags.SYSTEM;
1060         android.hardware.automotive.vehicle.V2_0.UserInfo user12 =
1061                 new android.hardware.automotive.vehicle.V2_0.UserInfo();
1062         user12.userId = 12;
1063         user12.flags = UserFlags.GUEST;
1064 
1065         // existing users
1066         request.usersInfo.numberUsers = 3;
1067         request.usersInfo.existingUsers.add(user10);
1068         request.usersInfo.existingUsers.add(user11);
1069         request.usersInfo.existingUsers.add(user12);
1070 
1071         // current user
1072         request.usersInfo.currentUser.userId = 12;
1073         request.usersInfo.currentUser.flags = UserFlags.GUEST;
1074 
1075         // new user
1076         request.newUserInfo.userId = 10;
1077         request.newUserInfo.flags = UserFlags.ADMIN;
1078         request.newUserName = "Dude";
1079 
1080 
1081         VehiclePropValue propValue = UserHalHelper.toVehiclePropValue(request);
1082 
1083         assertWithMessage("wrong prop on %s", propValue).that(propValue.prop)
1084                 .isEqualTo(CREATE_USER_PROPERTY);
1085         assertWithMessage("wrong int32values on %s", propValue).that(propValue.value.int32Values)
1086                 .containsExactly(42, // request id
1087                         10, UserFlags.ADMIN, // new user
1088                         12, UserFlags.GUEST, // current user
1089                         3, // number of users
1090                         10, UserFlags.ADMIN,  // existing user 1
1091                         11, UserFlags.SYSTEM, // existing user 2
1092                         12, UserFlags.GUEST   // existing user 3
1093                         ).inOrder();
1094         assertWithMessage("wrong name %s", propValue).that(propValue.value.stringValue)
1095                 .isEqualTo("Dude");
1096     }
1097 
1098     @Test
testSwitchUserRequestToVehiclePropValue_null()1099     public void testSwitchUserRequestToVehiclePropValue_null() {
1100         assertThrows(NullPointerException.class,
1101                 () -> UserHalHelper.toVehiclePropValue((SwitchUserRequest) null));
1102     }
1103 
1104     @Test
testSwitchUserRequestToVehiclePropValue_emptyRequest()1105     public void testSwitchUserRequestToVehiclePropValue_emptyRequest() {
1106         SwitchUserRequest request = new SwitchUserRequest();
1107 
1108         assertThrows(IllegalArgumentException.class,
1109                 () -> UserHalHelper.toVehiclePropValue(request));
1110     }
1111 
1112     @Test
testSwitchUserRequestToVehiclePropValue_missingMessageType()1113     public void testSwitchUserRequestToVehiclePropValue_missingMessageType() {
1114         SwitchUserRequest request = new SwitchUserRequest();
1115         request.requestId = 42;
1116         android.hardware.automotive.vehicle.V2_0.UserInfo user10 =
1117                 new android.hardware.automotive.vehicle.V2_0.UserInfo();
1118         user10.userId = 10;
1119         request.usersInfo.numberUsers = 1;
1120         request.usersInfo.existingUsers.add(user10);
1121         request.usersInfo.currentUser = user10;
1122         request.targetUser = user10;
1123 
1124         assertThrows(IllegalArgumentException.class,
1125                 () -> UserHalHelper.toVehiclePropValue(request));
1126     }
1127 
1128     @Test
testSwitchUserRequestToVehiclePropValue_incorrectMessageType()1129     public void testSwitchUserRequestToVehiclePropValue_incorrectMessageType() {
1130         SwitchUserRequest request = new SwitchUserRequest();
1131         request.requestId = 42;
1132         request.messageType = -1;
1133         android.hardware.automotive.vehicle.V2_0.UserInfo user10 =
1134                 new android.hardware.automotive.vehicle.V2_0.UserInfo();
1135         user10.userId = 10;
1136         request.usersInfo.numberUsers = 1;
1137         request.usersInfo.existingUsers.add(user10);
1138         request.usersInfo.currentUser = user10;
1139         request.targetUser = user10;
1140 
1141         assertThrows(IllegalArgumentException.class,
1142                 () -> UserHalHelper.toVehiclePropValue(request));
1143     }
1144 
1145     @Test
tesSwitchUserRequestToVehiclePropValue_ok()1146     public void tesSwitchUserRequestToVehiclePropValue_ok() {
1147         SwitchUserRequest request = new SwitchUserRequest();
1148         request.requestId = 42;
1149         android.hardware.automotive.vehicle.V2_0.UserInfo user10 =
1150                 new android.hardware.automotive.vehicle.V2_0.UserInfo();
1151         user10.userId = 10;
1152         user10.flags = UserFlags.ADMIN;
1153         // existing users
1154         request.usersInfo.numberUsers = 1;
1155         request.usersInfo.existingUsers.add(user10);
1156         // current user
1157         request.usersInfo.currentUser = user10;
1158         // user to remove
1159         request.targetUser = user10;
1160         request.messageType = SwitchUserMessageType.ANDROID_SWITCH;
1161 
1162         VehiclePropValue propValue = UserHalHelper.toVehiclePropValue(request);
1163 
1164         assertWithMessage("wrong prop on %s", propValue).that(propValue.prop)
1165                 .isEqualTo(SWITCH_USER_PROPERTY);
1166         assertWithMessage("wrong int32values on %s", propValue).that(propValue.value.int32Values)
1167                 .containsExactly(42, // request id
1168                         SwitchUserMessageType.ANDROID_SWITCH, // message type
1169                         10, UserFlags.ADMIN, // target user
1170                         10, UserFlags.ADMIN, // current user
1171                         1, // number of users
1172                         10, UserFlags.ADMIN  // existing user 1
1173                         ).inOrder();
1174     }
1175 
1176     @Test
testNewUsersInfo_nullUm()1177     public void testNewUsersInfo_nullUm() {
1178         assertThrows(IllegalArgumentException.class, () -> UserHalHelper.newUsersInfo(null, 100));
1179     }
1180 
1181     @Test
testNewUsersInfo_nullUsers()1182     public void testNewUsersInfo_nullUsers() {
1183         UsersInfo usersInfo = UserHalHelper.newUsersInfo(mUm, 100);
1184 
1185         assertEmptyUsersInfo(usersInfo);
1186     }
1187 
1188     @Test
testNewUsersInfo_noUsers()1189     public void testNewUsersInfo_noUsers() {
1190         mockGetAllUsersButPrecreated(new UserInfo[0]);
1191 
1192         UsersInfo usersInfo = UserHalHelper.newUsersInfo(mUm, 100);
1193 
1194         assertEmptyUsersInfo(usersInfo);
1195     }
1196 
1197     @Test
testNewUsersInfo_ok()1198     public void testNewUsersInfo_ok() {
1199         UserInfo user100 = new UserInfoBuilder(100).setFlags(UserInfo.FLAG_ADMIN).build();
1200         UserInfo user200 = new UserInfoBuilder(200).build();
1201 
1202         mockGetAllUsersButPrecreated(user100, user200);
1203         mockAmGetCurrentUser(300); // just to make sure it's not used
1204 
1205         UsersInfo usersInfo = UserHalHelper.newUsersInfo(mUm, 100);
1206 
1207         assertThat(usersInfo).isNotNull();
1208         assertThat(usersInfo.currentUser.userId).isEqualTo(100);
1209         assertThat(usersInfo.currentUser.flags).isEqualTo(UserFlags.ADMIN);
1210 
1211         assertThat(usersInfo.numberUsers).isEqualTo(2);
1212         assertThat(usersInfo.existingUsers).hasSize(2);
1213 
1214         assertThat(usersInfo.existingUsers.get(0).userId).isEqualTo(100);
1215         assertThat(usersInfo.existingUsers.get(0).flags).isEqualTo(UserFlags.ADMIN);
1216         assertThat(usersInfo.existingUsers.get(1).userId).isEqualTo(200);
1217         assertThat(usersInfo.existingUsers.get(1).flags).isEqualTo(UserFlags.NONE);
1218     }
1219 
1220     @Test
testNewUsersInfo_currentUser_ok()1221     public void testNewUsersInfo_currentUser_ok() {
1222         UserInfo user100 = new UserInfoBuilder(100).setFlags(UserInfo.FLAG_ADMIN).build();
1223         UserInfo user200 = new UserInfoBuilder(200).build();
1224 
1225         mockGetAllUsersButPrecreated(user100, user200);
1226         mockAmGetCurrentUser(100);
1227 
1228         UsersInfo usersInfo = UserHalHelper.newUsersInfo(mUm);
1229 
1230         assertThat(usersInfo).isNotNull();
1231         assertThat(usersInfo.currentUser.userId).isEqualTo(100);
1232         assertThat(usersInfo.currentUser.flags).isEqualTo(UserFlags.ADMIN);
1233 
1234         assertThat(usersInfo.numberUsers).isEqualTo(2);
1235         assertThat(usersInfo.existingUsers).hasSize(2);
1236 
1237         assertThat(usersInfo.existingUsers.get(0).userId).isEqualTo(100);
1238         assertThat(usersInfo.existingUsers.get(0).flags).isEqualTo(UserFlags.ADMIN);
1239         assertThat(usersInfo.existingUsers.get(1).userId).isEqualTo(200);
1240         assertThat(usersInfo.existingUsers.get(1).flags).isEqualTo(UserFlags.NONE);
1241     }
1242 
1243     @Test
1244     @ExpectWtf
testNewUsersInfo_noCurrentUser()1245     public void testNewUsersInfo_noCurrentUser() {
1246         UserInfo user100 = new UserInfoBuilder(100).setFlags(UserInfo.FLAG_ADMIN).build();
1247         UserInfo user200 = new UserInfoBuilder(200).build();
1248 
1249         mockGetAllUsersButPrecreated(user100, user200);
1250         mockAmGetCurrentUser(300);
1251 
1252         UsersInfo usersInfo = UserHalHelper.newUsersInfo(mUm);
1253 
1254         assertThat(usersInfo).isNotNull();
1255         assertThat(usersInfo.currentUser.userId).isEqualTo(300);
1256         assertThat(usersInfo.currentUser.flags).isEqualTo(UserFlags.NONE);
1257 
1258         assertThat(usersInfo.numberUsers).isEqualTo(2);
1259         assertThat(usersInfo.existingUsers).hasSize(2);
1260 
1261         assertThat(usersInfo.existingUsers.get(0).userId).isEqualTo(100);
1262         assertThat(usersInfo.existingUsers.get(0).flags).isEqualTo(UserFlags.ADMIN);
1263         assertThat(usersInfo.existingUsers.get(1).userId).isEqualTo(200);
1264         assertThat(usersInfo.existingUsers.get(1).flags).isEqualTo(UserFlags.NONE);
1265     }
1266 
1267     @Test
testCheckValidUsersInfo_null()1268     public void testCheckValidUsersInfo_null() {
1269         assertThrows(IllegalArgumentException.class, () -> UserHalHelper.checkValid(null));
1270     }
1271 
1272     @Test
testCheckValidUsersInfo_empty()1273     public void testCheckValidUsersInfo_empty() {
1274         UsersInfo usersInfo = new UsersInfo();
1275         assertThrows(IllegalArgumentException.class, () -> UserHalHelper.checkValid(usersInfo));
1276     }
1277 
1278     @Test
testCheckValidUsersInfo_sizeMismatch()1279     public void testCheckValidUsersInfo_sizeMismatch() {
1280         UsersInfo usersInfo = new UsersInfo();
1281         usersInfo.numberUsers = 1;
1282         assertThrows(IllegalArgumentException.class, () -> UserHalHelper.checkValid(usersInfo));
1283     }
1284 
1285     @Test
testCheckValidUsersInfo_currentUserMissing()1286     public void testCheckValidUsersInfo_currentUserMissing() {
1287         UsersInfo usersInfo = new UsersInfo();
1288         usersInfo.numberUsers = 1;
1289         usersInfo.currentUser.userId = 10;
1290         usersInfo.existingUsers.add(new android.hardware.automotive.vehicle.V2_0.UserInfo());
1291 
1292         assertThrows(IllegalArgumentException.class, () -> UserHalHelper.checkValid(usersInfo));
1293     }
1294 
1295     @Test
testCheckValidUsersInfo_currentUserFlagsMismatch()1296     public void testCheckValidUsersInfo_currentUserFlagsMismatch() {
1297         UsersInfo usersInfo = new UsersInfo();
1298         usersInfo.numberUsers = 1;
1299         usersInfo.currentUser.userId = 10;
1300         usersInfo.currentUser.flags = UserFlags.ADMIN;
1301         android.hardware.automotive.vehicle.V2_0.UserInfo currentUser =
1302                 new android.hardware.automotive.vehicle.V2_0.UserInfo();
1303         currentUser.userId = 10;
1304         currentUser.flags = UserFlags.SYSTEM;
1305         usersInfo.existingUsers.add(currentUser);
1306 
1307         assertThrows(IllegalArgumentException.class, () -> UserHalHelper.checkValid(usersInfo));
1308     }
1309 
1310     @Test
testCheckValidUsersInfo_ok()1311     public void testCheckValidUsersInfo_ok() {
1312         UsersInfo usersInfo = new UsersInfo();
1313         usersInfo.numberUsers = 1;
1314         usersInfo.currentUser.userId = 10;
1315 
1316         android.hardware.automotive.vehicle.V2_0.UserInfo currentUser =
1317                 new android.hardware.automotive.vehicle.V2_0.UserInfo();
1318         currentUser.userId = 10;
1319         usersInfo.existingUsers.add(currentUser);
1320 
1321         UserHalHelper.checkValid(usersInfo);
1322     }
1323 
mockGetAllUsersButPrecreated(@onNull UserInfo... users)1324     private void mockGetAllUsersButPrecreated(@NonNull UserInfo... users) {
1325         mockUmGetUsers(mUm, /* excludePartial= */ false, /* excludeDying= */ false,
1326                 /* excludePreCreated= */ true, Arrays.asList(users));
1327     }
1328 
assertEmptyUsersInfo(UsersInfo usersInfo)1329     private static void assertEmptyUsersInfo(UsersInfo usersInfo) {
1330         assertThat(usersInfo).isNotNull();
1331         assertThat(usersInfo.currentUser.userId).isEqualTo(UserHandle.USER_NULL);
1332         assertThat(usersInfo.currentUser.flags).isEqualTo(UserFlags.NONE);
1333         assertThat(usersInfo.numberUsers).isEqualTo(0);
1334         assertThat(usersInfo.existingUsers).isEmpty();
1335     }
1336 
assertAssociation(@onNull UserIdentificationResponse response, int index, int expectedType, int expectedValue)1337     private static void assertAssociation(@NonNull UserIdentificationResponse response, int index,
1338             int expectedType, int expectedValue) {
1339         UserIdentificationAssociation actualAssociation = response.associations.get(index);
1340         if (actualAssociation.type != expectedType) {
1341             fail("Wrong type for association at index " + index + " on " + response + "; expected "
1342                     + UserIdentificationAssociationType.toString(expectedType) + ", got "
1343                     + UserIdentificationAssociationType.toString(actualAssociation.type));
1344         }
1345         if (actualAssociation.type != expectedType) {
1346             fail("Wrong value for association at index " + index + " on " + response + "; expected "
1347                     + UserIdentificationAssociationValue.toString(expectedValue) + ", got "
1348                     + UserIdentificationAssociationValue.toString(actualAssociation.value));
1349         }
1350     }
1351 }
1352