From 6a7a7f6bad9ddb3b09620b5bd3e931e4a7f94037 Mon Sep 17 00:00:00 2001 From: Jon Miranda Date: Thu, 1 Apr 2021 13:14:23 -0400 Subject: [PATCH 01/11] Set FLAG_IMMUTABLE flag on FirstScreenBroadcast PendingIntent. Bug: 179289753 Bug: 183927137 Test: restore phone and ensure broadcast is sent Change-Id: I8d8e38a1aa6bdf13879d460cfa84cabe6c6bb1f2 (cherry picked from commit b62fba0d0199d719ac63761846e09b4b28e1dc2c) Merged-In: I8d8e38a1aa6bdf13879d460cfa84cabe6c6bb1f2 --- .../android/launcher3/model/FirstScreenBroadcast.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/com/android/launcher3/model/FirstScreenBroadcast.java b/src/com/android/launcher3/model/FirstScreenBroadcast.java index 1149b553f6..b8dbd08901 100644 --- a/src/com/android/launcher3/model/FirstScreenBroadcast.java +++ b/src/com/android/launcher3/model/FirstScreenBroadcast.java @@ -15,6 +15,15 @@ */ package com.android.launcher3.model; +import static android.app.PendingIntent.FLAG_IMMUTABLE; +import static android.app.PendingIntent.FLAG_ONE_SHOT; +import static android.os.Process.myUserHandle; + +import static com.android.launcher3.pm.InstallSessionHelper.getUserHandle; + +import static java.util.stream.Collectors.groupingBy; +import static java.util.stream.Collectors.mapping; + import android.app.PendingIntent; import android.content.Context; import android.content.Intent; @@ -140,7 +149,7 @@ public class FirstScreenBroadcast { .putStringArrayListExtra(HOTSEAT_ITEM_EXTRA, new ArrayList<>(hotseatItems)) .putStringArrayListExtra(WIDGET_ITEM_EXTRA, new ArrayList<>(widgetItems)) .putExtra(VERIFICATION_TOKEN_EXTRA, PendingIntent.getActivity(context, 0, - new Intent(), PendingIntent.FLAG_ONE_SHOT))); + new Intent(), FLAG_ONE_SHOT | FLAG_IMMUTABLE))); } private static String getPackageName(ItemInfo info) { From 60b97de72bc3fabe88d27df6f56b30579abeda73 Mon Sep 17 00:00:00 2001 From: shawnlin Date: Mon, 7 Jun 2021 15:58:00 +0800 Subject: [PATCH 02/11] Play the nav bar animation for app launch from recent in live tile Bug: 189278432 Test: manual - launch an app from recent in live tile mode Change-Id: I9a39cdbbe0b8b9ee6d11a3ee53936d2fea699dd8 --- .../android/quickstep/RecentsAnimationController.java | 9 +++++++++ quickstep/src/com/android/quickstep/TaskViewUtils.java | 8 ++++++++ .../src/com/android/quickstep/views/RecentsView.java | 6 ++++++ 3 files changed, 23 insertions(+) diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationController.java b/quickstep/src/com/android/quickstep/RecentsAnimationController.java index 50d0569cf2..0ebe13be8d 100644 --- a/quickstep/src/com/android/quickstep/RecentsAnimationController.java +++ b/quickstep/src/com/android/quickstep/RecentsAnimationController.java @@ -18,6 +18,7 @@ package com.android.quickstep; import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; +import android.view.IRecentsAnimationController; import android.view.SurfaceControl; import android.window.PictureInPictureSurfaceTransaction; @@ -162,6 +163,14 @@ public class RecentsAnimationController { UI_HELPER_EXECUTOR.execute(() -> mController.detachNavigationBarFromApp(moveHomeToTop)); } + /** + * @see IRecentsAnimationController#animateNavigationBarToApp(long) + */ + @UiThread + public void animateNavigationBarToApp(long duration) { + UI_HELPER_EXECUTOR.execute(() -> mController.animateNavigationBarToApp(duration)); + } + /** * Sets the final surface transaction on a Task. This is used by Launcher to notify the system * that animating Activity to PiP has completed and the associated task surface should be diff --git a/quickstep/src/com/android/quickstep/TaskViewUtils.java b/quickstep/src/com/android/quickstep/TaskViewUtils.java index a59ba5136d..59bd1ed9ea 100644 --- a/quickstep/src/com/android/quickstep/TaskViewUtils.java +++ b/quickstep/src/com/android/quickstep/TaskViewUtils.java @@ -263,6 +263,14 @@ public final class TaskViewUtils { finalParams.applySurfaceParams(navBuilder.build()); } }); + } else if (inLiveTileMode) { + // There is no transition animation for app launch from recent in live tile mode so + // we have to trigger the navigation bar animation from system here. + final RecentsAnimationController controller = + recentsView.getRecentsAnimationController(); + if (controller != null) { + controller.animateNavigationBarToApp(RECENTS_LAUNCH_DURATION); + } } topMostSimulator = tsv; } diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index 74906ddac0..b7aca065bf 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -3843,4 +3843,10 @@ public abstract class RecentsView Date: Wed, 2 Jun 2021 16:02:37 -0700 Subject: [PATCH 03/11] [AA+] Reset search manager when exiting all apps. This is required to log search session exits properly, especially when exiting AllApps without clearing search query. Bug: 178562918 Test: Manual Change-Id: Id4c1007b051e9efd9ae5929c274a70cf3ae3cbf1 --- src/com/android/launcher3/Launcher.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 9aa7168f4e..578379b70d 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -1076,9 +1076,10 @@ public class Launcher extends StatefulActivity implements Launche getRotationHelper().setCurrentStateRequest(REQUEST_NONE); } - if (mPrevLauncherState != state && !ALL_APPS.equals(state) + if (ALL_APPS.equals(mPrevLauncherState) && !ALL_APPS.equals(state) // Making sure mAllAppsSessionLogId is not null to avoid double logging. && mAllAppsSessionLogId != null) { + getAppsView().getSearchUiManager().resetSearch(); getStatsLogManager().logger().log(LAUNCHER_ALLAPPS_EXIT); mAllAppsSessionLogId = null; } From 22b6039270bf85025a2e5c510539f736d4626700 Mon Sep 17 00:00:00 2001 From: Steven Ng Date: Mon, 7 Jun 2021 22:43:11 +0100 Subject: [PATCH 04/11] Exact widget sizes functionalities into an utility class Test: resize widget, move widget, add widget. Bug: 189975670 Change-Id: Ia0bc2297891e1cfa33697e985064db5d1dcdfc8b --- .../launcher3/AppWidgetResizeFrame.java | 89 +---------- src/com/android/launcher3/Workspace.java | 6 +- .../LauncherAccessibilityDelegate.java | 4 +- .../model/data/LauncherAppWidgetInfo.java | 4 +- .../launcher3/qsb/QsbContainerView.java | 6 +- .../widget/PendingAddWidgetInfo.java | 4 +- .../launcher3/widget/util/WidgetSizes.java | 145 ++++++++++++++++++ 7 files changed, 159 insertions(+), 99 deletions(-) create mode 100644 src/com/android/launcher3/widget/util/WidgetSizes.java diff --git a/src/com/android/launcher3/AppWidgetResizeFrame.java b/src/com/android/launcher3/AppWidgetResizeFrame.java index 5d9797ff88..74ac8c24c4 100644 --- a/src/com/android/launcher3/AppWidgetResizeFrame.java +++ b/src/com/android/launcher3/AppWidgetResizeFrame.java @@ -4,7 +4,6 @@ import static android.appwidget.AppWidgetHostView.getDefaultPaddingForWidget; import static com.android.launcher3.LauncherAnimUtils.LAYOUT_HEIGHT; import static com.android.launcher3.LauncherAnimUtils.LAYOUT_WIDTH; -import static com.android.launcher3.Utilities.ATLEAST_S; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_WIDGET_RESIZE_COMPLETED; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_WIDGET_RESIZE_STARTED; import static com.android.launcher3.views.BaseDragLayer.LAYOUT_X; @@ -13,18 +12,12 @@ import static com.android.launcher3.views.BaseDragLayer.LAYOUT_Y; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.animation.PropertyValuesHolder; -import android.appwidget.AppWidgetHostView; -import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetProviderInfo; -import android.content.ComponentName; import android.content.Context; -import android.graphics.Point; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.graphics.drawable.GradientDrawable; -import android.os.Bundle; import android.util.AttributeSet; -import android.util.SizeF; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; @@ -39,10 +32,10 @@ import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.util.PendingRequestArgs; import com.android.launcher3.widget.LauncherAppWidgetHostView; import com.android.launcher3.widget.LauncherAppWidgetProviderInfo; +import com.android.launcher3.widget.util.WidgetSizes; import java.util.ArrayList; import java.util.List; -import java.util.stream.Collectors; public class AppWidgetResizeFrame extends AbstractFloatingView implements View.OnKeyListener { private static final int SNAP_DURATION = 150; @@ -415,90 +408,12 @@ public class AppWidgetResizeFrame extends AbstractFloatingView implements View.O mRunningHInc += hSpanDelta; if (!onDismiss) { - updateWidgetSizeRanges(mWidgetView, mLauncher, spanX, spanY); + WidgetSizes.updateWidgetSizeRanges(mWidgetView, mLauncher, spanX, spanY); } } mWidgetView.requestLayout(); } - 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); - } - } - - /** Returns the list of sizes for a widget of given span, in dp. */ - public static ArrayList getWidgetSizes(Context context, int spanX, int spanY) { - ArrayList sizes = new ArrayList<>(2); - final float density = context.getResources().getDisplayMetrics().density; - Point cellSize = new Point(); - - for (DeviceProfile profile : LauncherAppState.getIDP(context).supportedProfiles) { - final float hBorderSpacing = (spanX - 1) * profile.cellLayoutBorderSpacingPx; - final float vBorderSpacing = (spanY - 1) * profile.cellLayoutBorderSpacingPx; - profile.getCellSize(cellSize); - sizes.add(new SizeF( - ((spanX * cellSize.x) + hBorderSpacing) / density, - ((spanY * cellSize.y) + vBorderSpacing) / density)); - } - return sizes; - } - - /** - * Returns the bundle to be used as the default options for a widget with provided size - */ - 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)); - - Rect rect = AppWidgetResizeFrame.getMinMaxSizes(paddedSizes); - Bundle options = new Bundle(); - options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH, rect.left); - options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT, rect.top); - options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH, rect.right); - options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT, rect.bottom); - options.putParcelableArrayList(AppWidgetManager.OPTION_APPWIDGET_SIZES, paddedSizes); - return options; - } - - /** - * Returns the min and max widths and heights given a list of sizes, in dp. - * - * @param sizes List of sizes to get the min/max from. - * @return A rectangle with the left (resp. top) is used for the min width (resp. height) and - * the right (resp. bottom) for the max. The returned rectangle is set with 0s if the list is - * empty. - */ - private static Rect getMinMaxSizes(List sizes) { - if (sizes.isEmpty()) { - return new Rect(); - } else { - SizeF first = sizes.get(0); - Rect result = new Rect((int) first.getWidth(), (int) first.getHeight(), - (int) first.getWidth(), (int) first.getHeight()); - for (int i = 1; i < sizes.size(); i++) { - result.union((int) sizes.get(i).getWidth(), (int) sizes.get(i).getHeight()); - } - return result; - } - } - @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java index d136cdadd9..17c8edce6e 100644 --- a/src/com/android/launcher3/Workspace.java +++ b/src/com/android/launcher3/Workspace.java @@ -114,6 +114,7 @@ import com.android.launcher3.widget.PendingAddWidgetInfo; import com.android.launcher3.widget.PendingAppWidgetHostView; import com.android.launcher3.widget.WidgetManagerHelper; import com.android.launcher3.widget.dragndrop.AppWidgetHostViewDragListener; +import com.android.launcher3.widget.util.WidgetSizes; import com.android.systemui.plugins.shared.LauncherOverlayManager.LauncherOverlay; import java.util.ArrayList; @@ -1854,7 +1855,7 @@ public class Workspace extends PagedView item.spanX = resultSpan[0]; item.spanY = resultSpan[1]; AppWidgetHostView awhv = (AppWidgetHostView) cell; - AppWidgetResizeFrame.updateWidgetSizeRanges(awhv, mLauncher, resultSpan[0], + WidgetSizes.updateWidgetSizeRanges(awhv, mLauncher, resultSpan[0], resultSpan[1]); } @@ -2528,8 +2529,7 @@ public class Workspace extends PagedView ((PendingAddWidgetInfo) pendingInfo).boundWidget : null; if (finalView != null && updateWidgetSize) { - AppWidgetResizeFrame.updateWidgetSizeRanges(finalView, mLauncher, item.spanX, - item.spanY); + WidgetSizes.updateWidgetSizeRanges(finalView, mLauncher, item.spanX, item.spanY); } int animationStyle = ANIMATE_INTO_POSITION_AND_DISAPPEAR; diff --git a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java index 2b36f19226..9faac5b7ef 100644 --- a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java +++ b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java @@ -21,7 +21,6 @@ import android.view.View.AccessibilityDelegate; import android.view.accessibility.AccessibilityNodeInfo; import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction; -import com.android.launcher3.AppWidgetResizeFrame; import com.android.launcher3.BubbleTextView; import com.android.launcher3.ButtonDropTarget; import com.android.launcher3.CellLayout; @@ -51,6 +50,7 @@ import com.android.launcher3.util.Thunk; import com.android.launcher3.views.OptionsPopupView; import com.android.launcher3.views.OptionsPopupView.OptionItem; import com.android.launcher3.widget.LauncherAppWidgetHostView; +import com.android.launcher3.widget.util.WidgetSizes; import java.util.ArrayList; import java.util.Collections; @@ -367,7 +367,7 @@ public class LauncherAccessibilityDelegate extends AccessibilityDelegate impleme } layout.markCellsAsOccupiedForView(host); - AppWidgetResizeFrame.updateWidgetSizeRanges(((LauncherAppWidgetHostView) host), mLauncher, + WidgetSizes.updateWidgetSizeRanges(((LauncherAppWidgetHostView) host), mLauncher, info.spanX, info.spanY); host.requestLayout(); mLauncher.getModelWriter().updateItemInDatabase(info); diff --git a/src/com/android/launcher3/model/data/LauncherAppWidgetInfo.java b/src/com/android/launcher3/model/data/LauncherAppWidgetInfo.java index 003b3bdc22..658c6e1dc6 100644 --- a/src/com/android/launcher3/model/data/LauncherAppWidgetInfo.java +++ b/src/com/android/launcher3/model/data/LauncherAppWidgetInfo.java @@ -26,13 +26,13 @@ import android.os.Process; import androidx.annotation.Nullable; -import com.android.launcher3.AppWidgetResizeFrame; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherSettings; import com.android.launcher3.logger.LauncherAtom; import com.android.launcher3.util.ContentWriter; import com.android.launcher3.widget.LauncherAppWidgetHostView; import com.android.launcher3.widget.LauncherAppWidgetProviderInfo; +import com.android.launcher3.widget.util.WidgetSizes; /** * Represents a widget (either instantiated or about to be) in the Launcher. @@ -196,7 +196,7 @@ public class LauncherAppWidgetInfo extends ItemInfo { */ public void onBindAppWidget(Launcher launcher, AppWidgetHostView hostView) { if (!mHasNotifiedInitialWidgetSizeChanged) { - AppWidgetResizeFrame.updateWidgetSizeRanges(hostView, launcher, spanX, spanY); + WidgetSizes.updateWidgetSizeRanges(hostView, launcher, spanX, spanY); mHasNotifiedInitialWidgetSizeChanged = true; } } diff --git a/src/com/android/launcher3/qsb/QsbContainerView.java b/src/com/android/launcher3/qsb/QsbContainerView.java index 22c3f58574..23ee251772 100644 --- a/src/com/android/launcher3/qsb/QsbContainerView.java +++ b/src/com/android/launcher3/qsb/QsbContainerView.java @@ -20,8 +20,6 @@ import static android.appwidget.AppWidgetManager.ACTION_APPWIDGET_BIND; import static android.appwidget.AppWidgetManager.EXTRA_APPWIDGET_ID; import static android.appwidget.AppWidgetManager.EXTRA_APPWIDGET_PROVIDER; -import static com.android.launcher3.AppWidgetResizeFrame.getWidgetSizeOptions; - import android.app.Activity; import android.app.Fragment; import android.app.SearchManager; @@ -49,6 +47,7 @@ import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.graphics.FragmentWithPreview; +import com.android.launcher3.widget.util.WidgetSizes; /** * A frame layout which contains a QSB. This internally uses fragment to bind the view, which @@ -292,7 +291,8 @@ public class QsbContainerView extends FrameLayout { protected Bundle createBindOptions() { InvariantDeviceProfile idp = LauncherAppState.getIDP(getContext()); - return getWidgetSizeOptions(getContext(), mWidgetInfo.provider, idp.numColumns, 1); + return WidgetSizes.getWidgetSizeOptions(getContext(), mWidgetInfo.provider, + idp.numColumns, 1); } protected View getDefaultView(ViewGroup container, boolean showSetupIcon) { diff --git a/src/com/android/launcher3/widget/PendingAddWidgetInfo.java b/src/com/android/launcher3/widget/PendingAddWidgetInfo.java index 3377abbb7b..c04c8dc8b5 100644 --- a/src/com/android/launcher3/widget/PendingAddWidgetInfo.java +++ b/src/com/android/launcher3/widget/PendingAddWidgetInfo.java @@ -15,7 +15,6 @@ */ package com.android.launcher3.widget; -import static com.android.launcher3.AppWidgetResizeFrame.getWidgetSizeOptions; import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_WIDGETS_TRAY; import android.appwidget.AppWidgetHostView; @@ -24,6 +23,7 @@ import android.os.Bundle; import com.android.launcher3.LauncherSettings; import com.android.launcher3.PendingAddItemInfo; +import com.android.launcher3.widget.util.WidgetSizes; /** * Meta data used for late binding of {@link LauncherAppWidgetProviderInfo}. @@ -61,6 +61,6 @@ public class PendingAddWidgetInfo extends PendingAddItemInfo { } public Bundle getDefaultSizeOptions(Context context) { - return getWidgetSizeOptions(context, componentName, spanX, spanY); + return WidgetSizes.getWidgetSizeOptions(context, componentName, spanX, spanY); } } diff --git a/src/com/android/launcher3/widget/util/WidgetSizes.java b/src/com/android/launcher3/widget/util/WidgetSizes.java new file mode 100644 index 0000000000..5c8ea7299b --- /dev/null +++ b/src/com/android/launcher3/widget/util/WidgetSizes.java @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +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; +import android.content.Context; +import android.graphics.Point; +import android.graphics.Rect; +import android.os.Bundle; +import android.util.Size; +import android.util.SizeF; + +import androidx.annotation.Nullable; + +import com.android.launcher3.DeviceProfile; +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. + */ + public static ArrayList getWidgetSizes(Context context, int spanX, int spanY) { + 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); + sizes.add(new SizeF(widgetSizePx.getWidth() / density, + widgetSizePx.getHeight() / density)); + } + return sizes; + } + + /** Returns the size, in pixels, a widget of given spans & {@code profile}. */ + public static Size getWidgetSizePx(DeviceProfile profile, int spanX, int spanY) { + return getWidgetSizePx(profile, spanX, spanY, /* recycledCellSize= */ null); + } + + private static Size getWidgetSizePx(DeviceProfile profile, int spanX, int spanY, + @Nullable Point recycledCellSize) { + final int hBorderSpacing = (spanX - 1) * profile.cellLayoutBorderSpacingPx; + final int vBorderSpacing = (spanY - 1) * profile.cellLayoutBorderSpacingPx; + if (recycledCellSize == null) { + recycledCellSize = new Point(); + } + profile.getCellSize(recycledCellSize); + return new Size(((spanX * recycledCellSize.x) + hBorderSpacing), + ((spanY * recycledCellSize.y) + vBorderSpacing)); + } + + /** + * Updates a given {@code widgetView} with size, {@code spanX}, {@code spanY}. + * + *

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); + } + } + + /** + * Returns the bundle to be used as the default options for a widget with provided size. + */ + 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)); + + Rect rect = getMinMaxSizes(paddedSizes); + Bundle options = new Bundle(); + options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH, rect.left); + options.putInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT, rect.top); + options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH, rect.right); + options.putInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT, rect.bottom); + options.putParcelableArrayList(AppWidgetManager.OPTION_APPWIDGET_SIZES, paddedSizes); + return options; + } + + /** + * Returns the min and max widths and heights given a list of sizes, in dp. + * + * @param sizes List of sizes to get the min/max from. + * @return A rectangle with the left (resp. top) is used for the min width (resp. height) and + * the right (resp. bottom) for the max. The returned rectangle is set with 0s if the list is + * empty. + */ + private static Rect getMinMaxSizes(List sizes) { + if (sizes.isEmpty()) { + return new Rect(); + } else { + SizeF first = sizes.get(0); + Rect result = new Rect((int) first.getWidth(), (int) first.getHeight(), + (int) first.getWidth(), (int) first.getHeight()); + for (int i = 1; i < sizes.size(); i++) { + result.union((int) sizes.get(i).getWidth(), (int) sizes.get(i).getHeight()); + } + return result; + } + } +} From 7e06df2b50461b9f2cef5b7b00eeba1fefd74bb7 Mon Sep 17 00:00:00 2001 From: Steven Ng Date: Mon, 7 Jun 2021 23:46:03 +0100 Subject: [PATCH 05/11] Use WidgetSizes to estimate widget size instead of custom calculation Also fix 2 bugs in WidgetCell 1. preview layout: padding is added to the AppWidgetHostView rather than the preview container. We shouldn't add padding to the size of the preview container. 2. widget_preview_shortcut_padding is a padding added to shortcuts but not widgets. Test: Open full widgets picker and observe widgets are rendered correctly in the widgets recommendation table. Also, observe the generated bitmap images are correctly rendered. Run AddWidgetTest. Bug: 189975670 Change-Id: I00db3200e0b61dc5e82f3c4bfdf34e197ea20314 --- .../launcher3/WidgetPreviewLoader.java | 12 ++++------ .../android/launcher3/widget/WidgetCell.java | 23 +++++++++---------- .../WidgetsRecommendationTableLayout.java | 11 +++++---- 3 files changed, 22 insertions(+), 24 deletions(-) diff --git a/src/com/android/launcher3/WidgetPreviewLoader.java b/src/com/android/launcher3/WidgetPreviewLoader.java index c7323d025b..ff3584acd3 100644 --- a/src/com/android/launcher3/WidgetPreviewLoader.java +++ b/src/com/android/launcher3/WidgetPreviewLoader.java @@ -27,10 +27,10 @@ import android.os.AsyncTask; import android.os.CancellationSignal; import android.os.Process; import android.os.UserHandle; -import android.util.ArrayMap; import android.util.Log; import android.util.LongSparseArray; import android.util.Pair; +import android.util.Size; import androidx.annotation.Nullable; @@ -50,6 +50,7 @@ import com.android.launcher3.util.Thunk; import com.android.launcher3.widget.LauncherAppWidgetProviderInfo; import com.android.launcher3.widget.WidgetCell; import com.android.launcher3.widget.WidgetManagerHelper; +import com.android.launcher3.widget.util.WidgetSizes; import java.util.ArrayList; import java.util.Collections; @@ -79,9 +80,6 @@ public class WidgetPreviewLoader { private final UserCache mUserCache; private final CacheDb mDb; - private final UserHandle mMyUser = Process.myUserHandle(); - private final ArrayMap mUserBadges = new ArrayMap<>(); - public WidgetPreviewLoader(Context context, IconCache iconCache) { mContext = context; mIconCache = iconCache; @@ -366,9 +364,9 @@ public class WidgetPreviewLoader { previewHeight = drawable.getIntrinsicHeight(); } else { DeviceProfile dp = launcher.getDeviceProfile(); - int tileSize = Math.min(dp.cellWidthPx, dp.cellHeightPx); - previewWidth = tileSize * spanX; - previewHeight = tileSize * spanY; + Size widgetSize = WidgetSizes.getWidgetSizePx(dp, spanX, spanY); + previewWidth = widgetSize.getWidth(); + previewHeight = widgetSize.getHeight(); } // Scale to fit width only - let the widget preview be clipped in the diff --git a/src/com/android/launcher3/widget/WidgetCell.java b/src/com/android/launcher3/widget/WidgetCell.java index e1999c9c3a..b1ccfd9591 100644 --- a/src/com/android/launcher3/widget/WidgetCell.java +++ b/src/com/android/launcher3/widget/WidgetCell.java @@ -21,12 +21,12 @@ import static com.android.launcher3.Utilities.ATLEAST_S; import android.content.Context; import android.content.res.Resources; import android.graphics.Bitmap; -import android.graphics.Point; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.os.CancellationSignal; import android.util.AttributeSet; import android.util.Log; +import android.util.Size; import android.view.Gravity; import android.view.MotionEvent; import android.view.View; @@ -48,6 +48,7 @@ import com.android.launcher3.WidgetPreviewLoader; import com.android.launcher3.icons.FastBitmapDrawable; import com.android.launcher3.icons.RoundDrawableWrapper; import com.android.launcher3.model.WidgetItem; +import com.android.launcher3.widget.util.WidgetSizes; /** * Represents the individual cell of the widget inside the widget tray. The preview is drawn @@ -96,7 +97,7 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener { protected final BaseActivity mActivity; private final CheckLongPressHelper mLongPressHelper; private final float mEnforcedCornerRadius; - private final int mPreviewPadding; + private final int mShortcutPreviewPadding; private RemoteViews mRemoteViewsPreview; private NavigableAppWidgetHostView mAppWidgetHostViewPreview; @@ -114,14 +115,14 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener { mActivity = BaseActivity.fromContext(context); mLongPressHelper = new CheckLongPressHelper(this); - mLongPressHelper.setLongPressTimeoutFactor(1); + setContainerWidth(); setWillNotDraw(false); setClipToPadding(false); setAccessibilityDelegate(mActivity.getAccessibilityDelegate()); mEnforcedCornerRadius = RoundedCornerEnforcement.computeEnforcedRadius(context); - mPreviewPadding = + mShortcutPreviewPadding = 2 * getResources().getDimensionPixelSize(R.dimen.widget_preview_shortcut_padding); } @@ -200,6 +201,8 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener { mWidgetPreviewLoader = loader; if (item.activityInfo != null) { setTag(new PendingAddShortcutInfo(item.activityInfo)); + mPreviewWidth += mShortcutPreviewPadding; + mPreviewHeight += mShortcutPreviewPadding; } else { setTag(new PendingAddWidgetInfo(item.widgetInfo)); } @@ -251,8 +254,6 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener { } appWidgetHostViewPreview.setPadding(padding.left, padding.top, padding.right, padding.bottom); - mPreviewWidth += padding.left + padding.right; - mPreviewHeight += padding.top + padding.bottom; appWidgetHostViewPreview.updateAppWidget(remoteViews); } @@ -299,7 +300,7 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener { float scale = 1f; if (getWidth() > 0 && getHeight() > 0) { // Scale down the preview size if it's wider than the cell. - float maxWidth = getWidth() - mPreviewPadding; + float maxWidth = getWidth(); float previewWidth = drawable.getIntrinsicWidth() * mPreviewScale; scale = Math.min(maxWidth / previewWidth, 1); } @@ -355,11 +356,9 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener { /** Sets the widget preview image size, in number of cells, and preview scale. */ public void setPreviewSize(int spanX, int spanY, float previewScale) { DeviceProfile deviceProfile = mActivity.getDeviceProfile(); - Point cellSize = deviceProfile.getCellSize(); - mPreviewWidth = cellSize.x * spanX + mPreviewPadding - + deviceProfile.cellLayoutBorderSpacingPx * (spanX - 1); - mPreviewHeight = cellSize.y * spanY + mPreviewPadding - + deviceProfile.cellLayoutBorderSpacingPx * (spanY - 1); + Size widgetSize = WidgetSizes.getWidgetSizePx(deviceProfile, spanX, spanY); + mPreviewWidth = widgetSize.getWidth(); + mPreviewHeight = widgetSize.getHeight(); mPreviewScale = previewScale; } diff --git a/src/com/android/launcher3/widget/picker/WidgetsRecommendationTableLayout.java b/src/com/android/launcher3/widget/picker/WidgetsRecommendationTableLayout.java index 62ef4ff64e..9167d870e3 100644 --- a/src/com/android/launcher3/widget/picker/WidgetsRecommendationTableLayout.java +++ b/src/com/android/launcher3/widget/picker/WidgetsRecommendationTableLayout.java @@ -18,6 +18,7 @@ package com.android.launcher3.widget.picker; import android.content.Context; import android.util.AttributeSet; import android.util.Log; +import android.util.Size; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; @@ -33,6 +34,7 @@ import com.android.launcher3.LauncherAppState; import com.android.launcher3.R; import com.android.launcher3.model.WidgetItem; import com.android.launcher3.widget.WidgetCell; +import com.android.launcher3.widget.util.WidgetSizes; import java.util.ArrayList; import java.util.List; @@ -44,7 +46,6 @@ public final class WidgetsRecommendationTableLayout extends TableLayout { private static final float MAX_DOWN_SCALE_RATIO = 0.5f; private final float mWidgetsRecommendationTableVerticalPadding; private final float mWidgetCellTextViewsHeight; - private final float mWidgetPreviewPadding; private float mRecommendationTableMaxHeight = Float.MAX_VALUE; @Nullable private OnLongClickListener mWidgetCellOnLongClickListener; @@ -61,8 +62,6 @@ public final class WidgetsRecommendationTableLayout extends TableLayout { mWidgetsRecommendationTableVerticalPadding = 2 * getResources() .getDimensionPixelSize(R.dimen.widget_cell_vertical_padding); mWidgetCellTextViewsHeight = 4 * getResources().getDimension(R.dimen.widget_cell_font_size); - mWidgetPreviewPadding = 2 * getResources() - .getDimensionPixelSize(R.dimen.widget_preview_shortcut_padding); } /** Sets a {@link android.view.View.OnLongClickListener} for all widget cells in this table. */ @@ -149,8 +148,10 @@ public final class WidgetsRecommendationTableLayout extends TableLayout { List widgetItems = recommendedWidgetsInTable.get(i); float rowHeight = 0; for (int j = 0; j < widgetItems.size(); j++) { - float previewHeight = widgetItems.get(j).spanY * deviceProfile.cellHeightPx - * previewScale + mWidgetPreviewPadding; + WidgetItem widgetItem = widgetItems.get(j); + Size widgetSize = WidgetSizes.getWidgetSizePx( + deviceProfile, widgetItem.spanX, widgetItem.spanY); + float previewHeight = widgetSize.getHeight() * previewScale; rowHeight = Math.max(rowHeight, previewHeight + mWidgetCellTextViewsHeight); } totalHeight += rowHeight; From 9b4448f4776ff2be373f1d53b3893bd4b8757d98 Mon Sep 17 00:00:00 2001 From: Jon Miranda Date: Tue, 8 Jun 2021 10:55:58 -0700 Subject: [PATCH 06/11] Set folder dot color to spec. Bug: 188095988 Test: manual Change-Id: Idf4d7f7b8f95d1d112ece8cd03d9c7d441a5fe0f --- res/values-v31/colors.xml | 2 ++ res/values/colors.xml | 2 ++ res/values/styles.xml | 6 +++--- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/res/values-v31/colors.xml b/res/values-v31/colors.xml index 7b37001ade..a9721a4434 100644 --- a/res/values-v31/colors.xml +++ b/res/values-v31/colors.xml @@ -37,4 +37,6 @@ @android:color/system_neutral1_900 + @android:color/system_accent2_50 + diff --git a/res/values/colors.xml b/res/values/colors.xml index c2b07e022d..7aab4fa88c 100644 --- a/res/values/colors.xml +++ b/res/values/colors.xml @@ -59,6 +59,8 @@ #FFF #FF000000 + ?attr/colorPrimary + #FFFFFFFF #FFFFFFFF #CCFFFFFF diff --git a/res/values/styles.xml b/res/values/styles.xml index 86dcf4cd53..571377cd3f 100644 --- a/res/values/styles.xml +++ b/res/values/styles.xml @@ -47,7 +47,7 @@ #89000000 @drawable/workspace_bg @style/WidgetContainerTheme - ?android:attr/colorPrimary + @color/folder_dot_color ?android:attr/colorBackgroundFloating ?android:attr/colorPrimary ?android:attr/textColorPrimary @@ -86,7 +86,7 @@ @android:color/transparent true @null - #FF464646 + @color/folder_dot_color ?android:attr/colorBackgroundFloating #FF80868B ?attr/workspaceTextColor @@ -108,7 +108,7 @@ @color/popup_color_secondary_dark @color/popup_color_tertiary_dark @style/WidgetContainerTheme.Dark - ?android:attr/colorPrimary + @color/folder_dot_color ?android:attr/colorBackgroundFloating ?android:attr/colorPrimary ?android:attr/textColorPrimary From e721f7272c96328ca272709a1367893608f8d144 Mon Sep 17 00:00:00 2001 From: Samuel Fufa Date: Tue, 8 Jun 2021 13:30:56 -0500 Subject: [PATCH 07/11] Fix wrong highlighted personal | work tab Bug: 189915880 Test: Manual Change-Id: I3e8687038d4f0bfdd1c5b7d8c444520730a2bcd4 --- .../launcher3/workprofile/PersonalWorkSlidingTabStrip.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/com/android/launcher3/workprofile/PersonalWorkSlidingTabStrip.java b/src/com/android/launcher3/workprofile/PersonalWorkSlidingTabStrip.java index 8f9cdc8a4c..59ada7b518 100644 --- a/src/com/android/launcher3/workprofile/PersonalWorkSlidingTabStrip.java +++ b/src/com/android/launcher3/workprofile/PersonalWorkSlidingTabStrip.java @@ -126,6 +126,7 @@ public class PersonalWorkSlidingTabStrip extends LinearLayout implements PageInd @Override public void setActiveMarker(int activePage) { updateTabTextColor(activePage); + updateIndicatorPosition(activePage); if (mOnActivePageChangedListener != null && mLastActivePage != activePage) { mOnActivePageChangedListener.onActivePageChanged(activePage); } From 284eef2bf91daddd8d07b16b83b7a680eb728dc6 Mon Sep 17 00:00:00 2001 From: zakcohen Date: Fri, 4 Jun 2021 13:49:04 -0700 Subject: [PATCH 08/11] Re-enable swipe up view inflation test. Disable chips by default as they are not plan of record for launch. Bug: 141579810 Test: Local and ran test Change-Id: Iae270c6ac4bbec4f7c29b1137cf926383443e85e --- .../android/quickstep/ViewInflationDuringSwipeUp.java | 9 +++++---- src/com/android/launcher3/config/FeatureFlags.java | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/quickstep/tests/src/com/android/quickstep/ViewInflationDuringSwipeUp.java b/quickstep/tests/src/com/android/quickstep/ViewInflationDuringSwipeUp.java index 4ca1f593c9..b4329c1765 100644 --- a/quickstep/tests/src/com/android/quickstep/ViewInflationDuringSwipeUp.java +++ b/quickstep/tests/src/com/android/quickstep/ViewInflationDuringSwipeUp.java @@ -43,7 +43,6 @@ import android.view.ViewConfiguration; import android.widget.RemoteViews; import androidx.test.filters.LargeTest; -import androidx.test.filters.Suppress; import androidx.test.runner.AndroidJUnit4; import androidx.test.uiautomator.By; import androidx.test.uiautomator.UiDevice; @@ -79,10 +78,7 @@ import java.util.function.IntConsumer; * directly (ex: new LinearLayout) * Using ExtendedMockito: Mocking static methods from platform classes (loaded in zygote) makes * the main thread extremely slow and untestable - * - * Suppressed until b/141579810 is resolved */ -@Suppress @LargeTest @RunWith(AndroidJUnit4.class) public class ViewInflationDuringSwipeUp extends AbstractQuickStepTest { @@ -188,6 +184,11 @@ public class ViewInflationDuringSwipeUp extends AbstractQuickStepTest { LauncherSettings.Settings.call(mResolver, LauncherSettings.Settings.METHOD_CLEAR_EMPTY_DB_FLAG); LauncherAppWidgetProviderInfo info = TestViewHelpers.findWidgetProvider(this, false); + // Make sure the widget is big enough to show a list of items + info.minSpanX = 2; + info.minSpanY = 2; + info.spanX = 2; + info.spanY = 2; LauncherAppWidgetInfo item = createWidgetInfo(info, getTargetContext(), true); addItemToScreen(item); diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java index ab72a077a1..0e710b7898 100644 --- a/src/com/android/launcher3/config/FeatureFlags.java +++ b/src/com/android/launcher3/config/FeatureFlags.java @@ -93,7 +93,7 @@ public final class FeatureFlags { // Keep as DeviceFlag to allow remote disable in emergency. public static final BooleanFlag ENABLE_SUGGESTED_ACTIONS_OVERVIEW = new DeviceFlag( - "ENABLE_SUGGESTED_ACTIONS_OVERVIEW", true, "Show chip hints on the overview screen"); + "ENABLE_SUGGESTED_ACTIONS_OVERVIEW", false, "Show chip hints on the overview screen"); public static final BooleanFlag ENABLE_DEVICE_SEARCH = new DeviceFlag( From 76877fda732a657086755a47a885ccf7b58aaa5e Mon Sep 17 00:00:00 2001 From: Lucas Dupin Date: Tue, 8 Jun 2021 21:51:47 -0700 Subject: [PATCH 09/11] Update blur radius Bug: 189976220 Test: manual Change-Id: If5e6d6be7314dacfad8c501a5ae2da6556ca3cea --- quickstep/res/values/config.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quickstep/res/values/config.xml b/quickstep/res/values/config.xml index b2ff7709d4..f22a9d7dbe 100644 --- a/quickstep/res/values/config.xml +++ b/quickstep/res/values/config.xml @@ -37,5 +37,5 @@ - 150 + 72 From 08cca82ecab9327fce8ca959feaf0f88902d8f37 Mon Sep 17 00:00:00 2001 From: Samuel Fufa Date: Tue, 25 May 2021 19:21:37 -0500 Subject: [PATCH 10/11] [AllApps][Work] Introduce work toggle Fab Screenshot: https://screenshot.googleplex.com/C4r7kKPxv3PKdyN Bug: 186856928 Test: on-device Change-Id: I69ffa0ef367b182688e69c730fc9dee1afa7cadd --- res/drawable/work_apps_toggle_background.xml | 31 +++ res/layout/work_mode_fab.xml | 33 +++ res/layout/work_mode_switch.xml | 9 +- res/layout/work_profile_edu.xml | 61 ----- res/values/dimens.xml | 4 + res/values/strings.xml | 13 +- .../allapps/AllAppsContainerView.java | 4 +- .../allapps/LauncherAllAppsContainerView.java | 8 - .../launcher3/allapps/WorkModeSwitch.java | 168 +++---------- .../android/launcher3/views/WorkEduView.java | 230 ------------------ 10 files changed, 118 insertions(+), 443 deletions(-) create mode 100644 res/drawable/work_apps_toggle_background.xml create mode 100644 res/layout/work_mode_fab.xml delete mode 100644 res/layout/work_profile_edu.xml delete mode 100644 src/com/android/launcher3/views/WorkEduView.java diff --git a/res/drawable/work_apps_toggle_background.xml b/res/drawable/work_apps_toggle_background.xml new file mode 100644 index 0000000000..a04d269875 --- /dev/null +++ b/res/drawable/work_apps_toggle_background.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + diff --git a/res/layout/work_mode_fab.xml b/res/layout/work_mode_fab.xml new file mode 100644 index 0000000000..21f269fed6 --- /dev/null +++ b/res/layout/work_mode_fab.xml @@ -0,0 +1,33 @@ + + + \ No newline at end of file diff --git a/res/layout/work_mode_switch.xml b/res/layout/work_mode_switch.xml index 31953c72aa..538a180992 100644 --- a/res/layout/work_mode_switch.xml +++ b/res/layout/work_mode_switch.xml @@ -1,5 +1,4 @@ - - - + android:paddingTop="@dimen/work_profile_footer_padding" /> diff --git a/res/layout/work_profile_edu.xml b/res/layout/work_profile_edu.xml deleted file mode 100644 index c3c7010f7e..0000000000 --- a/res/layout/work_profile_edu.xml +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - -