Merge "Update WM display info when nonOverrideDisplayInfo changes"

This commit is contained in:
Shawn Lin
2020-09-02 08:21:15 +00:00
committed by Android (Google) Code Review
2 changed files with 123 additions and 4 deletions

View File

@@ -284,6 +284,7 @@ public final class DisplayManagerService extends SystemService {
// Temporary display info, used for comparing display configurations.
private final DisplayInfo mTempDisplayInfo = new DisplayInfo();
private final DisplayInfo mTempNonOverrideDisplayInfo = new DisplayInfo();
// Temporary viewports, used when sending new viewport information to the
// input system. May be used outside of the lock but only on the handler thread.
@@ -508,7 +509,8 @@ public final class DisplayManagerService extends SystemService {
mDisplayTransactionListeners.remove(listener);
}
private void setDisplayInfoOverrideFromWindowManagerInternal(
@VisibleForTesting
void setDisplayInfoOverrideFromWindowManagerInternal(
int displayId, DisplayInfo info) {
synchronized (mSyncRoot) {
LogicalDisplay display = mLogicalDisplays.get(displayId);
@@ -936,7 +938,8 @@ public final class DisplayManagerService extends SystemService {
adapter.registerLocked();
}
private void handleDisplayDeviceAdded(DisplayDevice device) {
@VisibleForTesting
void handleDisplayDeviceAdded(DisplayDevice device) {
synchronized (mSyncRoot) {
handleDisplayDeviceAddedLocked(device);
}
@@ -948,7 +951,6 @@ public final class DisplayManagerService extends SystemService {
Slog.w(TAG, "Attempted to add already added display device: " + info);
return;
}
Slog.i(TAG, "Display device added: " + info);
device.mDebugLastLoggedDeviceInfo = info;
@@ -961,7 +963,8 @@ public final class DisplayManagerService extends SystemService {
scheduleTraversalLocked(false);
}
private void handleDisplayDeviceChanged(DisplayDevice device) {
@VisibleForTesting
void handleDisplayDeviceChanged(DisplayDevice device) {
synchronized (mSyncRoot) {
DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
if (!mDisplayDevices.contains(device)) {
@@ -1235,6 +1238,7 @@ public final class DisplayManagerService extends SystemService {
LogicalDisplay display = mLogicalDisplays.valueAt(i);
mTempDisplayInfo.copyFrom(display.getDisplayInfoLocked());
display.getNonOverrideDisplayInfoLocked(mTempNonOverrideDisplayInfo);
display.updateLocked(mDisplayDevices);
if (!display.isValidLocked()) {
mLogicalDisplays.removeAt(i);
@@ -1243,6 +1247,15 @@ public final class DisplayManagerService extends SystemService {
} else if (!mTempDisplayInfo.equals(display.getDisplayInfoLocked())) {
handleLogicalDisplayChanged(displayId, display);
changed = true;
} else {
// While applications shouldn't know nor care about the non-overridden info, we
// still need to let WindowManager know so it can update its own internal state for
// things like display cutouts.
display.getNonOverrideDisplayInfoLocked(mTempDisplayInfo);
if (!mTempNonOverrideDisplayInfo.equals(mTempDisplayInfo)) {
handleLogicalDisplayChanged(displayId, display);
changed = true;
}
}
}
return changed;

View File

@@ -19,6 +19,7 @@ package com.android.server.display;
import static com.android.server.display.VirtualDisplayAdapter.UNIQUE_ID_PREFIX;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -28,18 +29,23 @@ import static org.mockito.Mockito.when;
import android.app.PropertyInvalidatedCache;
import android.content.Context;
import android.graphics.Insets;
import android.graphics.Rect;
import android.hardware.display.BrightnessConfiguration;
import android.hardware.display.Curve;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManagerGlobal;
import android.hardware.display.DisplayViewport;
import android.hardware.display.DisplayedContentSample;
import android.hardware.display.DisplayedContentSamplingAttributes;
import android.hardware.display.IDisplayManagerCallback;
import android.hardware.display.IVirtualDisplayCallback;
import android.hardware.display.VirtualDisplayConfig;
import android.hardware.input.InputManagerInternal;
import android.os.Handler;
import android.os.IBinder;
import android.view.Display;
import android.view.DisplayCutout;
import android.view.DisplayInfo;
import android.view.Surface;
import android.view.SurfaceControl;
@@ -281,6 +287,68 @@ public class DisplayManagerServiceTest {
displayManager.onBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
}
/**
* Tests that there should be a display change notification to WindowManager to update its own
* internal state for things like display cutout when nonOverrideDisplayInfo is changed.
*/
@Test
public void testShouldNotifyChangeWhenNonOverrideDisplayInfoChanged() throws Exception {
DisplayManagerService displayManager =
new DisplayManagerService(mContext, mShortMockedInjector);
registerDefaultDisplays(displayManager);
displayManager.onBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
// Add the FakeDisplayDevice
FakeDisplayDevice displayDevice = new FakeDisplayDevice();
DisplayDeviceInfo displayDeviceInfo = new DisplayDeviceInfo();
displayDeviceInfo.width = 100;
displayDeviceInfo.height = 200;
final Rect zeroRect = new Rect();
displayDeviceInfo.displayCutout = new DisplayCutout(
Insets.of(0, 10, 0, 0),
zeroRect, new Rect(0, 0, 10, 10), zeroRect, zeroRect);
displayDeviceInfo.flags = DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY;
displayDevice.setDisplayDeviceInfo(displayDeviceInfo);
displayManager.handleDisplayDeviceAdded(displayDevice);
// Find the display id of the added FakeDisplayDevice
DisplayManagerService.BinderService bs = displayManager.new BinderService();
final int[] displayIds = bs.getDisplayIds();
assertTrue(displayIds.length > 0);
int displayId = Display.INVALID_DISPLAY;
for (int i = 0; i < displayIds.length; i++) {
DisplayDeviceInfo ddi = displayManager.getDisplayDeviceInfoInternal(displayIds[i]);
if (displayDeviceInfo.equals(ddi)) {
displayId = displayIds[i];
break;
}
}
assertFalse(displayId == Display.INVALID_DISPLAY);
// Setup override DisplayInfo
DisplayInfo overrideInfo = bs.getDisplayInfo(displayId);
displayManager.setDisplayInfoOverrideFromWindowManagerInternal(displayId, overrideInfo);
Handler handler = displayManager.getDisplayHandler();
handler.runWithScissors(() -> {
}, 0 /* now */);
// register display listener callback
FakeDisplayManagerCallback callback = new FakeDisplayManagerCallback(displayId);
bs.registerCallback(callback);
// Simulate DisplayDevice change
DisplayDeviceInfo displayDeviceInfo2 = new DisplayDeviceInfo();
displayDeviceInfo2.copyFrom(displayDeviceInfo);
displayDeviceInfo2.displayCutout = null;
displayDevice.setDisplayDeviceInfo(displayDeviceInfo2);
displayManager.handleDisplayDeviceChanged(displayDevice);
handler.runWithScissors(() -> {
}, 0 /* now */);
assertTrue(callback.mCalled);
}
/**
* Tests that we get a Runtime exception when we cannot initialize the default display.
*/
@@ -512,4 +580,42 @@ public class DisplayManagerServiceTest {
// flush the handler
handler.runWithScissors(() -> {}, 0 /* now */);
}
private class FakeDisplayManagerCallback extends IDisplayManagerCallback.Stub {
int mDisplayId;
boolean mCalled = false;
FakeDisplayManagerCallback(int displayId) {
mDisplayId = displayId;
}
@Override
public void onDisplayEvent(int displayId, int event) {
if (displayId == mDisplayId && event == DisplayManagerGlobal.EVENT_DISPLAY_CHANGED) {
mCalled = true;
}
}
}
private class FakeDisplayDevice extends DisplayDevice {
private DisplayDeviceInfo mDisplayDeviceInfo;
FakeDisplayDevice() {
super(null, null, "");
}
public void setDisplayDeviceInfo(DisplayDeviceInfo displayDeviceInfo) {
mDisplayDeviceInfo = displayDeviceInfo;
}
@Override
public boolean hasStableUniqueId() {
return false;
}
@Override
public DisplayDeviceInfo getDisplayDeviceInfoLocked() {
return mDisplayDeviceInfo;
}
}
}