diff --git a/core/java/android/view/DisplayCutout.java b/core/java/android/view/DisplayCutout.java index e1a4402d89644..0257e55073dc8 100644 --- a/core/java/android/view/DisplayCutout.java +++ b/core/java/android/view/DisplayCutout.java @@ -31,6 +31,7 @@ import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.res.Resources; +import android.content.res.TypedArray; import android.graphics.Insets; import android.graphics.Matrix; import android.graphics.Path; @@ -872,6 +873,135 @@ public final class DisplayCutout { false /* copyArguments */); } + /** + * Gets the index of the given display unique id in {@link R.array#config_displayUniqueIdArray} + * which is used to get the related cutout configs for that display. + * + * For multi-display device, {@link R.array#config_displayUniqueIdArray} should be set for each + * display if there are different type of cutouts on each display. + * For single display device, {@link R.array#config_displayUniqueIdArray} should not to be set + * and the system will load the default configs for main built-in display. + */ + private static int getDisplayCutoutConfigIndex(Resources res, String displayUniqueId) { + int index = -1; + if (displayUniqueId == null || displayUniqueId.isEmpty()) { + return index; + } + final String[] ids = res.getStringArray(R.array.config_displayUniqueIdArray); + final int size = ids.length; + for (int i = 0; i < size; i++) { + if (displayUniqueId.equals(ids[i])) { + index = i; + break; + } + } + return index; + } + + /** + * Gets the display cutout by the given display unique id. + * + * Loads the default config {@link R.string#config_mainBuiltInDisplayCutout) if + * {@link R.array#config_displayUniqueIdArray} is not set. + */ + private static String getDisplayCutoutPath(Resources res, String displayUniqueId) { + final int index = getDisplayCutoutConfigIndex(res, displayUniqueId); + final String[] array = res.getStringArray(R.array.config_displayCutoutPathArray); + if (index >= 0 && index < array.length) { + return array[index]; + } + return res.getString(R.string.config_mainBuiltInDisplayCutout); + } + + /** + * Gets the display cutout approximation rect by the given display unique id. + * + * Loads the default config {@link R.string#config_mainBuiltInDisplayCutoutRectApproximation} if + * {@link R.array#config_displayUniqueIdArray} is not set. + */ + private static String getDisplayCutoutApproximationRect(Resources res, String displayUniqueId) { + final int index = getDisplayCutoutConfigIndex(res, displayUniqueId); + final String[] array = res.getStringArray( + R.array.config_displayCutoutApproximationRectArray); + if (index >= 0 && index < array.length) { + return array[index]; + } + return res.getString(R.string.config_mainBuiltInDisplayCutoutRectApproximation); + } + + /** + * Gets whether to mask a built-in display cutout of a display which is determined by the + * given display unique id. + * + * Loads the default config {@link R.bool#config_maskMainBuiltInDisplayCutout} if + * {@link R.array#config_displayUniqueIdArray} is not set. + * + * @hide + */ + public static boolean getMaskBuiltInDisplayCutout(Resources res, String displayUniqueId) { + final int index = getDisplayCutoutConfigIndex(res, displayUniqueId); + final TypedArray array = res.obtainTypedArray(R.array.config_maskBuiltInDisplayCutoutArray); + boolean maskCutout; + if (index >= 0 && index < array.length()) { + maskCutout = array.getBoolean(index, false); + } else { + maskCutout = res.getBoolean(R.bool.config_maskMainBuiltInDisplayCutout); + } + array.recycle(); + return maskCutout; + } + + /** + * Gets whether to fill a built-in display cutout of a display which is determined by the + * given display unique id. + * + * Loads the default config{@link R.bool#config_fillMainBuiltInDisplayCutout} if + * {@link R.array#config_displayUniqueIdArray} is not set. + * + * @hide + */ + public static boolean getFillBuiltInDisplayCutout(Resources res, String displayUniqueId) { + final int index = getDisplayCutoutConfigIndex(res, displayUniqueId); + final TypedArray array = res.obtainTypedArray(R.array.config_fillBuiltInDisplayCutoutArray); + boolean fillCutout; + if (index >= 0 && index < array.length()) { + fillCutout = array.getBoolean(index, false); + } else { + fillCutout = res.getBoolean(R.bool.config_fillMainBuiltInDisplayCutout); + } + array.recycle(); + return fillCutout; + } + + /** + * Gets the waterfall cutout by the given display unique id. + * + * Loads the default waterfall dimens if {@link R.array#config_displayUniqueIdArray} is not set. + * {@link R.dimen#waterfall_display_left_edge_size}, + * {@link R.dimen#waterfall_display_top_edge_size}, + * {@link R.dimen#waterfall_display_right_edge_size}, + * {@link R.dimen#waterfall_display_bottom_edge_size} + */ + private static Insets getWaterfallInsets(Resources res, String displayUniqueId) { + Insets insets; + final int index = getDisplayCutoutConfigIndex(res, displayUniqueId); + final TypedArray array = res.obtainTypedArray(R.array.config_waterfallCutoutArray); + if (index >= 0 && index < array.length() && array.getResourceId(index, 0) > 0) { + final int resourceId = array.getResourceId(index, 0); + final TypedArray waterfall = res.obtainTypedArray(resourceId); + insets = Insets.of( + waterfall.getDimensionPixelSize(0 /* waterfall left edge size */, 0), + waterfall.getDimensionPixelSize(1 /* waterfall top edge size */, 0), + waterfall.getDimensionPixelSize(2 /* waterfall right edge size */, 0), + waterfall.getDimensionPixelSize(3 /* waterfall bottom edge size */, 0)); + waterfall.recycle(); + } else { + insets = loadWaterfallInset(res); + } + array.recycle(); + return insets; + } + /** * Creates the display cutout according to * @android:string/config_mainBuiltInDisplayCutoutRectApproximation, which is the closest @@ -879,12 +1009,12 @@ public final class DisplayCutout { * * @hide */ - public static DisplayCutout fromResourcesRectApproximation(Resources res, int displayWidth, - int displayHeight) { - return pathAndDisplayCutoutFromSpec(res.getString(R.string.config_mainBuiltInDisplayCutout), - res.getString(R.string.config_mainBuiltInDisplayCutoutRectApproximation), + public static DisplayCutout fromResourcesRectApproximation(Resources res, + String displayUniqueId, int displayWidth, int displayHeight) { + return pathAndDisplayCutoutFromSpec(getDisplayCutoutPath(res, displayUniqueId), + getDisplayCutoutApproximationRect(res, displayUniqueId), displayWidth, displayHeight, DENSITY_DEVICE_STABLE / (float) DENSITY_DEFAULT, - loadWaterfallInset(res)).second; + getWaterfallInsets(res, displayUniqueId)).second; } /** @@ -892,11 +1022,11 @@ public final class DisplayCutout { * * @hide */ - public static Path pathFromResources(Resources res, int displayWidth, int displayHeight) { - return pathAndDisplayCutoutFromSpec( - res.getString(R.string.config_mainBuiltInDisplayCutout), null, + public static Path pathFromResources(Resources res, String displayUniqueId, int displayWidth, + int displayHeight) { + return pathAndDisplayCutoutFromSpec(getDisplayCutoutPath(res, displayUniqueId), null, displayWidth, displayHeight, DENSITY_DEVICE_STABLE / (float) DENSITY_DEFAULT, - loadWaterfallInset(res)).first; + getWaterfallInsets(res, displayUniqueId)).first; } /** diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index ef8e938cbca76..1586f164a0a5d 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -5047,4 +5047,80 @@ 32 + + + + + @string/config_secondaryBuiltInDisplayCutout + + false + false + + + + + + + + + @string/config_mainBuiltInDisplayCutout + @string/config_secondaryBuiltInDisplayCutout + + + + + @string/config_mainBuiltInDisplayCutoutRectApproximation + @string/config_secondaryBuiltInDisplayCutoutRectApproximation + + + + + @bool/config_maskMainBuiltInDisplayCutout + @bool/config_maskSecondaryBuiltInDisplayCutout + + + + + @bool/config_fillMainBuiltInDisplayCutout + @bool/config_fillSecondaryBuiltInDisplayCutout + + + + @dimen/waterfall_display_left_edge_size + @dimen/waterfall_display_top_edge_size + @dimen/waterfall_display_right_edge_size + @dimen/waterfall_display_bottom_edge_size + + + + @dimen/secondary_waterfall_display_left_edge_size + @dimen/secondary_waterfall_display_top_edge_size + @dimen/secondary_waterfall_display_right_edge_size + @dimen/secondary_waterfall_display_bottom_edge_size + + + + + @array/config_mainBuiltInDisplayWaterfallCutout + @array/config_secondaryBuiltInDisplayWaterfallCutout + diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml index de7a1175b4a30..7be9c7b42e5a3 100644 --- a/core/res/res/values/dimens.xml +++ b/core/res/res/values/dimens.xml @@ -920,7 +920,7 @@ 18dp - + 0px 0px 0px @@ -943,4 +943,10 @@ 160dp 108dp + + + 0px + 0px + 0px + 0px diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 908721fc5ed9a..cd590cbbe2b0c 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -4426,4 +4426,21 @@ + + + + + + + + + + + + + + + + + diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java index e9c5653775306..f653088e552a0 100644 --- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java +++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java @@ -797,8 +797,8 @@ public class ScreenDecorations extends SystemUI implements Tunable { } static boolean shouldDrawCutout(Context context) { - return context.getResources().getBoolean( - com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout); + return DisplayCutout.getFillBuiltInDisplayCutout( + context.getResources(), context.getDisplay().getUniqueId()); } private void updateLayoutParams() { @@ -1085,7 +1085,8 @@ public class ScreenDecorations extends SystemUI implements Tunable { int dw = flipped ? lh : lw; int dh = flipped ? lw : lh; - Path path = DisplayCutout.pathFromResources(getResources(), dw, dh); + Path path = DisplayCutout.pathFromResources( + getResources(), getDisplay().getUniqueId(), dw, dh); if (path != null) { mBoundingPath.set(path); } else { diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java index f953cc8c8a271..17697127d5080 100644 --- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java +++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java @@ -601,12 +601,6 @@ final class LocalDisplayAdapter extends DisplayAdapter { && SystemProperties.getBoolean(PROPERTY_EMULATOR_CIRCULAR, false))) { mInfo.flags |= DisplayDeviceInfo.FLAG_ROUND; } - if (res.getBoolean( - com.android.internal.R.bool.config_maskMainBuiltInDisplayCutout)) { - mInfo.flags |= DisplayDeviceInfo.FLAG_MASK_DISPLAY_CUTOUT; - } - mInfo.displayCutout = DisplayCutout.fromResourcesRectApproximation(res, - mInfo.width, mInfo.height); mInfo.roundedCorners = RoundedCorners.fromResources( res, mInfo.width, mInfo.height); } else { @@ -620,6 +614,12 @@ final class LocalDisplayAdapter extends DisplayAdapter { } } + if (DisplayCutout.getMaskBuiltInDisplayCutout(res, mInfo.uniqueId)) { + mInfo.flags |= DisplayDeviceInfo.FLAG_MASK_DISPLAY_CUTOUT; + } + mInfo.displayCutout = DisplayCutout.fromResourcesRectApproximation(res, + mInfo.uniqueId, mInfo.width, mInfo.height); + if (mStaticDisplayInfo.isInternal) { mInfo.type = Display.TYPE_INTERNAL; mInfo.touch = DisplayDeviceInfo.TOUCH_INTERNAL;