From 199aec50ad1b117e2a555f3ac2ec46e820115124 Mon Sep 17 00:00:00 2001 From: Pierre Barbier de Reuille Date: Thu, 1 Jul 2021 14:22:31 +0100 Subject: [PATCH 1/2] Avoid calling AppWidgetHostViedw#updateAppWidgetSize We cannot call it anymore, because the system padding is not always used. Bug: 191612352 Test: Manually, using CtsVerifier and dedicated widgets Change-Id: I06353ba49a8e62127e593cdbcb86fadcf89ecb24 --- .../launcher3/widget/util/WidgetSizes.java | 48 ++++++++++--------- 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/src/com/android/launcher3/widget/util/WidgetSizes.java b/src/com/android/launcher3/widget/util/WidgetSizes.java index 5c8ea7299b..6d053be812 100644 --- a/src/com/android/launcher3/widget/util/WidgetSizes.java +++ b/src/com/android/launcher3/widget/util/WidgetSizes.java @@ -17,9 +17,7 @@ package com.android.launcher3.widget.util; import static android.appwidget.AppWidgetHostView.getDefaultPaddingForWidget; -import static com.android.launcher3.Utilities.ATLEAST_S; -import android.annotation.SuppressLint; import android.appwidget.AppWidgetHostView; import android.appwidget.AppWidgetManager; import android.content.ComponentName; @@ -37,21 +35,30 @@ import com.android.launcher3.LauncherAppState; import java.util.ArrayList; import java.util.List; -import java.util.stream.Collectors; /** A utility class for widget sizes related calculations. */ public final class WidgetSizes { /** * Returns the list of all possible sizes, in dp, for a widget of given spans on this device. + * + *

