From 348c66b52b5cc4347e10f73cf09d48a9338a58e7 Mon Sep 17 00:00:00 2001 From: shawnlin Date: Wed, 21 Jul 2021 16:41:39 +0800 Subject: [PATCH] [DO NOT MERGE] Support display cutout for multi-display devices - Add a new string array config that stores the unique id of each display and when loading the cutout configs we first look up the index of the unique id of the added display in the array and use this index to load the corresponding cutout configs. - Add new array configs for every cutout configs. Bug: 186604541 Test: make Test: check the device and see if the cutout is correctly set for each display Change-Id: I038832795c11cd16969caff5031fa1090493b008 --- core/java/android/view/DisplayCutout.java | 148 ++++++++++++++++-- core/res/res/values/config.xml | 76 +++++++++ core/res/res/values/dimens.xml | 8 +- core/res/res/values/symbols.xml | 17 ++ .../android/systemui/ScreenDecorations.java | 7 +- .../server/display/LocalDisplayAdapter.java | 12 +- 6 files changed, 249 insertions(+), 19 deletions(-) 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;