1 /* 2 * Copyright (C) 2019 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 com.android.car; 18 19 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; 20 21 import static com.google.common.truth.Truth.assertThat; 22 import static com.google.common.truth.Truth.assertWithMessage; 23 24 import static org.junit.Assert.fail; 25 import static org.mockito.ArgumentMatchers.any; 26 import static org.mockito.Mockito.doReturn; 27 import static org.mockito.Mockito.when; 28 import static org.testng.Assert.assertThrows; 29 import static org.testng.Assert.expectThrows; 30 31 import android.annotation.UserIdInt; 32 import android.car.Car; 33 import android.car.CarOccupantZoneManager; 34 import android.car.CarOccupantZoneManager.OccupantZoneInfo; 35 import android.car.VehicleAreaSeat; 36 import android.car.media.CarAudioManager; 37 import android.car.user.CarUserManager; 38 import android.car.user.CarUserManager.UserLifecycleEvent; 39 import android.content.Context; 40 import android.content.pm.ApplicationInfo; 41 import android.content.res.Resources; 42 import android.hardware.display.DisplayManager; 43 import android.os.Looper; 44 import android.os.UserHandle; 45 import android.os.UserManager; 46 import android.util.ArrayMap; 47 import android.util.SparseArray; 48 import android.util.SparseIntArray; 49 import android.view.Display; 50 import android.view.DisplayAddress; 51 52 import com.android.car.CarOccupantZoneService.DisplayConfig; 53 import com.android.car.CarOccupantZoneService.DisplayInfo; 54 import com.android.car.CarOccupantZoneService.OccupantConfig; 55 import com.android.car.user.CarUserService; 56 import com.android.car.user.UserHandleHelper; 57 58 import org.junit.After; 59 import org.junit.Before; 60 import org.junit.Test; 61 import org.junit.runner.RunWith; 62 import org.mockito.Mock; 63 import org.mockito.junit.MockitoJUnitRunner; 64 65 import java.util.ArrayList; 66 import java.util.Arrays; 67 import java.util.HashMap; 68 import java.util.LinkedList; 69 import java.util.List; 70 import java.util.concurrent.Semaphore; 71 import java.util.concurrent.TimeUnit; 72 import java.util.stream.Collectors; 73 74 @RunWith(MockitoJUnitRunner.class) 75 public class CarOccupantZoneServiceTest { 76 77 private static final String TAG = CarOccupantZoneServiceTest.class.getSimpleName(); 78 79 private CarOccupantZoneService mService; 80 private CarOccupantZoneManager mManager; 81 82 @Mock 83 private CarPropertyService mCarPropertyService; 84 85 @Mock 86 private CarUserService mCarUserService; 87 88 @Mock 89 private UserHandleHelper mUserHandleHelper; 90 91 @Mock 92 private Context mContext; 93 94 @Mock 95 private DisplayManager mDisplayManager; 96 97 @Mock 98 private UserManager mUserManager; 99 100 @Mock 101 private Resources mResources; 102 103 @Mock 104 private Display mDisplay0; 105 106 @Mock 107 private Display mDisplay1; 108 109 @Mock 110 private Display mDisplay2; 111 112 @Mock 113 private Display mDisplay3; // not listed by default 114 115 @Mock 116 private Display mDisplay4; 117 118 @Mock 119 private Display mDisplay5; // outside display config and become unknown display 120 121 private static final int CURRENT_USER = 100; 122 private static final int PROFILE_USER1 = 1001; 123 private static final int PROFILE_USER2 = 1002; 124 125 private static final String[] DEFAULT_OCCUPANT_ZONES = { 126 "occupantZoneId=0,occupantType=DRIVER,seatRow=1,seatSide=driver", 127 "occupantZoneId=1,occupantType=FRONT_PASSENGER,seatRow=1,seatSide=oppositeDriver", 128 "occupantZoneId=2,occupantType=REAR_PASSENGER,seatRow=2,seatSide=left", 129 "occupantZoneId=3,occupantType=REAR_PASSENGER,seatRow=2,seatSide=right" 130 }; 131 132 private static final int PRIMARY_AUDIO_ZONE_ID = 0; 133 private static final int PRIMARY_AUDIO_ZONE_ID_OCCUPANT = 0; 134 private static final int SECONDARY_AUDIO_ZONE_ID = 1; 135 private static final int SECONDARY_AUDIO_ZONE_ID_OCCUPANT = 3; 136 private static final int UNMAPPED_AUDIO_ZONE_ID_OCCUPANT = 2; 137 private static final int INVALID_AUDIO_ZONE_ID_OCCUPANT = 100; 138 139 // LHD : Left Hand Drive 140 private final OccupantZoneInfo mZoneDriverLHD = new OccupantZoneInfo(0, 141 CarOccupantZoneManager.OCCUPANT_TYPE_DRIVER, 142 VehicleAreaSeat.SEAT_ROW_1_LEFT); 143 private final OccupantZoneInfo mZoneFrontPassengerLHD = new OccupantZoneInfo(1, 144 CarOccupantZoneManager.OCCUPANT_TYPE_FRONT_PASSENGER, 145 VehicleAreaSeat.SEAT_ROW_1_RIGHT); 146 private final OccupantZoneInfo mZoneRearLeft = new OccupantZoneInfo(2, 147 CarOccupantZoneManager.OCCUPANT_TYPE_REAR_PASSENGER, 148 VehicleAreaSeat.SEAT_ROW_2_LEFT); 149 private final OccupantZoneInfo mZoneRearRight = new OccupantZoneInfo(3, 150 CarOccupantZoneManager.OCCUPANT_TYPE_REAR_PASSENGER, 151 VehicleAreaSeat.SEAT_ROW_2_RIGHT); 152 153 private static final String CLUSTER_DISPLAY_UNIQUE_ID = 154 "virtual:android.car.cluster.ClusterDisplay0"; 155 // port address set to mocked displayid + 10 so that any possible mix of port address and 156 // display id can be detected. 157 private static final String[] DEFAULT_OCCUPANT_DISPLAY_MAPPING = { 158 "displayPort=10,displayType=MAIN,occupantZoneId=0", 159 "displayUniqueId=" + CLUSTER_DISPLAY_UNIQUE_ID 160 + ",displayType=INSTRUMENT_CLUSTER,occupantZoneId=0", 161 "displayPort=12,displayType=MAIN,occupantZoneId=1", 162 "displayPort=13,displayType=MAIN,occupantZoneId=2", 163 "displayPort=14,displayType=MAIN,occupantZoneId=3" 164 }; 165 166 // Stores last changeFlags from onOccupantZoneConfigChanged call. 167 private int mLastChangeFlags; 168 private final Semaphore mChangeEventSignal = new Semaphore(0); 169 170 private final ICarServiceHelperImpl mICarServiceHelper = new ICarServiceHelperImpl(); 171 172 private final CarOccupantZoneManager.OccupantZoneConfigChangeListener mChangeListener = 173 new CarOccupantZoneManager.OccupantZoneConfigChangeListener() { 174 @Override 175 public void onOccupantZoneConfigChanged(int changeFlags) { 176 // should be dispatched to main thread. 177 assertThat(Looper.getMainLooper()).isEqualTo(Looper.myLooper()); 178 mLastChangeFlags = changeFlags; 179 mChangeEventSignal.release(); 180 } 181 }; 182 resetConfigChangeEventWait()183 private void resetConfigChangeEventWait() { 184 mLastChangeFlags = 0; 185 mChangeEventSignal.drainPermits(); 186 } 187 waitForConfigChangeEventAndAssertFlag(long timeoutMs, int expectedFlag)188 private boolean waitForConfigChangeEventAndAssertFlag(long timeoutMs, int expectedFlag) { 189 boolean acquired = false; 190 try { 191 acquired = mChangeEventSignal.tryAcquire(timeoutMs, TimeUnit.MILLISECONDS); 192 } catch (Exception ignored) { 193 194 } 195 if (acquired) { 196 assertThat(expectedFlag).isEqualTo(mLastChangeFlags); 197 } 198 return acquired; 199 } 200 mockDisplay(DisplayManager displayManager, Display display, int displayId, int portAddress)201 private void mockDisplay(DisplayManager displayManager, Display display, int displayId, 202 int portAddress) { 203 when(displayManager.getDisplay(displayId)).thenReturn(display); 204 when(display.getDisplayId()).thenReturn(displayId); 205 when(display.getAddress()).thenReturn(DisplayAddress.fromPhysicalDisplayId(portAddress)); 206 } 207 mockDisplay(DisplayManager displayManager, Display display, int displayId, String uniqueId)208 private void mockDisplay(DisplayManager displayManager, Display display, int displayId, 209 String uniqueId) { 210 when(displayManager.getDisplay(displayId)).thenReturn(display); 211 when(display.getDisplayId()).thenReturn(displayId); 212 when(display.getUniqueId()).thenReturn(uniqueId); 213 } 214 215 @Before setUp()216 public void setUp() { 217 when(mContext.getResources()).thenReturn(mResources); 218 when(mContext.getSystemService(DisplayManager.class)).thenReturn(mDisplayManager); 219 when(mResources.getStringArray(R.array.config_occupant_zones)) 220 .thenReturn(DEFAULT_OCCUPANT_ZONES); 221 when(mResources.getStringArray(R.array.config_occupant_display_mapping)) 222 .thenReturn(DEFAULT_OCCUPANT_DISPLAY_MAPPING); 223 when(mContext.getApplicationInfo()).thenReturn(new ApplicationInfo()); 224 // Stored as static: Other tests can leave things behind and fail this test in add call. 225 // So just remove as safety guard. 226 CarLocalServices.removeServiceForTest(CarPropertyService.class); 227 CarLocalServices.addService(CarPropertyService.class, mCarPropertyService); 228 CarLocalServices.removeServiceForTest(CarUserService.class); 229 CarLocalServices.addService(CarUserService.class, mCarUserService); 230 mockDisplay(mDisplayManager, mDisplay0, 0, 10); 231 mockDisplay(mDisplayManager, mDisplay1, 1, CLUSTER_DISPLAY_UNIQUE_ID); 232 mockDisplay(mDisplayManager, mDisplay2, 2, 12); 233 mockDisplay(mDisplayManager, mDisplay4, 4, 14); 234 mockDisplay(mDisplayManager, mDisplay5, 5, 15); 235 when(mDisplayManager.getDisplays()).thenReturn(new Display[]{ 236 mDisplay0, 237 mDisplay1, 238 mDisplay2, 239 mDisplay4, 240 mDisplay5 241 }); 242 243 mService = new CarOccupantZoneService(mContext, mDisplayManager, mUserManager, 244 /* enableProfileUserAssignmentForMultiDisplay= */ false, mUserHandleHelper); 245 spyOn(mService); 246 doReturn(VehicleAreaSeat.SEAT_ROW_1_LEFT).when(mService).getDriverSeat(); 247 doReturn(CURRENT_USER).when(mService).getCurrentUser(); 248 249 Car car = new Car(mContext, /* service= */ null, /* handler= */ null); 250 mManager = new CarOccupantZoneManager(car, mService); 251 } 252 253 @After tearDown()254 public void tearDown() { 255 CarLocalServices.removeServiceForTest(CarUserService.class); 256 CarLocalServices.removeServiceForTest(CarPropertyService.class); 257 } 258 259 @Test testDefaultOccupantConfig()260 public void testDefaultOccupantConfig() { 261 mService.init(); 262 263 // key : zone id 264 SparseArray<OccupantZoneInfo> configs = mService.getOccupantsConfig(); 265 assertThat(configs.size()).isEqualTo(DEFAULT_OCCUPANT_ZONES.length); 266 assertThat(mZoneDriverLHD).isEqualTo(configs.get(0)); 267 assertThat(mZoneFrontPassengerLHD).isEqualTo(configs.get(1)); 268 assertThat(mZoneRearLeft).isEqualTo(configs.get(2)); 269 assertThat(mZoneRearRight).isEqualTo(configs.get(3)); 270 } 271 272 @Test testDefaultAudioZoneConfig()273 public void testDefaultAudioZoneConfig() { 274 mService.init(); 275 SparseIntArray audioConfigs = mService.getAudioConfigs(); 276 assertThat(audioConfigs.size()).isEqualTo(0); 277 } 278 279 /** RHD: Right Hand Drive */ 280 @Test testDefaultOccupantConfigForRHD()281 public void testDefaultOccupantConfigForRHD() { 282 // driver is right side and opposite should be left. 283 doReturn(VehicleAreaSeat.SEAT_ROW_1_RIGHT).when(mService).getDriverSeat(); 284 285 mService.init(); 286 287 // key : zone id 288 SparseArray<OccupantZoneInfo> configs = mService.getOccupantsConfig(); 289 assertThat(configs.size()).isEqualTo(DEFAULT_OCCUPANT_ZONES.length); 290 assertThat(new OccupantZoneInfo(0, CarOccupantZoneManager.OCCUPANT_TYPE_DRIVER, 291 VehicleAreaSeat.SEAT_ROW_1_RIGHT)).isEqualTo(configs.get(0)); 292 assertThat(new OccupantZoneInfo(1, CarOccupantZoneManager.OCCUPANT_TYPE_FRONT_PASSENGER, 293 VehicleAreaSeat.SEAT_ROW_1_LEFT)).isEqualTo(configs.get(1)); 294 assertThat(mZoneRearLeft).isEqualTo(configs.get(2)); 295 assertThat(mZoneRearRight).isEqualTo(configs.get(3)); 296 } 297 assertDisplayConfig(DisplayConfig c, int displayType, int occupantZoneId)298 private void assertDisplayConfig(DisplayConfig c, int displayType, int occupantZoneId) { 299 assertThat(displayType).isEqualTo(c.displayType); 300 assertThat(occupantZoneId).isEqualTo(c.occupantZoneId); 301 } 302 303 @Test testDefaultOccupantDisplayMapping()304 public void testDefaultOccupantDisplayMapping() { 305 mService.init(); 306 307 // key: display port address 308 SparseArray<DisplayConfig> configs = mService.getDisplayPortConfigs(); 309 assertDisplayConfig(configs.get(10), CarOccupantZoneManager.DISPLAY_TYPE_MAIN, 0); 310 assertDisplayConfig(configs.get(12), CarOccupantZoneManager.DISPLAY_TYPE_MAIN, 1); 311 assertDisplayConfig(configs.get(13), CarOccupantZoneManager.DISPLAY_TYPE_MAIN, 2); 312 assertDisplayConfig(configs.get(14), CarOccupantZoneManager.DISPLAY_TYPE_MAIN, 3); 313 314 ArrayMap<String, DisplayConfig> uniqueIdConfigs = mService.getDisplayUniqueIdConfigs(); 315 assertDisplayConfig(uniqueIdConfigs.get(CLUSTER_DISPLAY_UNIQUE_ID), 316 CarOccupantZoneManager.DISPLAY_TYPE_INSTRUMENT_CLUSTER, 0); 317 318 assertWithMessage( 319 "The sum of portConfigSize(%s) and uniqueIdConfigSize(%s) should be equal to " 320 + "mapping size(%s).", configs.size(), uniqueIdConfigs.size(), 321 DEFAULT_OCCUPANT_DISPLAY_MAPPING.length).that( 322 configs.size() + uniqueIdConfigs.size()).isEqualTo( 323 DEFAULT_OCCUPANT_DISPLAY_MAPPING.length); 324 } 325 setUpServiceWithProfileSupportEnabled()326 private void setUpServiceWithProfileSupportEnabled() { 327 mService = new CarOccupantZoneService(mContext, mDisplayManager, mUserManager, 328 /* enableProfileUserAssignmentForMultiDisplay= */ true, mUserHandleHelper); 329 spyOn(mService); 330 doReturn(VehicleAreaSeat.SEAT_ROW_1_LEFT).when(mService).getDriverSeat(); 331 doReturn(CURRENT_USER).when(mService).getCurrentUser(); 332 LinkedList<UserHandle> profileUsers = new LinkedList<>(); 333 profileUsers.add(UserHandle.of(PROFILE_USER1)); 334 profileUsers.add(UserHandle.of(PROFILE_USER2)); 335 doReturn(profileUsers).when(mUserHandleHelper).getEnabledProfiles(CURRENT_USER); 336 doReturn(true).when(mUserManager).isUserRunning(any()); 337 338 Car car = new Car(mContext, /* service= */ null, /* handler= */ null); 339 mManager = new CarOccupantZoneManager(car, mService); 340 } 341 342 @Test testAssignProfileUserFailForNonProfileUser()343 public void testAssignProfileUserFailForNonProfileUser() throws Exception { 344 setUpServiceWithProfileSupportEnabled(); 345 mService.init(); 346 347 int invalidProfileUser = 2000; 348 assertThat(mManager.assignProfileUserToOccupantZone(mZoneFrontPassengerLHD, 349 invalidProfileUser)).isFalse(); 350 } 351 assertDisplayAllowlist(int userId, int[] displays)352 private void assertDisplayAllowlist(int userId, int[] displays) { 353 assertThat(mICarServiceHelper.mAllowlists).containsKey(userId); 354 assertThat(mICarServiceHelper.mAllowlists.get(userId)).hasSize(displays.length); 355 for (int display : displays) { 356 assertThat(mICarServiceHelper.mAllowlists.get(userId)).contains(display); 357 } 358 } 359 assertPassengerDisplaysFromDefaultConfig()360 private void assertPassengerDisplaysFromDefaultConfig() throws Exception { 361 assertThat(mICarServiceHelper.mPassengerDisplayIds).hasSize(2); 362 assertThat(mICarServiceHelper.mPassengerDisplayIds).contains( 363 mDisplay2.getDisplayId()); 364 assertThat(mICarServiceHelper.mPassengerDisplayIds).contains( 365 mDisplay4.getDisplayId()); 366 } 367 368 @Test testAssignProfileUserOnce()369 public void testAssignProfileUserOnce() throws Exception { 370 setUpServiceWithProfileSupportEnabled(); 371 mService.init(); 372 mService.setCarServiceHelper(mICarServiceHelper); 373 374 assertPassengerDisplaysFromDefaultConfig(); 375 376 mICarServiceHelper.mAllowlists.clear(); 377 assertThat(mManager.assignProfileUserToOccupantZone(mZoneFrontPassengerLHD, 378 PROFILE_USER1)).isTrue(); 379 assertPassengerDisplaysFromDefaultConfig(); 380 assertDisplayAllowlist(CURRENT_USER, new int[]{mDisplay4.getDisplayId()}); 381 assertDisplayAllowlist(PROFILE_USER1, new int[]{mDisplay2.getDisplayId()}); 382 } 383 384 @Test testAssignProfileUserFailForStoppedUser()385 public void testAssignProfileUserFailForStoppedUser() throws Exception { 386 setUpServiceWithProfileSupportEnabled(); 387 mService.init(); 388 mService.setCarServiceHelper(mICarServiceHelper); 389 390 assertPassengerDisplaysFromDefaultConfig(); 391 392 mICarServiceHelper.mAllowlists.clear(); 393 doReturn(false).when(mUserManager).isUserRunning(UserHandle.of(PROFILE_USER1)); 394 assertThat(mManager.assignProfileUserToOccupantZone(mZoneFrontPassengerLHD, 395 PROFILE_USER1)).isFalse(); 396 } 397 398 @Test testAssignProfileUserSwitch()399 public void testAssignProfileUserSwitch() throws Exception { 400 setUpServiceWithProfileSupportEnabled(); 401 mService.init(); 402 mService.setCarServiceHelper(mICarServiceHelper); 403 404 assertThat(mManager.assignProfileUserToOccupantZone(mZoneFrontPassengerLHD, 405 PROFILE_USER1)).isTrue(); 406 407 assertPassengerDisplaysFromDefaultConfig(); 408 assertDisplayAllowlist(CURRENT_USER, new int[]{mDisplay4.getDisplayId()}); 409 assertDisplayAllowlist(PROFILE_USER1, new int[]{mDisplay2.getDisplayId()}); 410 411 mICarServiceHelper.mAllowlists.clear(); 412 assertThat(mManager.assignProfileUserToOccupantZone(mZoneFrontPassengerLHD, 413 PROFILE_USER2)).isTrue(); 414 assertPassengerDisplaysFromDefaultConfig(); 415 assertDisplayAllowlist(CURRENT_USER, new int[]{mDisplay4.getDisplayId()}); 416 assertDisplayAllowlist(PROFILE_USER2, new int[]{mDisplay2.getDisplayId()}); 417 } 418 419 @Test testAssignProfileFollowedByUserSwitch()420 public void testAssignProfileFollowedByUserSwitch() throws Exception { 421 setUpServiceWithProfileSupportEnabled(); 422 mService.init(); 423 mService.setCarServiceHelper(mICarServiceHelper); 424 425 assertThat(mManager.assignProfileUserToOccupantZone(mZoneFrontPassengerLHD, 426 PROFILE_USER1)).isTrue(); 427 428 assertPassengerDisplaysFromDefaultConfig(); 429 assertDisplayAllowlist(CURRENT_USER, new int[]{mDisplay4.getDisplayId()}); 430 assertDisplayAllowlist(PROFILE_USER1, new int[]{mDisplay2.getDisplayId()}); 431 432 mICarServiceHelper.mAllowlists.clear(); 433 int newUserId = 200; 434 doReturn(newUserId).when(mService).getCurrentUser(); 435 mService.mUserLifecycleListener.onEvent(new UserLifecycleEvent( 436 CarUserManager.USER_LIFECYCLE_EVENT_TYPE_SWITCHING, newUserId)); 437 438 assertPassengerDisplaysFromDefaultConfig(); 439 assertDisplayAllowlist(newUserId, new int[]{mDisplay2.getDisplayId(), 440 mDisplay4.getDisplayId()}); 441 assertThat(mICarServiceHelper.mAllowlists).hasSize(1); 442 } 443 444 @Test testAssignProfileFollowedByNullUserAssignment()445 public void testAssignProfileFollowedByNullUserAssignment() throws Exception { 446 setUpServiceWithProfileSupportEnabled(); 447 mService.init(); 448 mService.setCarServiceHelper(mICarServiceHelper); 449 450 assertThat(mManager.assignProfileUserToOccupantZone(mZoneFrontPassengerLHD, 451 PROFILE_USER1)).isTrue(); 452 453 assertPassengerDisplaysFromDefaultConfig(); 454 assertDisplayAllowlist(CURRENT_USER, new int[]{mDisplay4.getDisplayId()}); 455 assertDisplayAllowlist(PROFILE_USER1, new int[]{mDisplay2.getDisplayId()}); 456 457 mICarServiceHelper.mAllowlists.clear(); 458 assertThat(mManager.assignProfileUserToOccupantZone(mZoneFrontPassengerLHD, 459 UserHandle.USER_NULL)).isTrue(); 460 assertPassengerDisplaysFromDefaultConfig(); 461 assertDisplayAllowlist(CURRENT_USER, new int[]{mDisplay2.getDisplayId(), 462 mDisplay4.getDisplayId()}); 463 assertThat(mICarServiceHelper.mAllowlists).hasSize(1); 464 } 465 466 @Test testCarServiceHelperInitialUpdate()467 public void testCarServiceHelperInitialUpdate() throws Exception { 468 setUpServiceWithProfileSupportEnabled(); 469 mService.init(); 470 mService.setCarServiceHelper(mICarServiceHelper); 471 472 assertPassengerDisplaysFromDefaultConfig(); 473 assertDisplayAllowlist(CURRENT_USER, new int[]{mDisplay2.getDisplayId(), 474 mDisplay4.getDisplayId()}); 475 assertThat(mICarServiceHelper.mAllowlists).hasSize(1); 476 } 477 assertDisplayInfoIncluded( ArrayList<DisplayInfo> displayInfos, Display display, int displayType)478 private void assertDisplayInfoIncluded( 479 ArrayList<DisplayInfo> displayInfos, Display display, int displayType) { 480 for (DisplayInfo info : displayInfos) { 481 if (info.display == display && info.displayType == displayType) { 482 return; 483 } 484 } 485 fail("Cannot find display:" + display + " type:" + displayType); 486 } 487 assertOccupantConfig(OccupantConfig c, int userId, Display[] displays, int[] displayTypes)488 private void assertOccupantConfig(OccupantConfig c, int userId, Display[] displays, 489 int[] displayTypes) { 490 assertThat(userId).isEqualTo(c.userId); 491 assertThat(c.displayInfos).hasSize(displays.length); 492 assertThat(c.displayInfos).hasSize(displayTypes.length); 493 for (int i = 0; i < displays.length; i++) { 494 assertDisplayInfoIncluded(c.displayInfos, displays[i], displayTypes[i]); 495 } 496 } 497 498 @Test testSetAudioConfigMapping()499 public void testSetAudioConfigMapping() { 500 mService.init(); 501 502 SparseIntArray audioZoneIdToOccupantZoneMapping = 503 getDefaultAudioZoneToOccupantZoneMapping(); 504 505 mService.setAudioZoneIdsForOccupantZoneIds(audioZoneIdToOccupantZoneMapping); 506 507 assertThat(mService.getAudioZoneIdForOccupant(PRIMARY_AUDIO_ZONE_ID_OCCUPANT)) 508 .isEqualTo(PRIMARY_AUDIO_ZONE_ID); 509 510 assertThat(mService.getAudioZoneIdForOccupant(SECONDARY_AUDIO_ZONE_ID_OCCUPANT)) 511 .isEqualTo(SECONDARY_AUDIO_ZONE_ID); 512 } 513 getDefaultAudioZoneToOccupantZoneMapping()514 private SparseIntArray getDefaultAudioZoneToOccupantZoneMapping() { 515 SparseIntArray audioZoneIdToOccupantZoneMapping = new SparseIntArray(2); 516 audioZoneIdToOccupantZoneMapping.put(PRIMARY_AUDIO_ZONE_ID, 517 PRIMARY_AUDIO_ZONE_ID_OCCUPANT); 518 audioZoneIdToOccupantZoneMapping.put(SECONDARY_AUDIO_ZONE_ID, 519 SECONDARY_AUDIO_ZONE_ID_OCCUPANT); 520 return audioZoneIdToOccupantZoneMapping; 521 } 522 523 @Test testOccupantZoneConfigInfoForAudio()524 public void testOccupantZoneConfigInfoForAudio() { 525 mService.init(); 526 SparseIntArray audioZoneIdToOccupantZoneMapping = 527 getDefaultAudioZoneToOccupantZoneMapping(); 528 529 SparseArray<CarOccupantZoneManager.OccupantZoneInfo> occupantZoneConfigs = 530 mService.getOccupantsConfig(); 531 532 mService.setAudioZoneIdsForOccupantZoneIds(audioZoneIdToOccupantZoneMapping); 533 534 CarOccupantZoneManager.OccupantZoneInfo primaryOccupantInfo = 535 mService.getOccupantForAudioZoneId(PRIMARY_AUDIO_ZONE_ID); 536 assertThat(primaryOccupantInfo).isEqualTo( 537 occupantZoneConfigs.get(PRIMARY_AUDIO_ZONE_ID_OCCUPANT)); 538 539 CarOccupantZoneManager.OccupantZoneInfo secondaryOccupantInfo = 540 mService.getOccupantForAudioZoneId(SECONDARY_AUDIO_ZONE_ID); 541 assertThat(secondaryOccupantInfo).isEqualTo( 542 occupantZoneConfigs.get(SECONDARY_AUDIO_ZONE_ID_OCCUPANT)); 543 544 CarOccupantZoneManager.OccupantZoneInfo nullOccupantInfo = 545 mService.getOccupantForAudioZoneId(UNMAPPED_AUDIO_ZONE_ID_OCCUPANT); 546 assertThat(nullOccupantInfo).isNull(); 547 } 548 549 @Test testMissingAudioConfigMapping()550 public void testMissingAudioConfigMapping() { 551 mService.init(); 552 SparseIntArray audioZoneIdToOccupantZoneMapping = 553 getDefaultAudioZoneToOccupantZoneMapping(); 554 555 mService.setAudioZoneIdsForOccupantZoneIds(audioZoneIdToOccupantZoneMapping); 556 557 assertThat(mService.getAudioZoneIdForOccupant(UNMAPPED_AUDIO_ZONE_ID_OCCUPANT)) 558 .isEqualTo(CarAudioManager.INVALID_AUDIO_ZONE); 559 } 560 561 @Test testSetInvalidAudioConfigMapping()562 public void testSetInvalidAudioConfigMapping() { 563 mService.init(); 564 SparseIntArray audioZoneIdToOccupantZoneMapping = new SparseIntArray(2); 565 audioZoneIdToOccupantZoneMapping.put(PRIMARY_AUDIO_ZONE_ID, 566 PRIMARY_AUDIO_ZONE_ID_OCCUPANT); 567 audioZoneIdToOccupantZoneMapping.put(SECONDARY_AUDIO_ZONE_ID, 568 INVALID_AUDIO_ZONE_ID_OCCUPANT); 569 IllegalArgumentException thrown = 570 expectThrows(IllegalArgumentException.class, 571 () -> mService.setAudioZoneIdsForOccupantZoneIds( 572 audioZoneIdToOccupantZoneMapping)); 573 thrown.getMessage().contains("does not exist"); 574 } 575 576 @Test testActiveOccupantConfigs()577 public void testActiveOccupantConfigs() { 578 mService.init(); 579 580 // key : zone id 581 SparseArray<OccupantConfig> configs = mService.getActiveOccupantConfigs(); 582 assertThat(configs.size()).isEqualTo(3); // driver, front passenger, one rear 583 assertOccupantConfig(configs.get(0), CURRENT_USER, new Display[]{mDisplay0, mDisplay1}, 584 new int[]{CarOccupantZoneManager.DISPLAY_TYPE_MAIN, 585 CarOccupantZoneManager.DISPLAY_TYPE_INSTRUMENT_CLUSTER}); 586 assertOccupantConfig(configs.get(1), CURRENT_USER, new Display[]{mDisplay2}, 587 new int[]{CarOccupantZoneManager.DISPLAY_TYPE_MAIN}); 588 assertOccupantConfig(configs.get(3), CURRENT_USER, new Display[]{mDisplay4}, 589 new int[]{CarOccupantZoneManager.DISPLAY_TYPE_MAIN}); 590 } 591 592 @Test testActiveOccupantConfigsAfterDisplayAdd()593 public void testActiveOccupantConfigsAfterDisplayAdd() { 594 mService.init(); 595 596 mockDisplay(mDisplayManager, mDisplay3, 3, 13); 597 when(mDisplayManager.getDisplays()).thenReturn(new Display[]{ 598 mDisplay0, 599 mDisplay1, 600 mDisplay2, 601 mDisplay3, 602 mDisplay4, 603 mDisplay5 604 }); 605 mService.mDisplayListener.onDisplayAdded(3); 606 607 // key : zone id 608 SparseArray<OccupantConfig> configs = mService.getActiveOccupantConfigs(); 609 assertThat(configs.size()).isEqualTo(4); // driver, front passenger, two rear 610 assertOccupantConfig(configs.get(0), CURRENT_USER, new Display[]{mDisplay0, mDisplay1}, 611 new int[]{CarOccupantZoneManager.DISPLAY_TYPE_MAIN, 612 CarOccupantZoneManager.DISPLAY_TYPE_INSTRUMENT_CLUSTER}); 613 assertOccupantConfig(configs.get(1), CURRENT_USER, new Display[]{mDisplay2}, 614 new int[]{CarOccupantZoneManager.DISPLAY_TYPE_MAIN}); 615 assertOccupantConfig(configs.get(2), CURRENT_USER, new Display[]{mDisplay3}, 616 new int[]{CarOccupantZoneManager.DISPLAY_TYPE_MAIN}); 617 assertOccupantConfig(configs.get(3), CURRENT_USER, new Display[]{mDisplay4}, 618 new int[]{CarOccupantZoneManager.DISPLAY_TYPE_MAIN}); 619 } 620 621 @Test testActiveOccupantConfigsAfterDisplayRemoval()622 public void testActiveOccupantConfigsAfterDisplayRemoval() { 623 mService.init(); 624 625 when(mDisplayManager.getDisplays()).thenReturn(new Display[]{ 626 mDisplay0, 627 mDisplay1, 628 mDisplay2, 629 }); 630 mService.mDisplayListener.onDisplayRemoved(4); 631 632 // key : zone id 633 SparseArray<OccupantConfig> configs = mService.getActiveOccupantConfigs(); 634 assertThat(configs.size()).isEqualTo(2); // driver, front passenger 635 assertOccupantConfig(configs.get(0), CURRENT_USER, new Display[]{mDisplay0, mDisplay1}, 636 new int[]{CarOccupantZoneManager.DISPLAY_TYPE_MAIN, 637 CarOccupantZoneManager.DISPLAY_TYPE_INSTRUMENT_CLUSTER}); 638 assertOccupantConfig(configs.get(1), CURRENT_USER, new Display[]{mDisplay2}, 639 new int[]{CarOccupantZoneManager.DISPLAY_TYPE_MAIN}); 640 } 641 642 @Test testActiveUserAfterUserSwitching()643 public void testActiveUserAfterUserSwitching() { 644 mService.init(); 645 646 final int newUserId = 200; 647 doReturn(newUserId).when(mService).getCurrentUser(); 648 mService.mUserLifecycleListener.onEvent(new UserLifecycleEvent( 649 CarUserManager.USER_LIFECYCLE_EVENT_TYPE_SWITCHING, newUserId)); 650 651 // key : zone id 652 SparseArray<OccupantConfig> configs = mService.getActiveOccupantConfigs(); 653 assertThat(configs.size()).isEqualTo(3); // driver, front passenger, one rear 654 assertOccupantConfig(configs.get(0), newUserId, new Display[]{mDisplay0, mDisplay1}, 655 new int[]{CarOccupantZoneManager.DISPLAY_TYPE_MAIN, 656 CarOccupantZoneManager.DISPLAY_TYPE_INSTRUMENT_CLUSTER}); 657 assertOccupantConfig(configs.get(1), newUserId, new Display[]{mDisplay2}, 658 new int[]{CarOccupantZoneManager.DISPLAY_TYPE_MAIN}); 659 assertOccupantConfig(configs.get(3), newUserId, new Display[]{mDisplay4}, 660 new int[]{CarOccupantZoneManager.DISPLAY_TYPE_MAIN}); 661 } 662 assertParsingFailure()663 private void assertParsingFailure() { 664 assertThrows(Exception.class, () -> mService.init()); 665 // call release to return it to clean state. 666 mService.release(); 667 } 668 669 @Test testWrongZoneConfigs()670 public void testWrongZoneConfigs() { 671 final String[] wrongZoneConfigs = { 672 "unknownKeyword", 673 "unknownKey=0", 674 "occupantZoneId=0,occupantType=Unknown,seatRow=1,seatSide=driver", 675 "occupantZoneId=0,occupantType=DRIVER,seatRow=0,seatSide=driver", // wrong row 676 "occupantZoneId=0,occupantType=DRIVER,seatRow=1,seatSide=wrongSide" 677 }; 678 679 String[] zoneConfig = new String[1]; 680 when(mResources.getStringArray(R.array.config_occupant_zones)) 681 .thenReturn(zoneConfig); 682 for (int i = 0; i < wrongZoneConfigs.length; i++) { 683 zoneConfig[0] = wrongZoneConfigs[i]; 684 assertParsingFailure(); 685 } 686 } 687 688 @Test testWrongDisplayConfigs()689 public void testWrongDisplayConfigs() { 690 final String[] wrongDisplayConfigs = { 691 "unknownKeyword", 692 "unknownKey=0", 693 "displayPort=10,displayType=Unknown,occupantZoneId=0", 694 "displayPort=10,displayType=MAIN,occupantZoneId=100" // wrong zone id 695 }; 696 697 String[] displayConfig = new String[1]; 698 when(mResources.getStringArray(R.array.config_occupant_display_mapping)) 699 .thenReturn(displayConfig); 700 for (int i = 0; i < wrongDisplayConfigs.length; i++) { 701 displayConfig[0] = wrongDisplayConfigs[i]; 702 assertParsingFailure(); 703 } 704 } 705 706 @Test testManagerGetAllOccupantZones()707 public void testManagerGetAllOccupantZones() { 708 mService.init(); 709 710 List<OccupantZoneInfo> infos = mManager.getAllOccupantZones(); 711 assertThat(infos).hasSize(3); 712 assertThat(infos).contains(mZoneDriverLHD); 713 assertThat(infos).contains(mZoneFrontPassengerLHD); 714 assertThat(infos).contains(mZoneRearRight); 715 } 716 717 @Test testManagerGetAllDisplaysForOccupant()718 public void testManagerGetAllDisplaysForOccupant() { 719 mService.init(); 720 721 List<Display> displaysForDriver = mManager.getAllDisplaysForOccupant(mZoneDriverLHD); 722 assertThat(displaysForDriver).hasSize(2); 723 assertThat(displaysForDriver).contains(mDisplay0); 724 assertThat(displaysForDriver).contains(mDisplay1); 725 726 List<Display> displaysForFrontPassenger = mManager.getAllDisplaysForOccupant( 727 mZoneFrontPassengerLHD); 728 assertThat(displaysForFrontPassenger).hasSize(1); 729 assertThat(displaysForFrontPassenger).contains(mDisplay2); 730 731 List<Display> displaysForRearLeft = mManager.getAllDisplaysForOccupant( 732 mZoneRearLeft); 733 assertThat(displaysForRearLeft).hasSize(0); 734 735 List<Display> displaysForRearRight = mManager.getAllDisplaysForOccupant( 736 mZoneRearRight); 737 assertThat(displaysForRearRight).hasSize(1); 738 assertThat(displaysForRearRight).contains(mDisplay4); 739 } 740 741 @Test testManagerGetAllDisplaysForOccupantAfterDisplayAdd()742 public void testManagerGetAllDisplaysForOccupantAfterDisplayAdd() { 743 mService.init(); 744 745 mockDisplay(mDisplayManager, mDisplay3, 3, 13); 746 when(mDisplayManager.getDisplays()).thenReturn(new Display[]{ 747 mDisplay0, 748 mDisplay1, 749 mDisplay2, 750 mDisplay3, 751 mDisplay4, 752 mDisplay5 753 }); 754 mService.mDisplayListener.onDisplayAdded(3); 755 756 List<Display> displaysForDriver = mManager.getAllDisplaysForOccupant(mZoneDriverLHD); 757 assertThat(displaysForDriver).hasSize(2); 758 assertThat(displaysForDriver).contains(mDisplay0); 759 assertThat(displaysForDriver).contains(mDisplay1); 760 761 List<Display> displaysForFrontPassenger = mManager.getAllDisplaysForOccupant( 762 mZoneFrontPassengerLHD); 763 assertThat(displaysForFrontPassenger).hasSize(1); 764 assertThat(displaysForFrontPassenger).contains(mDisplay2); 765 766 List<Display> displaysForRearLeft = mManager.getAllDisplaysForOccupant( 767 mZoneRearLeft); 768 assertThat(displaysForRearLeft).hasSize(1); 769 assertThat(displaysForRearLeft).contains(mDisplay3); 770 771 List<Display> displaysForRearRight = mManager.getAllDisplaysForOccupant( 772 mZoneRearRight); 773 assertThat(displaysForRearRight).hasSize(1); 774 assertThat(displaysForRearRight).contains(mDisplay4); 775 } 776 777 @Test testManagerGetAllDisplaysForOccupantAfterDisplayRemoval()778 public void testManagerGetAllDisplaysForOccupantAfterDisplayRemoval() { 779 mService.init(); 780 781 when(mDisplayManager.getDisplays()).thenReturn(new Display[]{ 782 mDisplay0, 783 mDisplay1, 784 mDisplay2, 785 }); 786 mService.mDisplayListener.onDisplayRemoved(4); 787 788 List<Display> displaysForDriver = mManager.getAllDisplaysForOccupant(mZoneDriverLHD); 789 assertThat(displaysForDriver).hasSize(2); 790 assertThat(displaysForDriver).contains(mDisplay0); 791 assertThat(displaysForDriver).contains(mDisplay1); 792 793 List<Display> displaysForFrontPassenger = mManager.getAllDisplaysForOccupant( 794 mZoneFrontPassengerLHD); 795 assertThat(displaysForFrontPassenger).hasSize(1); 796 assertThat(displaysForFrontPassenger).contains(mDisplay2); 797 798 List<Display> displaysForRearLeft = mManager.getAllDisplaysForOccupant( 799 mZoneRearLeft); 800 assertThat(displaysForRearLeft).hasSize(0); 801 802 List<Display> displaysForRearRight = mManager.getAllDisplaysForOccupant( 803 mZoneRearRight); 804 assertThat(displaysForRearRight).hasSize(0); 805 } 806 807 @Test testManagerGetDisplayForOccupant()808 public void testManagerGetDisplayForOccupant() { 809 mService.init(); 810 811 assertThat(mDisplay0).isEqualTo(mManager.getDisplayForOccupant(mZoneDriverLHD, 812 CarOccupantZoneManager.DISPLAY_TYPE_MAIN)); 813 assertThat(mDisplay1).isEqualTo(mManager.getDisplayForOccupant(mZoneDriverLHD, 814 CarOccupantZoneManager.DISPLAY_TYPE_INSTRUMENT_CLUSTER)); 815 assertThat(mManager.getDisplayForOccupant(mZoneDriverLHD, 816 CarOccupantZoneManager.DISPLAY_TYPE_HUD)).isNull(); 817 818 assertThat(mDisplay2).isEqualTo(mManager.getDisplayForOccupant(mZoneFrontPassengerLHD, 819 CarOccupantZoneManager.DISPLAY_TYPE_MAIN)); 820 821 assertThat(mManager.getDisplayForOccupant(mZoneRearLeft, 822 CarOccupantZoneManager.DISPLAY_TYPE_MAIN)).isNull(); 823 824 assertThat(mDisplay4).isEqualTo(mManager.getDisplayForOccupant(mZoneRearRight, 825 CarOccupantZoneManager.DISPLAY_TYPE_MAIN)); 826 } 827 828 @Test testManagerGetDisplayIdForDriver_driverDisplays()829 public void testManagerGetDisplayIdForDriver_driverDisplays() { 830 mService.init(); 831 832 // Driver displays 833 assertThat(mManager.getDisplayIdForDriver( 834 CarOccupantZoneManager.DISPLAY_TYPE_MAIN)).isEqualTo(mDisplay0.getDisplayId()); 835 assertThat(mManager.getDisplayIdForDriver( 836 CarOccupantZoneManager.DISPLAY_TYPE_INSTRUMENT_CLUSTER)).isEqualTo( 837 mDisplay1.getDisplayId()); 838 } 839 840 @Test testManagerGetDisplayIdForDriver_nonDriverDisplays()841 public void testManagerGetDisplayIdForDriver_nonDriverDisplays() { 842 mService.init(); 843 844 // Non driver displays 845 assertThat(mManager.getDisplayIdForDriver( 846 CarOccupantZoneManager.DISPLAY_TYPE_UNKNOWN)).isEqualTo(Display.INVALID_DISPLAY); 847 assertThat(mManager.getDisplayIdForDriver( 848 CarOccupantZoneManager.DISPLAY_TYPE_INPUT)).isEqualTo(Display.INVALID_DISPLAY); 849 assertThat(mManager.getDisplayIdForDriver( 850 CarOccupantZoneManager.DISPLAY_TYPE_HUD)).isEqualTo(Display.INVALID_DISPLAY); 851 assertThat(mManager.getDisplayIdForDriver( 852 CarOccupantZoneManager.DISPLAY_TYPE_AUXILIARY)).isEqualTo(Display.INVALID_DISPLAY); 853 } 854 855 @Test testManagerGetDisplayType()856 public void testManagerGetDisplayType() { 857 mService.init(); 858 859 assertThat(mManager.getDisplayType(mDisplay0)).isEqualTo( 860 CarOccupantZoneManager.DISPLAY_TYPE_MAIN); 861 assertThat(mManager.getDisplayType(mDisplay1)).isEqualTo( 862 CarOccupantZoneManager.DISPLAY_TYPE_INSTRUMENT_CLUSTER); 863 assertThat(mManager.getDisplayType(mDisplay2)).isEqualTo( 864 CarOccupantZoneManager.DISPLAY_TYPE_MAIN); 865 assertThat(mManager.getDisplayType(mDisplay4)).isEqualTo( 866 CarOccupantZoneManager.DISPLAY_TYPE_MAIN); 867 assertThat(mManager.getDisplayType(mDisplay5)).isEqualTo( 868 CarOccupantZoneManager.DISPLAY_TYPE_UNKNOWN); 869 } 870 871 @Test testManagerGetUserForOccupant()872 public void testManagerGetUserForOccupant() { 873 mService.init(); 874 875 int driverUser = mManager.getUserForOccupant(mZoneDriverLHD); 876 assertThat(CURRENT_USER).isEqualTo(driverUser); 877 878 //TODO update this after secondary user handling 879 assertThat(mManager.getUserForOccupant(mZoneFrontPassengerLHD)).isEqualTo(driverUser); 880 assertThat(mManager.getUserForOccupant(mZoneRearLeft)).isEqualTo(UserHandle.USER_NULL); 881 assertThat(mManager.getUserForOccupant(mZoneRearRight)).isEqualTo(driverUser); 882 } 883 884 @Test testManagerGetUserForOccupantAfterUserSwitch()885 public void testManagerGetUserForOccupantAfterUserSwitch() { 886 mService.init(); 887 888 final int newUserId = 200; 889 doReturn(newUserId).when(mService).getCurrentUser(); 890 mService.mUserLifecycleListener.onEvent(new UserLifecycleEvent( 891 CarUserManager.USER_LIFECYCLE_EVENT_TYPE_SWITCHING, newUserId)); 892 893 assertThat(newUserId).isEqualTo(mManager.getUserForOccupant(mZoneDriverLHD)); 894 //TODO update this after secondary user handling 895 assertThat(mManager.getUserForOccupant(mZoneFrontPassengerLHD)).isEqualTo(newUserId); 896 assertThat(mManager.getUserForOccupant(mZoneRearLeft)).isEqualTo(UserHandle.USER_NULL); 897 assertThat(mManager.getUserForOccupant(mZoneRearRight)).isEqualTo(newUserId); 898 } 899 900 @Test testManagerRegisterUnregister()901 public void testManagerRegisterUnregister() { 902 mService.init(); 903 904 final long eventWaitTimeMs = 300; 905 906 mManager.registerOccupantZoneConfigChangeListener(mChangeListener); 907 908 resetConfigChangeEventWait(); 909 mService.mUserLifecycleListener.onEvent(new UserLifecycleEvent( 910 CarUserManager.USER_LIFECYCLE_EVENT_TYPE_SWITCHING, 0)); // user id does not matter. 911 912 assertThat(waitForConfigChangeEventAndAssertFlag(eventWaitTimeMs, 913 CarOccupantZoneManager.ZONE_CONFIG_CHANGE_FLAG_USER)).isTrue(); 914 915 resetConfigChangeEventWait(); 916 mService.mDisplayListener.onDisplayAdded(0); // displayid ignored 917 assertThat(waitForConfigChangeEventAndAssertFlag(eventWaitTimeMs, 918 CarOccupantZoneManager.ZONE_CONFIG_CHANGE_FLAG_DISPLAY)).isTrue(); 919 920 resetConfigChangeEventWait(); 921 mManager.unregisterOccupantZoneConfigChangeListener(mChangeListener); 922 mService.mUserLifecycleListener.onEvent(new UserLifecycleEvent( 923 CarUserManager.USER_LIFECYCLE_EVENT_TYPE_SWITCHING, 0)); 924 assertThat(waitForConfigChangeEventAndAssertFlag(eventWaitTimeMs, 0)).isFalse(); 925 } 926 927 @Test testManagerRegisterUnregisterForAudioConfigs()928 public void testManagerRegisterUnregisterForAudioConfigs() { 929 mService.init(); 930 931 long eventWaitTimeMs = 300; 932 933 mManager.registerOccupantZoneConfigChangeListener(mChangeListener); 934 935 resetConfigChangeEventWait(); 936 937 SparseIntArray audioZoneIdToOccupantZoneMapping = 938 getDefaultAudioZoneToOccupantZoneMapping(); 939 940 mService.setAudioZoneIdsForOccupantZoneIds(audioZoneIdToOccupantZoneMapping); 941 942 assertThat(waitForConfigChangeEventAndAssertFlag(eventWaitTimeMs, 943 CarOccupantZoneManager.ZONE_CONFIG_CHANGE_FLAG_AUDIO)).isTrue(); 944 945 resetConfigChangeEventWait(); 946 mManager.unregisterOccupantZoneConfigChangeListener(mChangeListener); 947 mService.setAudioZoneIdsForOccupantZoneIds(audioZoneIdToOccupantZoneMapping); 948 assertThat(waitForConfigChangeEventAndAssertFlag(eventWaitTimeMs, 949 CarOccupantZoneManager.ZONE_CONFIG_CHANGE_FLAG_AUDIO)).isFalse(); 950 } 951 952 private static class ICarServiceHelperImpl extends AbstractICarServiceHelperStub { 953 private List<Integer> mPassengerDisplayIds; 954 955 /** key: user id, value: display allowlists */ 956 private HashMap<Integer, List<Integer>> mAllowlists = new HashMap<>(); 957 958 @Override setDisplayAllowlistForUser(@serIdInt int userId, int[] displayIds)959 public void setDisplayAllowlistForUser(@UserIdInt int userId, int[] displayIds) { 960 mAllowlists.put(userId, Arrays.stream(displayIds).boxed().collect(Collectors.toList())); 961 } 962 963 @Override setPassengerDisplays(int[] displayIdsForPassenger)964 public void setPassengerDisplays(int[] displayIdsForPassenger) { 965 mPassengerDisplayIds = Arrays.stream(displayIdsForPassenger).boxed().collect( 966 Collectors.toList()); 967 } 968 } 969 } 970