The returned sizes already take into account the system padding, and whether it is applied + * or not in that specific configuration. */ - public static ArrayList getWidgetSizes(Context context, int spanX, int spanY) { + public static ArrayList getWidgetPaddedSizes(Context context, ComponentName provider, + int spanX, int spanY) { + Rect padding = getDefaultPaddingForWidget(context, provider, /* padding= */ null); + ArrayList sizes = new ArrayList<>(2); final float density = context.getResources().getDisplayMetrics().density; final Point cellSize = new Point(); for (DeviceProfile profile : LauncherAppState.getIDP(context).supportedProfiles) { Size widgetSizePx = getWidgetSizePx(profile, spanX, spanY, cellSize); + if (!profile.shouldInsetWidgets()) { + widgetSizePx = new Size(widgetSizePx.getWidth() - padding.left - padding.right, + widgetSizePx.getHeight() - padding.top - padding.bottom); + } sizes.add(new SizeF(widgetSizePx.getWidth() / density, widgetSizePx.getHeight() / density)); } @@ -81,17 +88,22 @@ public final class WidgetSizes { *

On Android S+, it also updates the given {@code widgetView} with a list of sizes derived * from {@code spanX}, {@code spanY} in all supported device profiles. */ - @SuppressLint("NewApi") // Already added API check. public static void updateWidgetSizeRanges(AppWidgetHostView widgetView, Context context, int spanX, int spanY) { - List sizes = getWidgetSizes(context, spanX, spanY); - if (ATLEAST_S) { - widgetView.updateAppWidgetSize(new Bundle(), sizes); - } else { - Rect bounds = getMinMaxSizes(sizes); - widgetView.updateAppWidgetSize(new Bundle(), bounds.left, bounds.top, bounds.right, - bounds.bottom); + AppWidgetManager widgetManager = AppWidgetManager.getInstance(context); + int widgetId = widgetView.getAppWidgetId(); + if (widgetId <= 0) { + return; } + Bundle sizeOptions = getWidgetSizeOptions(context, widgetView.getAppWidgetInfo().provider, + spanX, spanY); + if (sizeOptions.getParcelableArrayList( + AppWidgetManager.OPTION_APPWIDGET_SIZES).equals( + widgetManager.getAppWidgetOptions(widgetId).getParcelableArrayList( + AppWidgetManager.OPTION_APPWIDGET_SIZES))) { + return; + } + widgetManager.updateAppWidgetOptions(widgetId, sizeOptions); } /** @@ -99,17 +111,7 @@ public final class WidgetSizes { */ public static Bundle getWidgetSizeOptions(Context context, ComponentName provider, int spanX, int spanY) { - ArrayList sizes = getWidgetSizes(context, spanX, spanY); - Rect padding = getDefaultPaddingForWidget(context, provider, null); - float density = context.getResources().getDisplayMetrics().density; - float xPaddingDips = (padding.left + padding.right) / density; - float yPaddingDips = (padding.top + padding.bottom) / density; - - ArrayList paddedSizes = sizes.stream() - .map(size -> new SizeF( - Math.max(0.f, size.getWidth() - xPaddingDips), - Math.max(0.f, size.getHeight() - yPaddingDips))) - .collect(Collectors.toCollection(ArrayList::new)); + ArrayList paddedSizes = getWidgetPaddedSizes(context, provider, spanX, spanY); Rect rect = getMinMaxSizes(paddedSizes); Bundle options = new Bundle(); From a7b3a14e7550f161e0a0173bce6fd6bfdd2c8c16 Mon Sep 17 00:00:00 2001 From: Pierre Barbier de Reuille Date: Thu, 1 Jul 2021 15:38:15 +0100 Subject: [PATCH 2/2] Use the computation of the widget size including padding. Found all the uses of getWidgetSizePx and replaced them with the computation of padded sizes (checked it all made sense). Test: Try the various widget pickers. Bug: 191612352 Change-Id: Id2a8d12ee7ce6baabef186dbb78d817975ea2212 --- .../widget/DatabaseWidgetPreviewLoader.java | 3 ++- .../android/launcher3/widget/WidgetCell.java | 4 ++- .../widget/picker/WidgetsListAdapter.java | 7 ++--- .../WidgetsRecommendationTableLayout.java | 4 +-- .../launcher3/widget/util/WidgetSizes.java | 27 +++++++++++++++++++ 5 files changed, 36 insertions(+), 9 deletions(-) diff --git a/src/com/android/launcher3/widget/DatabaseWidgetPreviewLoader.java b/src/com/android/launcher3/widget/DatabaseWidgetPreviewLoader.java index 867c770278..4ec7e60c86 100644 --- a/src/com/android/launcher3/widget/DatabaseWidgetPreviewLoader.java +++ b/src/com/android/launcher3/widget/DatabaseWidgetPreviewLoader.java @@ -417,7 +417,8 @@ public class DatabaseWidgetPreviewLoader implements WidgetPreviewLoader { previewHeight = drawable.getIntrinsicHeight(); } else { DeviceProfile dp = launcher.getDeviceProfile(); - Size widgetSize = WidgetSizes.getWidgetSizePx(dp, spanX, spanY); + Size widgetSize = WidgetSizes.getWidgetPaddedSizePx(mContext, info.provider, dp, spanX, + spanY); previewWidth = widgetSize.getWidth(); previewHeight = widgetSize.getHeight(); } diff --git a/src/com/android/launcher3/widget/WidgetCell.java b/src/com/android/launcher3/widget/WidgetCell.java index 8798332c85..c3edcce95a 100644 --- a/src/com/android/launcher3/widget/WidgetCell.java +++ b/src/com/android/launcher3/widget/WidgetCell.java @@ -363,7 +363,9 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener { /** Sets the widget preview image size, in number of cells, and preview scale. */ public Size setPreviewSize(int spanX, int spanY, float previewScale) { DeviceProfile deviceProfile = mActivity.getDeviceProfile(); - Size widgetSize = WidgetSizes.getWidgetSizePx(deviceProfile, spanX, spanY); + Size widgetSize = + mItem != null ? WidgetSizes.getWidgetItemSizePx(getContext(), deviceProfile, mItem) + : WidgetSizes.getWidgetSizePx(deviceProfile, spanX, spanY); mPreviewWidth = widgetSize.getWidth(); mPreviewHeight = widgetSize.getHeight(); mPreviewScale = previewScale; diff --git a/src/com/android/launcher3/widget/picker/WidgetsListAdapter.java b/src/com/android/launcher3/widget/picker/WidgetsListAdapter.java index 08a2263eff..1125b82150 100644 --- a/src/com/android/launcher3/widget/picker/WidgetsListAdapter.java +++ b/src/com/android/launcher3/widget/picker/WidgetsListAdapter.java @@ -296,11 +296,8 @@ public class WidgetsListAdapter extends Adapter implements OnHeaderC for (int i = 0; i < entry.mWidgets.size(); i++) { WidgetItem widgetItem = entry.mWidgets.get(i); DeviceProfile deviceProfile = activity.getDeviceProfile(); - Size widgetSize = - WidgetSizes.getWidgetSizePx( - deviceProfile, - widgetItem.spanX, - widgetItem.spanY); + Size widgetSize = WidgetSizes.getWidgetItemSizePx(mContext, deviceProfile, + widgetItem); if (widgetItem.isShortcut()) { widgetSize = new Size( diff --git a/src/com/android/launcher3/widget/picker/WidgetsRecommendationTableLayout.java b/src/com/android/launcher3/widget/picker/WidgetsRecommendationTableLayout.java index 6fc684862d..3800ede169 100644 --- a/src/com/android/launcher3/widget/picker/WidgetsRecommendationTableLayout.java +++ b/src/com/android/launcher3/widget/picker/WidgetsRecommendationTableLayout.java @@ -155,8 +155,8 @@ public final class WidgetsRecommendationTableLayout extends TableLayout { float rowHeight = 0; for (int j = 0; j < widgetItems.size(); j++) { WidgetItem widgetItem = widgetItems.get(j); - Size widgetSize = WidgetSizes.getWidgetSizePx( - deviceProfile, widgetItem.spanX, widgetItem.spanY); + Size widgetSize = WidgetSizes.getWidgetItemSizePx(getContext(), deviceProfile, + widgetItem); float previewHeight = widgetSize.getHeight() * previewScale; rowHeight = Math.max(rowHeight, previewHeight + mWidgetCellTextViewsHeight + mWidgetCellVerticalPadding); diff --git a/src/com/android/launcher3/widget/util/WidgetSizes.java b/src/com/android/launcher3/widget/util/WidgetSizes.java index 6d053be812..e2c84b5770 100644 --- a/src/com/android/launcher3/widget/util/WidgetSizes.java +++ b/src/com/android/launcher3/widget/util/WidgetSizes.java @@ -32,6 +32,7 @@ import androidx.annotation.Nullable; import com.android.launcher3.DeviceProfile; import com.android.launcher3.LauncherAppState; +import com.android.launcher3.model.WidgetItem; import java.util.ArrayList; import java.util.List; @@ -70,6 +71,32 @@ public final class WidgetSizes { return getWidgetSizePx(profile, spanX, spanY, /* recycledCellSize= */ null); } + /** + * Returns the size, in pixels and removing padding, a widget of given spans & {@code profile}. + */ + public static Size getWidgetPaddedSizePx(Context context, ComponentName component, + DeviceProfile profile, int spanX, int spanY) { + Size size = getWidgetSizePx(profile, spanX, spanY); + if (profile.shouldInsetWidgets()) { + return size; + } + Rect padding = getDefaultPaddingForWidget(context, component, /* padding= */ null); + return new Size(size.getWidth() - padding.left - padding.right, + size.getHeight() - padding.top - padding.bottom); + } + + /** + * Returns the size of a WidgetItem. + */ + public static Size getWidgetItemSizePx(Context context, DeviceProfile profile, + WidgetItem widgetItem) { + if (widgetItem.isShortcut()) { + return getWidgetSizePx(profile, widgetItem.spanX, widgetItem.spanY); + } + return getWidgetPaddedSizePx(context, widgetItem.componentName, profile, widgetItem.spanX, + widgetItem.spanY); + } + private static Size getWidgetSizePx(DeviceProfile profile, int spanX, int spanY, @Nullable Point recycledCellSize) { final int hBorderSpacing = (spanX - 1) * profile.cellLayoutBorderSpacingPx;