Refactor device padding to be set per grid option

- Fixes bug where devices with scaled grids were not
  getting the correct deivce padding.
- Also fix bug where device padding was invalid.
  Added validation check when processing paddings to prevent
  this from happening again.

Bug: 175329686
Test: manual, enable debug flag,
      run and verify no crash from validation check

Change-Id: I35b019c40667c08de4fad95ac4b05b2d8f8a0e74
This commit is contained in:
Jon Miranda
2021-03-22 17:13:34 -04:00
parent dedbc8ac36
commit c9e69fa98d
5 changed files with 74 additions and 14 deletions
+1
View File
@@ -134,6 +134,7 @@
<attr name="defaultLayoutId" format="reference" />
<attr name="demoModeLayoutId" format="reference" />
<attr name="isScalable" format="boolean" />
<attr name="devicePaddingId" format="reference" />
</declare-styleable>
@@ -38,7 +38,7 @@
<workspaceBottomPadding
launcher:a="0.50"
launcher:b="0"
launcher:c="-16dp"/>
launcher:c="16dp"/>
<hotseatBottomPadding
launcher:a="0.50"
launcher:b="0"
+39 -5
View File
@@ -52,8 +52,8 @@ public class DevicePaddings {
ArrayList<DevicePadding> mDevicePaddings = new ArrayList<>();
public DevicePaddings(Context context) {
try (XmlResourceParser parser = context.getResources().getXml(R.xml.size_limits)) {
public DevicePaddings(Context context, int devicePaddingId) {
try (XmlResourceParser parser = context.getResources().getXml(devicePaddingId)) {
final int depth = parser.getDepth();
int type;
while (((type = parser.next()) != XmlPullParser.END_TAG ||
@@ -94,16 +94,27 @@ public class DevicePaddings {
if (workspaceTopPadding == null
|| workspaceBottomPadding == null
|| hotseatBottomPadding == null) {
throw new RuntimeException("DevicePadding missing padding.");
if (Utilities.IS_DEBUG_DEVICE) {
throw new RuntimeException("DevicePadding missing padding.");
}
}
mDevicePaddings.add(new DevicePadding(maxWidthPx, workspaceTopPadding,
workspaceBottomPadding, hotseatBottomPadding));
DevicePadding dp = new DevicePadding(maxWidthPx, workspaceTopPadding,
workspaceBottomPadding, hotseatBottomPadding);
if (dp.isValid()) {
mDevicePaddings.add(dp);
} else {
Log.e(TAG, "Invalid device padding found.");
if (Utilities.IS_DEBUG_DEVICE) {
throw new RuntimeException("DevicePadding is invalid");
}
}
}
}
}
}
} catch (IOException | XmlPullParserException e) {
Log.e(TAG, "Failure parsing device padding layout.", e);
throw new RuntimeException(e);
}
@@ -128,6 +139,9 @@ public class DevicePaddings {
*/
public static final class DevicePadding {
// One for each padding since they can each be off by 1 due to rounding errors.
private static final int ROUNDING_THRESHOLD_PX = 3;
private final int maxEmptySpacePx;
private final PaddingFormula workspaceTopPadding;
private final PaddingFormula workspaceBottomPadding;
@@ -143,6 +157,10 @@ public class DevicePaddings {
this.hotseatBottomPadding = hotseatBottomPadding;
}
public int getMaxEmptySpacePx() {
return maxEmptySpacePx;
}
public int getWorkspaceTopPadding(int extraSpacePx) {
return workspaceTopPadding.calculate(extraSpacePx);
}
@@ -154,6 +172,22 @@ public class DevicePaddings {
public int getHotseatBottomPadding(int extraSpacePx) {
return hotseatBottomPadding.calculate(extraSpacePx);
}
public boolean isValid() {
int workspaceTopPadding = getWorkspaceTopPadding(maxEmptySpacePx);
int workspaceBottomPadding = getWorkspaceBottomPadding(maxEmptySpacePx);
int hotseatBottomPadding = getHotseatBottomPadding(maxEmptySpacePx);
int sum = workspaceTopPadding + workspaceBottomPadding + hotseatBottomPadding;
int diff = Math.abs(sum - maxEmptySpacePx);
if (DEBUG) {
Log.d(TAG, "isValid: workspaceTopPadding=" + workspaceTopPadding
+ ", workspaceBottomPadding=" + workspaceBottomPadding
+ ", hotseatBottomPadding=" + hotseatBottomPadding
+ ", sum=" + sum
+ ", diff=" + diff);
}
return diff <= ROUNDING_THRESHOLD_PX;
}
}
/**
+22 -5
View File
@@ -104,6 +104,7 @@ public class DeviceProfile {
private final int mWorkspacePageIndicatorOverlapWorkspace;
// Workspace icons
public float iconScale;
public int iconSizePx;
public int iconTextSizePx;
public int iconDrawablePaddingPx;
@@ -312,12 +313,19 @@ public class DeviceProfile {
// Calculate all of the remaining variables.
extraSpace = updateAvailableDimensions(res);
// Now that we have all of the variables calculated, we can tune certain sizes.
if (isScalableGrid) {
DevicePadding padding = inv.devicePaddings.getDevicePadding(extraSpace);
workspaceTopPadding = padding.getWorkspaceTopPadding(extraSpace);
workspaceBottomPadding = padding.getWorkspaceBottomPadding(extraSpace);
if (isScalableGrid && inv.devicePaddings != null) {
// Paddings were created assuming no scaling, so we first unscale the extra space.
int unscaledExtraSpace = (int) (extraSpace / iconScale);
DevicePadding padding = inv.devicePaddings.getDevicePadding(unscaledExtraSpace);
int paddingWorkspaceTop = padding.getWorkspaceTopPadding(unscaledExtraSpace);
int paddingWorkspaceBottom = padding.getWorkspaceBottomPadding(unscaledExtraSpace);
int paddingHotseatBottom = padding.getHotseatBottomPadding(unscaledExtraSpace);
workspaceTopPadding = Math.round(paddingWorkspaceTop * iconScale);
workspaceBottomPadding = Math.round(paddingWorkspaceBottom * iconScale);
extraHotseatBottomPadding = Math.round(paddingHotseatBottom * iconScale);
extraHotseatBottomPadding = padding.getHotseatBottomPadding(extraSpace);
hotseatBarSizePx += extraHotseatBottomPadding;
hotseatBarBottomPaddingPx += extraHotseatBottomPadding;
} else if (!isVerticalBarLayout() && isPhone && isTallDevice) {
@@ -490,6 +498,8 @@ public class DeviceProfile {
* hotseat sizes, workspaceSpringLoadedShrinkFactor, folderIconSizePx, and folderIconOffsetYPx.
*/
public void updateIconSize(float scale, Resources res) {
iconScale = scale;
// Workspace
final boolean isVerticalLayout = isVerticalBarLayout();
float invIconSizeDp = isVerticalLayout ? inv.landscapeIconSize : inv.iconSize;
@@ -890,7 +900,14 @@ public class DeviceProfile {
writer.println(prefix + pxToDpStr("workspacePadding.right", workspacePadding.right));
writer.println(prefix + pxToDpStr("workspacePadding.bottom", workspacePadding.bottom));
writer.println(prefix + pxToDpStr("scaleToFit", iconScale));
writer.println(prefix + pxToDpStr("extraSpace", extraSpace));
if (inv.devicePaddings != null) {
int unscaledExtraSpace = (int) (extraSpace / iconScale);
writer.println(prefix + pxToDpStr("maxEmptySpace",
inv.devicePaddings.getDevicePadding(unscaledExtraSpace).getMaxEmptySpacePx()));
}
writer.println(prefix + pxToDpStr("workspaceTopPadding", workspaceTopPadding));
writer.println(prefix + pxToDpStr("workspaceBottomPadding", workspaceBottomPadding));
writer.println(prefix + pxToDpStr("extraHotseatBottomPadding", extraHotseatBottomPadding));
@@ -132,6 +132,7 @@ public class InvariantDeviceProfile {
* Do not query directly. see {@link DeviceProfile#isScalableGrid}.
*/
protected boolean isScalable;
public int devicePaddingId;
public String dbFile;
public int defaultLayoutId;
@@ -140,7 +141,7 @@ public class InvariantDeviceProfile {
public DeviceProfile landscapeProfile;
public DeviceProfile portraitProfile;
public DevicePaddings devicePaddings;
@Nullable public DevicePaddings devicePaddings;
public Point defaultWallpaperSize;
public Rect defaultWidgetPadding;
@@ -165,6 +166,7 @@ public class InvariantDeviceProfile {
numHotseatIcons = p.numHotseatIcons;
numAllAppsColumns = p.numAllAppsColumns;
isScalable = p.isScalable;
devicePaddingId = p.devicePaddingId;
minCellHeight = p.minCellHeight;
minCellWidth = p.minCellWidth;
borderSpacing = p.borderSpacing;
@@ -231,7 +233,6 @@ public class InvariantDeviceProfile {
result.minCellWidth = defaultDisplayOption.minCellWidth;
result.borderSpacing = defaultDisplayOption.borderSpacing;
devicePaddings = new DevicePaddings(context);
initGrid(context, myInfo, result);
}
@@ -262,7 +263,6 @@ public class InvariantDeviceProfile {
ArrayList<DisplayOption> allOptions = getPredefinedDeviceProfiles(context, gridName);
DisplayOption displayOption = invDistWeightedInterpolate(displayInfo, allOptions);
devicePaddings = new DevicePaddings(context);
initGrid(context, displayInfo, displayOption);
return displayOption.grid.name;
}
@@ -280,6 +280,7 @@ public class InvariantDeviceProfile {
numFolderColumns = closestProfile.numFolderColumns;
numAllAppsColumns = closestProfile.numAllAppsColumns;
isScalable = closestProfile.isScalable;
devicePaddingId = closestProfile.devicePaddingId;
mExtraAttrs = closestProfile.extraAttrs;
@@ -302,6 +303,10 @@ public class InvariantDeviceProfile {
allAppsIconTextSize = iconTextSize;
}
if (devicePaddingId != 0) {
devicePaddings = new DevicePaddings(context, devicePaddingId);
}
// If the partner customization apk contains any grid overrides, apply them
// Supported overrides: numRows, numColumns, iconSize
applyPartnerDeviceProfileOverrides(context, displayInfo.metrics);
@@ -615,6 +620,7 @@ public class InvariantDeviceProfile {
private final int demoModeLayoutId;
private final boolean isScalable;
private final int devicePaddingId;
private final SparseArray<TypedValue> extraAttrs;
@@ -641,6 +647,8 @@ public class InvariantDeviceProfile {
isScalable = a.getBoolean(
R.styleable.GridDisplayOption_isScalable, false);
devicePaddingId = a.getResourceId(
R.styleable.GridDisplayOption_devicePaddingId, 0);
a.recycle();