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 8de3a98a3585a..f084159b3f58a 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 fc3c1f74ce4f4..b7385d85d2961 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.