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.