blob: ae85ceb729587ade74f7d4568d0c417a52ecf991 [file] [log] [blame]
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.wm;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
import static org.mockito.ArgumentMatchers.any;
import android.content.res.Configuration;
import android.graphics.Insets;
import android.graphics.Rect;
import android.hardware.display.DisplayManagerGlobal;
import android.view.Display;
import android.view.DisplayCutout;
import android.view.DisplayInfo;
class TestDisplayContent extends DisplayContent {
/** Please use the {@link Builder} to create, visible for use in test builder overrides only. */
TestDisplayContent(RootWindowContainer rootWindowContainer, Display display) {
super(display, rootWindowContainer);
// Normally this comes from display-properties as exposed by WM. Without that, just
// hard-code to FULLSCREEN for tests.
setWindowingMode(WINDOWING_MODE_FULLSCREEN);
spyOn(this);
forAllTaskDisplayAreas(taskDisplayArea -> {
spyOn(taskDisplayArea);
});
final DisplayRotation displayRotation = getDisplayRotation();
spyOn(displayRotation);
doAnswer(invocation -> {
// Bypass all the rotation animation and display freezing stuff for testing and just
// set the rotation we want for the display
final int oldRotation = displayRotation.getRotation();
final int rotation = displayRotation.rotationForOrientation(
displayRotation.getLastOrientation(), oldRotation);
if (oldRotation == rotation) {
return false;
}
setLayoutNeeded();
displayRotation.setRotation(rotation);
return true;
}).when(displayRotation).updateRotationUnchecked(anyBoolean());
final InputMonitor inputMonitor = getInputMonitor();
spyOn(inputMonitor);
doNothing().when(inputMonitor).resumeDispatchingLw(any());
}
public static class Builder {
private final DisplayInfo mInfo;
private boolean mCanRotate = true;
private int mWindowingMode = WINDOWING_MODE_FULLSCREEN;
private int mPosition = POSITION_BOTTOM;
protected final ActivityTaskManagerService mService;
private boolean mSystemDecorations = false;
Builder(ActivityTaskManagerService service, int width, int height) {
mService = service;
mInfo = new DisplayInfo();
mService.mContext.getDisplay().getDisplayInfo(mInfo);
mInfo.logicalWidth = width;
mInfo.logicalHeight = height;
mInfo.logicalDensityDpi = 300;
mInfo.displayCutout = null;
}
Builder(ActivityTaskManagerService service, DisplayInfo info) {
mService = service;
mInfo = info;
}
Builder setSystemDecorations(boolean yes) {
mSystemDecorations = yes;
return this;
}
Builder setPosition(int position) {
mPosition = position;
return this;
}
Builder setUniqueId(String uniqueId) {
mInfo.uniqueId = uniqueId;
return this;
}
Builder setType(int type) {
mInfo.type = type;
return this;
}
Builder setOwnerUid(int ownerUid) {
mInfo.ownerUid = ownerUid;
return this;
}
Builder setNotch(int height) {
mInfo.displayCutout = new DisplayCutout(
Insets.of(0, height, 0, 0), null, new Rect(20, 0, 80, height), null, null);
return this;
}
Builder setCanRotate(boolean canRotate) {
mCanRotate = canRotate;
return this;
}
Builder setWindowingMode(int windowingMode) {
mWindowingMode = windowingMode;
return this;
}
Builder setDensityDpi(int dpi) {
mInfo.logicalDensityDpi = dpi;
return this;
}
TestDisplayContent createInternal(Display display) {
return new TestDisplayContent(mService.mRootWindowContainer, display);
}
TestDisplayContent build() {
SystemServicesTestRule.checkHoldsLock(mService.mGlobalLock);
final int displayId = SystemServicesTestRule.sNextDisplayId++;
final Display display = new Display(DisplayManagerGlobal.getInstance(), displayId,
mInfo, DEFAULT_DISPLAY_ADJUSTMENTS);
final TestDisplayContent newDisplay = createInternal(display);
// disable the normal system decorations
final DisplayPolicy displayPolicy = newDisplay.getDisplayPolicy();
spyOn(displayPolicy);
if (mSystemDecorations) {
doReturn(true).when(newDisplay).supportsSystemDecorations();
doReturn(true).when(displayPolicy).hasNavigationBar();
} else {
doReturn(false).when(displayPolicy).hasNavigationBar();
doReturn(false).when(displayPolicy).hasStatusBar();
doReturn(false).when(newDisplay).supportsSystemDecorations();
}
Configuration c = new Configuration();
newDisplay.computeScreenConfiguration(c);
c.windowConfiguration.setWindowingMode(mWindowingMode);
newDisplay.onRequestedOverrideConfigurationChanged(c);
if (!mCanRotate) {
final DisplayRotation displayRotation = newDisplay.getDisplayRotation();
doReturn(true).when(displayRotation).isFixedToUserRotation();
}
// Please add stubbing before this line. Services will start using this display in other
// threads immediately after adding it to hierarchy. Calling doAnswer() type of stubbing
// reduces chance of races, but still doesn't eliminate race conditions.
mService.mRootWindowContainer.addChild(newDisplay, mPosition);
// Set the default focused TDA.
newDisplay.onLastFocusedTaskDisplayAreaChanged(newDisplay.getDefaultTaskDisplayArea());
return newDisplay;
}
}
}