blob: 9e255fe19881bb0e11787f1cbdd4a476cc46c948 [file] [log] [blame]
Keun young Parkabf38e32019-04-23 19:18:34 -07001/*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.display;
18
19import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
20import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
21import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
22
23import static org.junit.Assert.assertEquals;
24import static org.junit.Assert.assertNotNull;
25
26import android.content.Context;
27import android.content.res.Resources;
28import android.os.Binder;
29import android.os.Handler;
30import android.os.IBinder;
31import android.os.Looper;
32import android.view.DisplayAddress;
33import android.view.SurfaceControl;
34
35import androidx.test.filters.SmallTest;
36import androidx.test.runner.AndroidJUnit4;
37
38import com.android.dx.mockito.inline.extended.StaticMockitoSession;
39import com.android.server.LocalServices;
40import com.android.server.lights.LightsManager;
41
42import org.junit.After;
43import org.junit.Before;
44import org.junit.Test;
45import org.junit.runner.RunWith;
46import org.mockito.Mock;
47import org.mockito.quality.Strictness;
48
49import java.util.ArrayList;
50import java.util.LinkedList;
51
52
53@SmallTest
54@RunWith(AndroidJUnit4.class)
55public class LocalDisplayAdapterTest {
56 private static final long HANDLER_WAIT_MS = 100;
57
58 private static final int PHYSICAL_DISPLAY_ID_MODEL_SHIFT = 8;
59
60 private StaticMockitoSession mMockitoSession;
61
62 private LocalDisplayAdapter mAdapter;
63
64 @Mock
65 private DisplayManagerService.SyncRoot mMockedSyncRoot;
66 @Mock
67 private Context mMockedContext;
68 @Mock
69 private Resources mMockedResources;
70 @Mock
71 private LightsManager mMockedLightsManager;
72
73 private Handler mHandler;
74
75 private TestListener mListener = new TestListener();
76
77 private LinkedList<Long> mDisplayIds = new LinkedList<>();
78
79 @Before
80 public void setUp() throws Exception {
81 mMockitoSession = mockitoSession()
82 .initMocks(this)
83 .mockStatic(SurfaceControl.class)
84 .strictness(Strictness.LENIENT)
85 .startMocking();
86 mHandler = new Handler(Looper.getMainLooper());
87 doReturn(mMockedResources).when(mMockedContext).getResources();
88 LocalServices.removeServiceForTest(LightsManager.class);
89 LocalServices.addService(LightsManager.class, mMockedLightsManager);
90 mAdapter = new LocalDisplayAdapter(mMockedSyncRoot, mMockedContext, mHandler,
91 mListener);
92 spyOn(mAdapter);
93 doReturn(mMockedContext).when(mAdapter).getOverlayContext();
94 }
95
96 @After
97 public void tearDown() {
98 if (mMockitoSession != null) {
99 mMockitoSession.finishMocking();
100 }
101 }
102
103 /**
104 * Confirm that display is marked as private when it is listed in
105 * com.android.internal.R.array.config_localPrivateDisplayPorts.
106 */
107 @Test
108 public void testPrivateDisplay() throws Exception {
109 // needs default one always
110 final long displayId0 = 0;
111 setUpDisplay(new DisplayConfig(displayId0, createDummyDisplayInfo()));
112 final long displayId1 = 1;
113 setUpDisplay(new DisplayConfig(displayId1, createDummyDisplayInfo()));
114 final long displayId2 = 2;
115 setUpDisplay(new DisplayConfig(displayId2, createDummyDisplayInfo()));
116 updateAvailableDisplays();
117 // display 1 should be marked as private while display 2 is not.
118 doReturn(new int[]{(int) displayId1}).when(mMockedResources)
119 .getIntArray(com.android.internal.R.array.config_localPrivateDisplayPorts);
120 mAdapter.registerLocked();
121
122 waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
123
124 // This should be public
125 assertDisplay(mListener.addedDisplays.get(0).getDisplayDeviceInfoLocked(), displayId0,
126 false);
127 // This should be private
128 assertDisplay(mListener.addedDisplays.get(1).getDisplayDeviceInfoLocked(), displayId1,
129 true);
130 // This should be public
131 assertDisplay(mListener.addedDisplays.get(2).getDisplayDeviceInfoLocked(), displayId2,
132 false);
133 }
134
135 /**
136 * Confirm that all local displays are public when config_localPrivateDisplayPorts is empty.
137 */
138 @Test
139 public void testPublicDisplaysForNoConfigLocalPrivateDisplayPorts() throws Exception {
140 // needs default one always
141 final long displayId0 = 0;
142 setUpDisplay(new DisplayConfig(displayId0, createDummyDisplayInfo()));
143 final long displayId1 = 1;
144 setUpDisplay(new DisplayConfig(displayId1, createDummyDisplayInfo()));
145 updateAvailableDisplays();
146 // config_localPrivateDisplayPorts is null
147 mAdapter.registerLocked();
148
149 waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
150
151 // This should be public
152 assertDisplay(mListener.addedDisplays.get(0).getDisplayDeviceInfoLocked(), displayId0,
153 false);
154 // This should be public
155 assertDisplay(mListener.addedDisplays.get(1).getDisplayDeviceInfoLocked(), displayId1,
156 false);
157 }
158
159 private void assertDisplay(DisplayDeviceInfo info, long expectedPort, boolean shouldBePrivate) {
160 DisplayAddress.Physical physical = (DisplayAddress.Physical) info.address;
161 assertNotNull(physical);
162 assertEquals(expectedPort, physical.getPort());
163 assertEquals(shouldBePrivate, (info.flags & DisplayDeviceInfo.FLAG_PRIVATE) != 0);
164 }
165
166 private class DisplayConfig {
167 public final long displayId;
168 public final IBinder displayToken = new Binder();
169 public final SurfaceControl.PhysicalDisplayInfo displayInfo;
170
171 private DisplayConfig(long displayId, SurfaceControl.PhysicalDisplayInfo displayInfo) {
172 this.displayId = displayId | (0x1 << PHYSICAL_DISPLAY_ID_MODEL_SHIFT);
173 this.displayInfo = displayInfo;
174 }
175 }
176
177 private void setUpDisplay(DisplayConfig config) {
178 mDisplayIds.add(config.displayId);
179 doReturn(config.displayToken).when(
180 () -> SurfaceControl.getPhysicalDisplayToken(config.displayId));
181 doReturn(new SurfaceControl.PhysicalDisplayInfo[]{
182 config.displayInfo
183 }).when(() -> SurfaceControl.getDisplayConfigs(config.displayToken));
184 doReturn(0).when(() -> SurfaceControl.getActiveConfig(config.displayToken));
185 doReturn(0).when(() -> SurfaceControl.getActiveColorMode(config.displayToken));
186 doReturn(new int[]{
187 0
188 }).when(() -> SurfaceControl.getDisplayColorModes(config.displayToken));
189 doReturn(new int[]{
190 0
191 }).when(() -> SurfaceControl.getAllowedDisplayConfigs(config.displayToken));
192 }
193
194 private void updateAvailableDisplays() {
195 long[] ids = new long[mDisplayIds.size()];
196 int i = 0;
197 for (long id : mDisplayIds) {
198 ids[i] = id;
199 i++;
200 }
201 doReturn(ids).when(() -> SurfaceControl.getPhysicalDisplayIds());
202 }
203
204 private SurfaceControl.PhysicalDisplayInfo createDummyDisplayInfo() {
205 SurfaceControl.PhysicalDisplayInfo info = new SurfaceControl.PhysicalDisplayInfo();
206 info.density = 100;
207 info.xDpi = 100;
208 info.yDpi = 100;
209 info.secure = false;
210 info.width = 800;
211 info.height = 600;
212
213 return info;
214 }
215
216 private void waitForHandlerToComplete(Handler handler, long waitTimeMs)
217 throws InterruptedException {
218 final Object lock = new Object();
219 synchronized (lock) {
220 handler.post(() -> {
221 synchronized (lock) {
222 lock.notify();
223 }
224 });
225 lock.wait(waitTimeMs);
226 }
227 }
228
229 private class TestListener implements DisplayAdapter.Listener {
230 public ArrayList<DisplayDevice> addedDisplays = new ArrayList<>();
231
232 @Override
233 public void onDisplayDeviceEvent(DisplayDevice device, int event) {
234 if (event == DisplayAdapter.DISPLAY_DEVICE_EVENT_ADDED) {
235 addedDisplays.add(device);
236 }
237 }
238
239 @Override
240 public void onTraversalRequested() {
241
242 }
243 }
244}