From 30f5321310bbf7d5fdda21d336afd9f76aecbdfc Mon Sep 17 00:00:00 2001 From: Adrian Roos Date: Fri, 5 Jan 2018 16:14:34 +0100 Subject: [PATCH] DisplayCutout: Move emulation into resource overlay Bug: 65689439 Test: atest PhoneWindowManagerLayoutTest Test: adb shell cmd overlay enable com.android.internal.display.cutout.emulation && adb shell stop && adb shell start Change-Id: I7a319c28da53f78f884556cf176e01321b9c6b55 --- core/res/res/values/config.xml | 5 ++ core/res/res/values/symbols.xml | 1 + .../systemui/EmulatedDisplayCutout.java | 34 ++++++------ .../DisplayCutoutEmulationOverlay/Android.mk | 13 +++++ .../AndroidManifest.xml | 8 +++ .../res/values/config.xml | 44 +++++++++++++++ .../res/values/strings.xml | 24 ++++++++ .../server/display/LocalDisplayAdapter.java | 8 ++- .../server/policy/PhoneWindowManager.java | 11 +--- .../com/android/server/wm/DisplayFrames.java | 55 +------------------ .../policy/PhoneWindowManagerTestBase.java | 33 +++++++++-- 11 files changed, 153 insertions(+), 83 deletions(-) create mode 100644 packages/overlays/DisplayCutoutEmulationOverlay/Android.mk create mode 100644 packages/overlays/DisplayCutoutEmulationOverlay/AndroidManifest.xml create mode 100644 packages/overlays/DisplayCutoutEmulationOverlay/res/values/config.xml create mode 100644 packages/overlays/DisplayCutoutEmulationOverlay/res/values/strings.xml diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 2440e9b431168..699285a693bb2 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -2776,6 +2776,11 @@ the display's native orientation. --> + + false + diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index fb7baf662852e..c5429d82c05ea 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -3199,6 +3199,7 @@ + diff --git a/packages/SystemUI/src/com/android/systemui/EmulatedDisplayCutout.java b/packages/SystemUI/src/com/android/systemui/EmulatedDisplayCutout.java index a1022604c27f7..f41425a1f8483 100644 --- a/packages/SystemUI/src/com/android/systemui/EmulatedDisplayCutout.java +++ b/packages/SystemUI/src/com/android/systemui/EmulatedDisplayCutout.java @@ -38,6 +38,9 @@ import android.view.ViewGroup.LayoutParams; import android.view.WindowInsets; import android.view.WindowManager; +import com.android.systemui.statusbar.policy.ConfigurationController; +import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener; + import java.util.Collections; import java.util.List; @@ -45,18 +48,28 @@ import java.util.List; * Emulates a display cutout by drawing its shape in an overlay as supplied by * {@link DisplayCutout}. */ -public class EmulatedDisplayCutout extends SystemUI { +public class EmulatedDisplayCutout extends SystemUI implements ConfigurationListener { private View mOverlay; private boolean mAttached; private WindowManager mWindowManager; @Override public void start() { + Dependency.get(ConfigurationController.class).addCallback(this); + mWindowManager = mContext.getSystemService(WindowManager.class); - mContext.getContentResolver().registerContentObserver( - Settings.Global.getUriFor(Settings.Global.EMULATE_DISPLAY_CUTOUT), - false, mObserver, UserHandle.USER_ALL); - mObserver.onChange(false); + updateAttached(); + } + + @Override + public void onOverlayChanged() { + updateAttached(); + } + + private void updateAttached() { + boolean shouldAttach = mContext.getResources().getBoolean( + com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout); + setAttached(shouldAttach); } private void setAttached(boolean attached) { @@ -94,17 +107,6 @@ public class EmulatedDisplayCutout extends SystemUI { return lp; } - private ContentObserver mObserver = new ContentObserver(new Handler(Looper.getMainLooper())) { - @Override - public void onChange(boolean selfChange) { - boolean emulateCutout = Settings.Global.getInt( - mContext.getContentResolver(), Settings.Global.EMULATE_DISPLAY_CUTOUT, - Settings.Global.EMULATE_DISPLAY_CUTOUT_OFF) - != Settings.Global.EMULATE_DISPLAY_CUTOUT_OFF; - setAttached(emulateCutout); - } - }; - private static class CutoutView extends View { private final Paint mPaint = new Paint(); private final Path mBounds = new Path(); diff --git a/packages/overlays/DisplayCutoutEmulationOverlay/Android.mk b/packages/overlays/DisplayCutoutEmulationOverlay/Android.mk new file mode 100644 index 0000000000000..f4205ad68a1b7 --- /dev/null +++ b/packages/overlays/DisplayCutoutEmulationOverlay/Android.mk @@ -0,0 +1,13 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_RRO_THEME := DisplayCutoutEmulation +LOCAL_CERTIFICATE := platform + +LOCAL_SRC_FILES := $(call all-subdir-java-files) + +LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res + +LOCAL_PACKAGE_NAME := DisplayCutoutEmulationOverlay + +include $(BUILD_RRO_PACKAGE) diff --git a/packages/overlays/DisplayCutoutEmulationOverlay/AndroidManifest.xml b/packages/overlays/DisplayCutoutEmulationOverlay/AndroidManifest.xml new file mode 100644 index 0000000000000..dd43690949008 --- /dev/null +++ b/packages/overlays/DisplayCutoutEmulationOverlay/AndroidManifest.xml @@ -0,0 +1,8 @@ + + + + + diff --git a/packages/overlays/DisplayCutoutEmulationOverlay/res/values/config.xml b/packages/overlays/DisplayCutoutEmulationOverlay/res/values/config.xml new file mode 100644 index 0000000000000..88c19c7ccf05f --- /dev/null +++ b/packages/overlays/DisplayCutoutEmulationOverlay/res/values/config.xml @@ -0,0 +1,44 @@ + + + + + + + M 687.0,0 + l -66,50 + l 0,50 + l 66,50 + l 66,0 + l 66,-50 + l 0,-50 + l -66,-50 + z + + + + true + + + 150px + + + + diff --git a/packages/overlays/DisplayCutoutEmulationOverlay/res/values/strings.xml b/packages/overlays/DisplayCutoutEmulationOverlay/res/values/strings.xml new file mode 100644 index 0000000000000..5d5c42590b210 --- /dev/null +++ b/packages/overlays/DisplayCutoutEmulationOverlay/res/values/strings.xml @@ -0,0 +1,24 @@ + + + + + Display Cutout Emulation + + + diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java index 483b02c2bf65a..23e4c9bf69cdb 100644 --- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java +++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java @@ -16,6 +16,7 @@ package com.android.server.display; +import android.app.ActivityThread; import android.content.res.Resources; import com.android.server.LocalServices; import com.android.server.lights.Light; @@ -392,7 +393,7 @@ final class LocalDisplayAdapter extends DisplayAdapter { | DisplayDeviceInfo.FLAG_SUPPORTS_PROTECTED_BUFFERS; } - final Resources res = getContext().getResources(); + final Resources res = getOverlayContext().getResources(); if (mBuiltInDisplayId == SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN) { mInfo.name = res.getString( com.android.internal.R.string.display_manager_built_in_display_name); @@ -687,6 +688,11 @@ final class LocalDisplayAdapter extends DisplayAdapter { } } + /** Supplies a context whose Resources apply runtime-overlays */ + Context getOverlayContext() { + return ActivityThread.currentActivityThread().getSystemUiContext(); + } + /** * Keeps track of a display configuration. */ diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 076c0e4d2d4a6..1bbfe2a87a164 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -601,8 +601,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { PointerLocationView mPointerLocationView; - boolean mEmulateDisplayCutout = false; - // During layout, the layer at which the doc window is placed. int mDockLayer; // During layout, this is the layer of the status bar. @@ -955,9 +953,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { resolver.registerContentObserver(Settings.Global.getUriFor( Settings.Global.POLICY_CONTROL), false, this, UserHandle.USER_ALL); - resolver.registerContentObserver(Settings.Global.getUriFor( - Settings.Global.EMULATE_DISPLAY_CUTOUT), false, this, - UserHandle.USER_ALL); updateSettings(); } @@ -2344,10 +2339,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { if (mImmersiveModeConfirmation != null) { mImmersiveModeConfirmation.loadSetting(mCurrentUserId); } - mEmulateDisplayCutout = Settings.Global.getInt(resolver, - Settings.Global.EMULATE_DISPLAY_CUTOUT, - Settings.Global.EMULATE_DISPLAY_CUTOUT_OFF) - != Settings.Global.EMULATE_DISPLAY_CUTOUT_OFF; } synchronized (mWindowManagerFuncs.getWindowManagerLock()) { PolicyControl.reloadFromSetting(mContext); @@ -4382,7 +4373,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { /** {@inheritDoc} */ @Override public void beginLayoutLw(DisplayFrames displayFrames, int uiMode) { - displayFrames.onBeginLayout(mEmulateDisplayCutout, mStatusBarHeight); + displayFrames.onBeginLayout(); // TODO(multi-display): This doesn't seem right...Maybe only apply to default display? mSystemGestures.screenWidth = displayFrames.mUnrestricted.width(); mSystemGestures.screenHeight = displayFrames.mUnrestricted.height(); diff --git a/services/core/java/com/android/server/wm/DisplayFrames.java b/services/core/java/com/android/server/wm/DisplayFrames.java index bd06192b09fde..13d0c86959c7a 100644 --- a/services/core/java/com/android/server/wm/DisplayFrames.java +++ b/services/core/java/com/android/server/wm/DisplayFrames.java @@ -101,7 +101,7 @@ public class DisplayFrames { /** During layout, the current screen borders along which input method windows are placed. */ public final Rect mDock = new Rect(); - /** The display cutout used for layout (after rotation and emulation) */ + /** The display cutout used for layout (after rotation) */ @NonNull public DisplayCutout mDisplayCutout = DisplayCutout.NO_CUTOUT; /** The cutout as supplied by display info */ @@ -134,7 +134,7 @@ public class DisplayFrames { ? info.displayCutout : DisplayCutout.NO_CUTOUT; } - public void onBeginLayout(boolean emulateDisplayCutout, int statusBarHeight) { + public void onBeginLayout() { switch (mRotation) { case ROTATION_90: mRotatedDisplayInfoOverscan.left = mDisplayInfoOverscan.top; @@ -172,12 +172,8 @@ public class DisplayFrames { mStable.set(mUnrestricted); mStableFullscreen.set(mUnrestricted); mCurrent.set(mUnrestricted); - mDisplayCutout = mDisplayInfoCutout; - if (emulateDisplayCutout) { - setEmulatedDisplayCutout((int) (statusBarHeight * 0.8)); - } - mDisplayCutout = mDisplayCutout.calculateRelativeTo(mOverscan); + mDisplayCutout = mDisplayInfoCutout.calculateRelativeTo(mOverscan); mDisplayCutoutSafe.set(Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE); if (!mDisplayCutout.isEmpty()) { @@ -201,51 +197,6 @@ public class DisplayFrames { return mDock.bottom - mCurrent.bottom; } - private void setEmulatedDisplayCutout(int height) { - final boolean swappedDimensions = mRotation == ROTATION_90 || mRotation == ROTATION_270; - - final int screenWidth = swappedDimensions ? mDisplayHeight : mDisplayWidth; - final int screenHeight = swappedDimensions ? mDisplayWidth : mDisplayHeight; - - final int widthTop = (int) (screenWidth * 0.3); - final int widthBottom = widthTop - height; - - switch (mRotation) { - case ROTATION_90: - mDisplayCutout = DisplayCutout.fromBoundingPolygon(Arrays.asList( - new Point(0, (screenWidth - widthTop) / 2), - new Point(height, (screenWidth - widthBottom) / 2), - new Point(height, (screenWidth + widthBottom) / 2), - new Point(0, (screenWidth + widthTop) / 2) - )); - break; - case ROTATION_180: - mDisplayCutout = DisplayCutout.fromBoundingPolygon(Arrays.asList( - new Point((screenWidth - widthTop) / 2, screenHeight), - new Point((screenWidth - widthBottom) / 2, screenHeight - height), - new Point((screenWidth + widthBottom) / 2, screenHeight - height), - new Point((screenWidth + widthTop) / 2, screenHeight) - )); - break; - case ROTATION_270: - mDisplayCutout = DisplayCutout.fromBoundingPolygon(Arrays.asList( - new Point(screenHeight, (screenWidth - widthTop) / 2), - new Point(screenHeight - height, (screenWidth - widthBottom) / 2), - new Point(screenHeight - height, (screenWidth + widthBottom) / 2), - new Point(screenHeight, (screenWidth + widthTop) / 2) - )); - break; - default: - mDisplayCutout = DisplayCutout.fromBoundingPolygon(Arrays.asList( - new Point((screenWidth - widthTop) / 2, 0), - new Point((screenWidth - widthBottom) / 2, height), - new Point((screenWidth + widthBottom) / 2, height), - new Point((screenWidth + widthTop) / 2, 0) - )); - break; - } - } - public void writeToProto(ProtoOutputStream proto, long fieldId) { final long token = proto.start(fieldId); mStable.writeToProto(proto, STABLE_BOUNDS); diff --git a/services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerTestBase.java b/services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerTestBase.java index e7e9abad5bbe1..ad8995325a6a4 100644 --- a/services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerTestBase.java +++ b/services/tests/servicestests/src/com/android/server/policy/PhoneWindowManagerTestBase.java @@ -24,6 +24,8 @@ import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR; import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR; +import static com.android.server.wm.utils.CoordinateTransforms.transformPhysicalToLogicalCoordinates; + import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.mock; @@ -31,6 +33,8 @@ import android.content.Context; import android.content.ContextWrapper; import android.content.pm.PackageManager; import android.content.res.Resources; +import android.graphics.Matrix; +import android.graphics.Path; import android.graphics.PixelFormat; import android.graphics.Rect; import android.os.IBinder; @@ -38,6 +42,7 @@ import android.os.UserHandle; import android.support.test.InstrumentationRegistry; import android.testing.TestableResources; import android.view.Display; +import android.view.DisplayCutout; import android.view.DisplayInfo; import android.view.Gravity; import android.view.View; @@ -65,6 +70,9 @@ public class PhoneWindowManagerTestBase { FakeWindowState mStatusBar; FakeWindowState mNavigationBar; + private boolean mHasDisplayCutout; + private int mRotation = ROTATION_0; + private final Matrix mTmpMatrix = new Matrix(); @Before public void setUpBase() throws Exception { @@ -80,16 +88,32 @@ public class PhoneWindowManagerTestBase { mPolicy = TestablePhoneWindowManager.create(mContext); - setRotation(ROTATION_0); + updateDisplayFrames(); } public void setRotation(int rotation) { + mRotation = rotation; + updateDisplayFrames(); + } + + private void updateDisplayFrames() { DisplayInfo info = new DisplayInfo(); - final boolean flippedDimensions = rotation == ROTATION_90 || rotation == ROTATION_270; + final boolean flippedDimensions = mRotation == ROTATION_90 || mRotation == ROTATION_270; info.logicalWidth = flippedDimensions ? DISPLAY_HEIGHT : DISPLAY_WIDTH; info.logicalHeight = flippedDimensions ? DISPLAY_WIDTH : DISPLAY_HEIGHT; - info.rotation = rotation; + info.rotation = mRotation; + if (mHasDisplayCutout) { + Path p = new Path(); + p.addRect(DISPLAY_WIDTH / 4, 0, DISPLAY_WIDTH * 3 / 4, DISPLAY_CUTOUT_HEIGHT, + Path.Direction.CCW); + transformPhysicalToLogicalCoordinates( + mRotation, DISPLAY_WIDTH, DISPLAY_HEIGHT, mTmpMatrix); + p.transform(mTmpMatrix); + info.displayCutout = DisplayCutout.fromBounds(p); + } else { + info.displayCutout = null; + } mFrames = new DisplayFrames(Display.DEFAULT_DISPLAY, info); } @@ -116,7 +140,8 @@ public class PhoneWindowManagerTestBase { } public void addDisplayCutout() { - mPolicy.mEmulateDisplayCutout = true; + mHasDisplayCutout = true; + updateDisplayFrames(); } /** Asserts that {@code actual} is inset by the given amounts from the full display rect. */