Home | History | Annotate | Download | only in display
      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 android.content.Context;
     20 import android.hardware.display.BrightnessConfiguration;
     21 import android.hardware.display.Curve;
     22 import android.hardware.display.DisplayManager;
     23 import android.hardware.display.DisplayViewport;
     24 import android.hardware.display.IVirtualDisplayCallback;
     25 import android.hardware.input.InputManagerInternal;
     26 import android.os.Handler;
     27 import android.os.IBinder;
     28 import android.os.UserHandle;
     29 import android.test.AndroidTestCase;
     30 import android.test.suitebuilder.annotation.SmallTest;
     31 import android.view.SurfaceControl;
     32 
     33 import com.android.server.LocalServices;
     34 import com.android.server.SystemService;
     35 import com.android.server.display.DisplayDeviceInfo;
     36 import com.android.server.display.DisplayManagerService.SyncRoot;
     37 import com.android.server.display.VirtualDisplayAdapter.SurfaceControlDisplayFactory;
     38 import com.android.server.lights.LightsManager;
     39 import com.android.server.wm.WindowManagerInternal;
     40 
     41 import org.mockito.ArgumentCaptor;
     42 import org.mockito.Mock;
     43 import org.mockito.MockitoAnnotations;
     44 
     45 import java.util.List;
     46 
     47 import static org.mockito.Matchers.any;
     48 import static org.mockito.Mockito.verify;
     49 import static org.mockito.Mockito.when;
     50 import static org.mockito.Mockito.mock;
     51 
     52 @SmallTest
     53 public class DisplayManagerServiceTest extends AndroidTestCase {
     54     private static final int MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS = 1;
     55     private static final long SHORT_DEFAULT_DISPLAY_TIMEOUT_MILLIS = 10;
     56 
     57     private final DisplayManagerService.Injector mShortMockedInjector =
     58             new DisplayManagerService.Injector() {
     59                 @Override
     60                 VirtualDisplayAdapter getVirtualDisplayAdapter(SyncRoot syncRoot,
     61                         Context context, Handler handler, DisplayAdapter.Listener listener) {
     62                     return mMockVirtualDisplayAdapter;
     63                 }
     64 
     65                 @Override
     66                 long getDefaultDisplayDelayTimeout() {
     67                     return SHORT_DEFAULT_DISPLAY_TIMEOUT_MILLIS;
     68                 }
     69             };
     70     private final DisplayManagerService.Injector mBasicInjector =
     71             new DisplayManagerService.Injector() {
     72                 @Override
     73                 VirtualDisplayAdapter getVirtualDisplayAdapter(SyncRoot syncRoot,
     74                         Context context, Handler handler,
     75                         DisplayAdapter.Listener displayAdapterListener) {
     76                     return new VirtualDisplayAdapter(syncRoot, context, handler,
     77                             displayAdapterListener,
     78                             (String name, boolean secure) -> mMockDisplayToken);
     79                 }
     80             };
     81 
     82     @Mock InputManagerInternal mMockInputManagerInternal;
     83     @Mock IVirtualDisplayCallback.Stub mMockAppToken;
     84     @Mock WindowManagerInternal mMockWindowManagerInternal;
     85     @Mock LightsManager mMockLightsManager;
     86     @Mock VirtualDisplayAdapter mMockVirtualDisplayAdapter;
     87     @Mock IBinder mMockDisplayToken;
     88 
     89     @Override
     90     protected void setUp() throws Exception {
     91         MockitoAnnotations.initMocks(this);
     92 
     93         LocalServices.removeServiceForTest(InputManagerInternal.class);
     94         LocalServices.addService(InputManagerInternal.class, mMockInputManagerInternal);
     95         LocalServices.removeServiceForTest(WindowManagerInternal.class);
     96         LocalServices.addService(WindowManagerInternal.class, mMockWindowManagerInternal);
     97         LocalServices.removeServiceForTest(LightsManager.class);
     98         LocalServices.addService(LightsManager.class, mMockLightsManager);
     99         super.setUp();
    100     }
    101 
    102     @Override
    103     protected void tearDown() throws Exception {
    104         super.tearDown();
    105     }
    106 
    107     public void testCreateVirtualDisplay_sentToInputManager() throws Exception {
    108         DisplayManagerService displayManager =
    109                 new DisplayManagerService(mContext, mBasicInjector);
    110         registerDefaultDisplays(displayManager);
    111         displayManager.systemReady(false /* safeMode */, true /* onlyCore */);
    112         displayManager.windowManagerAndInputReady();
    113 
    114         // This is effectively the DisplayManager service published to ServiceManager.
    115         DisplayManagerService.BinderService bs = displayManager.new BinderService();
    116 
    117         String uniqueId = "uniqueId --- Test";
    118         String uniqueIdPrefix = "virtual:" + mContext.getPackageName() + ":";
    119         int width = 600;
    120         int height = 800;
    121         int dpi = 320;
    122         int flags = DisplayManager.VIRTUAL_DISPLAY_FLAG_SUPPORTS_TOUCH;
    123 
    124         when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
    125         int displayId = bs.createVirtualDisplay(mMockAppToken /* callback */,
    126                 null /* projection */, "com.android.frameworks.servicestests",
    127                 "Test Virtual Display", width, height, dpi, null /* surface */, flags /* flags */,
    128                 uniqueId);
    129 
    130         displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
    131 
    132         // flush the handler
    133         displayManager.getDisplayHandler().runWithScissors(() -> {}, 0 /* now */);
    134 
    135         ArgumentCaptor<List<DisplayViewport>> virtualViewportCaptor =
    136                 ArgumentCaptor.forClass(List.class);
    137         verify(mMockInputManagerInternal).setDisplayViewports(
    138                 any(), any(), virtualViewportCaptor.capture());
    139 
    140         assertEquals(1, virtualViewportCaptor.getValue().size());
    141         DisplayViewport dv = virtualViewportCaptor.getValue().get(0);
    142         assertEquals(height, dv.deviceHeight);
    143         assertEquals(width, dv.deviceWidth);
    144         assertEquals(uniqueIdPrefix + uniqueId, dv.uniqueId);
    145         assertEquals(displayId, dv.displayId);
    146     }
    147 
    148     public void testCreateVirtualDisplayRotatesWithContent() throws Exception {
    149         DisplayManagerService displayManager =
    150                 new DisplayManagerService(mContext, mBasicInjector);
    151         registerDefaultDisplays(displayManager);
    152 
    153         // This is effectively the DisplayManager service published to ServiceManager.
    154         DisplayManagerService.BinderService bs = displayManager.new BinderService();
    155 
    156         String uniqueId = "uniqueId --- Rotates With Content Test";
    157         int width = 600;
    158         int height = 800;
    159         int dpi = 320;
    160         int flags = DisplayManager.VIRTUAL_DISPLAY_FLAG_ROTATES_WITH_CONTENT;
    161 
    162         when(mMockAppToken.asBinder()).thenReturn(mMockAppToken);
    163         int displayId = bs.createVirtualDisplay(mMockAppToken /* callback */,
    164                 null /* projection */, "com.android.frameworks.servicestests",
    165                 "Test Virtual Display", width, height, dpi, null /* surface */, flags /* flags */,
    166                 uniqueId);
    167 
    168         displayManager.performTraversalInternal(mock(SurfaceControl.Transaction.class));
    169 
    170         // flush the handler
    171         displayManager.getDisplayHandler().runWithScissors(() -> {}, 0 /* now */);
    172 
    173         DisplayDeviceInfo ddi = displayManager.getDisplayDeviceInfoInternal(displayId);
    174         assertNotNull(ddi);
    175         assertTrue((ddi.flags & DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT) != 0);
    176     }
    177 
    178     /**
    179      * Tests that the virtual display is created along-side the default display.
    180      */
    181     public void testStartVirtualDisplayWithDefaultDisplay_Succeeds() throws Exception {
    182         DisplayManagerService displayManager =
    183                 new DisplayManagerService(mContext, mShortMockedInjector);
    184         registerDefaultDisplays(displayManager);
    185         displayManager.onBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
    186     }
    187 
    188     /**
    189      * Tests that we get a Runtime exception when we cannot initialize the default display.
    190      */
    191     public void testStartVirtualDisplayWithDefDisplay_NoDefaultDisplay() throws Exception {
    192         DisplayManagerService displayManager =
    193                 new DisplayManagerService(mContext, mShortMockedInjector);
    194         Handler handler = displayManager.getDisplayHandler();
    195         handler.runWithScissors(() -> {}, 0 /* now */);
    196 
    197         try {
    198             displayManager.onBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
    199         } catch (RuntimeException e) {
    200             return;
    201         }
    202         fail("Expected DisplayManager to throw RuntimeException when it cannot initialize the"
    203                 + " default display");
    204     }
    205 
    206     /**
    207      * Tests that we get a Runtime exception when we cannot initialize the virtual display.
    208      */
    209     public void testStartVirtualDisplayWithDefDisplay_NoVirtualDisplayAdapter() throws Exception {
    210         DisplayManagerService displayManager = new DisplayManagerService(mContext,
    211                 new DisplayManagerService.Injector() {
    212                     @Override
    213                     VirtualDisplayAdapter getVirtualDisplayAdapter(SyncRoot syncRoot,
    214                             Context context, Handler handler, DisplayAdapter.Listener listener) {
    215                         return null;  // return null for the adapter.  This should cause a failure.
    216                     }
    217 
    218                     @Override
    219                     long getDefaultDisplayDelayTimeout() {
    220                         return SHORT_DEFAULT_DISPLAY_TIMEOUT_MILLIS;
    221                     }
    222                 });
    223         try {
    224             displayManager.onBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
    225         } catch (RuntimeException e) {
    226             return;
    227         }
    228         fail("Expected DisplayManager to throw RuntimeException when it cannot initialize the"
    229                 + " virtual display adapter");
    230     }
    231 
    232     /**
    233      * Tests that an exception is raised for too dark a brightness configuration.
    234      */
    235     public void testTooDarkBrightnessConfigurationThrowException() {
    236         DisplayManagerService displayManager =
    237                 new DisplayManagerService(mContext, mShortMockedInjector);
    238         Curve minimumBrightnessCurve = displayManager.getMinimumBrightnessCurveInternal();
    239         float[] lux = minimumBrightnessCurve.getX();
    240         float[] minimumNits = minimumBrightnessCurve.getY();
    241         float[] nits = new float[minimumNits.length];
    242         // For every control point, assert that making it slightly lower than the minimum throws an
    243         // exception.
    244         for (int i = 0; i < nits.length; i++) {
    245             for (int j = 0; j < nits.length; j++) {
    246                 nits[j] = minimumNits[j];
    247                 if (j == i) {
    248                     nits[j] -= 0.1f;
    249                 }
    250                 if (nits[j] < 0) {
    251                     nits[j] = 0;
    252                 }
    253             }
    254             BrightnessConfiguration config =
    255                     new BrightnessConfiguration.Builder(lux, nits).build();
    256             Exception thrown = null;
    257             try {
    258                 displayManager.validateBrightnessConfiguration(config);
    259             } catch (IllegalArgumentException e) {
    260                 thrown = e;
    261             }
    262             assertNotNull("Building too dark a brightness configuration must throw an exception");
    263         }
    264     }
    265 
    266     /**
    267      * Tests that no exception is raised for not too dark a brightness configuration.
    268      */
    269     public void testBrightEnoughBrightnessConfigurationDoesNotThrowException() {
    270         DisplayManagerService displayManager =
    271                 new DisplayManagerService(mContext, mShortMockedInjector);
    272         Curve minimumBrightnessCurve = displayManager.getMinimumBrightnessCurveInternal();
    273         float[] lux = minimumBrightnessCurve.getX();
    274         float[] nits = minimumBrightnessCurve.getY();
    275         BrightnessConfiguration config = new BrightnessConfiguration.Builder(lux, nits).build();
    276         displayManager.validateBrightnessConfiguration(config);
    277     }
    278 
    279     /**
    280      * Tests that null brightness configurations are alright.
    281      */
    282     public void testNullBrightnessConfiguration() {
    283         DisplayManagerService displayManager =
    284                 new DisplayManagerService(mContext, mShortMockedInjector);
    285         displayManager.validateBrightnessConfiguration(null);
    286     }
    287 
    288     private void registerDefaultDisplays(DisplayManagerService displayManager) {
    289         Handler handler = displayManager.getDisplayHandler();
    290         // Would prefer to call displayManager.onStart() directly here but it performs binderService
    291         // registration which triggers security exceptions when running from a test.
    292         handler.sendEmptyMessage(MSG_REGISTER_DEFAULT_DISPLAY_ADAPTERS);
    293         // flush the handler
    294         handler.runWithScissors(() -> {}, 0 /* now */);
    295     }
    296 }
    297