1 /* 2 * Copyright (C) 2020 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.wm; 18 19 import static android.view.Display.DEFAULT_DISPLAY; 20 import static android.window.DisplayAreaOrganizer.FEATURE_DEFAULT_TASK_CONTAINER; 21 import static android.window.DisplayAreaOrganizer.FEATURE_ROOT; 22 import static android.window.DisplayAreaOrganizer.FEATURE_RUNTIME_TASK_CONTAINER_FIRST; 23 import static android.window.DisplayAreaOrganizer.FEATURE_VENDOR_FIRST; 24 25 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; 26 27 import static com.google.common.truth.Truth.assertThat; 28 29 import static org.mockito.ArgumentMatchers.any; 30 import static org.mockito.Mockito.doReturn; 31 import static org.mockito.Mockito.mock; 32 import static org.mockito.Mockito.never; 33 import static org.mockito.Mockito.verify; 34 import static org.mockito.Mockito.when; 35 import static org.testng.Assert.assertThrows; 36 37 import android.content.res.Configuration; 38 import android.graphics.Rect; 39 import android.os.Binder; 40 import android.os.RemoteException; 41 import android.platform.test.annotations.Presubmit; 42 import android.view.SurfaceControl; 43 import android.window.DisplayAreaAppearedInfo; 44 import android.window.DisplayAreaInfo; 45 import android.window.IDisplayAreaOrganizer; 46 47 import androidx.test.filters.SmallTest; 48 49 import org.junit.After; 50 import org.junit.Before; 51 import org.junit.Test; 52 import org.junit.runner.RunWith; 53 54 import java.util.List; 55 56 /** 57 * Build/Install/Run: 58 * atest WmTests:DisplayAreaOrganizerTest 59 */ 60 @SmallTest 61 @Presubmit 62 @RunWith(WindowTestRunner.class) 63 public class DisplayAreaOrganizerTest extends WindowTestsBase { 64 65 private DisplayArea mTestDisplayArea; 66 private DisplayAreaOrganizerController mOrganizerController; 67 68 @Before setUp()69 public void setUp() { 70 mOrganizerController = 71 mWm.mAtmService.mWindowOrganizerController.mDisplayAreaOrganizerController; 72 WindowContainer parentWindow = mDisplayContent.getDefaultTaskDisplayArea().getParent(); 73 mTestDisplayArea = new DisplayArea(mWm, DisplayArea.Type.ANY, 74 "TestDisplayArea", FEATURE_VENDOR_FIRST); 75 parentWindow.addChild(mTestDisplayArea, 76 parentWindow.mChildren.indexOf(mDisplayContent.getDefaultTaskDisplayArea()) + 1); 77 } 78 79 @After tearDown()80 public void tearDown() { 81 mTestDisplayArea.removeImmediately(); 82 } 83 registerMockOrganizer(int feature)84 private IDisplayAreaOrganizer registerMockOrganizer(int feature) { 85 return registerMockOrganizer(feature, new Binder()); 86 } 87 registerMockOrganizer(int feature, Binder binder)88 private IDisplayAreaOrganizer registerMockOrganizer(int feature, Binder binder) { 89 final IDisplayAreaOrganizer organizer = createMockOrganizer(binder); 90 mOrganizerController.registerOrganizer(organizer, feature); 91 return organizer; 92 } 93 createMockOrganizer(Binder binder)94 private IDisplayAreaOrganizer createMockOrganizer(Binder binder) { 95 final IDisplayAreaOrganizer organizer = mock(IDisplayAreaOrganizer.class); 96 when(organizer.asBinder()).thenReturn(binder); 97 return organizer; 98 } 99 100 @Test testRegisterOrganizer()101 public void testRegisterOrganizer() throws RemoteException { 102 final IDisplayAreaOrganizer organizer = createMockOrganizer(new Binder()); 103 List<DisplayAreaAppearedInfo> infos = mOrganizerController 104 .registerOrganizer(organizer, FEATURE_VENDOR_FIRST).getList(); 105 106 // Return a list contains the DA, and no onDisplayAreaAppeared triggered. 107 assertThat(infos).hasSize(1); 108 assertThat(infos.get(0).getDisplayAreaInfo().token) 109 .isEqualTo(mTestDisplayArea.getDisplayAreaInfo().token); 110 verify(organizer, never()).onDisplayAreaAppeared(any(DisplayAreaInfo.class), 111 any(SurfaceControl.class)); 112 } 113 114 @Test testRegisterOrganizer_ignoreUntrustedDisplay()115 public void testRegisterOrganizer_ignoreUntrustedDisplay() throws RemoteException { 116 doReturn(false).when(mDisplayContent).isTrusted(); 117 118 final IDisplayAreaOrganizer organizer = createMockOrganizer(new Binder()); 119 List<DisplayAreaAppearedInfo> infos = mOrganizerController 120 .registerOrganizer(organizer, FEATURE_VENDOR_FIRST).getList(); 121 122 assertThat(infos).isEmpty(); 123 verify(organizer, never()).onDisplayAreaAppeared(any(DisplayAreaInfo.class), 124 any(SurfaceControl.class)); 125 } 126 127 @Test testCreateTaskDisplayArea_topBelowRoot()128 public void testCreateTaskDisplayArea_topBelowRoot() { 129 final String newTdaName = "testTda"; 130 final IDisplayAreaOrganizer organizer = createMockOrganizer(new Binder()); 131 final DisplayAreaAppearedInfo tdaInfo = mOrganizerController.createTaskDisplayArea( 132 organizer, DEFAULT_DISPLAY, FEATURE_ROOT, newTdaName); 133 134 final int newTdaIndex = 135 mTestDisplayArea.getParent().mChildren.indexOf(mTestDisplayArea) + 1; 136 final WindowContainer wc = mTestDisplayArea.getParent().getChildAt(newTdaIndex); 137 138 // A new TaskDisplayArea is created on the top. 139 assertThat(wc).isInstanceOf(TaskDisplayArea.class); 140 assertThat(tdaInfo.getDisplayAreaInfo().displayId).isEqualTo(DEFAULT_DISPLAY); 141 assertThat(tdaInfo.getDisplayAreaInfo().token) 142 .isEqualTo(wc.mRemoteToken.toWindowContainerToken()); 143 144 final TaskDisplayArea tda = wc.asTaskDisplayArea(); 145 146 assertThat(tda.getName()).isEqualTo(newTdaName); 147 assertThat(tda.mFeatureId).isEqualTo(tdaInfo.getDisplayAreaInfo().featureId); 148 assertThat(tda.mCreatedByOrganizer).isTrue(); 149 assertThat(tda.mOrganizer).isEqualTo(organizer); 150 } 151 152 @Test testCreateTaskDisplayArea_topBelowAnotherTaskDisplayArea()153 public void testCreateTaskDisplayArea_topBelowAnotherTaskDisplayArea() { 154 final String newTdaName = "testTda"; 155 final TaskDisplayArea parentTda = mDisplayContent.getDefaultTaskDisplayArea(); 156 final IDisplayAreaOrganizer organizer = createMockOrganizer(new Binder()); 157 final DisplayAreaAppearedInfo tdaInfo = mOrganizerController.createTaskDisplayArea( 158 organizer, DEFAULT_DISPLAY, FEATURE_DEFAULT_TASK_CONTAINER, newTdaName); 159 160 final WindowContainer wc = parentTda.getChildAt(parentTda.getChildCount() - 1); 161 162 // A new TaskDisplayArea is created on the top. 163 assertThat(wc).isInstanceOf(TaskDisplayArea.class); 164 assertThat(tdaInfo.getDisplayAreaInfo().displayId).isEqualTo(DEFAULT_DISPLAY); 165 assertThat(tdaInfo.getDisplayAreaInfo().token) 166 .isEqualTo(wc.mRemoteToken.toWindowContainerToken()); 167 168 final TaskDisplayArea tda = wc.asTaskDisplayArea(); 169 170 assertThat(tda.getName()).isEqualTo(newTdaName); 171 assertThat(tda.mFeatureId).isEqualTo(tdaInfo.getDisplayAreaInfo().featureId); 172 assertThat(tda.mCreatedByOrganizer).isTrue(); 173 assertThat(tda.mOrganizer).isEqualTo(organizer); 174 } 175 176 @Test testCreateTaskDisplayArea_incrementalTdaFeatureId()177 public void testCreateTaskDisplayArea_incrementalTdaFeatureId() { 178 final String newTdaName = "testTda"; 179 final IDisplayAreaOrganizer organizer = createMockOrganizer(new Binder()); 180 final DisplayAreaAppearedInfo tdaInfo1 = mOrganizerController.createTaskDisplayArea( 181 organizer, DEFAULT_DISPLAY, FEATURE_ROOT, newTdaName); 182 final DisplayAreaAppearedInfo tdaInfo2 = mOrganizerController.createTaskDisplayArea( 183 organizer, DEFAULT_DISPLAY, FEATURE_ROOT, newTdaName); 184 185 // New created TDA has unique feature id starting from FEATURE_RUNTIME_TASK_CONTAINER_FIRST. 186 assertThat(tdaInfo1.getDisplayAreaInfo().featureId).isEqualTo( 187 FEATURE_RUNTIME_TASK_CONTAINER_FIRST); 188 assertThat(tdaInfo2.getDisplayAreaInfo().featureId).isEqualTo( 189 FEATURE_RUNTIME_TASK_CONTAINER_FIRST + 1); 190 } 191 192 193 @Test testCreateTaskDisplayArea_invalidDisplayAndRoot()194 public void testCreateTaskDisplayArea_invalidDisplayAndRoot() { 195 final IDisplayAreaOrganizer organizer = createMockOrganizer(new Binder()); 196 197 assertThrows(IllegalArgumentException.class, () -> 198 mOrganizerController.createTaskDisplayArea( 199 organizer, SystemServicesTestRule.sNextDisplayId + 1, FEATURE_ROOT, 200 "testTda")); 201 202 assertThrows(IllegalArgumentException.class, () -> 203 mOrganizerController.createTaskDisplayArea( 204 organizer, DEFAULT_DISPLAY, FEATURE_ROOT - 1, "testTda")); 205 206 doReturn(false).when(mDisplayContent).isTrusted(); 207 assertThrows(IllegalArgumentException.class, () -> 208 mOrganizerController.createTaskDisplayArea( 209 organizer, DEFAULT_DISPLAY, FEATURE_ROOT, "testTda")); 210 } 211 212 @Test testDeleteTaskDisplayArea()213 public void testDeleteTaskDisplayArea() { 214 final String newTdaName = "testTda"; 215 final IDisplayAreaOrganizer organizer = createMockOrganizer(new Binder()); 216 final DisplayAreaAppearedInfo tdaInfo = mOrganizerController.createTaskDisplayArea( 217 organizer, DEFAULT_DISPLAY, FEATURE_ROOT, newTdaName); 218 final int tdaFeatureId = tdaInfo.getDisplayAreaInfo().featureId; 219 220 final TaskDisplayArea newTda = mDisplayContent.getItemFromDisplayAreas( 221 da -> da.mFeatureId == tdaFeatureId ? da.asTaskDisplayArea() : null); 222 spyOn(newTda); 223 224 mOrganizerController.deleteTaskDisplayArea(newTda.mRemoteToken.toWindowContainerToken()); 225 226 verify(newTda).remove(); 227 verify(newTda).removeImmediately(); 228 assertThat(newTda.mOrganizer).isNull(); 229 assertThat(newTda.isRemoved()).isTrue(); 230 231 final TaskDisplayArea curTda = mDisplayContent.getItemFromDisplayAreas( 232 da -> da.mFeatureId == tdaFeatureId ? da.asTaskDisplayArea() : null); 233 234 assertThat(curTda).isNull(); 235 } 236 237 @Test testUnregisterOrganizer_deleteNewCreatedTaskDisplayArea()238 public void testUnregisterOrganizer_deleteNewCreatedTaskDisplayArea() { 239 final String newTdaName = "testTda"; 240 final IDisplayAreaOrganizer organizer = createMockOrganizer(new Binder()); 241 final DisplayAreaAppearedInfo tdaInfo = mOrganizerController.createTaskDisplayArea( 242 organizer, DEFAULT_DISPLAY, FEATURE_ROOT, newTdaName); 243 final int tdaFeatureId = tdaInfo.getDisplayAreaInfo().featureId; 244 245 final TaskDisplayArea newTda = mDisplayContent.getItemFromDisplayAreas( 246 da -> da.mFeatureId == tdaFeatureId ? da.asTaskDisplayArea() : null); 247 spyOn(newTda); 248 249 mOrganizerController.unregisterOrganizer(organizer); 250 251 verify(newTda).remove(); 252 verify(newTda).removeImmediately(); 253 assertThat(newTda.mOrganizer).isNull(); 254 assertThat(newTda.isRemoved()).isTrue(); 255 256 final TaskDisplayArea curTda = mDisplayContent.getItemFromDisplayAreas( 257 da -> da.mFeatureId == tdaFeatureId ? da.asTaskDisplayArea() : null); 258 259 assertThat(curTda).isNull(); 260 } 261 262 @Test testDeleteTaskDisplayArea_invalidTaskDisplayArea()263 public void testDeleteTaskDisplayArea_invalidTaskDisplayArea() { 264 final TaskDisplayArea tda = mDisplayContent.getDefaultTaskDisplayArea(); 265 assertThrows(IllegalArgumentException.class, () -> 266 mOrganizerController.deleteTaskDisplayArea( 267 tda.mRemoteToken.toWindowContainerToken())); 268 } 269 270 @Test testAppearedVanished()271 public void testAppearedVanished() throws RemoteException { 272 final IDisplayAreaOrganizer organizer = registerMockOrganizer(FEATURE_VENDOR_FIRST); 273 mOrganizerController.unregisterOrganizer(organizer); 274 275 verify(organizer).onDisplayAreaVanished(any()); 276 } 277 278 @Test testChanged()279 public void testChanged() throws RemoteException { 280 final IDisplayAreaOrganizer organizer = registerMockOrganizer(FEATURE_VENDOR_FIRST); 281 mDisplayContent.setBounds(new Rect(0, 0, 1000, 1000)); 282 283 verify(organizer).onDisplayAreaInfoChanged(any()); 284 285 Configuration tmpConfiguration = new Configuration(); 286 tmpConfiguration.setTo(mDisplayContent.getRequestedOverrideConfiguration()); 287 mDisplayContent.onRequestedOverrideConfigurationChanged(tmpConfiguration); 288 289 // Ensure it was still only called once if the bounds didn't change 290 verify(organizer).onDisplayAreaInfoChanged(any()); 291 } 292 293 @Test testUnregisterOrganizer()294 public void testUnregisterOrganizer() { 295 final Binder binder = new Binder(); 296 registerMockOrganizer(FEATURE_VENDOR_FIRST, binder); 297 298 assertThat(mTestDisplayArea.mOrganizer).isNotNull(); 299 300 mOrganizerController.unregisterOrganizer(createMockOrganizer(binder)); 301 302 assertThat(mTestDisplayArea.mOrganizer).isNull(); 303 } 304 } 305