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
This commit is contained in:
Adrian Roos
2018-01-18 17:45:52 +01:00
parent 7d0e1f8065
commit 16693f3466
4 changed files with 79 additions and 22 deletions

View File

@@ -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.
*

View File

@@ -2780,8 +2780,22 @@
<!-- The bounding path of the cutout region of the main built-in display.
Must either be empty if there is no cutout region, or a string that is parsable by
{@link android.util.PathParser}.
The path is assumed to be specified in display coordinates with pixel units and in
the display's native orientation. -->
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:
<string ...>M -5,0 L -5,10 L 5,10 L 5,0 Z</string>
Example for a 10dp x 10dp square top-center cutout:
<string ...>M -5,0 L -5,10 L 5,10 L 5,0 Z @dp</string>
@see https://www.w3.org/TR/SVG/paths.html#PathData
-->
<string translatable="false" name="config_mainBuiltInDisplayCutout"></string>
<!-- Whether the display cutout region of the main built-in display should be forced to

View File

@@ -18,17 +18,26 @@
<!-- The bounding path of the cutout region of the main built-in display.
Must either be empty if there is no cutout region, or a string that is parsable by
{@link android.util.PathParser}. -->
{@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.
-->
<string translatable="false" name="config_mainBuiltInDisplayCutout">
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
</string>
<!-- Whether the display cutout region of the main built-in display should be forced to
@@ -37,7 +46,7 @@
<bool name="config_fillMainBuiltInDisplayCutout">true</bool>
<!-- Height of the status bar -->
<dimen name="status_bar_height">150px</dimen>
<dimen name="status_bar_height">48dp</dimen>
</resources>

View File

@@ -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.