1 /* 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 17 package com.android.server.wm; 18 19 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; 20 import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS; 21 22 import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean; 23 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer; 24 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing; 25 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; 26 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn; 27 28 import static org.mockito.ArgumentMatchers.any; 29 30 import android.content.res.Configuration; 31 import android.graphics.Insets; 32 import android.graphics.Rect; 33 import android.hardware.display.DisplayManagerGlobal; 34 import android.view.Display; 35 import android.view.DisplayCutout; 36 import android.view.DisplayInfo; 37 38 class TestDisplayContent extends DisplayContent { 39 40 public static final int DEFAULT_LOGICAL_DISPLAY_DENSITY = 300; 41 42 /** Please use the {@link Builder} to create, visible for use in test builder overrides only. */ TestDisplayContent(RootWindowContainer rootWindowContainer, Display display)43 TestDisplayContent(RootWindowContainer rootWindowContainer, Display display) { 44 super(display, rootWindowContainer); 45 // Normally this comes from display-properties as exposed by WM. Without that, just 46 // hard-code to FULLSCREEN for tests. 47 setWindowingMode(WINDOWING_MODE_FULLSCREEN); 48 spyOn(this); 49 forAllTaskDisplayAreas(taskDisplayArea -> { 50 spyOn(taskDisplayArea); 51 }); 52 final DisplayRotation displayRotation = getDisplayRotation(); 53 spyOn(displayRotation); 54 doAnswer(invocation -> { 55 // Bypass all the rotation animation and display freezing stuff for testing and just 56 // set the rotation we want for the display 57 final int oldRotation = displayRotation.getRotation(); 58 final int rotation = displayRotation.rotationForOrientation( 59 displayRotation.getLastOrientation(), oldRotation); 60 if (oldRotation == rotation) { 61 return false; 62 } 63 setLayoutNeeded(); 64 displayRotation.setRotation(rotation); 65 return true; 66 }).when(displayRotation).updateRotationUnchecked(anyBoolean()); 67 68 final InputMonitor inputMonitor = getInputMonitor(); 69 spyOn(inputMonitor); 70 doNothing().when(inputMonitor).resumeDispatchingLw(any()); 71 } 72 73 public static class Builder { 74 private final DisplayInfo mInfo; 75 private boolean mCanRotate = true; 76 private int mWindowingMode = WINDOWING_MODE_FULLSCREEN; 77 private int mPosition = POSITION_BOTTOM; 78 protected final ActivityTaskManagerService mService; 79 private boolean mSystemDecorations = false; 80 Builder(ActivityTaskManagerService service, int width, int height)81 Builder(ActivityTaskManagerService service, int width, int height) { 82 mService = service; 83 mInfo = new DisplayInfo(); 84 mService.mContext.getDisplay().getDisplayInfo(mInfo); 85 mInfo.logicalWidth = width; 86 mInfo.logicalHeight = height; 87 mInfo.logicalDensityDpi = DEFAULT_LOGICAL_DISPLAY_DENSITY; 88 mInfo.displayCutout = null; 89 // Set unique ID so physical display overrides are not inheritted from 90 // DisplayWindowSettings. 91 mInfo.uniqueId = generateUniqueId(); 92 } Builder(ActivityTaskManagerService service, DisplayInfo info)93 Builder(ActivityTaskManagerService service, DisplayInfo info) { 94 mService = service; 95 mInfo = info; 96 // Set unique ID so physical display overrides are not inheritted from 97 // DisplayWindowSettings. 98 mInfo.uniqueId = generateUniqueId(); 99 } generateUniqueId()100 private String generateUniqueId() { 101 return "TEST_DISPLAY_CONTENT_" + System.currentTimeMillis(); 102 } setSystemDecorations(boolean yes)103 Builder setSystemDecorations(boolean yes) { 104 mSystemDecorations = yes; 105 return this; 106 } setPosition(int position)107 Builder setPosition(int position) { 108 mPosition = position; 109 return this; 110 } setUniqueId(String uniqueId)111 Builder setUniqueId(String uniqueId) { 112 mInfo.uniqueId = uniqueId; 113 return this; 114 } setType(int type)115 Builder setType(int type) { 116 mInfo.type = type; 117 return this; 118 } setOwnerUid(int ownerUid)119 Builder setOwnerUid(int ownerUid) { 120 mInfo.ownerUid = ownerUid; 121 return this; 122 } setNotch(int height)123 Builder setNotch(int height) { 124 mInfo.displayCutout = new DisplayCutout( 125 Insets.of(0, height, 0, 0), null, new Rect(20, 0, 80, height), null, null); 126 return this; 127 } setCanRotate(boolean canRotate)128 Builder setCanRotate(boolean canRotate) { 129 mCanRotate = canRotate; 130 return this; 131 } setWindowingMode(int windowingMode)132 Builder setWindowingMode(int windowingMode) { 133 mWindowingMode = windowingMode; 134 return this; 135 } setDensityDpi(int dpi)136 Builder setDensityDpi(int dpi) { 137 mInfo.logicalDensityDpi = dpi; 138 return this; 139 } createInternal(Display display)140 TestDisplayContent createInternal(Display display) { 141 return new TestDisplayContent(mService.mRootWindowContainer, display); 142 } build()143 TestDisplayContent build() { 144 SystemServicesTestRule.checkHoldsLock(mService.mGlobalLock); 145 146 final int displayId = SystemServicesTestRule.sNextDisplayId++; 147 final Display display = new Display(DisplayManagerGlobal.getInstance(), displayId, 148 mInfo, DEFAULT_DISPLAY_ADJUSTMENTS); 149 final TestDisplayContent newDisplay = createInternal(display); 150 // disable the normal system decorations 151 final DisplayPolicy displayPolicy = newDisplay.getDisplayPolicy(); 152 spyOn(displayPolicy); 153 if (mSystemDecorations) { 154 doReturn(true).when(newDisplay).supportsSystemDecorations(); 155 doReturn(true).when(displayPolicy).hasNavigationBar(); 156 } else { 157 doReturn(false).when(displayPolicy).hasNavigationBar(); 158 doReturn(false).when(displayPolicy).hasStatusBar(); 159 doReturn(false).when(newDisplay).supportsSystemDecorations(); 160 } 161 Configuration c = new Configuration(); 162 newDisplay.computeScreenConfiguration(c); 163 c.windowConfiguration.setWindowingMode(mWindowingMode); 164 newDisplay.onRequestedOverrideConfigurationChanged(c); 165 if (!mCanRotate) { 166 final DisplayRotation displayRotation = newDisplay.getDisplayRotation(); 167 doReturn(true).when(displayRotation).isFixedToUserRotation(); 168 } 169 // Please add stubbing before this line. Services will start using this display in other 170 // threads immediately after adding it to hierarchy. Calling doAnswer() type of stubbing 171 // reduces chance of races, but still doesn't eliminate race conditions. 172 mService.mRootWindowContainer.addChild(newDisplay, mPosition); 173 174 // Set the default focused TDA. 175 newDisplay.onLastFocusedTaskDisplayAreaChanged(newDisplay.getDefaultTaskDisplayArea()); 176 177 return newDisplay; 178 } 179 } 180 } 181