From 16693f3466108de69db77ae6dc7b73cc74102bc6 Mon Sep 17 00:00:00 2001 From: Adrian Roos Date: Thu, 18 Jan 2018 17:45:52 +0100 Subject: [PATCH] DisplayCutout: device-independent emulation overlay Adds an option to use dp instead of px when specifying the cutout bounds. Also centers the coordinate system in the middle, making it easier to specify the usually centered cutouts. Also makes the emulated cutout a bit prettier. Bug: 65689439 Test: adb shell overlay enable com.android.display.cutout.emulation Change-Id: I3bd16af15f1dad2af204d436abaa35fb9e5ae146 --- core/java/android/view/DisplayCutout.java | 43 +++++++++++++++++++ core/res/res/values/config.xml | 16 ++++++- .../res/values/config.xml | 31 ++++++++----- .../server/display/LocalDisplayAdapter.java | 11 +---- 4 files changed, 79 insertions(+), 22 deletions(-) diff --git a/core/java/android/view/DisplayCutout.java b/core/java/android/view/DisplayCutout.java index 1ef5f0950b16f..a61c8c1dba684 100644 --- a/core/java/android/view/DisplayCutout.java +++ b/core/java/android/view/DisplayCutout.java @@ -23,6 +23,8 @@ import static android.view.Surface.ROTATION_180; import static android.view.Surface.ROTATION_270; import static android.view.Surface.ROTATION_90; +import android.content.res.Resources; +import android.graphics.Matrix; import android.graphics.Path; import android.graphics.Point; import android.graphics.Rect; @@ -30,8 +32,12 @@ import android.graphics.RectF; import android.graphics.Region; import android.os.Parcel; import android.os.Parcelable; +import android.text.TextUtils; +import android.util.Log; +import android.util.PathParser; import android.util.proto.ProtoOutputStream; +import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import java.util.List; @@ -43,6 +49,9 @@ import java.util.List; */ public final class DisplayCutout { + private static final String TAG = "DisplayCutout"; + private static final String DP_MARKER = "@dp"; + private static final Rect ZERO_RECT = new Rect(); private static final Region EMPTY_REGION = new Region(); @@ -311,6 +320,40 @@ public final class DisplayCutout { return new DisplayCutout(ZERO_RECT, bounds); } + /** + * Creates an instance according to @android:string/config_mainBuiltInDisplayCutout. + * + * @hide + */ + public static DisplayCutout fromResources(Resources res, int displayWidth) { + String spec = res.getString(R.string.config_mainBuiltInDisplayCutout); + if (TextUtils.isEmpty(spec)) { + return null; + } + spec = spec.trim(); + final boolean inDp = spec.endsWith(DP_MARKER); + if (inDp) { + spec = spec.substring(0, spec.length() - DP_MARKER.length()); + } + + Path p; + try { + p = PathParser.createPathFromPathData(spec); + } catch (Throwable e) { + Log.wtf(TAG, "Could not inflate cutout: ", e); + return null; + } + + final Matrix m = new Matrix(); + if (inDp) { + final float dpToPx = res.getDisplayMetrics().density; + m.postScale(dpToPx, dpToPx); + } + m.postTranslate(displayWidth / 2f, 0); + p.transform(m); + return fromBounds(p); + } + /** * Helper class for passing {@link DisplayCutout} through binder. * diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index e3a910f5cc767..15de0f8428390 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -2780,8 +2780,22 @@ + the display's native orientation, with the origin of the coordinate system at the + center top of the display. + + To facilitate writing device-independent emulation overlays, the marker `@dp` can be + appended after the path string to interpret coordinates in dp instead of px units. + Note that a physical cutout should be configured in pixels for the best results. + + Example for a 10px x 10px square top-center cutout: + M -5,0 L -5,10 L 5,10 L 5,0 Z + Example for a 10dp x 10dp square top-center cutout: + M -5,0 L -5,10 L 5,10 L 5,0 Z @dp + + @see https://www.w3.org/TR/SVG/paths.html#PathData + --> + {@link android.util.PathParser}. + + The path is assumed to be specified in display coordinates with pixel units and in + the display's native orientation, with the origin of the coordinate system at the + center top of the display. + + To facilitate writing device-independent emulation overlays, the marker `@dp` can be + appended after the path string to interpret coordinates in dp instead of px units. + Note that a physical cutout should be configured in pixels for the best results. + --> - 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 + M 0,0 + L -24, 0 + L -21.9940446283, 20.0595537175 + C -21.1582133885, 28.4178661152 -17.2, 32.0 -8.8, 32.0 + L 8.8, 32.0 + C 17.2, 32.0 21.1582133885, 28.4178661152 21.9940446283, 20.0595537175 + L 24, 0 + Z + @dp - 150px + 48dp diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java index 23e4c9bf69cdb..47904e2f66225 100644 --- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java +++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java @@ -404,7 +404,7 @@ final class LocalDisplayAdapter extends DisplayAdapter { && SystemProperties.getBoolean(PROPERTY_EMULATOR_CIRCULAR, false))) { mInfo.flags |= DisplayDeviceInfo.FLAG_ROUND; } - mInfo.displayCutout = parseDefaultDisplayCutout(res); + mInfo.displayCutout = DisplayCutout.fromResources(res, mInfo.width); mInfo.type = Display.TYPE_BUILT_IN; mInfo.densityDpi = (int)(phys.density * 160 + 0.5f); mInfo.xDpi = phys.xDpi; @@ -440,15 +440,6 @@ final class LocalDisplayAdapter extends DisplayAdapter { return mInfo; } - private DisplayCutout parseDefaultDisplayCutout(Resources res) { - String cutoutString = res.getString( - com.android.internal.R.string.config_mainBuiltInDisplayCutout); - if (TextUtils.isEmpty(cutoutString)) { - return null; - } - return DisplayCutout.fromBounds(PathParser.createPathFromPathData(cutoutString)); - } - @Override public Runnable requestDisplayStateLocked(final int state, final int brightness) { // Assume that the brightness is off if the display is being turned off.