[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
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -5047,4 +5047,80 @@
|
||||
|
||||
<!-- the number of the max cached processes in the system. -->
|
||||
<integer name="config_customizedMaxCachedProcesses">32</integer>
|
||||
|
||||
<!-- The display cutout configs for secondary built-in display. -->
|
||||
<string name="config_secondaryBuiltInDisplayCutout" translatable="false"></string>
|
||||
<string name="config_secondaryBuiltInDisplayCutoutRectApproximation" translatable="false">
|
||||
@string/config_secondaryBuiltInDisplayCutout
|
||||
</string>
|
||||
<bool name="config_fillSecondaryBuiltInDisplayCutout">false</bool>
|
||||
<bool name="config_maskSecondaryBuiltInDisplayCutout">false</bool>
|
||||
|
||||
<!-- An array contains unique ids of all built-in displays and the unique id of a display can be
|
||||
obtained from {@link Display#getUniqueId}. This array should be set for multi-display
|
||||
devices if there are different display related configs(e.g. display cutout, rounded corner)
|
||||
between each built-in display.
|
||||
It is used as an index for multi-display related configs:
|
||||
First look up the index of the unique id of the given built-in display unique id in this
|
||||
array and use this index to get the info in corresponding config arrays such as:
|
||||
- config_displayCutoutPathArray
|
||||
- config_displayCutoutApproximationRectArray
|
||||
- config_fillBuiltInDisplayCutoutArray
|
||||
- config_maskBuiltInDisplayCutoutArray
|
||||
- config_waterfallCutoutArray
|
||||
|
||||
Leave this array empty for single display device and the system will load the default main
|
||||
built-in related configs.
|
||||
-->
|
||||
<string-array name="config_displayUniqueIdArray" translatable="false">
|
||||
<!-- Example:
|
||||
<item>"local:1234567891"</item> // main built-in display
|
||||
<item>"local:1234567892"</item> // secondary built-in display
|
||||
-->
|
||||
</string-array>
|
||||
|
||||
<!-- The display cutout path config for each display in a multi-display device. -->
|
||||
<string-array name="config_displayCutoutPathArray" translatable="false">
|
||||
<item>@string/config_mainBuiltInDisplayCutout</item>
|
||||
<item>@string/config_secondaryBuiltInDisplayCutout</item>
|
||||
</string-array>
|
||||
|
||||
<!-- The display cutout approximation rect config for each display in a multi-display device.
|
||||
-->
|
||||
<string-array name="config_displayCutoutApproximationRectArray" translatable="false">
|
||||
<item>@string/config_mainBuiltInDisplayCutoutRectApproximation</item>
|
||||
<item>@string/config_secondaryBuiltInDisplayCutoutRectApproximation</item>
|
||||
</string-array>
|
||||
|
||||
<!-- The maskBuiltInDisplayCutout config for each display in a multi-display device. -->
|
||||
<array name="config_maskBuiltInDisplayCutoutArray" translatable="false">
|
||||
<item>@bool/config_maskMainBuiltInDisplayCutout</item>
|
||||
<item>@bool/config_maskSecondaryBuiltInDisplayCutout</item>
|
||||
</array>
|
||||
|
||||
<!-- The fillBuiltInDisplayCutout config for each display in a multi-display device. -->
|
||||
<array name="config_fillBuiltInDisplayCutoutArray" translatable="false">
|
||||
<item>@bool/config_fillMainBuiltInDisplayCutout</item>
|
||||
<item>@bool/config_fillSecondaryBuiltInDisplayCutout</item>
|
||||
</array>
|
||||
|
||||
<array name="config_mainBuiltInDisplayWaterfallCutout" translatable="false">
|
||||
<item>@dimen/waterfall_display_left_edge_size</item>
|
||||
<item>@dimen/waterfall_display_top_edge_size</item>
|
||||
<item>@dimen/waterfall_display_right_edge_size</item>
|
||||
<item>@dimen/waterfall_display_bottom_edge_size</item>
|
||||
</array>
|
||||
|
||||
<array name="config_secondaryBuiltInDisplayWaterfallCutout" translatable="false">
|
||||
<item>@dimen/secondary_waterfall_display_left_edge_size</item>
|
||||
<item>@dimen/secondary_waterfall_display_top_edge_size</item>
|
||||
<item>@dimen/secondary_waterfall_display_right_edge_size</item>
|
||||
<item>@dimen/secondary_waterfall_display_bottom_edge_size</item>
|
||||
</array>
|
||||
|
||||
<!-- The waterfall cutout config for each display in a multi-display device. -->
|
||||
<array name="config_waterfallCutoutArray" translatable="false">
|
||||
<item>@array/config_mainBuiltInDisplayWaterfallCutout</item>
|
||||
<item>@array/config_secondaryBuiltInDisplayWaterfallCutout</item>
|
||||
</array>
|
||||
</resources>
|
||||
|
||||
@@ -920,7 +920,7 @@
|
||||
|
||||
<dimen name="chooser_action_button_icon_size">18dp</dimen>
|
||||
|
||||
<!-- For Waterfall Display -->
|
||||
<!-- For main built-in Waterfall Display -->
|
||||
<dimen name="waterfall_display_left_edge_size">0px</dimen>
|
||||
<dimen name="waterfall_display_top_edge_size">0px</dimen>
|
||||
<dimen name="waterfall_display_right_edge_size">0px</dimen>
|
||||
@@ -943,4 +943,10 @@
|
||||
<dimen name="starting_surface_icon_size">160dp</dimen>
|
||||
<!-- The default width/height of the icon on the spec of adaptive icon drawable. -->
|
||||
<dimen name="starting_surface_default_icon_size">108dp</dimen>
|
||||
|
||||
<!-- For secondary built-in Waterfall Display -->
|
||||
<dimen name="secondary_waterfall_display_left_edge_size">0px</dimen>
|
||||
<dimen name="secondary_waterfall_display_top_edge_size">0px</dimen>
|
||||
<dimen name="secondary_waterfall_display_right_edge_size">0px</dimen>
|
||||
<dimen name="secondary_waterfall_display_bottom_edge_size">0px</dimen>
|
||||
</resources>
|
||||
|
||||
@@ -4426,4 +4426,21 @@
|
||||
<java-symbol type="bool" name="config_volumeShowRemoteSessions" />
|
||||
|
||||
<java-symbol type="integer" name="config_customizedMaxCachedProcesses" />
|
||||
|
||||
<java-symbol type="string" name="config_secondaryBuiltInDisplayCutout" />
|
||||
<java-symbol type="string" name="config_secondaryBuiltInDisplayCutoutRectApproximation" />
|
||||
<java-symbol type="bool" name="config_fillSecondaryBuiltInDisplayCutout" />
|
||||
<java-symbol type="bool" name="config_maskSecondaryBuiltInDisplayCutout" />
|
||||
<java-symbol type="array" name="config_displayUniqueIdArray" />
|
||||
<java-symbol type="array" name="config_displayCutoutPathArray" />
|
||||
<java-symbol type="array" name="config_displayCutoutApproximationRectArray" />
|
||||
<java-symbol type="array" name="config_fillBuiltInDisplayCutoutArray" />
|
||||
<java-symbol type="array" name="config_maskBuiltInDisplayCutoutArray" />
|
||||
<java-symbol type="dimen" name="secondary_waterfall_display_left_edge_size" />
|
||||
<java-symbol type="dimen" name="secondary_waterfall_display_top_edge_size" />
|
||||
<java-symbol type="dimen" name="secondary_waterfall_display_right_edge_size" />
|
||||
<java-symbol type="dimen" name="secondary_waterfall_display_bottom_edge_size" />
|
||||
<java-symbol type="array" name="config_mainBuiltInDisplayWaterfallCutout" />
|
||||
<java-symbol type="array" name="config_secondaryBuiltInDisplayWaterfallCutout" />
|
||||
<java-symbol type="array" name="config_waterfallCutoutArray" />
|
||||
</resources>
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user