Merge "Make DisplayCutout support waterfall insets"
This commit is contained in:
@@ -50525,6 +50525,7 @@ package android.view {
|
||||
|
||||
public final class DisplayCutout {
|
||||
ctor public DisplayCutout(@NonNull android.graphics.Insets, @Nullable android.graphics.Rect, @Nullable android.graphics.Rect, @Nullable android.graphics.Rect, @Nullable android.graphics.Rect);
|
||||
ctor public DisplayCutout(@NonNull android.graphics.Insets, @Nullable android.graphics.Rect, @Nullable android.graphics.Rect, @Nullable android.graphics.Rect, @Nullable android.graphics.Rect, @NonNull android.graphics.Insets);
|
||||
ctor @Deprecated public DisplayCutout(@Nullable android.graphics.Rect, @Nullable java.util.List<android.graphics.Rect>);
|
||||
method @NonNull public android.graphics.Rect getBoundingRectBottom();
|
||||
method @NonNull public android.graphics.Rect getBoundingRectLeft();
|
||||
@@ -50535,6 +50536,7 @@ package android.view {
|
||||
method public int getSafeInsetLeft();
|
||||
method public int getSafeInsetRight();
|
||||
method public int getSafeInsetTop();
|
||||
method @NonNull public android.graphics.Insets getWaterfallInsets();
|
||||
}
|
||||
|
||||
public final class DragAndDropPermissions implements android.os.Parcelable {
|
||||
|
||||
@@ -86,7 +86,7 @@ public final class DisplayCutout {
|
||||
* @hide
|
||||
*/
|
||||
public static final DisplayCutout NO_CUTOUT = new DisplayCutout(
|
||||
ZERO_RECT, ZERO_RECT, ZERO_RECT, ZERO_RECT, ZERO_RECT,
|
||||
ZERO_RECT, Insets.NONE, ZERO_RECT, ZERO_RECT, ZERO_RECT, ZERO_RECT,
|
||||
false /* copyArguments */);
|
||||
|
||||
|
||||
@@ -103,8 +103,12 @@ public final class DisplayCutout {
|
||||
private static float sCachedDensity;
|
||||
@GuardedBy("CACHE_LOCK")
|
||||
private static Pair<Path, DisplayCutout> sCachedCutout = NULL_PAIR;
|
||||
@GuardedBy("CACHE_LOCK")
|
||||
private static Insets sCachedWaterfallInsets;
|
||||
|
||||
private final Rect mSafeInsets;
|
||||
@NonNull
|
||||
private final Insets mWaterfallInsets;
|
||||
|
||||
|
||||
/**
|
||||
@@ -251,7 +255,32 @@ public final class DisplayCutout {
|
||||
// TODO(b/73953958): @VisibleForTesting(visibility = PRIVATE)
|
||||
public DisplayCutout(@NonNull Insets safeInsets, @Nullable Rect boundLeft,
|
||||
@Nullable Rect boundTop, @Nullable Rect boundRight, @Nullable Rect boundBottom) {
|
||||
this(safeInsets.toRect(), boundLeft, boundTop, boundRight, boundBottom, true);
|
||||
this(safeInsets.toRect(), Insets.NONE, boundLeft, boundTop, boundRight, boundBottom, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a DisplayCutout instance.
|
||||
*
|
||||
* <p>Note that this is only useful for tests. For production code, developers should always
|
||||
* use a {@link DisplayCutout} obtained from the system.</p>
|
||||
*
|
||||
* @param safeInsets the insets from each edge which avoid the display cutout as returned by
|
||||
* {@link #getSafeInsetTop()} etc.
|
||||
* @param boundLeft the left bounding rect of the display cutout in pixels. If null is passed,
|
||||
* it's treated as an empty rectangle (0,0)-(0,0).
|
||||
* @param boundTop the top bounding rect of the display cutout in pixels. If null is passed,
|
||||
* it's treated as an empty rectangle (0,0)-(0,0).
|
||||
* @param boundRight the right bounding rect of the display cutout in pixels. If null is
|
||||
* passed, it's treated as an empty rectangle (0,0)-(0,0).
|
||||
* @param boundBottom the bottom bounding rect of the display cutout in pixels. If null is
|
||||
* passed, it's treated as an empty rectangle (0,0)-(0,0).
|
||||
* @param waterfallInsets the insets for the curved areas in waterfall display.
|
||||
*/
|
||||
public DisplayCutout(@NonNull Insets safeInsets, @Nullable Rect boundLeft,
|
||||
@Nullable Rect boundTop, @Nullable Rect boundRight, @Nullable Rect boundBottom,
|
||||
@NonNull Insets waterfallInsets) {
|
||||
this(safeInsets.toRect(), waterfallInsets, boundLeft, boundTop, boundRight, boundBottom,
|
||||
true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -269,7 +298,7 @@ public final class DisplayCutout {
|
||||
// TODO(b/73953958): @VisibleForTesting(visibility = PRIVATE)
|
||||
@Deprecated
|
||||
public DisplayCutout(@Nullable Rect safeInsets, @Nullable List<Rect> boundingRects) {
|
||||
this(safeInsets, extractBoundsFromList(safeInsets, boundingRects),
|
||||
this(safeInsets, Insets.NONE, extractBoundsFromList(safeInsets, boundingRects),
|
||||
true /* copyArguments */);
|
||||
}
|
||||
|
||||
@@ -281,19 +310,23 @@ public final class DisplayCutout {
|
||||
* @param copyArguments if true, create a copy of the arguments. If false, the passed arguments
|
||||
* are not copied and MUST remain unchanged forever.
|
||||
*/
|
||||
private DisplayCutout(Rect safeInsets, Rect boundLeft, Rect boundTop, Rect boundRight,
|
||||
Rect boundBottom, boolean copyArguments) {
|
||||
private DisplayCutout(Rect safeInsets, Insets waterfallInsets, Rect boundLeft,
|
||||
Rect boundTop, Rect boundRight, Rect boundBottom, boolean copyArguments) {
|
||||
mSafeInsets = getCopyOrRef(safeInsets, copyArguments);
|
||||
mWaterfallInsets = waterfallInsets == null ? Insets.NONE : waterfallInsets;
|
||||
mBounds = new Bounds(boundLeft, boundTop, boundRight, boundBottom, copyArguments);
|
||||
}
|
||||
|
||||
private DisplayCutout(Rect safeInsets, Rect[] bounds, boolean copyArguments) {
|
||||
private DisplayCutout(Rect safeInsets, Insets waterfallInsets, Rect[] bounds,
|
||||
boolean copyArguments) {
|
||||
mSafeInsets = getCopyOrRef(safeInsets, copyArguments);
|
||||
mWaterfallInsets = waterfallInsets == null ? Insets.NONE : waterfallInsets;
|
||||
mBounds = new Bounds(bounds, copyArguments);
|
||||
}
|
||||
|
||||
private DisplayCutout(Rect safeInsets, Bounds bounds) {
|
||||
private DisplayCutout(Rect safeInsets, Insets waterfallInsets, Bounds bounds) {
|
||||
mSafeInsets = safeInsets;
|
||||
mWaterfallInsets = waterfallInsets == null ? Insets.NONE : waterfallInsets;
|
||||
mBounds = bounds;
|
||||
|
||||
}
|
||||
@@ -308,6 +341,14 @@ public final class DisplayCutout {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the waterfall insets.
|
||||
*/
|
||||
public @NonNull Insets getWaterfallInsets() {
|
||||
return mWaterfallInsets;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Find the position of the bounding rect, and create an array of Rect whose index represents
|
||||
* the position (= BoundsPosition).
|
||||
@@ -476,7 +517,8 @@ public final class DisplayCutout {
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return mSafeInsets.hashCode() * 48271 + mBounds.hashCode();
|
||||
return (mSafeInsets.hashCode() * 48271 + mBounds.hashCode()) * 48271
|
||||
+ mWaterfallInsets.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -486,7 +528,8 @@ public final class DisplayCutout {
|
||||
}
|
||||
if (o instanceof DisplayCutout) {
|
||||
DisplayCutout c = (DisplayCutout) o;
|
||||
return mSafeInsets.equals(c.mSafeInsets) && mBounds.equals(c.mBounds);
|
||||
return mSafeInsets.equals(c.mSafeInsets) && mBounds.equals(c.mBounds)
|
||||
&& mWaterfallInsets.equals(c.mWaterfallInsets);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -494,6 +537,7 @@ public final class DisplayCutout {
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DisplayCutout{insets=" + mSafeInsets
|
||||
+ " waterfall=" + mWaterfallInsets
|
||||
+ " boundingRect={" + mBounds + "}"
|
||||
+ "}";
|
||||
}
|
||||
@@ -508,6 +552,7 @@ public final class DisplayCutout {
|
||||
mBounds.getRect(BOUNDS_POSITION_TOP).dumpDebug(proto, BOUND_TOP);
|
||||
mBounds.getRect(BOUNDS_POSITION_RIGHT).dumpDebug(proto, BOUND_RIGHT);
|
||||
mBounds.getRect(BOUNDS_POSITION_BOTTOM).dumpDebug(proto, BOUND_BOTTOM);
|
||||
mWaterfallInsets.toRect().dumpDebug(proto, INSETS);
|
||||
proto.end(token);
|
||||
}
|
||||
|
||||
@@ -553,7 +598,7 @@ public final class DisplayCutout {
|
||||
}
|
||||
}
|
||||
|
||||
return new DisplayCutout(safeInsets, bounds, false /* copyArguments */);
|
||||
return new DisplayCutout(safeInsets, mWaterfallInsets, bounds, false /* copyArguments */);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -565,7 +610,7 @@ public final class DisplayCutout {
|
||||
* @hide
|
||||
*/
|
||||
public DisplayCutout replaceSafeInsets(Rect safeInsets) {
|
||||
return new DisplayCutout(new Rect(safeInsets), mBounds);
|
||||
return new DisplayCutout(new Rect(safeInsets), mWaterfallInsets, mBounds);
|
||||
}
|
||||
|
||||
private static int atLeastZero(int value) {
|
||||
@@ -585,7 +630,16 @@ public final class DisplayCutout {
|
||||
for (int i = 0; i < BOUNDS_POSITION_LENGTH; ++i) {
|
||||
bounds[i] = (pos == i) ? new Rect(left, top, right, bottom) : new Rect();
|
||||
}
|
||||
return new DisplayCutout(ZERO_RECT, bounds, false /* copyArguments */);
|
||||
return new DisplayCutout(ZERO_RECT, Insets.NONE, bounds, false /* copyArguments */);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance from a bounding and waterfall insets.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public static DisplayCutout fromBoundsAndWaterfall(Rect[] bounds, Insets waterfallInsets) {
|
||||
return new DisplayCutout(ZERO_RECT, waterfallInsets, bounds, false /* copyArguments */);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -594,7 +648,7 @@ public final class DisplayCutout {
|
||||
* @hide
|
||||
*/
|
||||
public static DisplayCutout fromBounds(Rect[] bounds) {
|
||||
return new DisplayCutout(ZERO_RECT, bounds, false /* copyArguments */);
|
||||
return new DisplayCutout(ZERO_RECT, Insets.NONE, bounds, false /* copyArguments */);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -606,7 +660,8 @@ public final class DisplayCutout {
|
||||
*/
|
||||
public static DisplayCutout fromResourcesRectApproximation(Resources res, int displayWidth, int displayHeight) {
|
||||
return fromSpec(res.getString(R.string.config_mainBuiltInDisplayCutoutRectApproximation),
|
||||
displayWidth, displayHeight, DENSITY_DEVICE_STABLE / (float) DENSITY_DEFAULT);
|
||||
displayWidth, displayHeight, DENSITY_DEVICE_STABLE / (float) DENSITY_DEFAULT,
|
||||
loadWaterfallInset(res));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -617,7 +672,8 @@ public final class DisplayCutout {
|
||||
public static Path pathFromResources(Resources res, int displayWidth, int displayHeight) {
|
||||
return pathAndDisplayCutoutFromSpec(
|
||||
res.getString(R.string.config_mainBuiltInDisplayCutout),
|
||||
displayWidth, displayHeight, DENSITY_DEVICE_STABLE / (float) DENSITY_DEFAULT).first;
|
||||
displayWidth, displayHeight, DENSITY_DEVICE_STABLE / (float) DENSITY_DEFAULT,
|
||||
loadWaterfallInset(res)).first;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -627,91 +683,109 @@ public final class DisplayCutout {
|
||||
*/
|
||||
@VisibleForTesting(visibility = PRIVATE)
|
||||
public static DisplayCutout fromSpec(String spec, int displayWidth, int displayHeight,
|
||||
float density) {
|
||||
return pathAndDisplayCutoutFromSpec(spec, displayWidth, displayHeight, density).second;
|
||||
float density, Insets waterfallInsets) {
|
||||
return pathAndDisplayCutoutFromSpec(
|
||||
spec, displayWidth, displayHeight, density, waterfallInsets).second;
|
||||
}
|
||||
|
||||
private static Pair<Path, DisplayCutout> pathAndDisplayCutoutFromSpec(String spec,
|
||||
int displayWidth, int displayHeight, float density) {
|
||||
if (TextUtils.isEmpty(spec)) {
|
||||
int displayWidth, int displayHeight, float density, Insets waterfallInsets) {
|
||||
if (TextUtils.isEmpty(spec) && waterfallInsets.equals(Insets.NONE)) {
|
||||
return NULL_PAIR;
|
||||
}
|
||||
|
||||
synchronized (CACHE_LOCK) {
|
||||
if (spec.equals(sCachedSpec) && sCachedDisplayWidth == displayWidth
|
||||
&& sCachedDisplayHeight == displayHeight
|
||||
&& sCachedDensity == density) {
|
||||
&& sCachedDensity == density
|
||||
&& waterfallInsets.equals(sCachedWaterfallInsets)) {
|
||||
return sCachedCutout;
|
||||
}
|
||||
}
|
||||
spec = spec.trim();
|
||||
final float offsetX;
|
||||
if (spec.endsWith(RIGHT_MARKER)) {
|
||||
offsetX = displayWidth;
|
||||
spec = spec.substring(0, spec.length() - RIGHT_MARKER.length()).trim();
|
||||
} else if (spec.endsWith(LEFT_MARKER)) {
|
||||
offsetX = 0;
|
||||
spec = spec.substring(0, spec.length() - LEFT_MARKER.length()).trim();
|
||||
} else {
|
||||
offsetX = displayWidth / 2f;
|
||||
}
|
||||
final boolean inDp = spec.endsWith(DP_MARKER);
|
||||
if (inDp) {
|
||||
spec = spec.substring(0, spec.length() - DP_MARKER.length());
|
||||
}
|
||||
|
||||
String bottomSpec = null;
|
||||
if (spec.contains(BOTTOM_MARKER)) {
|
||||
String[] splits = spec.split(BOTTOM_MARKER, 2);
|
||||
spec = splits[0].trim();
|
||||
bottomSpec = splits[1].trim();
|
||||
}
|
||||
|
||||
final Path p;
|
||||
final Region r = Region.obtain();
|
||||
try {
|
||||
p = PathParser.createPathFromPathData(spec);
|
||||
} catch (Throwable e) {
|
||||
Log.wtf(TAG, "Could not inflate cutout: ", e);
|
||||
return NULL_PAIR;
|
||||
}
|
||||
|
||||
final Matrix m = new Matrix();
|
||||
if (inDp) {
|
||||
m.postScale(density, density);
|
||||
}
|
||||
m.postTranslate(offsetX, 0);
|
||||
p.transform(m);
|
||||
|
||||
Rect boundTop = new Rect();
|
||||
toRectAndAddToRegion(p, r, boundTop);
|
||||
final int topInset = boundTop.bottom;
|
||||
|
||||
Path p = null;
|
||||
Rect boundTop = null;
|
||||
Rect boundBottom = null;
|
||||
final int bottomInset;
|
||||
if (bottomSpec != null) {
|
||||
final Path bottomPath;
|
||||
try {
|
||||
bottomPath = PathParser.createPathFromPathData(bottomSpec);
|
||||
} catch (Throwable e) {
|
||||
Log.wtf(TAG, "Could not inflate bottom cutout: ", e);
|
||||
return NULL_PAIR;
|
||||
Rect safeInset = new Rect();
|
||||
String bottomSpec = null;
|
||||
if (!TextUtils.isEmpty(spec)) {
|
||||
spec = spec.trim();
|
||||
final float offsetX;
|
||||
if (spec.endsWith(RIGHT_MARKER)) {
|
||||
offsetX = displayWidth;
|
||||
spec = spec.substring(0, spec.length() - RIGHT_MARKER.length()).trim();
|
||||
} else if (spec.endsWith(LEFT_MARKER)) {
|
||||
offsetX = 0;
|
||||
spec = spec.substring(0, spec.length() - LEFT_MARKER.length()).trim();
|
||||
} else {
|
||||
offsetX = displayWidth / 2f;
|
||||
}
|
||||
final boolean inDp = spec.endsWith(DP_MARKER);
|
||||
if (inDp) {
|
||||
spec = spec.substring(0, spec.length() - DP_MARKER.length());
|
||||
}
|
||||
|
||||
if (spec.contains(BOTTOM_MARKER)) {
|
||||
String[] splits = spec.split(BOTTOM_MARKER, 2);
|
||||
spec = splits[0].trim();
|
||||
bottomSpec = splits[1].trim();
|
||||
}
|
||||
|
||||
final Matrix m = new Matrix();
|
||||
final Region r = Region.obtain();
|
||||
if (!spec.isEmpty()) {
|
||||
try {
|
||||
p = PathParser.createPathFromPathData(spec);
|
||||
} catch (Throwable e) {
|
||||
Log.wtf(TAG, "Could not inflate cutout: ", e);
|
||||
}
|
||||
|
||||
if (p != null) {
|
||||
if (inDp) {
|
||||
m.postScale(density, density);
|
||||
}
|
||||
m.postTranslate(offsetX, 0);
|
||||
p.transform(m);
|
||||
|
||||
boundTop = new Rect();
|
||||
toRectAndAddToRegion(p, r, boundTop);
|
||||
safeInset.top = boundTop.bottom;
|
||||
}
|
||||
}
|
||||
|
||||
if (bottomSpec != null) {
|
||||
int bottomInset = 0;
|
||||
Path bottomPath = null;
|
||||
try {
|
||||
bottomPath = PathParser.createPathFromPathData(bottomSpec);
|
||||
} catch (Throwable e) {
|
||||
Log.wtf(TAG, "Could not inflate bottom cutout: ", e);
|
||||
}
|
||||
|
||||
if (bottomPath != null) {
|
||||
// Keep top transform
|
||||
m.postTranslate(0, displayHeight);
|
||||
bottomPath.transform(m);
|
||||
p.addPath(bottomPath);
|
||||
boundBottom = new Rect();
|
||||
toRectAndAddToRegion(bottomPath, r, boundBottom);
|
||||
bottomInset = displayHeight - boundBottom.top;
|
||||
}
|
||||
safeInset.bottom = bottomInset;
|
||||
}
|
||||
// Keep top transform
|
||||
m.postTranslate(0, displayHeight);
|
||||
bottomPath.transform(m);
|
||||
p.addPath(bottomPath);
|
||||
boundBottom = new Rect();
|
||||
toRectAndAddToRegion(bottomPath, r, boundBottom);
|
||||
bottomInset = displayHeight - boundBottom.top;
|
||||
} else {
|
||||
bottomInset = 0;
|
||||
}
|
||||
|
||||
Rect safeInset = new Rect(0, topInset, 0, bottomInset);
|
||||
final DisplayCutout cutout = new DisplayCutout(
|
||||
safeInset, null /* boundLeft */, boundTop, null /* boundRight */, boundBottom,
|
||||
false /* copyArguments */);
|
||||
if (!waterfallInsets.equals(Insets.NONE)) {
|
||||
safeInset.set(
|
||||
Math.max(waterfallInsets.left, safeInset.left),
|
||||
Math.max(waterfallInsets.top, safeInset.top),
|
||||
Math.max(waterfallInsets.right, safeInset.right),
|
||||
Math.max(waterfallInsets.bottom, safeInset.bottom));
|
||||
}
|
||||
|
||||
final DisplayCutout cutout = new DisplayCutout(
|
||||
safeInset, waterfallInsets, null /* boundLeft */, boundTop,
|
||||
null /* boundRight */, boundBottom, false /* copyArguments */);
|
||||
final Pair<Path, DisplayCutout> result = new Pair<>(p, cutout);
|
||||
synchronized (CACHE_LOCK) {
|
||||
sCachedSpec = spec;
|
||||
@@ -719,6 +793,7 @@ public final class DisplayCutout {
|
||||
sCachedDisplayHeight = displayHeight;
|
||||
sCachedDensity = density;
|
||||
sCachedCutout = result;
|
||||
sCachedWaterfallInsets = waterfallInsets;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -730,6 +805,15 @@ public final class DisplayCutout {
|
||||
inoutRegion.op(inoutRect, Op.UNION);
|
||||
}
|
||||
|
||||
|
||||
private static Insets loadWaterfallInset(Resources res) {
|
||||
return Insets.of(
|
||||
res.getDimensionPixelSize(R.dimen.waterfall_display_left_edge_size),
|
||||
res.getDimensionPixelSize(R.dimen.waterfall_display_top_edge_size),
|
||||
res.getDimensionPixelSize(R.dimen.waterfall_display_right_edge_size),
|
||||
res.getDimensionPixelSize(R.dimen.waterfall_display_bottom_edge_size));
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper class for passing {@link DisplayCutout} through binder.
|
||||
*
|
||||
@@ -773,6 +857,7 @@ public final class DisplayCutout {
|
||||
out.writeInt(1);
|
||||
out.writeTypedObject(cutout.mSafeInsets, flags);
|
||||
out.writeTypedArray(cutout.mBounds.getRects(), flags);
|
||||
out.writeTypedObject(cutout.mWaterfallInsets, flags);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -815,8 +900,10 @@ public final class DisplayCutout {
|
||||
Rect safeInsets = in.readTypedObject(Rect.CREATOR);
|
||||
Rect[] bounds = new Rect[BOUNDS_POSITION_LENGTH];
|
||||
in.readTypedArray(bounds, Rect.CREATOR);
|
||||
Insets waterfallInsets = in.readTypedObject(Insets.CREATOR);
|
||||
|
||||
return new DisplayCutout(safeInsets, bounds, false /* copyArguments */);
|
||||
return new DisplayCutout(
|
||||
safeInsets, waterfallInsets, bounds, false /* copyArguments */);
|
||||
}
|
||||
|
||||
public DisplayCutout get() {
|
||||
|
||||
@@ -69,6 +69,8 @@ public class DisplayCutoutTest {
|
||||
null /* boundBottom */);
|
||||
|
||||
final DisplayCutout mCutoutTop = createCutoutTop();
|
||||
final DisplayCutout mCutoutWithWaterfall = createCutoutWithWaterfall();
|
||||
final DisplayCutout mWaterfallOnly = createCutoutWaterfallOnly();
|
||||
|
||||
@Test
|
||||
public void testExtractBoundsFromList_left() {
|
||||
@@ -126,9 +128,23 @@ public class DisplayCutoutTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hasCutout() throws Exception {
|
||||
assertTrue(NO_CUTOUT.isEmpty());
|
||||
assertFalse(mCutoutTop.isEmpty());
|
||||
public void testHasCutout_noCutout() throws Exception {
|
||||
assertTrue(NO_CUTOUT.isBoundsEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHasCutout_cutoutOnly() {
|
||||
assertFalse(mCutoutTop.isBoundsEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHasCutout_cutoutWithWaterfall() {
|
||||
assertFalse(mCutoutWithWaterfall.isBoundsEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHasCutout_waterfallOnly() {
|
||||
assertTrue(mWaterfallOnly.isBoundsEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -141,21 +157,28 @@ public class DisplayCutoutTest {
|
||||
assertEquals(new Rect(5, 6, 7, 8), mCutoutNumbers.getSafeInsets());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetWaterfallInsets() throws Exception {
|
||||
DisplayCutout cutout =
|
||||
createCutoutWaterfallOnly(Insets.of(5, 6, 7, 8));
|
||||
assertEquals(Insets.of(5, 6, 7, 8), cutout.getWaterfallInsets());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHashCode() throws Exception {
|
||||
assertEquals(mCutoutTop.hashCode(), createCutoutTop().hashCode());
|
||||
assertNotEquals(mCutoutTop.hashCode(), mCutoutNumbers.hashCode());
|
||||
assertEquals(mCutoutWithWaterfall.hashCode(), createCutoutWithWaterfall().hashCode());
|
||||
assertNotEquals(mCutoutWithWaterfall.hashCode(), mCutoutNumbers.hashCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEquals() throws Exception {
|
||||
assertEquals(mCutoutTop, createCutoutTop());
|
||||
assertNotEquals(mCutoutTop, mCutoutNumbers);
|
||||
assertEquals(mCutoutWithWaterfall, createCutoutWithWaterfall());
|
||||
assertNotEquals(mCutoutWithWaterfall, mCutoutNumbers);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToString() throws Exception {
|
||||
assertFalse(mCutoutTop.toString().isEmpty());
|
||||
assertFalse(mCutoutWithWaterfall.toString().isEmpty());
|
||||
assertFalse(mCutoutNumbers.toString().isEmpty());
|
||||
}
|
||||
|
||||
@@ -240,12 +263,12 @@ public class DisplayCutoutTest {
|
||||
public void parcel_unparcel_regular() {
|
||||
Parcel p = Parcel.obtain();
|
||||
|
||||
new ParcelableWrapper(mCutoutTop).writeToParcel(p, 0);
|
||||
new ParcelableWrapper(mCutoutWithWaterfall).writeToParcel(p, 0);
|
||||
int posAfterWrite = p.dataPosition();
|
||||
|
||||
p.setDataPosition(0);
|
||||
|
||||
assertEquals(mCutoutTop, ParcelableWrapper.CREATOR.createFromParcel(p).get());
|
||||
assertEquals(mCutoutWithWaterfall, ParcelableWrapper.CREATOR.createFromParcel(p).get());
|
||||
assertEquals(posAfterWrite, p.dataPosition());
|
||||
}
|
||||
|
||||
@@ -264,44 +287,64 @@ public class DisplayCutoutTest {
|
||||
|
||||
@Test
|
||||
public void fromSpec_caches() {
|
||||
DisplayCutout cached = fromSpec("L1,0 L1,1 L0,1 z", 200, 400, 1f);
|
||||
assertThat(fromSpec("L1,0 L1,1 L0,1 z", 200, 400, 1f), sameInstance(cached));
|
||||
Insets waterfallInsets = Insets.of(0, 20, 0, 20);
|
||||
DisplayCutout cached = fromSpec("L1,0 L1,1 L0,1 z", 200, 400, 1f, waterfallInsets);
|
||||
assertThat(
|
||||
fromSpec("L1,0 L1,1 L0,1 z", 200, 400, 1f, waterfallInsets),
|
||||
sameInstance(cached));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fromSpec_wontCacheIfSpecChanges() {
|
||||
DisplayCutout cached = fromSpec("L1,0 L1000,1000 L0,1 z", 200, 400, 1f);
|
||||
assertThat(fromSpec("L1,0 L1,1 L0,1 z", 200, 400, 1f), not(sameInstance(cached)));
|
||||
DisplayCutout cached = fromSpec("L1,0 L1000,1000 L0,1 z", 200, 400, 1f, Insets.NONE);
|
||||
assertThat(
|
||||
fromSpec("L1,0 L1,1 L0,1 z", 200, 400, 1f, Insets.NONE),
|
||||
not(sameInstance(cached)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fromSpec_wontCacheIfScreenWidthChanges() {
|
||||
DisplayCutout cached = fromSpec("L1,0 L1,1 L0,1 z", 2000, 400, 1f);
|
||||
assertThat(fromSpec("L1,0 L1,1 L0,1 z", 200, 400, 1f), not(sameInstance(cached)));
|
||||
DisplayCutout cached = fromSpec("L1,0 L1,1 L0,1 z", 2000, 400, 1f, Insets.NONE);
|
||||
assertThat(
|
||||
fromSpec("L1,0 L1,1 L0,1 z", 200, 400, 1f, Insets.NONE),
|
||||
not(sameInstance(cached)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fromSpec_wontCacheIfScreenHeightChanges() {
|
||||
DisplayCutout cached = fromSpec("L1,0 L1,1 L0,1 z", 200, 4000, 1f);
|
||||
assertThat(fromSpec("L1,0 L1,1 L0,1 z", 200, 400, 1f), not(sameInstance(cached)));
|
||||
DisplayCutout cached = fromSpec("L1,0 L1,1 L0,1 z", 200, 4000, 1f, Insets.NONE);
|
||||
assertThat(
|
||||
fromSpec("L1,0 L1,1 L0,1 z", 200, 400, 1f, Insets.NONE),
|
||||
not(sameInstance(cached)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fromSpec_wontCacheIfDensityChanges() {
|
||||
DisplayCutout cached = fromSpec("L1,0 L1,1 L0,1 z", 200, 400, 2f);
|
||||
assertThat(fromSpec("L1,0 L1,1 L0,1 z", 200, 400, 1f), not(sameInstance(cached)));
|
||||
DisplayCutout cached = fromSpec("L1,0 L1,1 L0,1 z", 200, 400, 2f, Insets.NONE);
|
||||
assertThat(
|
||||
fromSpec("L1,0 L1,1 L0,1 z", 200, 400, 1f, Insets.NONE),
|
||||
not(sameInstance(cached)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fromSpec_wontCacheIfWaterfallInsetsChange() {
|
||||
Insets waterfallInsets = Insets.of(0, 20, 0, 20);
|
||||
DisplayCutout cached = fromSpec("L1,0 L1,1 L0,1 z", 200, 400, 2f, Insets.NONE);
|
||||
assertThat(
|
||||
fromSpec("L1,0 L1,1 L0,1 z", 200, 400, 2f, waterfallInsets),
|
||||
not(sameInstance(cached)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fromSpec_setsSafeInsets_top() {
|
||||
DisplayCutout cutout = fromSpec("M -50,0 v 20 h 100 v -20 z", 200, 400, 2f);
|
||||
DisplayCutout cutout = fromSpec("M -50,0 v 20 h 100 v -20 z", 200, 400, 2f, Insets.NONE);
|
||||
assertThat(cutout.getSafeInsets(), equalTo(new Rect(0, 20, 0, 0)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fromSpec_setsSafeInsets_top_and_bottom() {
|
||||
DisplayCutout cutout = fromSpec("M -50,0 v 20 h 100 v -20 z"
|
||||
+ "@bottom M -50,0 v -10,0 h 100 v 20 z", 200, 400, 2f);
|
||||
+ "@bottom M -50,0 v -10,0 h 100 v 20 z", 200, 400, 2f, Insets.NONE);
|
||||
assertThat(cutout.getSafeInsets(), equalTo(new Rect(0, 20, 0, 10)));
|
||||
assertThat(cutout.getBoundingRectsAll(), equalTo(new Rect[]{
|
||||
ZERO_RECT, new Rect(50, 0, 150, 20),
|
||||
@@ -309,6 +352,38 @@ public class DisplayCutoutTest {
|
||||
}));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fromSpec_setsSafeInsets_waterfallTopBottom() {
|
||||
DisplayCutout cutout = fromSpec("", 200, 400, 2f, Insets.of(0, 30, 0, 30));
|
||||
assertThat(cutout.getSafeInsets(), equalTo(new Rect(0, 30, 0, 30)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fromSpec_setsSafeInsets_waterfallLeftRight() {
|
||||
DisplayCutout cutout = fromSpec("", 200, 400, 2f, Insets.of(30, 0, 30, 0));
|
||||
assertThat(cutout.getSafeInsets(), equalTo(new Rect(30, 0, 30, 0)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fromSpec_setsSafeInsets_waterfall_allEdges() {
|
||||
DisplayCutout cutout = fromSpec("", 200, 400, 2f, Insets.of(30, 30, 30, 30));
|
||||
assertThat(cutout.getSafeInsets(), equalTo(new Rect(30, 30, 30, 30)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fromSpec_setsSafeInsets_cutoutTopBottom_waterfallTopBottom() {
|
||||
DisplayCutout cutout = fromSpec("M -50,0 v 20 h 100 v -20 z"
|
||||
+ "@bottom M -50,0 v -20,0 h 100 v 20 z", 200, 400, 2f, Insets.of(0, 30, 0, 30));
|
||||
assertThat(cutout.getSafeInsets(), equalTo(new Rect(0, 30, 0, 30)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fromSpec_setsSafeInsets_cutoutTopBottom_waterfallLeftRight() {
|
||||
DisplayCutout cutout = fromSpec("M -50,0 v 20 h 100 v -20 z"
|
||||
+ "@bottom M -50,0 v -20,0 h 100 v 20 z", 200, 400, 2f, Insets.of(30, 0, 30, 0));
|
||||
assertThat(cutout.getSafeInsets(), equalTo(new Rect(30, 20, 30, 20)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parcel_unparcel_nocutout() {
|
||||
Parcel p = Parcel.obtain();
|
||||
@@ -326,7 +401,7 @@ public class DisplayCutoutTest {
|
||||
public void parcel_unparcel_inplace() {
|
||||
Parcel p = Parcel.obtain();
|
||||
|
||||
new ParcelableWrapper(mCutoutTop).writeToParcel(p, 0);
|
||||
new ParcelableWrapper(mCutoutWithWaterfall).writeToParcel(p, 0);
|
||||
int posAfterWrite = p.dataPosition();
|
||||
|
||||
p.setDataPosition(0);
|
||||
@@ -334,22 +409,24 @@ public class DisplayCutoutTest {
|
||||
ParcelableWrapper wrapper = new ParcelableWrapper();
|
||||
wrapper.readFromParcel(p);
|
||||
|
||||
assertEquals(mCutoutTop, wrapper.get());
|
||||
assertEquals(mCutoutWithWaterfall, wrapper.get());
|
||||
assertEquals(posAfterWrite, p.dataPosition());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void wrapper_hashcode() throws Exception {
|
||||
assertEquals(new ParcelableWrapper(mCutoutTop).hashCode(),
|
||||
new ParcelableWrapper(createCutoutTop()).hashCode());
|
||||
assertNotEquals(new ParcelableWrapper(mCutoutTop).hashCode(),
|
||||
assertEquals(new ParcelableWrapper(mCutoutWithWaterfall).hashCode(),
|
||||
new ParcelableWrapper(createCutoutWithWaterfall()).hashCode());
|
||||
assertNotEquals(new ParcelableWrapper(mCutoutWithWaterfall).hashCode(),
|
||||
new ParcelableWrapper(mCutoutNumbers).hashCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void wrapper_equals() throws Exception {
|
||||
assertEquals(new ParcelableWrapper(mCutoutTop), new ParcelableWrapper(createCutoutTop()));
|
||||
assertNotEquals(new ParcelableWrapper(mCutoutTop), new ParcelableWrapper(mCutoutNumbers));
|
||||
assertEquals(new ParcelableWrapper(mCutoutWithWaterfall),
|
||||
new ParcelableWrapper(createCutoutWithWaterfall()));
|
||||
assertNotEquals(new ParcelableWrapper(mCutoutWithWaterfall),
|
||||
new ParcelableWrapper(mCutoutNumbers));
|
||||
}
|
||||
|
||||
private static DisplayCutout createCutoutTop() {
|
||||
@@ -363,4 +440,28 @@ public class DisplayCutoutTest {
|
||||
safeInset, null /* boundLeft */, boundTop, null /* boundRight */,
|
||||
null /* boundBottom */);
|
||||
}
|
||||
|
||||
private static DisplayCutout createCutoutWithWaterfall() {
|
||||
return new DisplayCutout(
|
||||
Insets.of(20, 100, 20, 0),
|
||||
ZERO_RECT,
|
||||
new Rect(50, 0, 75, 100),
|
||||
ZERO_RECT,
|
||||
ZERO_RECT,
|
||||
Insets.of(20, 0, 20, 0));
|
||||
}
|
||||
|
||||
private static DisplayCutout createCutoutWaterfallOnly() {
|
||||
return createCutoutWaterfallOnly(Insets.of(20, 0, 20, 0));
|
||||
}
|
||||
|
||||
private static DisplayCutout createCutoutWaterfallOnly(Insets waterfallInsets) {
|
||||
return new DisplayCutout(
|
||||
Insets.of(20, 0, 20, 0),
|
||||
ZERO_RECT,
|
||||
ZERO_RECT,
|
||||
ZERO_RECT,
|
||||
ZERO_RECT,
|
||||
waterfallInsets);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user