1 /*
2  * Copyright (C) 2017 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.Manifest.permission.ADD_ALWAYS_UNLOCKED_DISPLAY;
20 import static android.Manifest.permission.ADD_TRUSTED_DISPLAY;
21 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED;
22 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY;
23 import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP;
24 import static android.view.ContentRecordingSession.RECORD_CONTENT_DISPLAY;
25 import static android.view.ContentRecordingSession.RECORD_CONTENT_TASK;
26 
27 import static com.android.server.display.VirtualDisplayAdapter.UNIQUE_ID_PREFIX;
28 
29 import static com.google.common.truth.Truth.assertThat;
30 
31 import static org.junit.Assert.assertEquals;
32 import static org.junit.Assert.assertFalse;
33 import static org.junit.Assert.assertNotEquals;
34 import static org.junit.Assert.assertNotNull;
35 import static org.junit.Assert.assertNull;
36 import static org.junit.Assert.assertThrows;
37 import static org.junit.Assert.assertTrue;
38 import static org.junit.Assert.fail;
39 import static org.mockito.ArgumentMatchers.anyInt;
40 import static org.mockito.ArgumentMatchers.anyLong;
41 import static org.mockito.ArgumentMatchers.eq;
42 import static org.mockito.ArgumentMatchers.nullable;
43 import static org.mockito.Mockito.any;
44 import static org.mockito.Mockito.atLeastOnce;
45 import static org.mockito.Mockito.doReturn;
46 import static org.mockito.Mockito.inOrder;
47 import static org.mockito.Mockito.mock;
48 import static org.mockito.Mockito.never;
49 import static org.mockito.Mockito.spy;
50 import static org.mockito.Mockito.verify;
51 import static org.mockito.Mockito.when;
52 
53 import android.app.PropertyInvalidatedCache;
54 import android.companion.virtual.IVirtualDevice;
55 import android.companion.virtual.IVirtualDeviceManager;
56 import android.companion.virtual.VirtualDeviceManager;
57 import android.compat.testing.PlatformCompatChangeRule;
58 import android.content.Context;
59 import android.content.ContextWrapper;
60 import android.content.pm.PackageManager;
61 import android.content.pm.PackageManagerInternal;
62 import android.content.res.Resources;
63 import android.graphics.Insets;
64 import android.graphics.Rect;
65 import android.hardware.Sensor;
66 import android.hardware.SensorManager;
67 import android.hardware.display.BrightnessConfiguration;
68 import android.hardware.display.Curve;
69 import android.hardware.display.DisplayManager;
70 import android.hardware.display.DisplayManagerGlobal;
71 import android.hardware.display.DisplayManagerInternal;
72 import android.hardware.display.DisplayViewport;
73 import android.hardware.display.DisplayedContentSample;
74 import android.hardware.display.DisplayedContentSamplingAttributes;
75 import android.hardware.display.HdrConversionMode;
76 import android.hardware.display.IDisplayManagerCallback;
77 import android.hardware.display.IVirtualDisplayCallback;
78 import android.hardware.display.VirtualDisplayConfig;
79 import android.media.projection.IMediaProjection;
80 import android.media.projection.IMediaProjectionManager;
81 import android.os.Binder;
82 import android.os.Handler;
83 import android.os.IBinder;
84 import android.os.MessageQueue;
85 import android.os.Process;
86 import android.os.RemoteException;
87 import android.view.ContentRecordingSession;
88 import android.view.Display;
89 import android.view.DisplayCutout;
90 import android.view.DisplayEventReceiver;
91 import android.view.DisplayInfo;
92 import android.view.Surface;
93 import android.view.SurfaceControl;
94 import android.window.DisplayWindowPolicyController;
95 
96 import androidx.test.InstrumentationRegistry;
97 import androidx.test.core.app.ApplicationProvider;
98 import androidx.test.filters.FlakyTest;
99 import androidx.test.filters.SmallTest;
100 import androidx.test.runner.AndroidJUnit4;
101 
102 import com.android.internal.R;
103 import com.android.server.LocalServices;
104 import com.android.server.SystemService;
105 import com.android.server.companion.virtual.VirtualDeviceManagerInternal;
106 import com.android.server.display.DisplayManagerService.DeviceStateListener;
107 import com.android.server.display.DisplayManagerService.SyncRoot;
108 import com.android.server.input.InputManagerInternal;
109 import com.android.server.lights.LightsManager;
110 import com.android.server.pm.UserManagerInternal;
111 import com.android.server.sensors.SensorManagerInternal;
112 import com.android.server.wm.WindowManagerInternal;
113 
114 import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges;
115 import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
116 
117 import org.junit.Before;
118 import org.junit.Rule;
119 import org.junit.Test;
120 import org.junit.rules.TestRule;
121 import org.junit.runner.RunWith;
122 import org.mockito.ArgumentCaptor;
123 import org.mockito.Captor;
124 import org.mockito.InOrder;
125 import org.mockito.Mock;
126 import org.mockito.Mockito;
127 import org.mockito.MockitoAnnotations;
128 
129 import java.time.Duration;
130 import java.util.Arrays;
131 import java.util.Collections;
132 import java.util.List;
133 import java.util.Map;
134 import java.util.concurrent.CountDownLatch;
135 import java.util.concurrent.TimeUnit;
136 import java.util.stream.LongStream;
137 
138 @SmallTest
139 @RunWith(AndroidJUnit4.class)
140 public class DisplayManagerServiceTest {
141     private static final int MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS = 1;
142     private static final long SHORT_DEFAULT_DISPLAY_TIMEOUT_MILLIS = 10;
143 
144     private static final float FLOAT_TOLERANCE = 0.01f;
145 
146     private static final String VIRTUAL_DISPLAY_NAME = "Test Virtual Display";
147     private static final String PACKAGE_NAME = "com.android.frameworks.displayservicetests";
148     private static final long STANDARD_DISPLAY_EVENTS = DisplayManager.EVENT_FLAG_DISPLAY_ADDED
149                     | DisplayManager.EVENT_FLAG_DISPLAY_CHANGED
150                     | DisplayManager.EVENT_FLAG_DISPLAY_REMOVED;
151 
152     @Rule
153     public TestRule compatChangeRule = new PlatformCompatChangeRule();
154 
155     private Context mContext;
156 
157     private int mHdrConversionMode;
158 
159     private int mPreferredHdrOutputType;
160 
161     private final DisplayManagerService.Injector mShortMockedInjector =
162             new DisplayManagerService.Injector() {
163                 @Override
164                 VirtualDisplayAdapter getVirtualDisplayAdapter(SyncRoot syncRoot,
165                         Context context, Handler handler, DisplayAdapter.Listener listener) {
166                     return mMockVirtualDisplayAdapter;
167                 }
168 
169                 @Override
170                 LocalDisplayAdapter getLocalDisplayAdapter(SyncRoot syncRoot, Context context,
171                         Handler handler, DisplayAdapter.Listener displayAdapterListener) {
172                     return new LocalDisplayAdapter(syncRoot, context, handler,
173                             displayAdapterListener, new LocalDisplayAdapter.Injector() {
174                         @Override
175                         public LocalDisplayAdapter.SurfaceControlProxy getSurfaceControlProxy() {
176                             return mSurfaceControlProxy;
177                         }
178                     });
179                 }
180 
181                 @Override
182                 long getDefaultDisplayDelayTimeout() {
183                     return SHORT_DEFAULT_DISPLAY_TIMEOUT_MILLIS;
184                 }
185             };
186 
187     class BasicInjector extends DisplayManagerService.Injector {
188         @Override
getProjectionService()189         IMediaProjectionManager getProjectionService() {
190             return mMockProjectionService;
191         }
192 
193         @Override
getVirtualDisplayAdapter(SyncRoot syncRoot, Context context, Handler handler, DisplayAdapter.Listener displayAdapterListener)194         VirtualDisplayAdapter getVirtualDisplayAdapter(SyncRoot syncRoot, Context context,
195                 Handler handler, DisplayAdapter.Listener displayAdapterListener) {
196             return new VirtualDisplayAdapter(syncRoot, context, handler, displayAdapterListener,
197                     new VirtualDisplayAdapter.SurfaceControlDisplayFactory() {
198                         @Override
199                         public IBinder createDisplay(String name, boolean secure,
200                                 float requestedRefreshRate) {
201                             return mMockDisplayToken;
202                         }
203 
204                         @Override
205                         public void destroyDisplay(IBinder displayToken) {
206                         }
207                     });
208         }
209 
210         @Override
getLocalDisplayAdapter(SyncRoot syncRoot, Context context, Handler handler, DisplayAdapter.Listener displayAdapterListener)211         LocalDisplayAdapter getLocalDisplayAdapter(SyncRoot syncRoot, Context context,
212                 Handler handler, DisplayAdapter.Listener displayAdapterListener) {
213             return new LocalDisplayAdapter(syncRoot, context, handler,
214                     displayAdapterListener, new LocalDisplayAdapter.Injector() {
215                         @Override
216                         public LocalDisplayAdapter.SurfaceControlProxy getSurfaceControlProxy() {
217                             return mSurfaceControlProxy;
218                         }
219                     });
220         }
221 
222         @Override
223         int setHdrConversionMode(int conversionMode, int preferredHdrOutputType,
224                 int[] autoHdrTypes) {
225             mHdrConversionMode = conversionMode;
226             mPreferredHdrOutputType = preferredHdrOutputType;
227             return Display.HdrCapabilities.HDR_TYPE_INVALID;
228         }
229 
230         @Override
231         int[] getSupportedHdrOutputTypes() {
232             return new int[]{};
233         }
234 
235         @Override
236         int[] getHdrOutputTypesWithLatency() {
237             return new int[]{Display.HdrCapabilities.HDR_TYPE_DOLBY_VISION};
238         }
239 
240         boolean getHdrOutputConversionSupport() {
241             return true;
242         }
243     }
244 
245     private final DisplayManagerService.Injector mBasicInjector = new BasicInjector();
246 
247     @Mock IMediaProjectionManager mMockProjectionService;
248     @Mock IVirtualDeviceManager mIVirtualDeviceManager;
249     @Mock InputManagerInternal mMockInputManagerInternal;
250     @Mock VirtualDeviceManagerInternal mMockVirtualDeviceManagerInternal;
251     @Mock IVirtualDisplayCallback.Stub mMockAppToken;
252     @Mock IVirtualDisplayCallback.Stub mMockAppToken2;
253     @Mock WindowManagerInternal mMockWindowManagerInternal;
254     @Mock LightsManager mMockLightsManager;
255     @Mock VirtualDisplayAdapter mMockVirtualDisplayAdapter;
256     @Mock LocalDisplayAdapter.SurfaceControlProxy mSurfaceControlProxy;
257     @Mock IBinder mMockDisplayToken;
258     @Mock SensorManagerInternal mMockSensorManagerInternal;
259     @Mock SensorManager mSensorManager;
260     @Mock DisplayDeviceConfig mMockDisplayDeviceConfig;
261     @Mock PackageManagerInternal mMockPackageManagerInternal;
262     @Mock UserManagerInternal mMockUserManagerInternal;
263 
264 
265     @Captor ArgumentCaptor<ContentRecordingSession> mContentRecordingSessionCaptor;
266 
267     @Before
268     public void setUp() throws Exception {
269         MockitoAnnotations.initMocks(this);
270 
271         LocalServices.removeServiceForTest(InputManagerInternal.class);
272         LocalServices.addService(InputManagerInternal.class, mMockInputManagerInternal);
273         LocalServices.removeServiceForTest(WindowManagerInternal.class);
274         LocalServices.addService(WindowManagerInternal.class, mMockWindowManagerInternal);
275         LocalServices.removeServiceForTest(LightsManager.class);
276         LocalServices.addService(LightsManager.class, mMockLightsManager);
277         LocalServices.removeServiceForTest(SensorManagerInternal.class);
278         LocalServices.addService(SensorManagerInternal.class, mMockSensorManagerInternal);
279         LocalServices.removeServiceForTest(VirtualDeviceManagerInternal.class);
280         LocalServices.addService(
281                 VirtualDeviceManagerInternal.class, mMockVirtualDeviceManagerInternal);
282         LocalServices.removeServiceForTest(PackageManagerInternal.class);
283         LocalServices.addService(PackageManagerInternal.class, mMockPackageManagerInternal);
284         LocalServices.removeServiceForTest(UserManagerInternal.class);
285         LocalServices.addService(UserManagerInternal.class, mMockUserManagerInternal);
286         // TODO: b/287945043
287         mContext = spy(new ContextWrapper(ApplicationProvider.getApplicationContext()));
288 
289         VirtualDeviceManager vdm = new VirtualDeviceManager(mIVirtualDeviceManager, mContext);
290         when(mContext.getSystemService(VirtualDeviceManager.class)).thenReturn(vdm);
291         // Disable binder caches in this process.
292         PropertyInvalidatedCache.disableForTestMode();
293         setUpDisplay();
294     }
295 
296     private void setUpDisplay() {
297         long[] ids = new long[] {100};
298         when(mSurfaceControlProxy.getPhysicalDisplayIds()).thenReturn(ids);
299         when(mSurfaceControlProxy.getPhysicalDisplayToken(anyLong()))
300                 .thenReturn(mMockDisplayToken);
301         SurfaceControl.StaticDisplayInfo staticDisplayInfo = new SurfaceControl.StaticDisplayInfo();
302         staticDisplayInfo.isInternal = true;
303         when(mSurfaceControlProxy.getStaticDisplayInfo(anyLong()))
304                 .thenReturn(staticDisplayInfo);
305         SurfaceControl.DynamicDisplayInfo dynamicDisplayMode =
306                 new SurfaceControl.DynamicDisplayInfo();
307         SurfaceControl.DisplayMode displayMode = new SurfaceControl.DisplayMode();
308         displayMode.width = 100;
309         displayMode.height = 200;
310         displayMode.supportedHdrTypes = new int[]{1, 2};
311         dynamicDisplayMode.supportedDisplayModes = new SurfaceControl.DisplayMode[] {displayMode};
312         when(mSurfaceControlProxy.getDynamicDisplayInfo(anyLong()))
313                 .thenReturn(dynamicDisplayMode);
314         when(mSurfaceControlProxy.getDesiredDisplayModeSpecs(mMockDisplayToken))
315                 .thenReturn(new SurfaceControl.DesiredDisplayModeSpecs());
316     }
317 
318     @Test
319     public void testCreateVirtualDisplay_sentToInputManager() throws RemoteException {
320         // This is to update the display device config such that DisplayManagerService can ignore
321         // the usage of SensorManager, which is available only after the PowerManagerService
322         // is ready.
323         resetConfigToIgnoreSensorManager(mContext);
324         DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
325         registerDefaultDisplays(displayManager);
326         displayManager.systemReady(false /* safeMode */);
327         displayManager.windowManagerAndInputReady();
328 
329         // This is effectively the DisplayManager service published to ServiceManager.
330         DisplayManagerService.BinderService bs = displayManager.new BinderService();
331 
332         String uniqueId = "uniqueId --- Test";
333         String uniqueIdPrefix = UNIQUE_ID_PREFIX + mContext.getPackageName() + ":";
334         int width = 600;
335         int height = 800;
336         int dpi = 320;
337         int flags = DisplayManager.VIRTUAL_DISPLAY_FLAG_SUPPORTS_TOUCH;
338 
339         when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
340         final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(
341                 VIRTUAL_DISPLAY_NAME, width, height, dpi);
342         builder.setUniqueId(uniqueId);
343         builder.setFlags(flags);
344         int displayId = bs.createVirtualDisplay(builder.build(), mMockAppToken /* callback */,
345                 null /* projection */, PACKAGE_NAME);
346         verify(mMockProjectionService, never()).setContentRecordingSession(any(),
347                 nullable(IMediaProjection.class));
348 
349         displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
350 
351         // flush the handler
352         displayManager.getDisplayHandler().runWithScissors(() -> {}, 0 /* now */);
353 
354         ArgumentCaptor<List<DisplayViewport>> viewportCaptor = ArgumentCaptor.forClass(List.class);
355         verify(mMockInputManagerInternal).setDisplayViewports(viewportCaptor.capture());
356         List<DisplayViewport> viewports = viewportCaptor.getValue();
357 
358         // Expect to receive at least 2 viewports: at least 1 internal, and 1 virtual
359         assertTrue(viewports.size() >= 2);
360 
361         DisplayViewport virtualViewport = null;
362         DisplayViewport internalViewport = null;
363         for (int i = 0; i < viewports.size(); i++) {
364             DisplayViewport v = viewports.get(i);
365             switch (v.type) {
366                 case DisplayViewport.VIEWPORT_INTERNAL: {
367                     // If more than one internal viewport, this will get overwritten several times,
368                     // which for the purposes of this test is fine.
369                     internalViewport = v;
370                     assertTrue(internalViewport.valid);
371                     break;
372                 }
373                 case DisplayViewport.VIEWPORT_EXTERNAL: {
374                     // External view port is present for auto devices in the form of instrument
375                     // cluster.
376                     break;
377                 }
378                 case DisplayViewport.VIEWPORT_VIRTUAL: {
379                     virtualViewport = v;
380                     break;
381                 }
382             }
383         }
384         // INTERNAL viewport gets created upon access.
385         assertNotNull(internalViewport);
386         assertNotNull(virtualViewport);
387 
388         // VIRTUAL
389         assertEquals(height, virtualViewport.deviceHeight);
390         assertEquals(width, virtualViewport.deviceWidth);
391         assertEquals(uniqueIdPrefix + uniqueId, virtualViewport.uniqueId);
392         assertEquals(displayId, virtualViewport.displayId);
393     }
394 
395     @Test
396     public void testPhysicalViewports() {
397         // This is to update the display device config such that DisplayManagerService can ignore
398         // the usage of SensorManager, which is available only after the PowerManagerService
399         // is ready.
400         resetConfigToIgnoreSensorManager(mContext);
401         DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
402         registerDefaultDisplays(displayManager);
403         displayManager.systemReady(false /* safeMode */);
404         displayManager.windowManagerAndInputReady();
405 
406         // This is effectively the DisplayManager service published to ServiceManager.
407         DisplayManagerService.BinderService bs = displayManager.new BinderService();
408 
409         when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
410 
411         final int[] displayIds = bs.getDisplayIds(/* includeDisabled= */ true);
412         final int size = displayIds.length;
413         assertTrue(size > 0);
414 
415         Map<Integer, Integer> expectedDisplayTypeToViewPortTypeMapping = Map.of(
416                 Display.TYPE_INTERNAL, DisplayViewport.VIEWPORT_INTERNAL,
417                 Display.TYPE_EXTERNAL, DisplayViewport.VIEWPORT_EXTERNAL
418         );
419         for (int i = 0; i < size; i++) {
420             DisplayInfo info = bs.getDisplayInfo(displayIds[i]);
421             assertTrue(expectedDisplayTypeToViewPortTypeMapping.keySet().contains(info.type));
422         }
423 
424         displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
425 
426         // flush the handler
427         displayManager.getDisplayHandler().runWithScissors(() -> {}, 0 /* now */);
428 
429         ArgumentCaptor<List<DisplayViewport>> viewportCaptor = ArgumentCaptor.forClass(List.class);
430         verify(mMockInputManagerInternal).setDisplayViewports(viewportCaptor.capture());
431         List<DisplayViewport> viewports = viewportCaptor.getValue();
432 
433         // Due to the nature of foldables, we may have a different number of viewports than
434         // displays, just verify there's at least one.
435         final int viewportSize = viewports.size();
436         assertTrue(viewportSize > 0);
437 
438         // Now verify that each viewport's displayId is valid.
439         Arrays.sort(displayIds);
440         for (int i = 0; i < viewportSize; i++) {
441             DisplayViewport viewport = viewports.get(i);
442             assertNotNull(viewport);
443             DisplayInfo displayInfo = bs.getDisplayInfo(viewport.displayId);
444             assertTrue(expectedDisplayTypeToViewPortTypeMapping.get(displayInfo.type)
445                     == viewport.type);
446             assertTrue(viewport.valid);
447             assertTrue(Arrays.binarySearch(displayIds, viewport.displayId) >= 0);
448         }
449     }
450 
451     @Test
452     public void testCreateVirtualDisplayRotatesWithContent() throws Exception {
453         DisplayManagerService displayManager =
454                 new DisplayManagerService(mContext, mBasicInjector);
455         registerDefaultDisplays(displayManager);
456 
457         // This is effectively the DisplayManager service published to ServiceManager.
458         DisplayManagerService.BinderService bs = displayManager.new BinderService();
459 
460         String uniqueId = "uniqueId --- Rotates With Content Test";
461         int width = 600;
462         int height = 800;
463         int dpi = 320;
464         int flags = DisplayManager.VIRTUAL_DISPLAY_FLAG_ROTATES_WITH_CONTENT;
465 
466         when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
467         final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(
468                 VIRTUAL_DISPLAY_NAME, width, height, dpi);
469         builder.setFlags(flags);
470         builder.setUniqueId(uniqueId);
471         int displayId = bs.createVirtualDisplay(builder.build(), mMockAppToken /* callback */,
472                 null /* projection */, PACKAGE_NAME);
473         verify(mMockProjectionService, never()).setContentRecordingSession(any(),
474                 nullable(IMediaProjection.class));
475 
476         displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
477 
478         // flush the handler
479         displayManager.getDisplayHandler().runWithScissors(() -> {}, 0 /* now */);
480 
481         DisplayDeviceInfo ddi = displayManager.getDisplayDeviceInfoInternal(displayId);
482         assertNotNull(ddi);
483         assertTrue((ddi.flags & DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT) != 0);
484     }
485 
486     @Test
487     public void testCreateVirtualRotatesWithContent() throws RemoteException {
488         DisplayManagerService displayManager =
489                 new DisplayManagerService(mContext, mBasicInjector);
490         registerDefaultDisplays(displayManager);
491 
492         // This is effectively the DisplayManager service published to ServiceManager.
493         DisplayManagerService.BinderService bs = displayManager.new BinderService();
494 
495         String uniqueId = "uniqueId --- Rotates with Content Test";
496         int width = 600;
497         int height = 800;
498         int dpi = 320;
499         int flags = DisplayManager.VIRTUAL_DISPLAY_FLAG_ROTATES_WITH_CONTENT;
500 
501         when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
502         final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(
503                 VIRTUAL_DISPLAY_NAME, width, height, dpi);
504         builder.setFlags(flags);
505         builder.setUniqueId(uniqueId);
506         int displayId = bs.createVirtualDisplay(builder.build(), /* callback= */ mMockAppToken,
507                 /* projection= */ null, PACKAGE_NAME);
508         verify(mMockProjectionService, never()).setContentRecordingSession(any(),
509                 nullable(IMediaProjection.class));
510 
511         displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
512 
513         // flush the handler
514         displayManager.getDisplayHandler().runWithScissors(() -> {}, /* now= */ 0);
515 
516         DisplayDeviceInfo ddi = displayManager.getDisplayDeviceInfoInternal(displayId);
517         assertNotNull(ddi);
518         assertTrue((ddi.flags & DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT) != 0);
519     }
520 
521     @Test
522     public void testCreateVirtualDisplayOwnFocus() throws RemoteException {
523         DisplayManagerService displayManager =
524                 new DisplayManagerService(mContext, mBasicInjector);
525         registerDefaultDisplays(displayManager);
526 
527         // This is effectively the DisplayManager service published to ServiceManager.
528         DisplayManagerService.BinderService bs = displayManager.new BinderService();
529 
530         String uniqueId = "uniqueId --- Own Focus Test";
531         int width = 600;
532         int height = 800;
533         int dpi = 320;
534         int flags = DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_FOCUS
535                 | DisplayManager.VIRTUAL_DISPLAY_FLAG_TRUSTED;
536 
537         when(mContext.checkCallingPermission(ADD_TRUSTED_DISPLAY)).thenReturn(
538                 PackageManager.PERMISSION_GRANTED);
539         when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
540         final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(
541                 VIRTUAL_DISPLAY_NAME, width, height, dpi);
542         builder.setFlags(flags);
543         builder.setUniqueId(uniqueId);
544         int displayId = bs.createVirtualDisplay(builder.build(), /* callback= */ mMockAppToken,
545                 /* projection= */ null, PACKAGE_NAME);
546         verify(mMockProjectionService, never()).setContentRecordingSession(any(),
547                 nullable(IMediaProjection.class));
548 
549         displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
550 
551         // flush the handler
552         displayManager.getDisplayHandler().runWithScissors(() -> {}, /* now= */ 0);
553 
554         DisplayDeviceInfo ddi = displayManager.getDisplayDeviceInfoInternal(displayId);
555         assertNotNull(ddi);
556         assertTrue((ddi.flags & DisplayDeviceInfo.FLAG_OWN_FOCUS) != 0);
557     }
558 
559     @Test
560     public void testCreateVirtualDisplayOwnFocus_nonTrustedDisplay() throws RemoteException {
561         DisplayManagerService displayManager =
562                 new DisplayManagerService(mContext, mBasicInjector);
563         registerDefaultDisplays(displayManager);
564 
565         // This is effectively the DisplayManager service published to ServiceManager.
566         DisplayManagerService.BinderService bs = displayManager.new BinderService();
567 
568         String uniqueId = "uniqueId --- Own Focus Test -- nonTrustedDisplay";
569         int width = 600;
570         int height = 800;
571         int dpi = 320;
572         int flags = DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_FOCUS;
573 
574         when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
575         final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(
576                 VIRTUAL_DISPLAY_NAME, width, height, dpi);
577         builder.setFlags(flags);
578         builder.setUniqueId(uniqueId);
579         int displayId = bs.createVirtualDisplay(builder.build(), /* callback= */ mMockAppToken,
580                 /* projection= */ null, PACKAGE_NAME);
581         verify(mMockProjectionService, never()).setContentRecordingSession(any(),
582                 nullable(IMediaProjection.class));
583 
584         displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
585 
586         // flush the handler
587         displayManager.getDisplayHandler().runWithScissors(() -> {}, /* now= */ 0);
588 
589         DisplayDeviceInfo ddi = displayManager.getDisplayDeviceInfoInternal(displayId);
590         assertNotNull(ddi);
591         assertTrue((ddi.flags & DisplayDeviceInfo.FLAG_OWN_FOCUS) == 0);
592     }
593 
594     /**
595      * Tests that the virtual display is created along-side the default display.
596      */
597     @Test
598     public void testStartVirtualDisplayWithDefaultDisplay_Succeeds() throws Exception {
599         DisplayManagerService displayManager =
600                 new DisplayManagerService(mContext, mShortMockedInjector);
601         registerDefaultDisplays(displayManager);
602         displayManager.onBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
603     }
604 
605     /**
606      * Tests that we send the device state to window manager
607      */
608     @Test
609     public void testOnStateChanged_sendsStateChangedEventToWm() throws Exception {
610         DisplayManagerService displayManager =
611                 new DisplayManagerService(mContext, mShortMockedInjector);
612         registerDefaultDisplays(displayManager);
613         displayManager.windowManagerAndInputReady();
614         displayManager.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);
615         DeviceStateListener listener = displayManager.new DeviceStateListener();
616         Handler handler = displayManager.getDisplayHandler();
617         IDisplayManagerCallback displayChangesCallback = registerDisplayChangeCallback(
618                 displayManager);
619 
620         listener.onStateChanged(123);
621         waitForIdleHandler(handler);
622 
623         InOrder inOrder = inOrder(mMockWindowManagerInternal, displayChangesCallback);
624         // Verify there are no display events before WM call
625         inOrder.verify(displayChangesCallback, never()).onDisplayEvent(anyInt(), anyInt());
626         inOrder.verify(mMockWindowManagerInternal).onDisplayManagerReceivedDeviceState(123);
627     }
628 
629     /**
630      * Tests that there should be a display change notification to WindowManager to update its own
631      * internal state for things like display cutout when nonOverrideDisplayInfo is changed.
632      */
633     @Test
634     public void testShouldNotifyChangeWhenNonOverrideDisplayInfoChanged() throws Exception {
635         DisplayManagerService displayManager =
636                 new DisplayManagerService(mContext, mShortMockedInjector);
637         registerDefaultDisplays(displayManager);
638         displayManager.onBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
639 
640         // Add the FakeDisplayDevice
641         FakeDisplayDevice displayDevice = new FakeDisplayDevice();
642         DisplayDeviceInfo displayDeviceInfo = new DisplayDeviceInfo();
643         displayDeviceInfo.width = 100;
644         displayDeviceInfo.height = 200;
645         displayDeviceInfo.supportedModes = new Display.Mode[1];
646         displayDeviceInfo.supportedModes[0] = new Display.Mode(1, 100, 200, 60f);
647         displayDeviceInfo.modeId = 1;
648         final Rect zeroRect = new Rect();
649         displayDeviceInfo.displayCutout = new DisplayCutout(
650                 Insets.of(0, 10, 0, 0),
651                 zeroRect, new Rect(0, 0, 10, 10), zeroRect, zeroRect);
652         displayDeviceInfo.flags = DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY;
653         displayDeviceInfo.address = new TestUtils.TestDisplayAddress();
654         displayDevice.setDisplayDeviceInfo(displayDeviceInfo);
655         displayManager.getDisplayDeviceRepository()
656                 .onDisplayDeviceEvent(displayDevice, DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED);
657 
658         // Find the display id of the added FakeDisplayDevice
659         DisplayManagerService.BinderService bs = displayManager.new BinderService();
660         int displayId = getDisplayIdForDisplayDevice(displayManager, bs, displayDevice);
661         // Setup override DisplayInfo
662         DisplayInfo overrideInfo = bs.getDisplayInfo(displayId);
663         displayManager.setDisplayInfoOverrideFromWindowManagerInternal(displayId, overrideInfo);
664 
665         FakeDisplayManagerCallback callback = registerDisplayListenerCallback(
666                 displayManager, bs, displayDevice);
667 
668         // Simulate DisplayDevice change
669         DisplayDeviceInfo displayDeviceInfo2 = new DisplayDeviceInfo();
670         displayDeviceInfo2.copyFrom(displayDeviceInfo);
671         displayDeviceInfo2.displayCutout = null;
672         displayDevice.setDisplayDeviceInfo(displayDeviceInfo2);
673         displayManager.getDisplayDeviceRepository()
674                 .onDisplayDeviceEvent(displayDevice, DisplayAdapter.DISPLAY_DEVICE_EVENT_CHANGED);
675 
676         Handler handler = displayManager.getDisplayHandler();
677         waitForIdleHandler(handler);
678         assertTrue(callback.mDisplayChangedCalled);
679     }
680 
681     /**
682      * Tests that we get a Runtime exception when we cannot initialize the default display.
683      */
684     @Test
685     public void testStartVirtualDisplayWithDefDisplay_NoDefaultDisplay() throws Exception {
686         DisplayManagerService displayManager =
687                 new DisplayManagerService(mContext, mShortMockedInjector);
688         Handler handler = displayManager.getDisplayHandler();
689         waitForIdleHandler(handler);
690 
691         try {
692             displayManager.onBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
693         } catch (RuntimeException e) {
694             return;
695         }
696         fail("Expected DisplayManager to throw RuntimeException when it cannot initialize the"
697                 + " default display");
698     }
699 
700     /**
701      * Tests that we get a Runtime exception when we cannot initialize the virtual display.
702      */
703     @Test
704     public void testStartVirtualDisplayWithDefDisplay_NoVirtualDisplayAdapter() throws Exception {
705         DisplayManagerService displayManager = new DisplayManagerService(mContext,
706                 new DisplayManagerService.Injector() {
707                     @Override
708                     VirtualDisplayAdapter getVirtualDisplayAdapter(SyncRoot syncRoot,
709                             Context context, Handler handler, DisplayAdapter.Listener listener) {
710                         return null;  // return null for the adapter.  This should cause a failure.
711                     }
712 
713                     @Override
714                     long getDefaultDisplayDelayTimeout() {
715                         return SHORT_DEFAULT_DISPLAY_TIMEOUT_MILLIS;
716                     }
717                 });
718         try {
719             displayManager.onBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
720         } catch (RuntimeException e) {
721             return;
722         }
723         fail("Expected DisplayManager to throw RuntimeException when it cannot initialize the"
724                 + " virtual display adapter");
725     }
726 
727     /**
728      * Tests that an exception is raised for too dark a brightness configuration.
729      */
730     @Test
731     public void testTooDarkBrightnessConfigurationThrowException() {
732         DisplayManagerService displayManager =
733                 new DisplayManagerService(mContext, mShortMockedInjector);
734         Curve minimumBrightnessCurve = displayManager.getMinimumBrightnessCurveInternal();
735         float[] lux = minimumBrightnessCurve.getX();
736         float[] minimumNits = minimumBrightnessCurve.getY();
737         float[] nits = new float[minimumNits.length];
738         // For every control point, assert that making it slightly lower than the minimum throws an
739         // exception.
740         for (int i = 0; i < nits.length; i++) {
741             for (int j = 0; j < nits.length; j++) {
742                 nits[j] = minimumNits[j];
743                 if (j == i) {
744                     nits[j] -= 0.1f;
745                 }
746                 if (nits[j] < 0) {
747                     nits[j] = 0;
748                 }
749             }
750             BrightnessConfiguration config =
751                     new BrightnessConfiguration.Builder(lux, nits).build();
752             Exception thrown = null;
753             try {
754                 displayManager.validateBrightnessConfiguration(config);
755             } catch (IllegalArgumentException e) {
756                 thrown = e;
757             }
758             assertNotNull("Building too dark a brightness configuration must throw an exception");
759         }
760     }
761 
762     /**
763      * Tests that no exception is raised for not too dark a brightness configuration.
764      */
765     @Test
766     public void testBrightEnoughBrightnessConfigurationDoesNotThrowException() {
767         DisplayManagerService displayManager =
768                 new DisplayManagerService(mContext, mShortMockedInjector);
769         Curve minimumBrightnessCurve = displayManager.getMinimumBrightnessCurveInternal();
770         float[] lux = minimumBrightnessCurve.getX();
771         float[] nits = minimumBrightnessCurve.getY();
772         BrightnessConfiguration config = new BrightnessConfiguration.Builder(lux, nits).build();
773         displayManager.validateBrightnessConfiguration(config);
774     }
775 
776     /**
777      * Tests that null brightness configurations are alright.
778      */
779     @Test
780     public void testNullBrightnessConfiguration() {
781         DisplayManagerService displayManager =
782                 new DisplayManagerService(mContext, mShortMockedInjector);
783         displayManager.validateBrightnessConfiguration(null);
784     }
785 
786     /**
787      * Tests that collection of display color sampling results are sensible.
788      */
789     @Test
790     public void testDisplayedContentSampling() {
791         DisplayManagerService displayManager =
792                 new DisplayManagerService(mContext, mShortMockedInjector);
793         registerDefaultDisplays(displayManager);
794 
795         DisplayDeviceInfo ddi = displayManager.getDisplayDeviceInfoInternal(0);
796         assertNotNull(ddi);
797 
798         DisplayedContentSamplingAttributes attr =
799                 displayManager.getDisplayedContentSamplingAttributesInternal(0);
800         if (attr == null) return; //sampling not supported on device, skip remainder of test.
801 
802         boolean enabled = displayManager.setDisplayedContentSamplingEnabledInternal(0, true, 0, 0);
803         assertTrue(enabled);
804 
805         displayManager.setDisplayedContentSamplingEnabledInternal(0, false, 0, 0);
806         DisplayedContentSample sample = displayManager.getDisplayedContentSampleInternal(0, 0, 0);
807         assertNotNull(sample);
808 
809         long numPixels = ddi.width * ddi.height * sample.getNumFrames();
810         long[] samples = sample.getSampleComponent(DisplayedContentSample.ColorComponent.CHANNEL0);
811         assertTrue(samples.length == 0 || LongStream.of(samples).sum() == numPixels);
812 
813         samples = sample.getSampleComponent(DisplayedContentSample.ColorComponent.CHANNEL1);
814         assertTrue(samples.length == 0 || LongStream.of(samples).sum() == numPixels);
815 
816         samples = sample.getSampleComponent(DisplayedContentSample.ColorComponent.CHANNEL2);
817         assertTrue(samples.length == 0 || LongStream.of(samples).sum() == numPixels);
818 
819         samples = sample.getSampleComponent(DisplayedContentSample.ColorComponent.CHANNEL3);
820         assertTrue(samples.length == 0 || LongStream.of(samples).sum() == numPixels);
821     }
822 
823     /**
824      * Tests that the virtual display is created with
825      * {@link VirtualDisplayConfig.Builder#setDisplayIdToMirror(int)}
826      */
827     @Test
828     @FlakyTest(bugId = 127687569)
829     public void testCreateVirtualDisplay_displayIdToMirror() throws Exception {
830         DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
831         registerDefaultDisplays(displayManager);
832 
833         // This is effectively the DisplayManager service published to ServiceManager.
834         DisplayManagerService.BinderService binderService = displayManager.new BinderService();
835         DisplayManagerService.LocalService localDisplayManager = displayManager.new LocalService();
836 
837         final String uniqueId = "uniqueId --- displayIdToMirrorTest";
838         final int width = 600;
839         final int height = 800;
840         final int dpi = 320;
841 
842         when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
843         final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(
844                 VIRTUAL_DISPLAY_NAME, width, height, dpi);
845         builder.setUniqueId(uniqueId);
846         final int firstDisplayId = binderService.createVirtualDisplay(builder.build(),
847                 mMockAppToken /* callback */, null /* projection */, PACKAGE_NAME);
848         verify(mMockProjectionService, never()).setContentRecordingSession(any(),
849                 nullable(IMediaProjection.class));
850 
851         // The second virtual display requests to mirror the first virtual display.
852         final String uniqueId2 = "uniqueId --- displayIdToMirrorTest #2";
853         when(mMockAppToken2.asBinder()).thenReturn(mMockAppToken2);
854         final VirtualDisplayConfig.Builder builder2 = new VirtualDisplayConfig.Builder(
855                 VIRTUAL_DISPLAY_NAME, width, height, dpi).setUniqueId(uniqueId2);
856         builder2.setUniqueId(uniqueId2);
857         builder2.setDisplayIdToMirror(firstDisplayId);
858         final int secondDisplayId = binderService.createVirtualDisplay(builder2.build(),
859                 mMockAppToken2 /* callback */, null /* projection */,
860                 PACKAGE_NAME);
861         verify(mMockProjectionService, never()).setContentRecordingSession(any(),
862                 nullable(IMediaProjection.class));
863         displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
864 
865         // flush the handler
866         displayManager.getDisplayHandler().runWithScissors(() -> {}, 0 /* now */);
867 
868         // The displayId to mirror should be a default display if there is none initially.
869         assertEquals(localDisplayManager.getDisplayIdToMirror(firstDisplayId),
870                 Display.DEFAULT_DISPLAY);
871         assertEquals(localDisplayManager.getDisplayIdToMirror(secondDisplayId),
872                 firstDisplayId);
873     }
874 
875     /** Tests that the virtual device is created in a device display group. */
876     @Test
877     public void createVirtualDisplay_addsDisplaysToDeviceDisplayGroups() throws Exception {
878         DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
879         DisplayManagerInternal localService = displayManager.new LocalService();
880 
881         registerDefaultDisplays(displayManager);
882         when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
883 
884         IVirtualDevice virtualDevice = mock(IVirtualDevice.class);
885         when(virtualDevice.getDeviceId()).thenReturn(1);
886         when(mIVirtualDeviceManager.isValidVirtualDeviceId(1)).thenReturn(true);
887         // Create a first virtual display. A display group should be created for this display on the
888         // virtual device.
889         final VirtualDisplayConfig.Builder builder1 =
890                 new VirtualDisplayConfig.Builder(VIRTUAL_DISPLAY_NAME, 600, 800, 320)
891                         .setUniqueId("uniqueId --- device display group 1");
892 
893         int displayId1 =
894                 localService.createVirtualDisplay(
895                         builder1.build(),
896                         mMockAppToken /* callback */,
897                         virtualDevice /* virtualDeviceToken */,
898                         mock(DisplayWindowPolicyController.class),
899                         PACKAGE_NAME);
900         verify(mMockProjectionService, never()).setContentRecordingSession(any(),
901                 nullable(IMediaProjection.class));
902         int displayGroupId1 = localService.getDisplayInfo(displayId1).displayGroupId;
903 
904         // Create a second virtual display. This should be added to the previously created display
905         // group.
906         final VirtualDisplayConfig.Builder builder2 =
907                 new VirtualDisplayConfig.Builder(VIRTUAL_DISPLAY_NAME, 600, 800, 320)
908                         .setUniqueId("uniqueId --- device display group 1");
909 
910         int displayId2 =
911                 localService.createVirtualDisplay(
912                         builder2.build(),
913                         mMockAppToken /* callback */,
914                         virtualDevice /* virtualDeviceToken */,
915                         mock(DisplayWindowPolicyController.class),
916                         PACKAGE_NAME);
917         verify(mMockProjectionService, never()).setContentRecordingSession(any(),
918                 nullable(IMediaProjection.class));
919         int displayGroupId2 = localService.getDisplayInfo(displayId2).displayGroupId;
920 
921         assertEquals(
922                 "Both displays should be added to the same displayGroup.",
923                 displayGroupId1,
924                 displayGroupId2);
925     }
926 
927     /**
928      * Tests that the virtual display is not added to the device display group when
929      * VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP is set.
930      */
931     @Test
932     public void createVirtualDisplay_addsDisplaysToOwnDisplayGroups() throws Exception {
933         DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
934         DisplayManagerInternal localService = displayManager.new LocalService();
935 
936         registerDefaultDisplays(displayManager);
937         when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
938 
939         IVirtualDevice virtualDevice = mock(IVirtualDevice.class);
940         when(virtualDevice.getDeviceId()).thenReturn(1);
941         when(mIVirtualDeviceManager.isValidVirtualDeviceId(1)).thenReturn(true);
942 
943         // Create a first virtual display. A display group should be created for this display on the
944         // virtual device.
945         final VirtualDisplayConfig.Builder builder1 =
946                 new VirtualDisplayConfig.Builder(VIRTUAL_DISPLAY_NAME, 600, 800, 320)
947                         .setUniqueId("uniqueId --- device display group");
948 
949         int displayId1 =
950                 localService.createVirtualDisplay(
951                         builder1.build(),
952                         mMockAppToken /* callback */,
953                         virtualDevice /* virtualDeviceToken */,
954                         mock(DisplayWindowPolicyController.class),
955                         PACKAGE_NAME);
956         verify(mMockProjectionService, never()).setContentRecordingSession(any(),
957                 nullable(IMediaProjection.class));
958         int displayGroupId1 = localService.getDisplayInfo(displayId1).displayGroupId;
959 
960         // Create a second virtual display. With the flag VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP,
961         // the display should not be added to the previously created display group.
962         final VirtualDisplayConfig.Builder builder2 =
963                 new VirtualDisplayConfig.Builder(VIRTUAL_DISPLAY_NAME, 600, 800, 320)
964                         .setFlags(VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP)
965                         .setUniqueId("uniqueId --- own display group");
966 
967         when(mIVirtualDeviceManager.isValidVirtualDeviceId(1)).thenReturn(true);
968 
969         int displayId2 =
970                 localService.createVirtualDisplay(
971                         builder2.build(),
972                         mMockAppToken /* callback */,
973                         virtualDevice /* virtualDeviceToken */,
974                         mock(DisplayWindowPolicyController.class),
975                         PACKAGE_NAME);
976         verify(mMockProjectionService, never()).setContentRecordingSession(any(),
977                 nullable(IMediaProjection.class));
978         int displayGroupId2 = localService.getDisplayInfo(displayId2).displayGroupId;
979 
980         assertNotEquals(
981                 "Display 1 should be in the device display group and display 2 in its own display"
982                         + " group.",
983                 displayGroupId1,
984                 displayGroupId2);
985     }
986 
987     @Test
988     public void displaysInDeviceOrOwnDisplayGroupShouldPreserveAlwaysUnlockedFlag()
989             throws Exception {
990         DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
991         DisplayManagerInternal localService = displayManager.new LocalService();
992 
993         registerDefaultDisplays(displayManager);
994         when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
995 
996         IVirtualDevice virtualDevice = mock(IVirtualDevice.class);
997         when(virtualDevice.getDeviceId()).thenReturn(1);
998         when(mIVirtualDeviceManager.isValidVirtualDeviceId(1)).thenReturn(true);
999 
1000         // Allow an ALWAYS_UNLOCKED display to be created.
1001         when(mContext.checkCallingPermission(ADD_TRUSTED_DISPLAY))
1002                 .thenReturn(PackageManager.PERMISSION_GRANTED);
1003 
1004         when(mContext.checkCallingPermission(ADD_ALWAYS_UNLOCKED_DISPLAY))
1005                 .thenReturn(PackageManager.PERMISSION_GRANTED);
1006 
1007         // Create a virtual display in a device display group.
1008         final VirtualDisplayConfig deviceDisplayGroupDisplayConfig =
1009                 new VirtualDisplayConfig.Builder(VIRTUAL_DISPLAY_NAME, 600, 800, 320)
1010                         .setUniqueId("uniqueId --- device display group 1")
1011                         .setFlags(VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED)
1012                         .build();
1013 
1014         int deviceDisplayGroupDisplayId =
1015                 localService.createVirtualDisplay(
1016                         deviceDisplayGroupDisplayConfig,
1017                         mMockAppToken /* callback */,
1018                         virtualDevice /* virtualDeviceToken */,
1019                         mock(DisplayWindowPolicyController.class),
1020                         PACKAGE_NAME);
1021         verify(mMockProjectionService, never()).setContentRecordingSession(any(),
1022                 nullable(IMediaProjection.class));
1023 
1024         // Check that FLAG_ALWAYS_UNLOCKED is set.
1025         assertNotEquals(
1026                 "FLAG_ALWAYS_UNLOCKED should be set for displays created in a device display"
1027                         + " group.",
1028                 (displayManager.getDisplayDeviceInfoInternal(deviceDisplayGroupDisplayId).flags
1029                         & DisplayDeviceInfo.FLAG_ALWAYS_UNLOCKED),
1030                 0);
1031 
1032         // Create a virtual display in its own display group.
1033         final VirtualDisplayConfig ownDisplayGroupConfig =
1034                 new VirtualDisplayConfig.Builder(VIRTUAL_DISPLAY_NAME, 600, 800, 320)
1035                         .setUniqueId("uniqueId --- own display group 1")
1036                         .setFlags(
1037                                 VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED
1038                                         | VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP)
1039                         .build();
1040 
1041         int ownDisplayGroupDisplayId =
1042                 localService.createVirtualDisplay(
1043                         ownDisplayGroupConfig,
1044                         mMockAppToken /* callback */,
1045                         virtualDevice /* virtualDeviceToken */,
1046                         mock(DisplayWindowPolicyController.class),
1047                         PACKAGE_NAME);
1048         verify(mMockProjectionService, never()).setContentRecordingSession(any(),
1049                 nullable(IMediaProjection.class));
1050 
1051         // Check that FLAG_ALWAYS_UNLOCKED is set.
1052         assertNotEquals(
1053                 "FLAG_ALWAYS_UNLOCKED should be set for displays created in their own display"
1054                         + " group.",
1055                 (displayManager.getDisplayDeviceInfoInternal(ownDisplayGroupDisplayId).flags
1056                         & DisplayDeviceInfo.FLAG_ALWAYS_UNLOCKED),
1057                 0);
1058 
1059         // Create a virtual display in a device display group.
1060         final VirtualDisplayConfig defaultDisplayGroupConfig =
1061                 new VirtualDisplayConfig.Builder(VIRTUAL_DISPLAY_NAME, 600, 800, 320)
1062                         .setUniqueId("uniqueId --- default display group 1")
1063                         .setFlags(VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED)
1064                         .build();
1065 
1066         int defaultDisplayGroupDisplayId =
1067                 localService.createVirtualDisplay(
1068                         defaultDisplayGroupConfig,
1069                         mMockAppToken /* callback */,
1070                         null /* virtualDeviceToken */,
1071                         mock(DisplayWindowPolicyController.class),
1072                         PACKAGE_NAME);
1073         verify(mMockProjectionService, never()).setContentRecordingSession(any(),
1074                 nullable(IMediaProjection.class));
1075 
1076         // Check that FLAG_ALWAYS_UNLOCKED is not set.
1077         assertEquals(
1078                 "FLAG_ALWAYS_UNLOCKED should not be set for displays created in the default"
1079                         + " display group.",
1080                 (displayManager.getDisplayDeviceInfoInternal(defaultDisplayGroupDisplayId).flags
1081                         & DisplayDeviceInfo.FLAG_ALWAYS_UNLOCKED),
1082                 0);
1083     }
1084 
1085     @Test
1086     public void testGetDisplayIdToMirror() throws Exception {
1087         DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
1088         registerDefaultDisplays(displayManager);
1089 
1090         // This is effectively the DisplayManager service published to ServiceManager.
1091         DisplayManagerService.BinderService binderService = displayManager.new BinderService();
1092         DisplayManagerService.LocalService localDisplayManager = displayManager.new LocalService();
1093 
1094         final String uniqueId = "uniqueId --- displayIdToMirrorTest";
1095         final int width = 600;
1096         final int height = 800;
1097         final int dpi = 320;
1098 
1099         when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
1100         final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(
1101                 VIRTUAL_DISPLAY_NAME, width, height, dpi)
1102                 .setUniqueId(uniqueId)
1103                 .setFlags(VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY);
1104         final int firstDisplayId = binderService.createVirtualDisplay(builder.build(),
1105                 mMockAppToken /* callback */, null /* projection */, PACKAGE_NAME);
1106         verify(mMockProjectionService, never()).setContentRecordingSession(any(),
1107                 nullable(IMediaProjection.class));
1108 
1109         // The second virtual display requests to mirror the first virtual display.
1110         final String uniqueId2 = "uniqueId --- displayIdToMirrorTest #2";
1111         when(mMockAppToken2.asBinder()).thenReturn(mMockAppToken2);
1112         final VirtualDisplayConfig.Builder builder2 = new VirtualDisplayConfig.Builder(
1113                 VIRTUAL_DISPLAY_NAME, width, height, dpi)
1114                 .setUniqueId(uniqueId2)
1115                 .setWindowManagerMirroringEnabled(true);
1116         final int secondDisplayId = binderService.createVirtualDisplay(builder2.build(),
1117                 mMockAppToken2 /* callback */, null /* projection */,
1118                 PACKAGE_NAME);
1119         verify(mMockProjectionService, never()).setContentRecordingSession(any(),
1120                 nullable(IMediaProjection.class));
1121         displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
1122 
1123         // flush the handler
1124         displayManager.getDisplayHandler().runWithScissors(() -> {}, 0 /* now */);
1125 
1126         // The displayId to mirror should be a invalid since the display had flag OWN_CONTENT_ONLY
1127         assertEquals(localDisplayManager.getDisplayIdToMirror(firstDisplayId),
1128                 Display.INVALID_DISPLAY);
1129         // The second display has mirroring managed by WindowManager so the mirror displayId should
1130         // be invalid.
1131         assertEquals(localDisplayManager.getDisplayIdToMirror(secondDisplayId),
1132                 Display.INVALID_DISPLAY);
1133     }
1134 
1135     @Test
1136     public void testCreateVirtualDisplay_isValidProjection_notValid()
1137             throws RemoteException {
1138         when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
1139         IMediaProjection projection = mock(IMediaProjection.class);
1140         doReturn(false).when(projection).isValid();
1141         when(mMockProjectionService
1142                 .setContentRecordingSession(any(ContentRecordingSession.class), eq(projection)))
1143                 .thenReturn(true);
1144         doReturn(true).when(mMockProjectionService).isCurrentProjection(eq(projection));
1145 
1146         final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(
1147                 VIRTUAL_DISPLAY_NAME, 600, 800, 320);
1148         builder.setUniqueId("uniqueId --- isValid false");
1149 
1150         DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
1151         registerDefaultDisplays(displayManager);
1152         displayManager.windowManagerAndInputReady();
1153 
1154         // Pass in a non-null projection.
1155         DisplayManagerService.BinderService binderService = displayManager.new BinderService();
1156         final int displayId = binderService.createVirtualDisplay(builder.build(),
1157                 mMockAppToken /* callback */, projection, PACKAGE_NAME);
1158 
1159         // VirtualDisplay is created for mirroring.
1160         assertThat(displayId).isNotEqualTo(Display.INVALID_DISPLAY);
1161         verify(mMockProjectionService, atLeastOnce()).setContentRecordingSession(
1162                 any(ContentRecordingSession.class), nullable(IMediaProjection.class));
1163         // But mirroring doesn't begin.
1164         verify(mMockProjectionService, atLeastOnce()).setContentRecordingSession(
1165                 mContentRecordingSessionCaptor.capture(), nullable(IMediaProjection.class));
1166         ContentRecordingSession session = mContentRecordingSessionCaptor.getValue();
1167         assertThat(session.isWaitingForConsent()).isTrue();
1168     }
1169 
1170     @Test
1171     public void testCreateVirtualDisplay_setContentRecordingSessionSuccess()
1172             throws RemoteException {
1173         final int displayToRecord = 50;
1174         when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
1175         IMediaProjection projection = mock(IMediaProjection.class);
1176         doReturn(true).when(projection).isValid();
1177         when(mMockProjectionService
1178                 .setContentRecordingSession(any(ContentRecordingSession.class), eq(projection)))
1179                 .thenReturn(true);
1180         doReturn(true).when(mMockProjectionService).isCurrentProjection(eq(projection));
1181 
1182         final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(
1183                 VIRTUAL_DISPLAY_NAME, 600, 800, 320);
1184         builder.setUniqueId("uniqueId --- setContentRecordingSession true");
1185         builder.setDisplayIdToMirror(displayToRecord);
1186 
1187         DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
1188         registerDefaultDisplays(displayManager);
1189         displayManager.windowManagerAndInputReady();
1190 
1191         DisplayManagerService.BinderService binderService = displayManager.new BinderService();
1192         final int displayId = binderService.createVirtualDisplay(builder.build(),
1193                 mMockAppToken /* callback */, projection, PACKAGE_NAME);
1194 
1195         assertThat(displayId).isNotEqualTo(Display.INVALID_DISPLAY);
1196         verify(mMockProjectionService, atLeastOnce()).setContentRecordingSession(
1197                 mContentRecordingSessionCaptor.capture(), nullable(IMediaProjection.class));
1198         ContentRecordingSession session = mContentRecordingSessionCaptor.getValue();
1199         assertThat(session.getContentToRecord()).isEqualTo(RECORD_CONTENT_DISPLAY);
1200         assertThat(session.getVirtualDisplayId()).isEqualTo(displayId);
1201         assertThat(session.getDisplayToRecord()).isEqualTo(displayToRecord);
1202         assertThat(session.isWaitingForConsent()).isFalse();
1203     }
1204 
1205     @Test
1206     public void testCreateVirtualDisplay_setContentRecordingSessionFail() throws RemoteException {
1207         when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
1208         IMediaProjection projection = mock(IMediaProjection.class);
1209         doReturn(true).when(projection).isValid();
1210         when(mMockProjectionService
1211                 .setContentRecordingSession(any(ContentRecordingSession.class), eq(projection)))
1212                 .thenReturn(false);
1213         doReturn(true).when(mMockProjectionService).isCurrentProjection(eq(projection));
1214 
1215         final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(
1216                 VIRTUAL_DISPLAY_NAME, 600, 800, 320);
1217         builder.setUniqueId("uniqueId --- setContentRecordingSession false");
1218 
1219         DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
1220         registerDefaultDisplays(displayManager);
1221         displayManager.windowManagerAndInputReady();
1222 
1223         DisplayManagerService.BinderService binderService = displayManager.new BinderService();
1224         final int displayId = binderService.createVirtualDisplay(builder.build(),
1225                 mMockAppToken /* callback */, projection, PACKAGE_NAME);
1226 
1227         assertThat(displayId).isEqualTo(Display.INVALID_DISPLAY);
1228     }
1229 
1230     @Test
1231     public void testCreateVirtualDisplay_setContentRecordingSession_taskSession()
1232             throws RemoteException {
1233         final int displayToRecord = 50;
1234         when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
1235         IMediaProjection projection = mock(IMediaProjection.class);
1236         doReturn(true).when(projection).isValid();
1237         when(mMockProjectionService
1238                 .setContentRecordingSession(any(ContentRecordingSession.class), eq(projection)))
1239                 .thenReturn(true);
1240         doReturn(mock(IBinder.class)).when(projection).getLaunchCookie();
1241         doReturn(true).when(mMockProjectionService).isCurrentProjection(eq(projection));
1242 
1243         final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(
1244                 VIRTUAL_DISPLAY_NAME, 600, 800, 320);
1245         builder.setUniqueId("uniqueId --- setContentRecordingSession false");
1246         builder.setDisplayIdToMirror(displayToRecord);
1247 
1248         DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
1249         registerDefaultDisplays(displayManager);
1250         displayManager.windowManagerAndInputReady();
1251 
1252         DisplayManagerService.BinderService binderService = displayManager.new BinderService();
1253         final int displayId = binderService.createVirtualDisplay(builder.build(),
1254                 mMockAppToken /* callback */, projection, PACKAGE_NAME);
1255 
1256         assertThat(displayId).isNotEqualTo(Display.INVALID_DISPLAY);
1257         verify(mMockProjectionService, atLeastOnce()).setContentRecordingSession(
1258                 mContentRecordingSessionCaptor.capture(), nullable(IMediaProjection.class));
1259         ContentRecordingSession session = mContentRecordingSessionCaptor.getValue();
1260         assertThat(session.getContentToRecord()).isEqualTo(RECORD_CONTENT_TASK);
1261         assertThat(session.getVirtualDisplayId()).isEqualTo(displayId);
1262         assertThat(session.getTokenToRecord()).isNotNull();
1263     }
1264 
1265     @Test
1266     public void testCreateVirtualDisplay_setContentRecordingSession_noProjection_noFlags()
1267             throws RemoteException {
1268         when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
1269 
1270         // Set no flags for the VirtualDisplay.
1271         final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(
1272                 VIRTUAL_DISPLAY_NAME, 600, 800, 320);
1273         builder.setUniqueId("uniqueId --- setContentRecordingSession false");
1274 
1275         DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
1276         registerDefaultDisplays(displayManager);
1277         displayManager.windowManagerAndInputReady();
1278 
1279         // Pass in a null projection.
1280         DisplayManagerService.BinderService binderService = displayManager.new BinderService();
1281         final int displayId = binderService.createVirtualDisplay(builder.build(),
1282                 mMockAppToken /* callback */, null /* projection */, PACKAGE_NAME);
1283 
1284         // VirtualDisplay is created but not for mirroring.
1285         assertThat(displayId).isNotEqualTo(Display.INVALID_DISPLAY);
1286         verify(mMockProjectionService, never()).setContentRecordingSession(
1287                 any(ContentRecordingSession.class), nullable(IMediaProjection.class));
1288     }
1289 
1290     @Test
1291     public void testCreateVirtualDisplay_setContentRecordingSession_noProjection_noMirroringFlag()
1292             throws RemoteException {
1293         when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
1294 
1295         // Set a non-mirroring flag for the VirtualDisplay.
1296         final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(
1297                 VIRTUAL_DISPLAY_NAME, 600, 800, 320);
1298         builder.setUniqueId("uniqueId --- setContentRecordingSession false");
1299         builder.setFlags(VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY);
1300 
1301         DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
1302         registerDefaultDisplays(displayManager);
1303         displayManager.windowManagerAndInputReady();
1304 
1305         // Pass in a null projection.
1306         DisplayManagerService.BinderService binderService = displayManager.new BinderService();
1307         final int displayId = binderService.createVirtualDisplay(builder.build(),
1308                 mMockAppToken /* callback */, null /* projection */, PACKAGE_NAME);
1309 
1310         // VirtualDisplay is created but not for mirroring.
1311         assertThat(displayId).isNotEqualTo(Display.INVALID_DISPLAY);
1312         verify(mMockProjectionService, never()).setContentRecordingSession(
1313                 any(ContentRecordingSession.class), nullable(IMediaProjection.class));
1314     }
1315 
1316     @Test
1317     public void testCreateVirtualDisplay_setContentRecordingSession_projection_noMirroringFlag()
1318             throws RemoteException {
1319         when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
1320         IMediaProjection projection = mock(IMediaProjection.class);
1321         doReturn(true).when(projection).isValid();
1322         when(mMockProjectionService
1323                 .setContentRecordingSession(any(ContentRecordingSession.class), eq(projection)))
1324                 .thenReturn(true);
1325         doReturn(true).when(mMockProjectionService).isCurrentProjection(eq(projection));
1326 
1327         // Set no flags for the VirtualDisplay.
1328         final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(
1329                 VIRTUAL_DISPLAY_NAME, 600, 800, 320);
1330         builder.setUniqueId("uniqueId --- setContentRecordingSession false");
1331 
1332         DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
1333         registerDefaultDisplays(displayManager);
1334         displayManager.windowManagerAndInputReady();
1335 
1336         // Pass in a non-null projection.
1337         DisplayManagerService.BinderService binderService = displayManager.new BinderService();
1338         final int displayId = binderService.createVirtualDisplay(builder.build(),
1339                 mMockAppToken /* callback */, projection, PACKAGE_NAME);
1340 
1341         // VirtualDisplay is created for mirroring.
1342         assertThat(displayId).isNotEqualTo(Display.INVALID_DISPLAY);
1343         verify(mMockProjectionService, atLeastOnce()).setContentRecordingSession(
1344                 any(ContentRecordingSession.class), nullable(IMediaProjection.class));
1345     }
1346 
1347     /**
1348      * Tests that the virtual display is created with
1349      * {@link VirtualDisplayConfig.Builder#setSurface(Surface)}
1350      */
1351     @Test
1352     @FlakyTest(bugId = 127687569)
1353     public void testCreateVirtualDisplay_setSurface() throws Exception {
1354         DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
1355         registerDefaultDisplays(displayManager);
1356 
1357         // This is effectively the DisplayManager service published to ServiceManager.
1358         DisplayManagerService.BinderService binderService = displayManager.new BinderService();
1359 
1360         final String uniqueId = "uniqueId --- setSurface";
1361         final int width = 600;
1362         final int height = 800;
1363         final int dpi = 320;
1364         final Surface surface = new Surface();
1365 
1366         when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
1367         final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(
1368                 VIRTUAL_DISPLAY_NAME, width, height, dpi);
1369         builder.setSurface(surface);
1370         builder.setUniqueId(uniqueId);
1371         final int displayId = binderService.createVirtualDisplay(builder.build(),
1372                 mMockAppToken /* callback */, null /* projection */, PACKAGE_NAME);
1373         verify(mMockProjectionService, never()).setContentRecordingSession(any(),
1374                 nullable(IMediaProjection.class));
1375 
1376         displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
1377 
1378         // flush the handler
1379         displayManager.getDisplayHandler().runWithScissors(() -> {}, 0 /* now */);
1380 
1381         assertEquals(displayManager.getVirtualDisplaySurfaceInternal(mMockAppToken), surface);
1382     }
1383 
1384     /**
1385      * Tests that specifying VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP is allowed when the permission
1386      * ADD_TRUSTED_DISPLAY is granted.
1387      */
1388     @Test
1389     public void testOwnDisplayGroup_allowCreationWithAddTrustedDisplayPermission()
1390             throws RemoteException {
1391         DisplayManagerService displayManager =
1392                 new DisplayManagerService(mContext, mBasicInjector);
1393         registerDefaultDisplays(displayManager);
1394 
1395         DisplayManagerService.BinderService bs = displayManager.new BinderService();
1396         when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
1397 
1398         when(mContext.checkCallingPermission(ADD_TRUSTED_DISPLAY)).thenReturn(
1399                 PackageManager.PERMISSION_GRANTED);
1400 
1401         final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(
1402                 VIRTUAL_DISPLAY_NAME, 600, 800, 320);
1403         builder.setFlags(DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP);
1404         builder.setUniqueId("uniqueId --- OWN_DISPLAY_GROUP");
1405 
1406         int displayId = bs.createVirtualDisplay(builder.build(), mMockAppToken /* callback */,
1407                 null /* projection */, PACKAGE_NAME);
1408         verify(mMockProjectionService, never()).setContentRecordingSession(any(),
1409                 nullable(IMediaProjection.class));
1410         displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
1411         displayManager.getDisplayHandler().runWithScissors(() -> {}, 0 /* now */);
1412         DisplayDeviceInfo ddi = displayManager.getDisplayDeviceInfoInternal(displayId);
1413         assertNotNull(ddi);
1414         assertNotEquals(0, ddi.flags & DisplayDeviceInfo.FLAG_OWN_DISPLAY_GROUP);
1415     }
1416 
1417     /**
1418      * Tests that specifying VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP is blocked when the permission
1419      * ADD_TRUSTED_DISPLAY is denied.
1420      */
1421     @Test
1422     public void testOwnDisplayGroup_withoutAddTrustedDisplayPermission_throwsSecurityException() {
1423         DisplayManagerService displayManager =
1424                 new DisplayManagerService(mContext, mBasicInjector);
1425         registerDefaultDisplays(displayManager);
1426 
1427         DisplayManagerService.BinderService bs = displayManager.new BinderService();
1428         when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
1429 
1430         when(mContext.checkCallingPermission(ADD_TRUSTED_DISPLAY)).thenReturn(
1431                 PackageManager.PERMISSION_DENIED);
1432 
1433         final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(
1434                 VIRTUAL_DISPLAY_NAME, 600, 800, 320);
1435         builder.setFlags(DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP);
1436         builder.setUniqueId("uniqueId --- OWN_DISPLAY_GROUP");
1437 
1438         try {
1439             bs.createVirtualDisplay(builder.build(), mMockAppToken /* callback */,
1440                     null /* projection */, PACKAGE_NAME);
1441             fail("Creating virtual display with VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP without "
1442                     + "ADD_TRUSTED_DISPLAY permission should throw SecurityException.");
1443         } catch (SecurityException e) {
1444             // SecurityException is expected
1445         }
1446     }
1447 
1448     /**
1449      * Tests that specifying VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP is allowed when called with
1450      * a virtual device, even if ADD_TRUSTED_DISPLAY is not granted.
1451      */
1452     @Test
1453     public void testOwnDisplayGroup_allowCreationWithVirtualDevice()  throws Exception {
1454         DisplayManagerService displayManager =
1455                 new DisplayManagerService(mContext, mBasicInjector);
1456         DisplayManagerInternal localService = displayManager.new LocalService();
1457 
1458         registerDefaultDisplays(displayManager);
1459 
1460         when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
1461 
1462         when(mContext.checkCallingPermission(ADD_TRUSTED_DISPLAY)).thenReturn(
1463                 PackageManager.PERMISSION_DENIED);
1464 
1465         final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(
1466                 VIRTUAL_DISPLAY_NAME, 600, 800, 320);
1467         builder.setFlags(DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP);
1468         builder.setUniqueId("uniqueId --- OWN_DISPLAY_GROUP");
1469 
1470         IVirtualDevice virtualDevice = mock(IVirtualDevice.class);
1471         when(virtualDevice.getDeviceId()).thenReturn(1);
1472         when(mIVirtualDeviceManager.isValidVirtualDeviceId(1)).thenReturn(true);
1473 
1474         int displayId = localService.createVirtualDisplay(builder.build(),
1475                 mMockAppToken /* callback */, virtualDevice /* virtualDeviceToken */,
1476                 mock(DisplayWindowPolicyController.class), PACKAGE_NAME);
1477         verify(mMockProjectionService, never()).setContentRecordingSession(any(),
1478                 nullable(IMediaProjection.class));
1479         displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
1480         displayManager.getDisplayHandler().runWithScissors(() -> {}, 0 /* now */);
1481         DisplayDeviceInfo ddi = displayManager.getDisplayDeviceInfoInternal(displayId);
1482         assertNotNull(ddi);
1483         assertNotEquals(0, ddi.flags & DisplayDeviceInfo.FLAG_OWN_DISPLAY_GROUP);
1484     }
1485 
1486     /**
1487      * Tests that there is a display change notification if the frame rate override
1488      * list is updated.
1489      */
1490     @Test
1491     public void testShouldNotifyChangeWhenDisplayInfoFrameRateOverrideChanged() throws Exception {
1492         DisplayManagerService displayManager =
1493                 new DisplayManagerService(mContext, mShortMockedInjector);
1494         DisplayManagerService.BinderService displayManagerBinderService =
1495                 displayManager.new BinderService();
1496         registerDefaultDisplays(displayManager);
1497         displayManager.onBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
1498 
1499         FakeDisplayDevice displayDevice = createFakeDisplayDevice(displayManager, new float[]{60f});
1500         FakeDisplayManagerCallback callback = registerDisplayListenerCallback(displayManager,
1501                 displayManagerBinderService, displayDevice);
1502 
1503         int myUid = Process.myUid();
1504         updateFrameRateOverride(displayManager, displayDevice,
1505                 new DisplayEventReceiver.FrameRateOverride[]{
1506                         new DisplayEventReceiver.FrameRateOverride(myUid, 30f),
1507                 });
1508         assertTrue(callback.mDisplayChangedCalled);
1509         callback.clear();
1510 
1511         updateFrameRateOverride(displayManager, displayDevice,
1512                 new DisplayEventReceiver.FrameRateOverride[]{
1513                         new DisplayEventReceiver.FrameRateOverride(myUid, 30f),
1514                         new DisplayEventReceiver.FrameRateOverride(1234, 30f),
1515                 });
1516         assertFalse(callback.mDisplayChangedCalled);
1517 
1518         updateFrameRateOverride(displayManager, displayDevice,
1519                 new DisplayEventReceiver.FrameRateOverride[]{
1520                         new DisplayEventReceiver.FrameRateOverride(myUid, 20f),
1521                         new DisplayEventReceiver.FrameRateOverride(1234, 30f),
1522                         new DisplayEventReceiver.FrameRateOverride(5678, 30f),
1523                 });
1524         assertTrue(callback.mDisplayChangedCalled);
1525         callback.clear();
1526 
1527         updateFrameRateOverride(displayManager, displayDevice,
1528                 new DisplayEventReceiver.FrameRateOverride[]{
1529                         new DisplayEventReceiver.FrameRateOverride(1234, 30f),
1530                         new DisplayEventReceiver.FrameRateOverride(5678, 30f),
1531                 });
1532         assertTrue(callback.mDisplayChangedCalled);
1533         callback.clear();
1534 
1535         updateFrameRateOverride(displayManager, displayDevice,
1536                 new DisplayEventReceiver.FrameRateOverride[]{
1537                         new DisplayEventReceiver.FrameRateOverride(5678, 30f),
1538                 });
1539         assertFalse(callback.mDisplayChangedCalled);
1540     }
1541 
1542     /**
1543      * Tests that the DisplayInfo is updated correctly with a frame rate override
1544      */
1545     @Test
1546     public void testDisplayInfoFrameRateOverride() throws Exception {
1547         DisplayManagerService displayManager =
1548                 new DisplayManagerService(mContext, mShortMockedInjector);
1549         DisplayManagerService.BinderService displayManagerBinderService =
1550                 displayManager.new BinderService();
1551         registerDefaultDisplays(displayManager);
1552         displayManager.onBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
1553 
1554         FakeDisplayDevice displayDevice = createFakeDisplayDevice(displayManager,
1555                 new float[]{60f, 30f, 20f});
1556         int displayId = getDisplayIdForDisplayDevice(displayManager, displayManagerBinderService,
1557                 displayDevice);
1558         DisplayInfo displayInfo = displayManagerBinderService.getDisplayInfo(displayId);
1559         assertEquals(60f, displayInfo.getRefreshRate(), 0.01f);
1560 
1561         updateFrameRateOverride(displayManager, displayDevice,
1562                 new DisplayEventReceiver.FrameRateOverride[]{
1563                         new DisplayEventReceiver.FrameRateOverride(
1564                                 Process.myUid(), 20f),
1565                         new DisplayEventReceiver.FrameRateOverride(
1566                                 Process.myUid() + 1, 30f)
1567                 });
1568         displayInfo = displayManagerBinderService.getDisplayInfo(displayId);
1569         assertEquals(20f, displayInfo.getRefreshRate(), 0.01f);
1570 
1571         // Changing the mode to 30Hz should not override the refresh rate to 20Hz anymore
1572         // as 20 is not a divider of 30.
1573         updateModeId(displayManager, displayDevice, 2);
1574         displayInfo = displayManagerBinderService.getDisplayInfo(displayId);
1575         assertEquals(30f, displayInfo.getRefreshRate(), 0.01f);
1576     }
1577 
1578     /**
1579      * Tests that the frame rate override is returning the correct value from
1580      * DisplayInfo#getRefreshRate
1581      */
1582     @Test
1583     public void testDisplayInfoNonNativeFrameRateOverride() throws Exception {
1584         DisplayManagerService displayManager =
1585                 new DisplayManagerService(mContext, mBasicInjector);
1586         DisplayManagerService.BinderService displayManagerBinderService =
1587                 displayManager.new BinderService();
1588         registerDefaultDisplays(displayManager);
1589         displayManager.onBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
1590 
1591         FakeDisplayDevice displayDevice = createFakeDisplayDevice(displayManager,
1592                 new float[]{60f});
1593         int displayId = getDisplayIdForDisplayDevice(displayManager, displayManagerBinderService,
1594                 displayDevice);
1595         DisplayInfo displayInfo = displayManagerBinderService.getDisplayInfo(displayId);
1596         assertEquals(60f, displayInfo.getRefreshRate(), 0.01f);
1597 
1598         updateFrameRateOverride(displayManager, displayDevice,
1599                 new DisplayEventReceiver.FrameRateOverride[]{
1600                         new DisplayEventReceiver.FrameRateOverride(
1601                                 Process.myUid(), 20f)
1602                 });
1603         displayInfo = displayManagerBinderService.getDisplayInfo(displayId);
1604         assertEquals(20f, displayInfo.getRefreshRate(), 0.01f);
1605     }
1606 
1607     /**
1608      * Tests that the mode reflects the frame rate override is in compat mode
1609      */
1610     @Test
1611     @DisableCompatChanges({DisplayManagerService.DISPLAY_MODE_RETURNS_PHYSICAL_REFRESH_RATE})
1612     public  void testDisplayInfoFrameRateOverrideModeCompat() throws Exception {
1613         testDisplayInfoFrameRateOverrideModeCompat(/*compatChangeEnabled*/ false);
1614     }
1615 
1616     /**
1617      * Tests that the mode reflects the physical display refresh rate when not in compat mode.
1618      */
1619     @Test
1620     @EnableCompatChanges({DisplayManagerService.DISPLAY_MODE_RETURNS_PHYSICAL_REFRESH_RATE})
1621     public  void testDisplayInfoFrameRateOverrideMode() throws Exception {
1622         testDisplayInfoFrameRateOverrideModeCompat(/*compatChangeEnabled*/ true);
1623     }
1624 
1625     /**
1626      * Tests that the mode reflects the frame rate override is in compat mode and accordingly to the
1627      * allowNonNativeRefreshRateOverride policy.
1628      */
1629     @Test
1630     @DisableCompatChanges({DisplayManagerService.DISPLAY_MODE_RETURNS_PHYSICAL_REFRESH_RATE})
1631     public void testDisplayInfoNonNativeFrameRateOverrideModeCompat() throws Exception {
1632         testDisplayInfoNonNativeFrameRateOverrideMode(/*compatChangeEnabled*/ false);
1633     }
1634 
1635     /**
1636      * Tests that the mode reflects the physical display refresh rate when not in compat mode.
1637      */
1638     @Test
1639     @EnableCompatChanges({DisplayManagerService.DISPLAY_MODE_RETURNS_PHYSICAL_REFRESH_RATE})
1640     public void testDisplayInfoNonNativeFrameRateOverrideMode() throws Exception {
1641         testDisplayInfoNonNativeFrameRateOverrideMode(/*compatChangeEnabled*/ true);
1642     }
1643 
1644     /**
1645      * Tests that there is a display change notification if the render frame rate is updated
1646      */
1647     @Test
1648     public void testShouldNotifyChangeWhenDisplayInfoRenderFrameRateChanged() throws Exception {
1649         DisplayManagerService displayManager =
1650                 new DisplayManagerService(mContext, mShortMockedInjector);
1651         DisplayManagerService.BinderService displayManagerBinderService =
1652                 displayManager.new BinderService();
1653         registerDefaultDisplays(displayManager);
1654         displayManager.onBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
1655 
1656         FakeDisplayDevice displayDevice = createFakeDisplayDevice(displayManager, new float[]{60f});
1657         FakeDisplayManagerCallback callback = registerDisplayListenerCallback(displayManager,
1658                 displayManagerBinderService, displayDevice);
1659 
1660         updateRenderFrameRate(displayManager, displayDevice, 30f);
1661         assertTrue(callback.mDisplayChangedCalled);
1662         callback.clear();
1663 
1664         updateRenderFrameRate(displayManager, displayDevice, 30f);
1665         assertFalse(callback.mDisplayChangedCalled);
1666 
1667         updateRenderFrameRate(displayManager, displayDevice, 20f);
1668         assertTrue(callback.mDisplayChangedCalled);
1669         callback.clear();
1670     }
1671 
1672     /**
1673      * Tests that the DisplayInfo is updated correctly with a render frame rate
1674      */
1675     @Test
1676     public void testDisplayInfoRenderFrameRate() throws Exception {
1677         DisplayManagerService displayManager =
1678                 new DisplayManagerService(mContext, mShortMockedInjector);
1679         DisplayManagerService.BinderService displayManagerBinderService =
1680                 displayManager.new BinderService();
1681         registerDefaultDisplays(displayManager);
1682         displayManager.onBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
1683 
1684         FakeDisplayDevice displayDevice = createFakeDisplayDevice(displayManager,
1685                 new float[]{60f, 30f, 20f});
1686         int displayId = getDisplayIdForDisplayDevice(displayManager, displayManagerBinderService,
1687                 displayDevice);
1688         DisplayInfo displayInfo = displayManagerBinderService.getDisplayInfo(displayId);
1689         assertEquals(60f, displayInfo.getRefreshRate(), 0.01f);
1690 
1691         updateRenderFrameRate(displayManager, displayDevice, 20f);
1692         displayInfo = displayManagerBinderService.getDisplayInfo(displayId);
1693         assertEquals(20f, displayInfo.getRefreshRate(), 0.01f);
1694     }
1695 
1696     /**
1697      * Tests that the mode reflects the render frame rate is in compat mode
1698      */
1699     @Test
1700     @DisableCompatChanges({DisplayManagerService.DISPLAY_MODE_RETURNS_PHYSICAL_REFRESH_RATE})
1701     public  void testDisplayInfoRenderFrameRateModeCompat() throws Exception {
1702         testDisplayInfoRenderFrameRateModeCompat(/*compatChangeEnabled*/ false);
1703     }
1704 
1705     /**
1706      * Tests that the mode reflects the physical display refresh rate when not in compat mode.
1707      */
1708     @Test
1709     @EnableCompatChanges({DisplayManagerService.DISPLAY_MODE_RETURNS_PHYSICAL_REFRESH_RATE})
1710     public  void testDisplayInfoRenderFrameRateMode() throws Exception {
1711         testDisplayInfoRenderFrameRateModeCompat(/*compatChangeEnabled*/ true);
1712     }
1713 
1714     /**
1715      * Tests that EVENT_DISPLAY_ADDED is sent when a display is added.
1716      */
1717     @Test
1718     public void testShouldNotifyDisplayAdded_WhenNewDisplayDeviceIsAdded() {
1719         DisplayManagerService displayManager =
1720                 new DisplayManagerService(mContext, mShortMockedInjector);
1721         DisplayManagerService.BinderService displayManagerBinderService =
1722                 displayManager.new BinderService();
1723 
1724         Handler handler = displayManager.getDisplayHandler();
1725         waitForIdleHandler(handler);
1726 
1727         // register display listener callback
1728         FakeDisplayManagerCallback callback = new FakeDisplayManagerCallback();
1729         displayManagerBinderService.registerCallbackWithEventMask(
1730                 callback, STANDARD_DISPLAY_EVENTS);
1731 
1732         waitForIdleHandler(handler);
1733 
1734         createFakeDisplayDevice(displayManager, new float[]{60f});
1735 
1736         waitForIdleHandler(handler);
1737 
1738         assertFalse(callback.mDisplayChangedCalled);
1739         assertFalse(callback.mDisplayRemovedCalled);
1740         assertTrue(callback.mDisplayAddedCalled);
1741     }
1742 
1743     /**
1744      * Tests that EVENT_DISPLAY_ADDED is not sent when a display is added and the
1745      * client has a callback which is not subscribed to this event type.
1746      */
1747     @Test
1748     public void testShouldNotNotifyDisplayAdded_WhenClientIsNotSubscribed() {
1749         DisplayManagerService displayManager =
1750                 new DisplayManagerService(mContext, mShortMockedInjector);
1751         DisplayManagerService.BinderService displayManagerBinderService =
1752                 displayManager.new BinderService();
1753 
1754         Handler handler = displayManager.getDisplayHandler();
1755         waitForIdleHandler(handler);
1756 
1757         // register display listener callback
1758         FakeDisplayManagerCallback callback = new FakeDisplayManagerCallback();
1759         long allEventsExceptDisplayAdded = STANDARD_DISPLAY_EVENTS
1760                 & ~DisplayManager.EVENT_FLAG_DISPLAY_ADDED;
1761         displayManagerBinderService.registerCallbackWithEventMask(callback,
1762                 allEventsExceptDisplayAdded);
1763 
1764         waitForIdleHandler(handler);
1765 
1766         createFakeDisplayDevice(displayManager, new float[]{60f});
1767 
1768         waitForIdleHandler(handler);
1769 
1770         assertFalse(callback.mDisplayChangedCalled);
1771         assertFalse(callback.mDisplayRemovedCalled);
1772         assertFalse(callback.mDisplayAddedCalled);
1773     }
1774 
1775     /**
1776      * Tests that EVENT_DISPLAY_REMOVED is sent when a display is removed.
1777      */
1778     @Test
1779     public void testShouldNotifyDisplayRemoved_WhenDisplayDeviceIsRemoved() {
1780         DisplayManagerService displayManager =
1781                 new DisplayManagerService(mContext, mShortMockedInjector);
1782         DisplayManagerService.BinderService displayManagerBinderService =
1783                 displayManager.new BinderService();
1784 
1785         Handler handler = displayManager.getDisplayHandler();
1786         waitForIdleHandler(handler);
1787 
1788         FakeDisplayDevice displayDevice = createFakeDisplayDevice(displayManager,
1789                 new float[]{60f});
1790 
1791         waitForIdleHandler(handler);
1792 
1793         FakeDisplayManagerCallback callback = registerDisplayListenerCallback(
1794                 displayManager, displayManagerBinderService, displayDevice);
1795 
1796         waitForIdleHandler(handler);
1797 
1798         displayManager.getDisplayDeviceRepository()
1799                 .onDisplayDeviceEvent(displayDevice, DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED);
1800 
1801         waitForIdleHandler(handler);
1802 
1803         assertFalse(callback.mDisplayChangedCalled);
1804         assertTrue(callback.mDisplayRemovedCalled);
1805         assertFalse(callback.mDisplayAddedCalled);
1806     }
1807 
1808     /**
1809      * Tests that EVENT_DISPLAY_REMOVED is not sent when a display is added and the
1810      * client has a callback which is not subscribed to this event type.
1811      */
1812     @Test
1813     public void testShouldNotNotifyDisplayRemoved_WhenClientIsNotSubscribed() {
1814         DisplayManagerService displayManager =
1815                 new DisplayManagerService(mContext, mShortMockedInjector);
1816         DisplayManagerService.BinderService displayManagerBinderService =
1817                 displayManager.new BinderService();
1818 
1819         Handler handler = displayManager.getDisplayHandler();
1820         waitForIdleHandler(handler);
1821 
1822         FakeDisplayDevice displayDevice = createFakeDisplayDevice(displayManager,
1823                 new float[]{60f});
1824 
1825         waitForIdleHandler(handler);
1826 
1827         FakeDisplayManagerCallback callback = new FakeDisplayManagerCallback();
1828         long allEventsExceptDisplayRemoved = STANDARD_DISPLAY_EVENTS
1829                 & ~DisplayManager.EVENT_FLAG_DISPLAY_REMOVED;
1830         displayManagerBinderService.registerCallbackWithEventMask(callback,
1831                 allEventsExceptDisplayRemoved);
1832 
1833         waitForIdleHandler(handler);
1834 
1835         displayManager.getDisplayDeviceRepository()
1836                 .onDisplayDeviceEvent(displayDevice, DisplayAdapter.DISPLAY_DEVICE_EVENT_REMOVED);
1837 
1838         waitForIdleHandler(handler);
1839 
1840         assertFalse(callback.mDisplayChangedCalled);
1841         assertFalse(callback.mDisplayRemovedCalled);
1842         assertFalse(callback.mDisplayAddedCalled);
1843     }
1844 
1845 
1846 
1847     @Test
1848     public void testSettingTwoBrightnessConfigurationsOnMultiDisplay() {
1849         Context mContext = InstrumentationRegistry.getInstrumentation().getContext();
1850         DisplayManager displayManager = mContext.getSystemService(DisplayManager.class);
1851 
1852         // get the first two internal displays
1853         Display[] displays = displayManager.getDisplays();
1854         Display internalDisplayOne = null;
1855         Display internalDisplayTwo = null;
1856         for (Display display : displays) {
1857             if (display.getType() == Display.TYPE_INTERNAL) {
1858                 if (internalDisplayOne == null) {
1859                     internalDisplayOne = display;
1860                 } else {
1861                     internalDisplayTwo = display;
1862                     break;
1863                 }
1864             }
1865         }
1866 
1867         // return if there are fewer than 2 displays on this device
1868         if (internalDisplayOne == null || internalDisplayTwo == null) {
1869             return;
1870         }
1871 
1872         final String uniqueDisplayIdOne = internalDisplayOne.getUniqueId();
1873         final String uniqueDisplayIdTwo = internalDisplayTwo.getUniqueId();
1874 
1875         BrightnessConfiguration configOne =
1876                 new BrightnessConfiguration.Builder(
1877                         new float[]{0.0f, 12345.0f}, new float[]{15.0f, 400.0f})
1878                         .setDescription("model:1").build();
1879         BrightnessConfiguration configTwo =
1880                 new BrightnessConfiguration.Builder(
1881                         new float[]{0.0f, 6789.0f}, new float[]{12.0f, 300.0f})
1882                         .setDescription("model:2").build();
1883 
1884         displayManager.setBrightnessConfigurationForDisplay(configOne,
1885                 uniqueDisplayIdOne);
1886         displayManager.setBrightnessConfigurationForDisplay(configTwo,
1887                 uniqueDisplayIdTwo);
1888 
1889         BrightnessConfiguration configFromOne =
1890                 displayManager.getBrightnessConfigurationForDisplay(uniqueDisplayIdOne);
1891         BrightnessConfiguration configFromTwo =
1892                 displayManager.getBrightnessConfigurationForDisplay(uniqueDisplayIdTwo);
1893 
1894         assertNotNull(configFromOne);
1895         assertEquals(configOne, configFromOne);
1896         assertEquals(configTwo, configFromTwo);
1897 
1898     }
1899 
1900     @Test
1901     public void testHdrConversionModeEquals() {
1902         assertEquals(
1903                 new HdrConversionMode(HdrConversionMode.HDR_CONVERSION_FORCE, 2),
1904                 new HdrConversionMode(HdrConversionMode.HDR_CONVERSION_FORCE, 2));
1905         assertNotEquals(
1906                 new HdrConversionMode(HdrConversionMode.HDR_CONVERSION_FORCE, 2),
1907                 new HdrConversionMode(HdrConversionMode.HDR_CONVERSION_FORCE, 3));
1908         assertEquals(
1909                 new HdrConversionMode(HdrConversionMode.HDR_CONVERSION_SYSTEM),
1910                 new HdrConversionMode(HdrConversionMode.HDR_CONVERSION_SYSTEM));
1911         assertNotEquals(
1912                 new HdrConversionMode(HdrConversionMode.HDR_CONVERSION_FORCE, 2),
1913                 new HdrConversionMode(HdrConversionMode.HDR_CONVERSION_SYSTEM));
1914     }
1915 
1916     @Test
1917     public void testCreateHdrConversionMode_withInvalidArguments_throwsException() {
1918         assertThrows(
1919                 "preferredHdrOutputType must not be set if the conversion mode is "
1920                         + "HDR_CONVERSION_PASSTHROUGH",
1921                 IllegalArgumentException.class,
1922                 () -> new HdrConversionMode(HdrConversionMode.HDR_CONVERSION_PASSTHROUGH,
1923                         Display.HdrCapabilities.HDR_TYPE_DOLBY_VISION));
1924     }
1925 
1926     @Test
1927     public void testSetHdrConversionModeInternal_withInvalidArguments_throwsException() {
1928         DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
1929         assertThrows("Expected DisplayManager to throw IllegalArgumentException when "
1930                         + "preferredHdrOutputType is set and the conversion mode is "
1931                         + "HDR_CONVERSION_SYSTEM",
1932                 IllegalArgumentException.class,
1933                 () -> displayManager.setHdrConversionModeInternal(new HdrConversionMode(
1934                         HdrConversionMode.HDR_CONVERSION_SYSTEM,
1935                         Display.HdrCapabilities.HDR_TYPE_DOLBY_VISION)));
1936     }
1937 
1938     @Test
1939     public void testSetAndGetHdrConversionModeInternal() {
1940         DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
1941         final HdrConversionMode mode = new HdrConversionMode(
1942                 HdrConversionMode.HDR_CONVERSION_FORCE,
1943                 Display.HdrCapabilities.HDR_TYPE_DOLBY_VISION);
1944         displayManager.setHdrConversionModeInternal(mode);
1945         assertEquals(mode, displayManager.getHdrConversionModeSettingInternal());
1946         assertEquals(mode.getConversionMode(), mHdrConversionMode);
1947         assertEquals(mode.getPreferredHdrOutputType(), mPreferredHdrOutputType);
1948     }
1949 
1950     @Test
1951     public void testHdrConversionMode_withMinimalPostProcessing() {
1952         DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
1953         DisplayManagerService.BinderService displayManagerBinderService =
1954                 displayManager.new BinderService();
1955         registerDefaultDisplays(displayManager);
1956         displayManager.onBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
1957         FakeDisplayDevice displayDevice = createFakeDisplayDevice(displayManager,
1958                 new float[]{60f, 30f, 20f});
1959         int displayId = getDisplayIdForDisplayDevice(displayManager, displayManagerBinderService,
1960                 displayDevice);
1961 
1962         final HdrConversionMode mode = new HdrConversionMode(
1963                 HdrConversionMode.HDR_CONVERSION_FORCE,
1964                 Display.HdrCapabilities.HDR_TYPE_DOLBY_VISION);
1965         displayManager.setHdrConversionModeInternal(mode);
1966         assertEquals(mode, displayManager.getHdrConversionModeSettingInternal());
1967 
1968         displayManager.setMinimalPostProcessingAllowed(true);
1969         displayManager.setDisplayPropertiesInternal(displayId, false /* hasContent */,
1970                 30.0f /* requestedRefreshRate */,
1971                 displayDevice.getDisplayDeviceInfoLocked().modeId /* requestedModeId */,
1972                 30.0f /* requestedMinRefreshRate */, 120.0f /* requestedMaxRefreshRate */,
1973                 true /* preferMinimalPostProcessing */, false /* disableHdrConversion */,
1974                 true /* inTraversal */);
1975 
1976         assertEquals(new HdrConversionMode(HdrConversionMode.HDR_CONVERSION_PASSTHROUGH),
1977                 displayManager.getHdrConversionModeInternal());
1978 
1979         displayManager.setDisplayPropertiesInternal(displayId, false /* hasContent */,
1980                 30.0f /* requestedRefreshRate */,
1981                 displayDevice.getDisplayDeviceInfoLocked().modeId /* requestedModeId */,
1982                 30.0f /* requestedMinRefreshRate */, 120.0f /* requestedMaxRefreshRate */,
1983                 false /* preferMinimalPostProcessing */, false /* disableHdrConversion */,
1984                 true /* inTraversal */);
1985         assertEquals(mode, displayManager.getHdrConversionModeInternal());
1986     }
1987 
1988     @Test
1989     public void testReturnsRefreshRateForDisplayAndSensor_proximitySensorSet() {
1990         DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
1991         DisplayManagerInternal localService = displayManager.new LocalService();
1992         DisplayManagerService.BinderService displayManagerBinderService =
1993                 displayManager.new BinderService();
1994         displayManager.overrideSensorManager(mSensorManager);
1995 
1996         FakeDisplayDevice displayDevice = createFakeDisplayDevice(displayManager, new float[]{60f});
1997         displayDevice.mDisplayDeviceConfig = mMockDisplayDeviceConfig;
1998         int displayId = getDisplayIdForDisplayDevice(displayManager, displayManagerBinderService,
1999                 displayDevice);
2000 
2001         String testSensorName = "testName";
2002         String testSensorType = "testType";
2003         Sensor testSensor = TestUtils.createSensor(testSensorType, testSensorName);
2004 
2005         DisplayDeviceConfig.SensorData sensorData = new DisplayDeviceConfig.SensorData();
2006         sensorData.type = testSensorType;
2007         sensorData.name = testSensorName;
2008         sensorData.minRefreshRate = 10f;
2009         sensorData.maxRefreshRate = 100f;
2010 
2011         when(mMockDisplayDeviceConfig.getProximitySensor()).thenReturn(sensorData);
2012         when(mSensorManager.getSensorList(Sensor.TYPE_ALL)).thenReturn(Collections.singletonList(
2013                 testSensor));
2014 
2015         SurfaceControl.RefreshRateRange result = localService.getRefreshRateForDisplayAndSensor(
2016                 displayId, testSensorName, testSensorType);
2017 
2018         assertNotNull(result);
2019         assertEquals(result.min, sensorData.minRefreshRate, FLOAT_TOLERANCE);
2020         assertEquals(result.max, sensorData.maxRefreshRate, FLOAT_TOLERANCE);
2021     }
2022 
2023     @Test
2024     public void testReturnsRefreshRateForDisplayAndSensor_proximitySensorNotSet() {
2025         DisplayManagerService displayManager = new DisplayManagerService(mContext, mBasicInjector);
2026         DisplayManagerInternal localService = displayManager.new LocalService();
2027         DisplayManagerService.BinderService displayManagerBinderService =
2028                 displayManager.new BinderService();
2029         displayManager.overrideSensorManager(mSensorManager);
2030 
2031         FakeDisplayDevice displayDevice = createFakeDisplayDevice(displayManager, new float[]{60f});
2032         displayDevice.mDisplayDeviceConfig = mMockDisplayDeviceConfig;
2033         int displayId = getDisplayIdForDisplayDevice(displayManager, displayManagerBinderService,
2034                 displayDevice);
2035 
2036         String testSensorName = "testName";
2037         String testSensorType = "testType";
2038         Sensor testSensor = TestUtils.createSensor(testSensorType, testSensorName);
2039 
2040         DisplayDeviceConfig.SensorData sensorData = new DisplayDeviceConfig.SensorData();
2041         sensorData.type = testSensorType;
2042         sensorData.name = testSensorName;
2043         sensorData.minRefreshRate = 10f;
2044         sensorData.maxRefreshRate = 100f;
2045 
2046         when(mMockDisplayDeviceConfig.getProximitySensor()).thenReturn(null);
2047         when(mSensorManager.getSensorList(Sensor.TYPE_ALL)).thenReturn(Collections.singletonList(
2048                 testSensor));
2049 
2050         SurfaceControl.RefreshRateRange result = localService.getRefreshRateForDisplayAndSensor(
2051                 displayId, testSensorName, testSensorType);
2052 
2053         assertNull(result);
2054     }
2055 
2056     private void testDisplayInfoFrameRateOverrideModeCompat(boolean compatChangeEnabled)
2057             throws Exception {
2058         DisplayManagerService displayManager =
2059                 new DisplayManagerService(mContext, mShortMockedInjector);
2060         DisplayManagerService.BinderService displayManagerBinderService =
2061                 displayManager.new BinderService();
2062         registerDefaultDisplays(displayManager);
2063         displayManager.onBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
2064 
2065         FakeDisplayDevice displayDevice = createFakeDisplayDevice(displayManager,
2066                 new float[]{60f, 30f, 20f});
2067         int displayId = getDisplayIdForDisplayDevice(displayManager, displayManagerBinderService,
2068                 displayDevice);
2069         DisplayInfo displayInfo = displayManagerBinderService.getDisplayInfo(displayId);
2070         assertEquals(60f, displayInfo.getRefreshRate(), 0.01f);
2071 
2072         updateFrameRateOverride(displayManager, displayDevice,
2073                 new DisplayEventReceiver.FrameRateOverride[]{
2074                         new DisplayEventReceiver.FrameRateOverride(
2075                                 Process.myUid(), 20f),
2076                         new DisplayEventReceiver.FrameRateOverride(
2077                                 Process.myUid() + 1, 30f)
2078                 });
2079         displayInfo = displayManagerBinderService.getDisplayInfo(displayId);
2080         assertEquals(20f, displayInfo.getRefreshRate(), 0.01f);
2081         Display.Mode expectedMode;
2082         if (compatChangeEnabled) {
2083             expectedMode = new Display.Mode(1, 100, 200, 60f);
2084         } else {
2085             expectedMode = new Display.Mode(3, 100, 200, 20f);
2086         }
2087         assertEquals(expectedMode, displayInfo.getMode());
2088     }
2089 
2090     private void testDisplayInfoRenderFrameRateModeCompat(boolean compatChangeEnabled)
2091             throws Exception {
2092         DisplayManagerService displayManager =
2093                 new DisplayManagerService(mContext, mShortMockedInjector);
2094         DisplayManagerService.BinderService displayManagerBinderService =
2095                 displayManager.new BinderService();
2096         registerDefaultDisplays(displayManager);
2097         displayManager.onBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
2098 
2099         FakeDisplayDevice displayDevice = createFakeDisplayDevice(displayManager,
2100                 new float[]{60f, 30f, 20f});
2101         int displayId = getDisplayIdForDisplayDevice(displayManager, displayManagerBinderService,
2102                 displayDevice);
2103         DisplayInfo displayInfo = displayManagerBinderService.getDisplayInfo(displayId);
2104         assertEquals(60f, displayInfo.getRefreshRate(), 0.01f);
2105 
2106         updateRenderFrameRate(displayManager, displayDevice, 20f);
2107         displayInfo = displayManagerBinderService.getDisplayInfo(displayId);
2108         assertEquals(20f, displayInfo.getRefreshRate(), 0.01f);
2109         Display.Mode expectedMode;
2110         if (compatChangeEnabled) {
2111             expectedMode = new Display.Mode(1, 100, 200, 60f);
2112         } else {
2113             expectedMode = new Display.Mode(3, 100, 200, 20f);
2114         }
2115         assertEquals(expectedMode, displayInfo.getMode());
2116     }
2117 
2118     private void testDisplayInfoNonNativeFrameRateOverrideMode(boolean compatChangeEnabled) {
2119         DisplayManagerService displayManager =
2120                 new DisplayManagerService(mContext, mBasicInjector);
2121         DisplayManagerService.BinderService displayManagerBinderService =
2122                 displayManager.new BinderService();
2123         registerDefaultDisplays(displayManager);
2124         displayManager.onBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
2125 
2126         FakeDisplayDevice displayDevice = createFakeDisplayDevice(displayManager,
2127                 new float[]{60f});
2128         int displayId = getDisplayIdForDisplayDevice(displayManager, displayManagerBinderService,
2129                 displayDevice);
2130         DisplayInfo displayInfo = displayManagerBinderService.getDisplayInfo(displayId);
2131         assertEquals(60f, displayInfo.getRefreshRate(), 0.01f);
2132 
2133         updateFrameRateOverride(displayManager, displayDevice,
2134                 new DisplayEventReceiver.FrameRateOverride[]{
2135                         new DisplayEventReceiver.FrameRateOverride(
2136                                 Process.myUid(), 20f)
2137                 });
2138         displayInfo = displayManagerBinderService.getDisplayInfo(displayId);
2139         Display.Mode expectedMode;
2140         if (compatChangeEnabled) {
2141             expectedMode = new Display.Mode(1, 100, 200, 60f);
2142         } else {
2143             expectedMode = new Display.Mode(255, 100, 200, 20f);
2144         }
2145         assertEquals(expectedMode, displayInfo.getMode());
2146     }
2147 
2148     private int getDisplayIdForDisplayDevice(
2149             DisplayManagerService displayManager,
2150             DisplayManagerService.BinderService displayManagerBinderService,
2151             FakeDisplayDevice displayDevice) {
2152 
2153         final int[] displayIds = displayManagerBinderService.getDisplayIds(
2154                 /* includeDisabled= */ true);
2155         assertTrue(displayIds.length > 0);
2156         int displayId = Display.INVALID_DISPLAY;
2157         for (int i = 0; i < displayIds.length; i++) {
2158             DisplayDeviceInfo ddi = displayManager.getDisplayDeviceInfoInternal(displayIds[i]);
2159             if (displayDevice.getDisplayDeviceInfoLocked().equals(ddi)) {
2160                 displayId = displayIds[i];
2161                 break;
2162             }
2163         }
2164         assertFalse(displayId == Display.INVALID_DISPLAY);
2165         return displayId;
2166     }
2167 
2168     private void updateDisplayDeviceInfo(DisplayManagerService displayManager,
2169             FakeDisplayDevice displayDevice,
2170             DisplayDeviceInfo displayDeviceInfo) {
2171         displayDevice.setDisplayDeviceInfo(displayDeviceInfo);
2172         displayManager.getDisplayDeviceRepository()
2173                 .onDisplayDeviceEvent(displayDevice, DisplayAdapter.DISPLAY_DEVICE_EVENT_CHANGED);
2174         Handler handler = displayManager.getDisplayHandler();
2175         waitForIdleHandler(handler);
2176     }
2177 
2178     private void updateFrameRateOverride(DisplayManagerService displayManager,
2179             FakeDisplayDevice displayDevice,
2180             DisplayEventReceiver.FrameRateOverride[] frameRateOverrides) {
2181         DisplayDeviceInfo displayDeviceInfo = new DisplayDeviceInfo();
2182         displayDeviceInfo.copyFrom(displayDevice.getDisplayDeviceInfoLocked());
2183         displayDeviceInfo.frameRateOverrides = frameRateOverrides;
2184         updateDisplayDeviceInfo(displayManager, displayDevice, displayDeviceInfo);
2185     }
2186 
2187     private void updateRenderFrameRate(DisplayManagerService displayManager,
2188             FakeDisplayDevice displayDevice,
2189             float renderFrameRate) {
2190         DisplayDeviceInfo displayDeviceInfo = new DisplayDeviceInfo();
2191         displayDeviceInfo.copyFrom(displayDevice.getDisplayDeviceInfoLocked());
2192         displayDeviceInfo.renderFrameRate = renderFrameRate;
2193         updateDisplayDeviceInfo(displayManager, displayDevice, displayDeviceInfo);
2194     }
2195 
2196     private void updateModeId(DisplayManagerService displayManager,
2197             FakeDisplayDevice displayDevice,
2198             int modeId) {
2199         DisplayDeviceInfo displayDeviceInfo = new DisplayDeviceInfo();
2200         displayDeviceInfo.copyFrom(displayDevice.getDisplayDeviceInfoLocked());
2201         displayDeviceInfo.modeId = modeId;
2202         updateDisplayDeviceInfo(displayManager, displayDevice, displayDeviceInfo);
2203     }
2204 
2205     private IDisplayManagerCallback registerDisplayChangeCallback(
2206             DisplayManagerService displayManager) {
2207         IDisplayManagerCallback displayChangesCallback = mock(IDisplayManagerCallback.class);
2208         when(displayChangesCallback.asBinder()).thenReturn(new Binder());
2209         DisplayManagerService.BinderService binderService = displayManager.new BinderService();
2210         binderService.registerCallback(displayChangesCallback);
2211         return displayChangesCallback;
2212     }
2213 
2214     private FakeDisplayManagerCallback registerDisplayListenerCallback(
2215             DisplayManagerService displayManager,
2216             DisplayManagerService.BinderService displayManagerBinderService,
2217             FakeDisplayDevice displayDevice) {
2218         // Find the display id of the added FakeDisplayDevice
2219         int displayId = getDisplayIdForDisplayDevice(displayManager, displayManagerBinderService,
2220                 displayDevice);
2221 
2222         Handler handler = displayManager.getDisplayHandler();
2223         waitForIdleHandler(handler);
2224 
2225         // register display listener callback
2226         FakeDisplayManagerCallback callback = new FakeDisplayManagerCallback(displayId);
2227         displayManagerBinderService.registerCallbackWithEventMask(
2228                 callback, STANDARD_DISPLAY_EVENTS);
2229         return callback;
2230     }
2231 
2232     private FakeDisplayDevice createFakeDisplayDevice(DisplayManagerService displayManager,
2233             float[] refreshRates) {
2234         FakeDisplayDevice displayDevice = new FakeDisplayDevice();
2235         DisplayDeviceInfo displayDeviceInfo = new DisplayDeviceInfo();
2236         int width = 100;
2237         int height = 200;
2238         displayDeviceInfo.supportedModes = new Display.Mode[refreshRates.length];
2239         for (int i = 0; i < refreshRates.length; i++) {
2240             displayDeviceInfo.supportedModes[i] =
2241                     new Display.Mode(i + 1, width, height, refreshRates[i]);
2242         }
2243         displayDeviceInfo.modeId = 1;
2244         displayDeviceInfo.renderFrameRate = displayDeviceInfo.supportedModes[0].getRefreshRate();
2245         displayDeviceInfo.width = width;
2246         displayDeviceInfo.height = height;
2247         final Rect zeroRect = new Rect();
2248         displayDeviceInfo.displayCutout = new DisplayCutout(
2249                 Insets.of(0, 10, 0, 0),
2250                 zeroRect, new Rect(0, 0, 10, 10), zeroRect, zeroRect);
2251         displayDeviceInfo.flags = DisplayDeviceInfo.FLAG_ALLOWED_TO_BE_DEFAULT_DISPLAY;
2252         displayDeviceInfo.address = new TestUtils.TestDisplayAddress();
2253         displayDevice.setDisplayDeviceInfo(displayDeviceInfo);
2254         displayManager.getDisplayDeviceRepository()
2255                 .onDisplayDeviceEvent(displayDevice, DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED);
2256         return displayDevice;
2257     }
2258 
2259     private void registerDefaultDisplays(DisplayManagerService displayManager) {
2260         Handler handler = displayManager.getDisplayHandler();
2261         // Would prefer to call displayManager.onStart() directly here but it performs binderService
2262         // registration which triggers security exceptions when running from a test.
2263         handler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS);
2264         waitForIdleHandler(handler);
2265     }
2266 
2267     private void waitForIdleHandler(Handler handler) {
2268         waitForIdleHandler(handler, Duration.ofSeconds(1));
2269     }
2270 
2271     private void waitForIdleHandler(Handler handler, Duration timeout) {
2272         final MessageQueue queue = handler.getLooper().getQueue();
2273         final CountDownLatch latch = new CountDownLatch(1);
2274         queue.addIdleHandler(() -> {
2275             latch.countDown();
2276             // Remove idle handler
2277             return false;
2278         });
2279         try {
2280             latch.await(timeout.toMillis(), TimeUnit.MILLISECONDS);
2281         } catch (InterruptedException e) {
2282             fail("Interrupted unexpectedly: " + e);
2283         }
2284     }
2285 
2286     private void resetConfigToIgnoreSensorManager(Context context) {
2287         final Resources res = Mockito.spy(context.getResources());
2288         doReturn(new int[]{-1}).when(res).getIntArray(R.array
2289                 .config_ambientThresholdsOfPeakRefreshRate);
2290         doReturn(new int[]{-1}).when(res).getIntArray(R.array
2291                 .config_brightnessThresholdsOfPeakRefreshRate);
2292         doReturn(new int[]{-1}).when(res).getIntArray(R.array
2293                 .config_highDisplayBrightnessThresholdsOfFixedRefreshRate);
2294         doReturn(new int[]{-1}).when(res).getIntArray(R.array
2295                 .config_highAmbientBrightnessThresholdsOfFixedRefreshRate);
2296 
2297         when(context.getResources()).thenReturn(res);
2298     }
2299 
2300     private class FakeDisplayManagerCallback extends IDisplayManagerCallback.Stub {
2301         int mDisplayId;
2302         boolean mDisplayAddedCalled = false;
2303         boolean mDisplayChangedCalled = false;
2304         boolean mDisplayRemovedCalled = false;
2305 
2306         FakeDisplayManagerCallback(int displayId) {
2307             mDisplayId = displayId;
2308         }
2309 
2310         FakeDisplayManagerCallback() {
2311             mDisplayId = -1;
2312         }
2313 
2314         @Override
2315         public void onDisplayEvent(int displayId, int event) {
2316             if (mDisplayId != -1 && displayId != mDisplayId) {
2317                 return;
2318             }
2319 
2320             if (event == DisplayManagerGlobal.EVENT_DISPLAY_ADDED) {
2321                 mDisplayAddedCalled = true;
2322             }
2323 
2324             if (event == DisplayManagerGlobal.EVENT_DISPLAY_CHANGED) {
2325                 mDisplayChangedCalled = true;
2326             }
2327 
2328             if (event == DisplayManagerGlobal.EVENT_DISPLAY_REMOVED) {
2329                 mDisplayRemovedCalled = true;
2330             }
2331         }
2332 
2333         public void clear() {
2334             mDisplayAddedCalled = false;
2335             mDisplayChangedCalled = false;
2336             mDisplayRemovedCalled = false;
2337         }
2338     }
2339 
2340     private class FakeDisplayDevice extends DisplayDevice {
2341         private DisplayDeviceInfo mDisplayDeviceInfo;
2342 
2343         FakeDisplayDevice() {
2344             super(null, null, "", mContext);
2345         }
2346 
2347         public void setDisplayDeviceInfo(DisplayDeviceInfo displayDeviceInfo) {
2348             mDisplayDeviceInfo = displayDeviceInfo;
2349         }
2350 
2351         @Override
2352         public boolean hasStableUniqueId() {
2353             return false;
2354         }
2355 
2356         @Override
2357         public DisplayDeviceInfo getDisplayDeviceInfoLocked() {
2358             return mDisplayDeviceInfo;
2359         }
2360     }
2361 }
2362