1 /*
2  * Copyright (C) 2021 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.server.display;
18 
19 import static android.hardware.devicestate.DeviceStateManager.INVALID_DEVICE_STATE;
20 import static android.view.Display.DEFAULT_DISPLAY;
21 import static android.view.Display.DEFAULT_DISPLAY_GROUP;
22 import static android.view.Display.FLAG_REAR;
23 import static android.view.Display.TYPE_EXTERNAL;
24 import static android.view.Display.TYPE_INTERNAL;
25 import static android.view.Display.TYPE_VIRTUAL;
26 
27 import static com.android.server.display.DeviceStateToLayoutMap.STATE_DEFAULT;
28 import static com.android.server.display.DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED;
29 import static com.android.server.display.DisplayAdapter.DISPLAY_DEVICE_EVENT_CHANGED;
30 import static com.android.server.display.DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED;
31 import static com.android.server.display.DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY;
32 import static com.android.server.display.LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_ADDED;
33 import static com.android.server.display.LogicalDisplayMapper.LOGICAL_DISPLAY_EVENT_REMOVED;
34 import static com.android.server.display.layout.Layout.Display.POSITION_REAR;
35 import static com.android.server.display.layout.Layout.Display.POSITION_UNKNOWN;
36 
37 import static com.google.common.truth.Truth.assertThat;
38 
39 import static org.junit.Assert.assertEquals;
40 import static org.junit.Assert.assertFalse;
41 import static org.junit.Assert.assertNotEquals;
42 import static org.junit.Assert.assertNotNull;
43 import static org.junit.Assert.assertNull;
44 import static org.junit.Assert.assertTrue;
45 import static org.mockito.ArgumentMatchers.anyInt;
46 import static org.mockito.ArgumentMatchers.anyLong;
47 import static org.mockito.ArgumentMatchers.eq;
48 import static org.mockito.Mockito.atLeastOnce;
49 import static org.mockito.Mockito.clearInvocations;
50 import static org.mockito.Mockito.never;
51 import static org.mockito.Mockito.verify;
52 import static org.mockito.Mockito.when;
53 
54 import android.app.PropertyInvalidatedCache;
55 import android.content.Context;
56 import android.content.res.Resources;
57 import android.os.Handler;
58 import android.os.IPowerManager;
59 import android.os.IThermalService;
60 import android.os.PowerManager;
61 import android.os.Process;
62 import android.os.RemoteException;
63 import android.os.test.TestLooper;
64 import android.view.Display;
65 import android.view.DisplayAddress;
66 import android.view.DisplayInfo;
67 
68 import androidx.test.ext.junit.runners.AndroidJUnit4;
69 import androidx.test.filters.SmallTest;
70 
71 import com.android.server.display.layout.DisplayIdProducer;
72 import com.android.server.display.layout.Layout;
73 import com.android.server.utils.FoldSettingProvider;
74 
75 import org.junit.Before;
76 import org.junit.Test;
77 import org.junit.runner.RunWith;
78 import org.mockito.ArgumentCaptor;
79 import org.mockito.Captor;
80 import org.mockito.Mock;
81 import org.mockito.MockitoAnnotations;
82 import org.mockito.Spy;
83 
84 import java.io.File;
85 import java.io.InputStream;
86 import java.io.OutputStream;
87 import java.util.Arrays;
88 
89 @SmallTest
90 @RunWith(AndroidJUnit4.class)
91 public class LogicalDisplayMapperTest {
92     private static int sUniqueTestDisplayId = 0;
93     private static final int DEVICE_STATE_CLOSED = 0;
94     private static final int DEVICE_STATE_OPEN = 2;
95     private static final int FLAG_GO_TO_SLEEP_ON_FOLD = 0;
96     private static int sNextNonDefaultDisplayId = DEFAULT_DISPLAY + 1;
97     private static final File NON_EXISTING_FILE = new File("/non_existing_folder/should_not_exist");
98 
99     private DisplayDeviceRepository mDisplayDeviceRepo;
100     private LogicalDisplayMapper mLogicalDisplayMapper;
101     private TestLooper mLooper;
102     private Handler mHandler;
103     private PowerManager mPowerManager;
104 
105     private final DisplayIdProducer mIdProducer = (isDefault) ->
106             isDefault ? DEFAULT_DISPLAY : sNextNonDefaultDisplayId++;
107 
108     @Mock LogicalDisplayMapper.Listener mListenerMock;
109     @Mock Context mContextMock;
110     @Mock FoldSettingProvider mFoldSettingProviderMock;
111     @Mock Resources mResourcesMock;
112     @Mock IPowerManager mIPowerManagerMock;
113     @Mock IThermalService mIThermalServiceMock;
114     @Spy DeviceStateToLayoutMap mDeviceStateToLayoutMapSpy =
115             new DeviceStateToLayoutMap(mIdProducer, NON_EXISTING_FILE);
116 
117     @Captor ArgumentCaptor<LogicalDisplay> mDisplayCaptor;
118 
119     @Before
setUp()120     public void setUp() throws RemoteException {
121         // Share classloader to allow package private access.
122         System.setProperty("dexmaker.share_classloader", "true");
123         MockitoAnnotations.initMocks(this);
124 
125         mDisplayDeviceRepo = new DisplayDeviceRepository(
126                 new DisplayManagerService.SyncRoot(),
127                 new PersistentDataStore(new PersistentDataStore.Injector() {
128                     @Override
129                     public InputStream openRead() {
130                         return null;
131                     }
132 
133                     @Override
134                     public OutputStream startWrite() {
135                         return null;
136                     }
137 
138                     @Override
139                     public void finishWrite(OutputStream os, boolean success) {}
140                 }));
141 
142         // Disable binder caches in this process.
143         PropertyInvalidatedCache.disableForTestMode();
144 
145         mPowerManager = new PowerManager(mContextMock, mIPowerManagerMock, mIThermalServiceMock,
146                 null);
147 
148         when(mContextMock.getSystemServiceName(PowerManager.class))
149                 .thenReturn(Context.POWER_SERVICE);
150         when(mFoldSettingProviderMock.shouldStayAwakeOnFold()).thenReturn(false);
151         when(mFoldSettingProviderMock.shouldSleepOnFold()).thenReturn(false);
152         when(mIPowerManagerMock.isInteractive()).thenReturn(true);
153         when(mContextMock.getSystemService(PowerManager.class)).thenReturn(mPowerManager);
154         when(mContextMock.getResources()).thenReturn(mResourcesMock);
155         when(mResourcesMock.getBoolean(
156                 com.android.internal.R.bool.config_supportsConcurrentInternalDisplays))
157                 .thenReturn(true);
158         when(mResourcesMock.getIntArray(
159                 com.android.internal.R.array.config_deviceStatesOnWhichToWakeUp))
160                 .thenReturn(new int[]{1, 2});
161         when(mResourcesMock.getIntArray(
162                 com.android.internal.R.array.config_deviceStatesOnWhichToSleep))
163                 .thenReturn(new int[]{0});
164 
165         mLooper = new TestLooper();
166         mHandler = new Handler(mLooper.getLooper());
167         mLogicalDisplayMapper = new LogicalDisplayMapper(mContextMock, mFoldSettingProviderMock,
168                 mDisplayDeviceRepo,
169                 mListenerMock, new DisplayManagerService.SyncRoot(), mHandler,
170                 mDeviceStateToLayoutMapSpy);
171     }
172 
173 
174     /////////////////
175     // Test Methods
176     /////////////////
177 
178     @Test
testDisplayDeviceAddAndRemove_Internal()179     public void testDisplayDeviceAddAndRemove_Internal() {
180         DisplayDevice device = createDisplayDevice(TYPE_INTERNAL, 600, 800,
181                 FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY);
182 
183         // add
184         LogicalDisplay displayAdded = add(device);
185         assertEquals(info(displayAdded).address, info(device).address);
186         assertEquals(DEFAULT_DISPLAY, id(displayAdded));
187 
188         // remove
189         mDisplayDeviceRepo.onDisplayDeviceEvent(device, DISPLAY_DEVICE_EVENT_REMOVED);
190         verify(mListenerMock).onLogicalDisplayEventLocked(
191                 mDisplayCaptor.capture(), eq(LOGICAL_DISPLAY_EVENT_REMOVED));
192         LogicalDisplay displayRemoved = mDisplayCaptor.getValue();
193         assertEquals(DEFAULT_DISPLAY, id(displayRemoved));
194         assertEquals(displayAdded, displayRemoved);
195     }
196 
197     @Test
testDisplayDeviceAddAndRemove_NonInternalTypes()198     public void testDisplayDeviceAddAndRemove_NonInternalTypes() {
199         testDisplayDeviceAddAndRemove_NonInternal(TYPE_EXTERNAL);
200         testDisplayDeviceAddAndRemove_NonInternal(Display.TYPE_WIFI);
201         testDisplayDeviceAddAndRemove_NonInternal(Display.TYPE_OVERLAY);
202         testDisplayDeviceAddAndRemove_NonInternal(TYPE_VIRTUAL);
203         testDisplayDeviceAddAndRemove_NonInternal(Display.TYPE_UNKNOWN);
204 
205         // Call the internal test again, just to verify that adding non-internal displays
206         // doesn't affect the ability for an internal display to become the default display.
207         testDisplayDeviceAddAndRemove_Internal();
208     }
209 
210     @Test
testDisplayDeviceAdd_TwoInternalOneDefault()211     public void testDisplayDeviceAdd_TwoInternalOneDefault() {
212         DisplayDevice device1 = createDisplayDevice(TYPE_INTERNAL, 600, 800, 0);
213         DisplayDevice device2 = createDisplayDevice(TYPE_INTERNAL, 600, 800,
214                 FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY);
215 
216         LogicalDisplay display1 = add(device1);
217         assertEquals(info(display1).address, info(device1).address);
218         assertNotEquals(DEFAULT_DISPLAY, id(display1));
219 
220         LogicalDisplay display2 = add(device2);
221         assertEquals(info(display2).address, info(device2).address);
222         assertEquals(DEFAULT_DISPLAY, id(display2));
223     }
224 
225     @Test
testDisplayDeviceAdd_TwoInternalBothDefault()226     public void testDisplayDeviceAdd_TwoInternalBothDefault() {
227         DisplayDevice device1 = createDisplayDevice(TYPE_INTERNAL, 600, 800,
228                 FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY);
229         DisplayDevice device2 = createDisplayDevice(TYPE_INTERNAL, 600, 800,
230                 FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY);
231 
232         LogicalDisplay display1 = add(device1);
233         assertEquals(info(display1).address, info(device1).address);
234         assertEquals(DEFAULT_DISPLAY, id(display1));
235 
236         LogicalDisplay display2 = add(device2);
237         assertEquals(info(display2).address, info(device2).address);
238         // Despite the flags, we can only have one default display
239         assertNotEquals(DEFAULT_DISPLAY, id(display2));
240     }
241 
242     @Test
testDisplayDeviceAddAndRemove_OneExternalDefault()243     public void testDisplayDeviceAddAndRemove_OneExternalDefault() {
244         DisplayDevice device = createDisplayDevice(TYPE_EXTERNAL, 600, 800,
245                 FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY);
246 
247         // add
248         LogicalDisplay displayAdded = add(device);
249         assertEquals(info(displayAdded).address, info(device).address);
250         assertEquals(Display.DEFAULT_DISPLAY, id(displayAdded));
251 
252         // remove
253         mDisplayDeviceRepo.onDisplayDeviceEvent(device, DISPLAY_DEVICE_EVENT_REMOVED);
254         verify(mListenerMock).onLogicalDisplayEventLocked(
255                 mDisplayCaptor.capture(), eq(LOGICAL_DISPLAY_EVENT_REMOVED));
256         LogicalDisplay displayRemoved = mDisplayCaptor.getValue();
257         assertEquals(DEFAULT_DISPLAY, id(displayRemoved));
258         assertEquals(displayAdded, displayRemoved);
259     }
260 
261     @Test
testDisplayDeviceAddAndRemove_SwitchDefault()262     public void testDisplayDeviceAddAndRemove_SwitchDefault() {
263         DisplayDevice device1 = createDisplayDevice(TYPE_INTERNAL, 600, 800,
264                 FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY);
265         DisplayDevice device2 = createDisplayDevice(TYPE_INTERNAL, 600, 800,
266                 FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY);
267 
268         LogicalDisplay display1 = add(device1);
269         assertEquals(info(display1).address, info(device1).address);
270         assertEquals(DEFAULT_DISPLAY, id(display1));
271 
272         LogicalDisplay display2 = add(device2);
273         assertEquals(info(display2).address, info(device2).address);
274         // We can only have one default display
275         assertEquals(DEFAULT_DISPLAY, id(display1));
276 
277         // remove
278         mDisplayDeviceRepo.onDisplayDeviceEvent(device1, DISPLAY_DEVICE_EVENT_REMOVED);
279 
280         verify(mListenerMock).onLogicalDisplayEventLocked(
281                 mDisplayCaptor.capture(), eq(LOGICAL_DISPLAY_EVENT_REMOVED));
282         LogicalDisplay displayRemoved = mDisplayCaptor.getValue();
283         // Display 1 is still the default logical display
284         assertEquals(DEFAULT_DISPLAY, id(display1));
285         // The logical displays had their devices swapped and Display 2 was removed
286         assertEquals(display2, displayRemoved);
287         assertEquals(info(display1).address, info(device2).address);
288     }
289 
290     @Test
testGetDisplayIdsLocked()291     public void testGetDisplayIdsLocked() {
292         add(createDisplayDevice(TYPE_INTERNAL, 600, 800,
293                 FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY));
294         add(createDisplayDevice(TYPE_EXTERNAL, 600, 800, 0));
295         add(createDisplayDevice(TYPE_VIRTUAL, 600, 800, 0));
296 
297         int [] ids = mLogicalDisplayMapper.getDisplayIdsLocked(Process.SYSTEM_UID,
298                 /* includeDisabled= */ true);
299         assertEquals(3, ids.length);
300         Arrays.sort(ids);
301         assertEquals(DEFAULT_DISPLAY, ids[0]);
302     }
303 
304     @Test
testGetDisplayInfoForStateLocked_defaultLayout()305     public void testGetDisplayInfoForStateLocked_defaultLayout() {
306         final DisplayDevice device1 = createDisplayDevice(TYPE_INTERNAL, 600, 800,
307                 FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY);
308         final DisplayDevice device2 = createDisplayDevice(TYPE_INTERNAL, 200, 800,
309                 FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY);
310 
311         add(device1);
312         add(device2);
313 
314         Layout layout1 = new Layout();
315         createDefaultDisplay(layout1, device1);
316         createNonDefaultDisplay(layout1, device2, /* enabled= */ true, /* group= */ null);
317         when(mDeviceStateToLayoutMapSpy.get(STATE_DEFAULT)).thenReturn(layout1);
318         assertThat(layout1.size()).isEqualTo(2);
319         final int logicalId2 = layout1.getByAddress(info(device2).address).getLogicalDisplayId();
320 
321         final DisplayInfo displayInfoDefault = mLogicalDisplayMapper.getDisplayInfoForStateLocked(
322                 STATE_DEFAULT, DEFAULT_DISPLAY);
323         assertThat(displayInfoDefault.displayId).isEqualTo(DEFAULT_DISPLAY);
324         assertThat(displayInfoDefault.logicalWidth).isEqualTo(width(device1));
325         assertThat(displayInfoDefault.logicalHeight).isEqualTo(height(device1));
326 
327         final DisplayInfo displayInfoOther = mLogicalDisplayMapper.getDisplayInfoForStateLocked(
328                 STATE_DEFAULT, logicalId2);
329         assertThat(displayInfoOther).isNotNull();
330         assertThat(displayInfoOther.displayId).isEqualTo(logicalId2);
331         assertThat(displayInfoOther.logicalWidth).isEqualTo(width(device2));
332         assertThat(displayInfoOther.logicalHeight).isEqualTo(height(device2));
333     }
334 
335     @Test
testGetDisplayInfoForStateLocked_multipleLayouts()336     public void testGetDisplayInfoForStateLocked_multipleLayouts() {
337         final DisplayDevice device1 = createDisplayDevice(TYPE_INTERNAL, 600, 800,
338                 FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY);
339         final DisplayDevice device2 = createDisplayDevice(TYPE_INTERNAL, 200, 800,
340                 FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY);
341         final DisplayDevice device3 = createDisplayDevice(TYPE_VIRTUAL, 700, 800,
342                 DisplayDeviceInfo.FLAG_OWN_DISPLAY_GROUP);
343 
344         add(device1);
345         add(device2);
346         add(device3);
347 
348         Layout layout1 = new Layout();
349         createDefaultDisplay(layout1, device1);
350         when(mDeviceStateToLayoutMapSpy.get(STATE_DEFAULT)).thenReturn(layout1);
351 
352         final int layoutState2 = 2;
353         Layout layout2 = new Layout();
354         createNonDefaultDisplay(layout2, device2, /* enabled= */ true, /* group= */ null);
355         // Device3 is the default display.
356         createDefaultDisplay(layout2, device3);
357         when(mDeviceStateToLayoutMapSpy.get(layoutState2)).thenReturn(layout2);
358         assertThat(layout2.size()).isEqualTo(2);
359         final int logicalId2 = layout2.getByAddress(info(device2).address).getLogicalDisplayId();
360 
361         // Default layout.
362         final DisplayInfo displayInfoLayout1Default =
363                 mLogicalDisplayMapper.getDisplayInfoForStateLocked(
364                         STATE_DEFAULT, DEFAULT_DISPLAY);
365         assertThat(displayInfoLayout1Default.displayId).isEqualTo(DEFAULT_DISPLAY);
366         assertThat(displayInfoLayout1Default.logicalWidth).isEqualTo(width(device1));
367         assertThat(displayInfoLayout1Default.logicalHeight).isEqualTo(height(device1));
368 
369         // Second layout, where device3 is the default display.
370         final DisplayInfo displayInfoLayout2Default =
371                 mLogicalDisplayMapper.getDisplayInfoForStateLocked(
372                         layoutState2, DEFAULT_DISPLAY);
373         assertThat(displayInfoLayout2Default.displayId).isEqualTo(DEFAULT_DISPLAY);
374         assertThat(displayInfoLayout2Default.logicalWidth).isEqualTo(width(device3));
375         assertThat(displayInfoLayout2Default.logicalHeight).isEqualTo(height(device3));
376 
377         final DisplayInfo displayInfoLayout2Other =
378                 mLogicalDisplayMapper.getDisplayInfoForStateLocked(
379                         layoutState2, logicalId2);
380         assertThat(displayInfoLayout2Other).isNotNull();
381         assertThat(displayInfoLayout2Other.displayId).isEqualTo(logicalId2);
382         assertThat(displayInfoLayout2Other.logicalWidth).isEqualTo(width(device2));
383         assertThat(displayInfoLayout2Other.logicalHeight).isEqualTo(height(device2));
384     }
385 
386     @Test
testGetDisplayInfoForStateLocked_multipleDisplayGroups()387     public void testGetDisplayInfoForStateLocked_multipleDisplayGroups() {
388         DisplayDevice device1 = createDisplayDevice(TYPE_INTERNAL, 600, 800,
389                 FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY);
390         DisplayDevice device2 = createDisplayDevice(TYPE_INTERNAL, 200, 800,
391                 FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY);
392         DisplayDevice device3 = createDisplayDevice(TYPE_INTERNAL, 700, 800,
393                 FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY);
394         DisplayDevice device4 = createDisplayDevice(TYPE_INTERNAL, 400, 600,
395                 FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY);
396 
397         Layout layout = new Layout();
398         createDefaultDisplay(layout, device1);
399         createNonDefaultDisplay(layout, device2, /* enabled= */  true, /* group= */ "group1");
400         createNonDefaultDisplay(layout, device3, /* enabled= */  true, /* group= */ "group1");
401         createNonDefaultDisplay(layout, device4, /* enabled= */  true, /* group= */ "group2");
402 
403         when(mDeviceStateToLayoutMapSpy.get(STATE_DEFAULT)).thenReturn(layout);
404 
405         LogicalDisplay display1 = add(device1);
406         LogicalDisplay display2 = add(device2);
407         LogicalDisplay display3 = add(device3);
408         LogicalDisplay display4 = add(device4);
409 
410         int displayGroupId1 =
411                 mLogicalDisplayMapper.getDisplayGroupIdFromDisplayIdLocked(id(display1));
412         int displayGroupId2 =
413                 mLogicalDisplayMapper.getDisplayGroupIdFromDisplayIdLocked(id(display2));
414         int displayGroupId3 =
415                 mLogicalDisplayMapper.getDisplayGroupIdFromDisplayIdLocked(id(display3));
416         int displayGroupId4 =
417                 mLogicalDisplayMapper.getDisplayGroupIdFromDisplayIdLocked(id(display4));
418         assertThat(displayGroupId1).isEqualTo(DEFAULT_DISPLAY_GROUP);
419         assertThat(displayGroupId2).isNotEqualTo(DEFAULT_DISPLAY_GROUP);
420         assertThat(displayGroupId2).isEqualTo(displayGroupId3);
421         assertThat(displayGroupId3).isNotEqualTo(DEFAULT_DISPLAY_GROUP);
422         assertThat(displayGroupId2).isNotEqualTo(displayGroupId4);
423     }
424 
425     @Test
testSingleDisplayGroup()426     public void testSingleDisplayGroup() {
427         LogicalDisplay display1 = add(createDisplayDevice(TYPE_INTERNAL, 600, 800,
428                 FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY));
429         LogicalDisplay display2 = add(createDisplayDevice(TYPE_INTERNAL, 600, 800, 0));
430         LogicalDisplay display3 = add(createDisplayDevice(TYPE_VIRTUAL, 600, 800, 0));
431 
432         assertEquals(DEFAULT_DISPLAY_GROUP,
433                 mLogicalDisplayMapper.getDisplayGroupIdFromDisplayIdLocked(id(display1)));
434         assertEquals(DEFAULT_DISPLAY_GROUP,
435                 mLogicalDisplayMapper.getDisplayGroupIdFromDisplayIdLocked(id(display2)));
436         assertEquals(DEFAULT_DISPLAY_GROUP,
437                 mLogicalDisplayMapper.getDisplayGroupIdFromDisplayIdLocked(id(display3)));
438     }
439 
440     @Test
testMultipleDisplayGroups()441     public void testMultipleDisplayGroups() {
442         LogicalDisplay display1 = add(createDisplayDevice(TYPE_INTERNAL, 600, 800,
443                 FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY));
444         LogicalDisplay display2 = add(createDisplayDevice(TYPE_INTERNAL, 600, 800, 0));
445 
446 
447         TestDisplayDevice device3 = createDisplayDevice(TYPE_VIRTUAL, 600, 800,
448                 DisplayDeviceInfo.FLAG_OWN_DISPLAY_GROUP);
449         LogicalDisplay display3 = add(device3);
450 
451         assertEquals(DEFAULT_DISPLAY_GROUP,
452                 mLogicalDisplayMapper.getDisplayGroupIdFromDisplayIdLocked(id(display1)));
453         assertEquals(DEFAULT_DISPLAY_GROUP,
454                 mLogicalDisplayMapper.getDisplayGroupIdFromDisplayIdLocked(id(display2)));
455         assertNotEquals(DEFAULT_DISPLAY_GROUP,
456                 mLogicalDisplayMapper.getDisplayGroupIdFromDisplayIdLocked(id(display3)));
457 
458         // Now switch it back to the default group by removing the flag and issuing an update
459         DisplayDeviceInfo info = device3.getSourceInfo();
460         info.flags = info.flags & ~DisplayDeviceInfo.FLAG_OWN_DISPLAY_GROUP;
461         mDisplayDeviceRepo.onDisplayDeviceEvent(device3, DISPLAY_DEVICE_EVENT_CHANGED);
462 
463         // Verify the new group is correct.
464         assertEquals(DEFAULT_DISPLAY_GROUP,
465                 mLogicalDisplayMapper.getDisplayGroupIdFromDisplayIdLocked(id(display3)));
466     }
467 
468     @Test
testDevicesAreAddedToDeviceDisplayGroups()469     public void testDevicesAreAddedToDeviceDisplayGroups() {
470         // Create the default internal display of the device.
471         LogicalDisplay defaultDisplay =
472                 add(
473                         createDisplayDevice(
474                                 Display.TYPE_INTERNAL,
475                                 600,
476                                 800,
477                                 DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY));
478 
479         // Create 3 virtual displays associated with a first virtual device.
480         int deviceId1 = 1;
481         TestDisplayDevice display1 =
482                 createDisplayDevice(Display.TYPE_VIRTUAL, "virtualDevice1Display1", 600, 800, 0);
483         mLogicalDisplayMapper.associateDisplayDeviceWithVirtualDevice(display1, deviceId1);
484         LogicalDisplay virtualDevice1Display1 = add(display1);
485 
486         TestDisplayDevice display2 =
487                 createDisplayDevice(Display.TYPE_VIRTUAL, "virtualDevice1Display2", 600, 800, 0);
488         mLogicalDisplayMapper.associateDisplayDeviceWithVirtualDevice(display2, deviceId1);
489         LogicalDisplay virtualDevice1Display2 = add(display2);
490 
491         TestDisplayDevice display3 =
492                 createDisplayDevice(Display.TYPE_VIRTUAL, "virtualDevice1Display3", 600, 800, 0);
493         mLogicalDisplayMapper.associateDisplayDeviceWithVirtualDevice(display3, deviceId1);
494         LogicalDisplay virtualDevice1Display3 = add(display3);
495 
496         // Create another 3 virtual displays associated with a second virtual device.
497         int deviceId2 = 2;
498         TestDisplayDevice display4 =
499                 createDisplayDevice(Display.TYPE_VIRTUAL, "virtualDevice2Display1", 600, 800, 0);
500         mLogicalDisplayMapper.associateDisplayDeviceWithVirtualDevice(display4, deviceId2);
501         LogicalDisplay virtualDevice2Display1 = add(display4);
502 
503         TestDisplayDevice display5 =
504                 createDisplayDevice(Display.TYPE_VIRTUAL, "virtualDevice2Display2", 600, 800, 0);
505         mLogicalDisplayMapper.associateDisplayDeviceWithVirtualDevice(display5, deviceId2);
506         LogicalDisplay virtualDevice2Display2 = add(display5);
507 
508         // The final display is created with FLAG_OWN_DISPLAY_GROUP set.
509         TestDisplayDevice display6 =
510                 createDisplayDevice(
511                         Display.TYPE_VIRTUAL,
512                         "virtualDevice2Display3",
513                         600,
514                         800,
515                         DisplayDeviceInfo.FLAG_OWN_DISPLAY_GROUP);
516         mLogicalDisplayMapper.associateDisplayDeviceWithVirtualDevice(display6, deviceId2);
517         LogicalDisplay virtualDevice2Display3 = add(display6);
518 
519         // Verify that the internal display is in the default display group.
520         assertEquals(
521                 DEFAULT_DISPLAY_GROUP,
522                 mLogicalDisplayMapper.getDisplayGroupIdFromDisplayIdLocked(id(defaultDisplay)));
523 
524         // Verify that all the displays for virtual device 1 are in the same (non-default) display
525         // group.
526         int virtualDevice1DisplayGroupId =
527                 mLogicalDisplayMapper.getDisplayGroupIdFromDisplayIdLocked(
528                         id(virtualDevice1Display1));
529         assertNotEquals(DEFAULT_DISPLAY_GROUP, virtualDevice1DisplayGroupId);
530         assertEquals(
531                 virtualDevice1DisplayGroupId,
532                 mLogicalDisplayMapper.getDisplayGroupIdFromDisplayIdLocked(
533                         id(virtualDevice1Display2)));
534         assertEquals(
535                 virtualDevice1DisplayGroupId,
536                 mLogicalDisplayMapper.getDisplayGroupIdFromDisplayIdLocked(
537                         id(virtualDevice1Display3)));
538 
539         // The first 2 displays for virtual device 2 should be in the same non-default group.
540         int virtualDevice2DisplayGroupId =
541                 mLogicalDisplayMapper.getDisplayGroupIdFromDisplayIdLocked(
542                         id(virtualDevice2Display1));
543         assertNotEquals(DEFAULT_DISPLAY_GROUP, virtualDevice2DisplayGroupId);
544         assertEquals(
545                 virtualDevice2DisplayGroupId,
546                 mLogicalDisplayMapper.getDisplayGroupIdFromDisplayIdLocked(
547                         id(virtualDevice2Display2)));
548         // virtualDevice2Display3 was created with FLAG_OWN_DISPLAY_GROUP and shouldn't be grouped
549         // with other displays of this device or be in the default display group.
550         assertNotEquals(
551                 virtualDevice2DisplayGroupId,
552                 mLogicalDisplayMapper.getDisplayGroupIdFromDisplayIdLocked(
553                         id(virtualDevice2Display3)));
554         assertNotEquals(
555                 DEFAULT_DISPLAY_GROUP,
556                 mLogicalDisplayMapper.getDisplayGroupIdFromDisplayIdLocked(
557                         id(virtualDevice2Display3)));
558     }
559 
560     @Test
testDeviceShouldBeWoken()561     public void testDeviceShouldBeWoken() {
562         assertTrue(mLogicalDisplayMapper.shouldDeviceBeWoken(DEVICE_STATE_OPEN,
563                 DEVICE_STATE_CLOSED,
564                 /* isInteractive= */false,
565                 /* isBootCompleted= */true));
566     }
567 
568     @Test
testDeviceShouldNotBeWoken()569     public void testDeviceShouldNotBeWoken() {
570         assertFalse(mLogicalDisplayMapper.shouldDeviceBeWoken(DEVICE_STATE_CLOSED,
571                 DEVICE_STATE_OPEN,
572                 /* isInteractive= */false,
573                 /* isBootCompleted= */true));
574     }
575 
576     @Test
testDeviceShouldBePutToSleep()577     public void testDeviceShouldBePutToSleep() {
578         assertTrue(mLogicalDisplayMapper.shouldDeviceBePutToSleep(DEVICE_STATE_CLOSED,
579                 DEVICE_STATE_OPEN,
580                 /* isOverrideActive= */false,
581                 /* isInteractive= */true,
582                 /* isBootCompleted= */true));
583     }
584 
585     @Test
testDeviceShouldNotSleepWhenStayAwakeSettingTrue()586     public void testDeviceShouldNotSleepWhenStayAwakeSettingTrue() {
587         when(mFoldSettingProviderMock.shouldStayAwakeOnFold()).thenReturn(true);
588 
589         assertFalse(mLogicalDisplayMapper.shouldDeviceBePutToSleep(DEVICE_STATE_CLOSED,
590                 DEVICE_STATE_OPEN,
591                 /* isOverrideActive= */false,
592                 /* isInteractive= */true,
593                 /* isBootCompleted= */true));
594     }
595 
596     @Test
testDeviceShouldNotBePutToSleep()597     public void testDeviceShouldNotBePutToSleep() {
598         assertFalse(mLogicalDisplayMapper.shouldDeviceBePutToSleep(DEVICE_STATE_OPEN,
599                 DEVICE_STATE_CLOSED,
600                 /* isOverrideActive= */false,
601                 /* isInteractive= */true,
602                 /* isBootCompleted= */true));
603         assertFalse(mLogicalDisplayMapper.shouldDeviceBePutToSleep(DEVICE_STATE_CLOSED,
604                 INVALID_DEVICE_STATE,
605                 /* isOverrideActive= */false,
606                 /* isInteractive= */true,
607                 /* isBootCompleted= */true));
608     }
609 
610     @Test
testDeviceShouldNotBePutToSleepDifferentBaseState()611     public void testDeviceShouldNotBePutToSleepDifferentBaseState() {
612         assertFalse(mLogicalDisplayMapper.shouldDeviceBePutToSleep(DEVICE_STATE_CLOSED,
613                 DEVICE_STATE_OPEN,
614                 /* isOverrideActive= */true,
615                 /* isInteractive= */true,
616                 /* isBootCompleted= */true));
617     }
618 
619     @Test
testDeviceShouldPutToSleepWhenSleepSettingTrue()620     public void testDeviceShouldPutToSleepWhenSleepSettingTrue() throws RemoteException {
621         when(mFoldSettingProviderMock.shouldSleepOnFold()).thenReturn(true);
622 
623         finishBootAndFoldDevice();
624 
625         verify(mIPowerManagerMock, atLeastOnce()).goToSleep(anyLong(), anyInt(),
626                 eq(FLAG_GO_TO_SLEEP_ON_FOLD));
627     }
628 
629     @Test
testDeviceShouldNotBePutToSleepWhenSleepSettingFalse()630     public void testDeviceShouldNotBePutToSleepWhenSleepSettingFalse() throws RemoteException {
631         when(mFoldSettingProviderMock.shouldSleepOnFold()).thenReturn(false);
632 
633         finishBootAndFoldDevice();
634 
635         verify(mIPowerManagerMock, never()).goToSleep(anyLong(), anyInt(),
636                 eq(FLAG_GO_TO_SLEEP_ON_FOLD));
637     }
638 
639     @Test
testDeviceStateLocked()640     public void testDeviceStateLocked() {
641         DisplayDevice device1 = createDisplayDevice(TYPE_INTERNAL, 600, 800,
642                 FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY);
643         DisplayDevice device2 = createDisplayDevice(TYPE_INTERNAL, 600, 800,
644                 FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY);
645 
646         Layout layout = new Layout();
647         layout.createDisplayLocked(device1.getDisplayDeviceInfoLocked().address,
648                 /* isDefault= */ true, /* isEnabled= */ true, /* displayGroup= */ null,
649                 mIdProducer, POSITION_UNKNOWN,
650                 /* leadDisplayAddress= */ null,
651                 /* brightnessThrottlingMapId= */ "concurrent",
652                 /* refreshRateZoneId= */ null, /* refreshRateThermalThrottlingMapId= */ null);
653         layout.createDisplayLocked(device2.getDisplayDeviceInfoLocked().address,
654                 /* isDefault= */ false, /* isEnabled= */ true, /* displayGroup= */ null,
655                 mIdProducer, POSITION_UNKNOWN,
656                 /* leadDisplayAddress= */ null,
657                 /* brightnessThrottlingMapId= */ "concurrent",
658                 /* refreshRateZoneId= */ null, /* refreshRateThermalThrottlingMapId= */ null);
659         when(mDeviceStateToLayoutMapSpy.get(0)).thenReturn(layout);
660 
661         layout = new Layout();
662         createNonDefaultDisplay(layout, device1, /* enabled= */ false, /* group= */ null);
663         createDefaultDisplay(layout, device2);
664         when(mDeviceStateToLayoutMapSpy.get(1)).thenReturn(layout);
665         when(mDeviceStateToLayoutMapSpy.get(2)).thenReturn(layout);
666 
667         when(mDeviceStateToLayoutMapSpy.size()).thenReturn(4);
668 
669         LogicalDisplay display1 = add(device1);
670         assertEquals(info(display1).address, info(device1).address);
671         assertEquals(DEFAULT_DISPLAY, id(display1));
672 
673         LogicalDisplay display2 = add(device2);
674         assertEquals(info(display2).address, info(device2).address);
675         // We can only have one default display
676         assertEquals(DEFAULT_DISPLAY, id(display1));
677 
678         mLogicalDisplayMapper.setDeviceStateLocked(0, false);
679         advanceTime(1000);
680         // The new state is not applied until the boot is completed
681         assertTrue(mLogicalDisplayMapper.getDisplayLocked(device1).isEnabledLocked());
682         assertFalse(mLogicalDisplayMapper.getDisplayLocked(device2).isEnabledLocked());
683 
684         mLogicalDisplayMapper.onBootCompleted();
685         advanceTime(1000);
686         assertTrue(mLogicalDisplayMapper.getDisplayLocked(device1).isEnabledLocked());
687         assertTrue(mLogicalDisplayMapper.getDisplayLocked(device2).isEnabledLocked());
688         assertFalse(mLogicalDisplayMapper.getDisplayLocked(device1).isInTransitionLocked());
689         assertFalse(mLogicalDisplayMapper.getDisplayLocked(device2).isInTransitionLocked());
690         assertEquals(-1, mLogicalDisplayMapper.getDisplayLocked(device1)
691                 .getLeadDisplayIdLocked());
692         assertEquals(-1, mLogicalDisplayMapper.getDisplayLocked(device2)
693                 .getLeadDisplayIdLocked());
694         assertEquals("concurrent", mLogicalDisplayMapper.getDisplayLocked(device1)
695                 .getDisplayInfoLocked().thermalBrightnessThrottlingDataId);
696         assertEquals("concurrent", mLogicalDisplayMapper.getDisplayLocked(device2)
697                 .getDisplayInfoLocked().thermalBrightnessThrottlingDataId);
698 
699         mLogicalDisplayMapper.setDeviceStateLocked(1, false);
700         advanceTime(1000);
701         assertFalse(mLogicalDisplayMapper.getDisplayLocked(device1).isEnabledLocked());
702         assertTrue(mLogicalDisplayMapper.getDisplayLocked(device2).isEnabledLocked());
703         assertFalse(mLogicalDisplayMapper.getDisplayLocked(device1).isInTransitionLocked());
704         assertFalse(mLogicalDisplayMapper.getDisplayLocked(device2).isInTransitionLocked());
705         assertEquals(DisplayDeviceConfig.DEFAULT_ID,
706                 mLogicalDisplayMapper.getDisplayLocked(device1)
707                         .getDisplayInfoLocked().thermalBrightnessThrottlingDataId);
708         assertEquals(DisplayDeviceConfig.DEFAULT_ID,
709                 mLogicalDisplayMapper.getDisplayLocked(device2)
710                         .getDisplayInfoLocked().thermalBrightnessThrottlingDataId);
711 
712         mLogicalDisplayMapper.setDeviceStateLocked(2, false);
713         advanceTime(1000);
714         assertFalse(mLogicalDisplayMapper.getDisplayLocked(device1).isEnabledLocked());
715         assertTrue(mLogicalDisplayMapper.getDisplayLocked(device2).isEnabledLocked());
716         assertFalse(mLogicalDisplayMapper.getDisplayLocked(device1).isInTransitionLocked());
717         assertFalse(mLogicalDisplayMapper.getDisplayLocked(device2).isInTransitionLocked());
718         assertEquals(DisplayDeviceConfig.DEFAULT_ID,
719                 mLogicalDisplayMapper.getDisplayLocked(device1)
720                         .getDisplayInfoLocked().thermalBrightnessThrottlingDataId);
721         assertEquals(DisplayDeviceConfig.DEFAULT_ID,
722                 mLogicalDisplayMapper.getDisplayLocked(device2)
723                         .getDisplayInfoLocked().thermalBrightnessThrottlingDataId);
724     }
725 
726     @Test
testEnabledAndDisabledDisplays()727     public void testEnabledAndDisabledDisplays() {
728         DisplayAddress displayAddressOne = new TestUtils.TestDisplayAddress();
729         DisplayAddress displayAddressTwo = new TestUtils.TestDisplayAddress();
730         DisplayAddress displayAddressThree = new TestUtils.TestDisplayAddress();
731 
732         TestDisplayDevice device1 = createDisplayDevice(displayAddressOne, "one",
733                 TYPE_INTERNAL, 600, 800, DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY);
734         TestDisplayDevice device2 = createDisplayDevice(displayAddressTwo, "two",
735                 TYPE_INTERNAL, 200, 800, DisplayDeviceInfo.FLAG_OWN_DISPLAY_GROUP);
736         TestDisplayDevice device3 = createDisplayDevice(displayAddressThree, "three",
737                 TYPE_INTERNAL, 600, 900, DisplayDeviceInfo.FLAG_OWN_DISPLAY_GROUP);
738 
739         Layout threeDevicesEnabledLayout = new Layout();
740         createDefaultDisplay(threeDevicesEnabledLayout, displayAddressOne);
741         createNonDefaultDisplay(threeDevicesEnabledLayout, displayAddressTwo,
742                 /* enabled= */ true, /* group= */ null);
743         createNonDefaultDisplay(threeDevicesEnabledLayout, displayAddressThree,
744                 /* enabled= */ true, /* group= */ null);
745 
746         when(mDeviceStateToLayoutMapSpy.get(STATE_DEFAULT))
747                 .thenReturn(threeDevicesEnabledLayout);
748 
749         LogicalDisplay display1 = add(device1);
750         LogicalDisplay display2 = add(device2);
751         LogicalDisplay display3 = add(device3);
752 
753         // ensure 3 displays are returned
754         int [] ids = mLogicalDisplayMapper.getDisplayIdsLocked(Process.SYSTEM_UID, false);
755         assertEquals(3, ids.length);
756         Arrays.sort(ids);
757         assertEquals(DEFAULT_DISPLAY, ids[0]);
758         assertNotNull(mLogicalDisplayMapper.getDisplayLocked(device1,
759                 /* includeDisabled= */ false));
760         assertNotNull(mLogicalDisplayMapper.getDisplayLocked(device2,
761                 /* includeDisabled= */ false));
762         assertNotNull(mLogicalDisplayMapper.getDisplayLocked(device3,
763                 /* includeDisabled= */ false));
764         assertNotNull(mLogicalDisplayMapper.getDisplayLocked(
765                 threeDevicesEnabledLayout.getByAddress(displayAddressOne).getLogicalDisplayId(),
766                 /* includeDisabled= */ false));
767         assertNotNull(mLogicalDisplayMapper.getDisplayLocked(
768                 threeDevicesEnabledLayout.getByAddress(displayAddressTwo).getLogicalDisplayId(),
769                 /* includeDisabled= */ false));
770         assertNotNull(mLogicalDisplayMapper.getDisplayLocked(
771                 threeDevicesEnabledLayout.getByAddress(displayAddressThree).getLogicalDisplayId(),
772                 /* includeDisabled= */ false));
773 
774         Layout oneDeviceEnabledLayout = new Layout();
775         createDefaultDisplay(oneDeviceEnabledLayout, displayAddressOne);
776         createNonDefaultDisplay(oneDeviceEnabledLayout, displayAddressTwo,
777                 /* enabled= */ false, /* group= */ null);
778         createNonDefaultDisplay(oneDeviceEnabledLayout, displayAddressThree,
779                 /* enabled= */ false, /* group= */ null);
780 
781         when(mDeviceStateToLayoutMapSpy.get(0)).thenReturn(oneDeviceEnabledLayout);
782         when(mDeviceStateToLayoutMapSpy.get(1)).thenReturn(threeDevicesEnabledLayout);
783 
784         // 1) Set the new state
785         // 2) Mark the displays as STATE_OFF so that it can continue with transition
786         // 3) Send DISPLAY_DEVICE_EVENT_CHANGE to inform the mapper of the new display state
787         // 4) Dispatch handler events.
788         mLogicalDisplayMapper.onBootCompleted();
789         mLogicalDisplayMapper.setDeviceStateLocked(0, false);
790         mDisplayDeviceRepo.onDisplayDeviceEvent(device3, DISPLAY_DEVICE_EVENT_CHANGED);
791         advanceTime(1000);
792         final int[] allDisplayIds = mLogicalDisplayMapper.getDisplayIdsLocked(
793                 Process.SYSTEM_UID, false);
794         if (allDisplayIds.length != 1) {
795             throw new RuntimeException("Displays: \n"
796                     + mLogicalDisplayMapper.getDisplayLocked(device1).toString()
797                     + "\n" + mLogicalDisplayMapper.getDisplayLocked(device2).toString()
798                     + "\n" + mLogicalDisplayMapper.getDisplayLocked(device3).toString());
799         }
800         // ensure only one display is returned
801         assertEquals(1, allDisplayIds.length);
802         assertNotNull(mLogicalDisplayMapper.getDisplayLocked(device1,
803                 /* includeDisabled= */ false));
804         assertNull(mLogicalDisplayMapper.getDisplayLocked(device2,
805                 /* includeDisabled= */ false));
806         assertNull(mLogicalDisplayMapper.getDisplayLocked(device3,
807                 /* includeDisabled= */ false));
808         assertNotNull(mLogicalDisplayMapper.getDisplayLocked(
809                 oneDeviceEnabledLayout.getByAddress(displayAddressOne).getLogicalDisplayId(),
810                 /* includeDisabled= */ false));
811         assertNull(mLogicalDisplayMapper.getDisplayLocked(
812                 oneDeviceEnabledLayout.getByAddress(displayAddressTwo).getLogicalDisplayId(),
813                 /* includeDisabled= */ false));
814         assertNull(mLogicalDisplayMapper.getDisplayLocked(
815                 oneDeviceEnabledLayout.getByAddress(displayAddressThree).getLogicalDisplayId(),
816                 /* includeDisabled= */ false));
817 
818         // Now do it again to go back to state 1
819         mLogicalDisplayMapper.setDeviceStateLocked(1, false);
820         mDisplayDeviceRepo.onDisplayDeviceEvent(device3, DISPLAY_DEVICE_EVENT_CHANGED);
821         advanceTime(1000);
822         final int[] threeDisplaysEnabled = mLogicalDisplayMapper.getDisplayIdsLocked(
823                 Process.SYSTEM_UID, false);
824 
825         // ensure all three displays are returned
826         assertEquals(3, threeDisplaysEnabled.length);
827     }
828 
829     @Test
testCreateNewLogicalDisplay()830     public void testCreateNewLogicalDisplay() {
831         DisplayDevice device1 = createDisplayDevice(TYPE_EXTERNAL, 600, 800,
832                 FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY);
833         when(mDeviceStateToLayoutMapSpy.size()).thenReturn(1);
834         LogicalDisplay display1 = add(device1);
835 
836         assertTrue(display1.isEnabledLocked());
837 
838         DisplayDevice device2 = createDisplayDevice(TYPE_INTERNAL, 600, 800,
839                 FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY);
840         when(mDeviceStateToLayoutMapSpy.size()).thenReturn(2);
841         LogicalDisplay display2 = add(device2);
842 
843         assertFalse(display2.isEnabledLocked());
844     }
845     @Test
testDisplayFlagRear()846     public void testDisplayFlagRear() {
847         DisplayDevice device1 = createDisplayDevice(TYPE_INTERNAL, 600, 800,
848                 FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY);
849         DisplayDevice device2 = createDisplayDevice(TYPE_INTERNAL, 600, 800,
850                 FLAG_REAR);
851 
852         Layout layout = new Layout();
853         layout.createDefaultDisplayLocked(device1.getDisplayDeviceInfoLocked().address,
854                 mIdProducer);
855         layout.createDisplayLocked(device2.getDisplayDeviceInfoLocked().address,
856                 /* isDefault= */ false, /* isEnabled= */ true, /* displayGroupName= */ null,
857                 mIdProducer, POSITION_REAR, /* leadDisplayAddress= */ null,
858                 /* brightnessThrottlingMapId= */ null, /* refreshRateZoneId= */ null,
859                 /* refreshRateThermalThrottlingMapId= */null);
860         when(mDeviceStateToLayoutMapSpy.get(0)).thenReturn(layout);
861 
862         when(mDeviceStateToLayoutMapSpy.size()).thenReturn(1);
863 
864         LogicalDisplay display1 = add(device1);
865         assertEquals(info(display1).address, info(device1).address);
866         assertEquals(DEFAULT_DISPLAY, id(display1));
867 
868         LogicalDisplay display2 = add(device2);
869         assertEquals(info(display2).address, info(device2).address);
870         // We can only have one default display
871         assertEquals(DEFAULT_DISPLAY, id(display1));
872 
873         mLogicalDisplayMapper.setDeviceStateLocked(0, false);
874         advanceTime(1000);
875         mLogicalDisplayMapper.onBootCompleted();
876         advanceTime(1000);
877 
878         assertTrue(mLogicalDisplayMapper.getDisplayLocked(device1).isEnabledLocked());
879         assertTrue(mLogicalDisplayMapper.getDisplayLocked(device2).isEnabledLocked());
880 
881         assertEquals(POSITION_UNKNOWN,
882                 mLogicalDisplayMapper.getDisplayLocked(device1).getDevicePositionLocked());
883         assertEquals(POSITION_REAR,
884                 mLogicalDisplayMapper.getDisplayLocked(device2).getDevicePositionLocked());
885     }
886 
887     /////////////////
888     // Helper Methods
889     /////////////////
890 
finishBootAndFoldDevice()891     private void finishBootAndFoldDevice() {
892         mLogicalDisplayMapper.setDeviceStateLocked(DEVICE_STATE_OPEN, false);
893         advanceTime(1000);
894         mLogicalDisplayMapper.onBootCompleted();
895         advanceTime(1000);
896         mLogicalDisplayMapper.setDeviceStateLocked(DEVICE_STATE_CLOSED, false);
897         advanceTime(1000);
898     }
899 
createDefaultDisplay(Layout layout, DisplayDevice device)900     private void createDefaultDisplay(Layout layout, DisplayDevice device) {
901         createDefaultDisplay(layout, info(device).address);
902     }
903 
createDefaultDisplay(Layout layout, DisplayAddress address)904     private void createDefaultDisplay(Layout layout, DisplayAddress address) {
905         layout.createDefaultDisplayLocked(address, mIdProducer);
906     }
907 
createNonDefaultDisplay(Layout layout, DisplayDevice device, boolean enabled, String group)908     private void createNonDefaultDisplay(Layout layout, DisplayDevice device, boolean enabled,
909             String group) {
910         createNonDefaultDisplay(layout, info(device).address, enabled, group);
911     }
912 
createNonDefaultDisplay(Layout layout, DisplayAddress address, boolean enabled, String group)913     private void createNonDefaultDisplay(Layout layout, DisplayAddress address, boolean enabled,
914             String group) {
915         layout.createDisplayLocked(address, /* isDefault= */ false, enabled, group, mIdProducer,
916                 Layout.Display.POSITION_UNKNOWN, /* leadDisplayAddress= */ null,
917                 /* brightnessThrottlingMapId= */ null, /* refreshRateZoneId= */ null,
918                 /* refreshRateThermalThrottlingMapId= */ null);
919     }
920 
advanceTime(long timeMs)921     private void advanceTime(long timeMs) {
922         mLooper.moveTimeForward(1000);
923         mLooper.dispatchAll();
924     }
925 
createDisplayDevice(int type, int width, int height, int flags)926     private TestDisplayDevice createDisplayDevice(int type, int width, int height, int flags) {
927         return createDisplayDevice(
928                 new TestUtils.TestDisplayAddress(), /*  uniqueId */ "", type, width, height, flags);
929     }
930 
createDisplayDevice( int type, String uniqueId, int width, int height, int flags)931     private TestDisplayDevice createDisplayDevice(
932             int type, String uniqueId, int width, int height, int flags) {
933         return createDisplayDevice(
934                 new TestUtils.TestDisplayAddress(), uniqueId, type, width, height, flags);
935     }
936 
createDisplayDevice( DisplayAddress address, String uniqueId, int type, int width, int height, int flags)937     private TestDisplayDevice createDisplayDevice(
938             DisplayAddress address, String uniqueId, int type, int width, int height, int flags) {
939         TestDisplayDevice device = new TestDisplayDevice();
940         DisplayDeviceInfo displayDeviceInfo = device.getSourceInfo();
941         displayDeviceInfo.type = type;
942         displayDeviceInfo.uniqueId = uniqueId;
943         displayDeviceInfo.width = width;
944         displayDeviceInfo.height = height;
945         displayDeviceInfo.flags = flags;
946         displayDeviceInfo.supportedModes = new Display.Mode[1];
947         displayDeviceInfo.supportedModes[0] = new Display.Mode(1, width, height, 60f);
948         displayDeviceInfo.modeId = 1;
949         displayDeviceInfo.address = address;
950         return device;
951     }
952 
info(DisplayDevice device)953     private DisplayDeviceInfo info(DisplayDevice device) {
954         return device.getDisplayDeviceInfoLocked();
955     }
956 
width(DisplayDevice device)957     private int width(DisplayDevice device) {
958         return info(device).width;
959     }
960 
height(DisplayDevice device)961     private int height(DisplayDevice device) {
962         return info(device).height;
963     }
964 
info(LogicalDisplay display)965     private DisplayInfo info(LogicalDisplay display) {
966         return display.getDisplayInfoLocked();
967     }
968 
id(LogicalDisplay display)969     private int id(LogicalDisplay display) {
970         return display.getDisplayIdLocked();
971     }
972 
add(DisplayDevice device)973     private LogicalDisplay add(DisplayDevice device) {
974         mDisplayDeviceRepo.onDisplayDeviceEvent(device, DISPLAY_DEVICE_EVENT_ADDED);
975         ArgumentCaptor<LogicalDisplay> displayCaptor =
976                 ArgumentCaptor.forClass(LogicalDisplay.class);
977         verify(mListenerMock).onLogicalDisplayEventLocked(
978                 displayCaptor.capture(), eq(LOGICAL_DISPLAY_EVENT_ADDED));
979         clearInvocations(mListenerMock);
980         return displayCaptor.getValue();
981     }
982 
testDisplayDeviceAddAndRemove_NonInternal(int type)983     private void testDisplayDeviceAddAndRemove_NonInternal(int type) {
984         DisplayDevice device = createDisplayDevice(type, 600, 800, 0);
985 
986         // add
987         LogicalDisplay displayAdded = add(device);
988         assertEquals(info(displayAdded).address, info(device).address);
989         assertNotEquals(DEFAULT_DISPLAY, id(displayAdded));
990 
991         // remove
992         mDisplayDeviceRepo.onDisplayDeviceEvent(device, DISPLAY_DEVICE_EVENT_REMOVED);
993         verify(mListenerMock).onLogicalDisplayEventLocked(
994                 mDisplayCaptor.capture(), eq(LOGICAL_DISPLAY_EVENT_REMOVED));
995         LogicalDisplay displayRemoved = mDisplayCaptor.getValue();
996         assertNotEquals(DEFAULT_DISPLAY, id(displayRemoved));
997     }
998 
999     class TestDisplayDevice extends DisplayDevice {
1000         private DisplayDeviceInfo mInfo;
1001         private DisplayDeviceInfo mSentInfo;
1002         private int mState;
1003 
TestDisplayDevice()1004         TestDisplayDevice() {
1005             super(null, null, "test_display_" + sUniqueTestDisplayId++, mContextMock);
1006             mInfo = new DisplayDeviceInfo();
1007         }
1008 
1009         @Override
getDisplayDeviceInfoLocked()1010         public DisplayDeviceInfo getDisplayDeviceInfoLocked() {
1011             if (mSentInfo == null) {
1012                 mSentInfo = new DisplayDeviceInfo();
1013                 mSentInfo.copyFrom(mInfo);
1014             }
1015             return mSentInfo;
1016         }
1017 
1018         @Override
applyPendingDisplayDeviceInfoChangesLocked()1019         public void applyPendingDisplayDeviceInfoChangesLocked() {
1020             mSentInfo = null;
1021         }
1022 
1023         @Override
hasStableUniqueId()1024         public boolean hasStableUniqueId() {
1025             return true;
1026         }
1027 
getSourceInfo()1028         public DisplayDeviceInfo getSourceInfo() {
1029             return mInfo;
1030         }
1031     }
1032 }
1033