• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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