From 9681849b164d822c8f096c1baf110b4d21f442f1 Mon Sep 17 00:00:00 2001 From: Josh Tsuji Date: Fri, 7 May 2021 18:39:38 -0400 Subject: [PATCH 1/5] Adds launcher-side support for the SmartSpace shared element transition. This adds a new SmartSpaceTransitionController, which Launcher uses to register its SmartSpace with SysUI so that SysUI can manipulate it during an unlock animation. Bug: 187025480 Test: manual with all the different lock types Change-Id: I8ebf33e1a253e90f97875548113106cd828721e0 --- .../launcher3/BaseQuickstepLauncher.java | 2 +- .../com/android/quickstep/SystemUiProxy.java | 31 +++++++++++++++++-- .../quickstep/TouchInteractionService.java | 8 ++++- 3 files changed, 37 insertions(+), 4 deletions(-) diff --git a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java index e777ee7354..1b711d352d 100644 --- a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java +++ b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java @@ -184,7 +184,7 @@ public abstract class BaseQuickstepLauncher extends Launcher } @Override - protected void onUiChangedWhileSleeping() { + public void onUiChangedWhileSleeping() { // Remove the snapshot because the content view may have obvious changes. UI_HELPER_EXECUTOR.execute( () -> ActivityManagerWrapper.getInstance().invalidateHomeTaskSnapshot(this)); diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java index acf999253f..c20a4ccdda 100644 --- a/quickstep/src/com/android/quickstep/SystemUiProxy.java +++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java @@ -40,6 +40,8 @@ import com.android.launcher3.util.SplitConfigurationOptions; import com.android.systemui.shared.recents.ISystemUiProxy; import com.android.systemui.shared.recents.model.Task; import com.android.systemui.shared.system.RemoteTransitionCompat; +import com.android.systemui.shared.system.smartspace.ISmartspaceCallback; +import com.android.systemui.shared.system.smartspace.ISmartspaceTransitionController; import com.android.wm.shell.onehanded.IOneHanded; import com.android.wm.shell.pip.IPip; import com.android.wm.shell.pip.IPipAnimationListener; @@ -61,6 +63,7 @@ public class SystemUiProxy implements ISystemUiProxy, private ISystemUiProxy mSystemUiProxy; private IPip mPip; + private ISmartspaceTransitionController mSmartspaceTransitionController; private ISplitScreen mSplitScreen; private IOneHanded mOneHanded; private IShellTransitions mShellTransitions; @@ -74,6 +77,7 @@ public class SystemUiProxy implements ISystemUiProxy, private IPipAnimationListener mPendingPipAnimationListener; private ISplitScreenListener mPendingSplitScreenListener; private IStartingWindowListener mPendingStartingWindowListener; + private ISmartspaceCallback mPendingSmartspaceCallback; // Used to dedupe calls to SystemUI private int mLastShelfHeight; @@ -125,7 +129,8 @@ public class SystemUiProxy implements ISystemUiProxy, public void setProxy(ISystemUiProxy proxy, IPip pip, ISplitScreen splitScreen, IOneHanded oneHanded, IShellTransitions shellTransitions, - IStartingWindow startingWindow) { + IStartingWindow startingWindow, + ISmartspaceTransitionController smartSpaceTransitionController) { unlinkToDeath(); mSystemUiProxy = proxy; mPip = pip; @@ -133,6 +138,7 @@ public class SystemUiProxy implements ISystemUiProxy, mOneHanded = oneHanded; mShellTransitions = shellTransitions; mStartingWindow = startingWindow; + mSmartspaceTransitionController = smartSpaceTransitionController; linkToDeath(); // re-attach the listeners once missing due to setProxy has not been initialized yet. if (mPendingPipAnimationListener != null && mPip != null) { @@ -147,10 +153,14 @@ public class SystemUiProxy implements ISystemUiProxy, setStartingWindowListener(mPendingStartingWindowListener); mPendingStartingWindowListener = null; } + if (mPendingSmartspaceCallback != null && mSmartspaceTransitionController != null) { + setSmartspaceCallback(mPendingSmartspaceCallback); + mPendingSmartspaceCallback = null; + } } public void clearProxy() { - setProxy(null, null, null, null, null, null); + setProxy(null, null, null, null, null, null, null); } // TODO(141886704): Find a way to remove this @@ -631,4 +641,21 @@ public class SystemUiProxy implements ISystemUiProxy, mPendingStartingWindowListener = listener; } } + + + // + // SmartSpace transitions + // + + public void setSmartspaceCallback(ISmartspaceCallback callback) { + if (mSmartspaceTransitionController != null) { + try { + mSmartspaceTransitionController.setSmartspace(callback); + } catch (RemoteException e) { + Log.w(TAG, "Failed call setStartingWindowListener", e); + } + } else { + mPendingSmartspaceCallback = callback; + } + } } diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java index edc7a3c8b8..419c60c5af 100644 --- a/quickstep/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java @@ -30,6 +30,7 @@ import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SHE import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SHELL_SHELL_TRANSITIONS; import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SHELL_SPLIT_SCREEN; import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SHELL_STARTING_WINDOW; +import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SMARTSPACE_TRANSITION_CONTROLLER; import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SYSUI_PROXY; import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_TRACING_ENABLED; @@ -107,6 +108,7 @@ import com.android.systemui.shared.system.InputChannelCompat; import com.android.systemui.shared.system.InputChannelCompat.InputEventReceiver; import com.android.systemui.shared.system.InputConsumerController; import com.android.systemui.shared.system.InputMonitorCompat; +import com.android.systemui.shared.system.smartspace.ISmartspaceTransitionController; import com.android.systemui.shared.tracing.ProtoTraceable; import com.android.wm.shell.onehanded.IOneHanded; import com.android.wm.shell.pip.IPip; @@ -176,9 +178,13 @@ public class TouchInteractionService extends Service implements PluginListener { SystemUiProxy.INSTANCE.get(TouchInteractionService.this).setProxy(proxy, pip, - splitscreen, onehanded, shellTransitions, startingWindow); + splitscreen, onehanded, shellTransitions, startingWindow, + smartspaceTransitionController); TouchInteractionService.this.initInputMonitor(); preloadOverview(true /* fromInit */); mDeviceState.runOnUserUnlocked(() -> { From 880fc577c0639bd14662db9e7d70d927279f6688 Mon Sep 17 00:00:00 2001 From: Samuel Fufa Date: Fri, 21 May 2021 12:42:32 -0500 Subject: [PATCH 2/5] Remove AllApps prediction edu Test: Manual Bug: 183579072 Change-Id: Ibaffc5ac711e35df5256baed8be57159046fbdda --- .../appprediction/AllAppsTipView.java | 83 ------------------- .../appprediction/PredictionRowView.java | 1 - res/drawable/all_apps_tabs_background.xml | 5 +- res/layout/arrow_toast.xml | 11 ++- res/values/dimens.xml | 1 + .../android/launcher3/views/ArrowTipView.java | 35 +++++--- 6 files changed, 33 insertions(+), 103 deletions(-) delete mode 100644 quickstep/src/com/android/launcher3/appprediction/AllAppsTipView.java diff --git a/quickstep/src/com/android/launcher3/appprediction/AllAppsTipView.java b/quickstep/src/com/android/launcher3/appprediction/AllAppsTipView.java deleted file mode 100644 index 98bf483a3d..0000000000 --- a/quickstep/src/com/android/launcher3/appprediction/AllAppsTipView.java +++ /dev/null @@ -1,83 +0,0 @@ -/** - * Copyright (C) 2019 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.appprediction; - -import static com.android.launcher3.AbstractFloatingView.TYPE_DISCOVERY_BOUNCE; -import static com.android.launcher3.AbstractFloatingView.TYPE_ON_BOARD_POPUP; -import static com.android.launcher3.LauncherState.ALL_APPS; - -import android.os.UserManager; - -import com.android.launcher3.AbstractFloatingView; -import com.android.launcher3.Launcher; -import com.android.launcher3.LauncherState; -import com.android.launcher3.R; -import com.android.launcher3.Utilities; -import com.android.launcher3.allapps.FloatingHeaderView; -import com.android.launcher3.statemanager.StateManager.StateListener; -import com.android.launcher3.views.ArrowTipView; - -/** - * ArrowTip helper aligned just above prediction apps, shown to users that enter all apps for the - * first time. - */ -public class AllAppsTipView { - - private static final String ALL_APPS_TIP_SEEN = "launcher.all_apps_tip_seen"; - - private static boolean showAllAppsTipIfNecessary(Launcher launcher) { - FloatingHeaderView floatingHeaderView = launcher.getAppsView().getFloatingHeaderView(); - if (!floatingHeaderView.hasVisibleContent() - || AbstractFloatingView.getOpenView(launcher, - TYPE_ON_BOARD_POPUP | TYPE_DISCOVERY_BOUNCE) != null - || !launcher.isInState(ALL_APPS) - || hasSeenAllAppsTip(launcher) - || launcher.getSystemService(UserManager.class).isDemoUser() - || Utilities.IS_RUNNING_IN_TEST_HARNESS) { - return false; - } - - int[] coords = new int[2]; - floatingHeaderView.findFixedRowByType(PredictionRowView.class).getLocationOnScreen(coords); - ArrowTipView arrowTipView = new ArrowTipView(launcher).setOnClosedCallback(() -> { - launcher.getSharedPrefs().edit().putBoolean(ALL_APPS_TIP_SEEN, true).apply(); - // TODO: add log to WW - }); - arrowTipView.show(launcher.getString(R.string.all_apps_prediction_tip), coords[1]); - - return true; - } - - private static boolean hasSeenAllAppsTip(Launcher launcher) { - return launcher.getSharedPrefs().getBoolean(ALL_APPS_TIP_SEEN, false); - } - - public static void scheduleShowIfNeeded(Launcher launcher) { - if (!hasSeenAllAppsTip(launcher)) { - launcher.getStateManager().addStateListener(new StateListener() { - @Override - public void onStateTransitionComplete(LauncherState finalState) { - if (finalState == ALL_APPS) { - if (showAllAppsTipIfNecessary(launcher)) { - launcher.getStateManager().removeStateListener(this); - } - } - } - }); - } - } -} diff --git a/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java b/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java index 6d5975f5fa..de040821b4 100644 --- a/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java +++ b/quickstep/src/com/android/launcher3/appprediction/PredictionRowView.java @@ -88,7 +88,6 @@ public class PredictionRowView extends LinearLayout implements @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); - AllAppsTipView.scheduleShowIfNeeded(mLauncher); } public void setup(FloatingHeaderView parent, FloatingHeaderRow[] rows, boolean tabsHidden) { diff --git a/res/drawable/all_apps_tabs_background.xml b/res/drawable/all_apps_tabs_background.xml index f88252217e..a345dd3afc 100644 --- a/res/drawable/all_apps_tabs_background.xml +++ b/res/drawable/all_apps_tabs_background.xml @@ -16,8 +16,9 @@ + android:top="@dimen/all_apps_tabs_vertical_padding" + android:bottom="@dimen/all_apps_tabs_vertical_padding +"> diff --git a/res/layout/arrow_toast.xml b/res/layout/arrow_toast.xml index ae60e1bf06..c071becb84 100644 --- a/res/layout/arrow_toast.xml +++ b/res/layout/arrow_toast.xml @@ -14,9 +14,7 @@ limitations under the License. --> - @@ -40,7 +38,8 @@ android:gravity="center" android:layout_gravity="center_vertical" android:textColor="@color/arrow_tip_view_content" - android:textSize="16sp"/> + android:textSize="16sp" /> + + android:contentDescription="@string/accessibility_close" /> diff --git a/res/values/dimens.xml b/res/values/dimens.xml index bfa02c07d3..7d412afa5a 100644 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -105,6 +105,7 @@ 8dp 2dp + 10dp 3dp diff --git a/src/com/android/launcher3/views/ArrowTipView.java b/src/com/android/launcher3/views/ArrowTipView.java index a6f2b42a29..5fdfda81ff 100644 --- a/src/com/android/launcher3/views/ArrowTipView.java +++ b/src/com/android/launcher3/views/ArrowTipView.java @@ -53,11 +53,19 @@ public class ArrowTipView extends AbstractFloatingView { protected final BaseDraggingActivity mActivity; private final Handler mHandler = new Handler(); + private final boolean mIsPointingUp; + private final int mArrowWidth; private Runnable mOnClosed; public ArrowTipView(Context context) { + this(context, false); + } + + public ArrowTipView(Context context, boolean isPointingUp) { super(context, null, 0); mActivity = BaseDraggingActivity.fromContext(context); + mIsPointingUp = isPointingUp; + mArrowWidth = context.getResources().getDimensionPixelSize(R.dimen.arrow_toast_arrow_width); init(context); } @@ -105,13 +113,17 @@ public class ArrowTipView extends AbstractFloatingView { View arrowView = findViewById(R.id.arrow); ViewGroup.LayoutParams arrowLp = arrowView.getLayoutParams(); ShapeDrawable arrowDrawable = new ShapeDrawable(TriangleShape.create( - arrowLp.width, arrowLp.height, false)); + arrowLp.width, arrowLp.height, mIsPointingUp)); Paint arrowPaint = arrowDrawable.getPaint(); - arrowPaint.setColor(ContextCompat.getColor(getContext(), R.color.arrow_tip_view_bg)); + arrowPaint.setColor(ContextCompat.getColor(getContext(), R.color.arrow_tip_view_bg)); // The corner path effect won't be reflected in the shadow, but shouldn't be noticeable. arrowPaint.setPathEffect(new CornerPathEffect( context.getResources().getDimension(R.dimen.arrow_toast_corner_radius))); arrowView.setBackground(arrowDrawable); + if (mIsPointingUp) { + removeView(arrowView); + addView(arrowView, 0); + } mIsOpen = true; @@ -128,10 +140,10 @@ public class ArrowTipView extends AbstractFloatingView { /** * Show the ArrowTipView (tooltip) center, start, or end aligned. * - * @param text The text to be shown in the tooltip. - * @param gravity The gravity aligns the tooltip center, start, or end. + * @param text The text to be shown in the tooltip. + * @param gravity The gravity aligns the tooltip center, start, or end. * @param arrowMarginStart The margin from start to place arrow (ignored if center) - * @param top The Y coordinate of the bottom of tooltip. + * @param top The Y coordinate of the bottom of tooltip. * @return The tooltip. */ public ArrowTipView show(String text, int gravity, int arrowMarginStart, int top) { @@ -149,15 +161,15 @@ public class ArrowTipView extends AbstractFloatingView { arrowMarginStart = parent.getMeasuredWidth() - arrowMarginStart; } if (gravity == Gravity.END) { - lp.setMarginEnd(parent.getMeasuredWidth() - arrowMarginStart); + lp.setMarginEnd(parent.getMeasuredWidth() - arrowMarginStart - mArrowWidth); } else if (gravity == Gravity.START) { - lp.setMarginStart(arrowMarginStart); + lp.setMarginStart(arrowMarginStart - mArrowWidth / 2); } requestLayout(); params.leftMargin = mActivity.getDeviceProfile().workspacePadding.left; params.rightMargin = mActivity.getDeviceProfile().workspacePadding.right; - post(() -> setY(top - getHeight())); + post(() -> setY(top - (mIsPointingUp ? 0 : getHeight()))); setAlpha(0); animate() .alpha(1f) @@ -172,13 +184,14 @@ public class ArrowTipView extends AbstractFloatingView { /** * Show the ArrowTipView (tooltip) custom aligned. * - * @param text The text to be shown in the tooltip. + * @param text The text to be shown in the tooltip. * @param arrowXCoord The X coordinate for the arrow on the tip. The arrow is usually in the * center of ArrowTipView unless the ArrowTipView goes beyond screen margin. - * @param yCoord The Y coordinate of the bottom of the tooltip. + * @param yCoord The Y coordinate of the bottom of the tooltip. * @return The tool tip view. */ - @Nullable public ArrowTipView showAtLocation(String text, int arrowXCoord, int yCoord) { + @Nullable + public ArrowTipView showAtLocation(String text, int arrowXCoord, int yCoord) { ViewGroup parent = mActivity.getDragLayer(); @Px int parentViewWidth = parent.getWidth(); @Px int textViewWidth = getContext().getResources() From da85cb91f16968abc86d89a6767172361afb6abc Mon Sep 17 00:00:00 2001 From: Jason Chang Date: Thu, 13 May 2021 17:20:05 +0800 Subject: [PATCH 3/5] Migrate trigger logic to fullfill new UI changes for One-handed mode settings. According to new key visual changes for One-handed mode, modify the trigger condition to reflect the changes. Bug: 175851783 Test: manual Test: atest WMShellUnitTests Change-Id: I4d734b31cafd5ce884010642b5e613c3deadfb20 --- .../android/quickstep/RecentsAnimationDeviceState.java | 2 +- .../inputconsumers/OneHandedModeInputConsumer.java | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java index e821e06180..fa37901f27 100644 --- a/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java +++ b/quickstep/src/com/android/quickstep/RecentsAnimationDeviceState.java @@ -561,7 +561,7 @@ public class RecentsAnimationDeviceState implements return false; } - if (mIsOneHandedModeEnabled || mIsSwipeToNotificationEnabled) { + if (mIsOneHandedModeEnabled) { final Info displayInfo = mDisplayController.getInfo(); return (mRotationTouchHelper.touchInOneHandedModeRegion(ev) && displayInfo.rotation != Surface.ROTATION_90 diff --git a/quickstep/src/com/android/quickstep/inputconsumers/OneHandedModeInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/OneHandedModeInputConsumer.java index 8d9c524a57..bc209027e8 100644 --- a/quickstep/src/com/android/quickstep/inputconsumers/OneHandedModeInputConsumer.java +++ b/quickstep/src/com/android/quickstep/inputconsumers/OneHandedModeInputConsumer.java @@ -147,12 +147,10 @@ public class OneHandedModeInputConsumer extends DelegateInputConsumer { } private void onStartGestureDetected() { - if (mDeviceState.isOneHandedModeEnabled()) { - if (!mDeviceState.isOneHandedModeActive()) { - SystemUiProxy.INSTANCE.get(mContext).startOneHandedMode(); - } - } else if (mDeviceState.isSwipeToNotificationEnabled()) { + if (mDeviceState.isSwipeToNotificationEnabled()) { SystemUiProxy.INSTANCE.get(mContext).expandNotificationPanel(); + } else if (!mDeviceState.isOneHandedModeActive()) { + SystemUiProxy.INSTANCE.get(mContext).startOneHandedMode(); } } From 295a4029083b88b6917adcaa02593bcf9976738b Mon Sep 17 00:00:00 2001 From: Pierre Barbier de Reuille Date: Wed, 26 May 2021 16:20:58 +0100 Subject: [PATCH 4/5] Update the computation of the widget span from size The new computation takes into account the new cell layout border spacing. Change-Id: Ic20e0906bbbaaf1e53475585e2a6ca31c277e09b Bug: 187461595 Test: Manual testing, varying the sizes in a widget --- .../LauncherAppWidgetProviderInfoTest.java | 43 +++++++ .../widget/LauncherAppWidgetProviderInfo.java | 107 +++++++++++------- 2 files changed, 109 insertions(+), 41 deletions(-) diff --git a/robolectric_tests/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfoTest.java b/robolectric_tests/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfoTest.java index d97701148b..d18138f8d2 100644 --- a/robolectric_tests/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfoTest.java +++ b/robolectric_tests/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfoTest.java @@ -20,8 +20,10 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doAnswer; +import android.appwidget.AppWidgetHostView; import android.content.Context; import android.graphics.Point; +import android.graphics.Rect; import com.android.launcher3.DeviceProfile; import com.android.launcher3.InvariantDeviceProfile; @@ -110,6 +112,47 @@ public final class LauncherAppWidgetProviderInfoTest { assertThat(info.minSpanY).isEqualTo(2); } + @Test + public void initSpans_minResizeWidthWithCellSpacingAndWidgetInset_shouldInitializeMinSpans() { + InvariantDeviceProfile idp = createIDP(); + DeviceProfile dp = idp.supportedProfiles.get(0); + Rect padding = new Rect(); + AppWidgetHostView.getDefaultPaddingForWidget(mContext, null, padding); + int maxPadding = Math.max(Math.max(padding.left, padding.right), + Math.max(padding.top, padding.bottom)); + dp.cellLayoutBorderSpacingPx = maxPadding + 1; + Mockito.when(dp.shouldInsetWidgets()).thenReturn(true); + + LauncherAppWidgetProviderInfo info = new LauncherAppWidgetProviderInfo(); + info.minResizeWidth = CELL_SIZE * 2 + maxPadding; + info.minResizeHeight = CELL_SIZE * 2 + maxPadding; + + info.initSpans(mContext, idp); + + assertThat(info.minSpanX).isEqualTo(2); + assertThat(info.minSpanY).isEqualTo(2); + } + + @Test + public void initSpans_minResizeWidthWithCellSpacingAndNoWidgetInset_shouldInitializeMinSpans() { + InvariantDeviceProfile idp = createIDP(); + DeviceProfile dp = idp.supportedProfiles.get(0); + Rect padding = new Rect(); + AppWidgetHostView.getDefaultPaddingForWidget(mContext, null, padding); + int maxPadding = Math.max(Math.max(padding.left, padding.right), + Math.max(padding.top, padding.bottom)); + dp.cellLayoutBorderSpacingPx = maxPadding - 1; + Mockito.when(dp.shouldInsetWidgets()).thenReturn(false); + LauncherAppWidgetProviderInfo info = new LauncherAppWidgetProviderInfo(); + info.minResizeWidth = CELL_SIZE * 2 + maxPadding; + info.minResizeHeight = CELL_SIZE * 2 + maxPadding; + + info.initSpans(mContext, idp); + + assertThat(info.minSpanX).isEqualTo(3); + assertThat(info.minSpanY).isEqualTo(3); + } + private InvariantDeviceProfile createIDP() { DeviceProfile profile = Mockito.mock(DeviceProfile.class); doAnswer(i -> { diff --git a/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfo.java b/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfo.java index 53b5fec31c..14108f614c 100644 --- a/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfo.java +++ b/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfo.java @@ -67,61 +67,86 @@ public class LauncherAppWidgetProviderInfo extends AppWidgetProviderInfo } public void initSpans(Context context, InvariantDeviceProfile idp) { - // Always assume we're working with the smallest span to make sure we - // reserve enough space in both orientations. - float smallestCellWidth = Float.MAX_VALUE; - float smallestCellHeight = Float.MAX_VALUE; + int minSpanX = 0; + int minSpanY = 0; + int maxSpanX = idp.numColumns; + int maxSpanY = idp.numRows; + int spanX = 0; + int spanY = 0; + + Rect widgetPadding = new Rect(); + Rect localPadding = new Rect(); + AppWidgetHostView.getDefaultPaddingForWidget(context, provider, widgetPadding); Point cellSize = new Point(); - boolean isWidgetPadded = false; for (DeviceProfile dp : idp.supportedProfiles) { dp.getCellSize(cellSize); - smallestCellWidth = Math.min(smallestCellWidth, cellSize.x); - smallestCellHeight = Math.min(smallestCellHeight, cellSize.y); - isWidgetPadded = isWidgetPadded || !dp.shouldInsetWidgets(); + // We want to account for the extra amount of padding that we are adding to the widget + // to ensure that it gets the full amount of space that it has requested. + // If grids supports insetting widgets, we do not account for widget padding. + if (dp.shouldInsetWidgets()) { + localPadding.setEmpty(); + } else { + localPadding.set(widgetPadding); + } + minSpanX = Math.max(minSpanX, + getSpanX(localPadding, minResizeWidth, dp.cellLayoutBorderSpacingPx, + cellSize.x)); + minSpanY = Math.max(minSpanY, + getSpanY(localPadding, minResizeHeight, dp.cellLayoutBorderSpacingPx, + cellSize.y)); + + if (ATLEAST_S) { + if (maxResizeWidth > 0) { + maxSpanX = Math.min(maxSpanX, + getSpanX(localPadding, maxResizeWidth, dp.cellLayoutBorderSpacingPx, + cellSize.x)); + } + if (maxResizeHeight > 0) { + maxSpanY = Math.min(maxSpanY, + getSpanY(localPadding, maxResizeHeight, dp.cellLayoutBorderSpacingPx, + cellSize.y)); + } + } + + spanX = Math.max(spanX, + getSpanX(localPadding, minWidth, dp.cellLayoutBorderSpacingPx, cellSize.x)); + spanY = Math.max(spanY, + getSpanY(localPadding, minHeight, dp.cellLayoutBorderSpacingPx, cellSize.y)); } - // We want to account for the extra amount of padding that we are adding to the widget - // to ensure that it gets the full amount of space that it has requested. - // If grids supports insetting widgets, we do not account for widget padding. - Rect widgetPadding = new Rect(); - if (isWidgetPadded) { - AppWidgetHostView.getDefaultPaddingForWidget(context, provider, widgetPadding); + if (ATLEAST_S) { + // Ensures maxSpan >= minSpan + maxSpanX = Math.max(maxSpanX, minSpanX); + maxSpanY = Math.max(maxSpanY, minSpanY); + + // Use targetCellWidth/Height if it is within the min/max ranges. + // Otherwise, use the span of minWidth/Height. + if (targetCellWidth >= minSpanX && targetCellWidth <= maxSpanX + && targetCellHeight >= minSpanY && targetCellHeight <= maxSpanY) { + spanX = targetCellWidth; + spanY = targetCellHeight; + } } - minSpanX = getSpanX(widgetPadding, minResizeWidth, smallestCellWidth); - minSpanY = getSpanY(widgetPadding, minResizeHeight, smallestCellHeight); - - // Use maxResizeWidth/Height if they are defined and we're on S or above. - maxSpanX = - (ATLEAST_S && maxResizeWidth > 0) - ? getSpanX(widgetPadding, maxResizeWidth, smallestCellWidth) - : idp.numColumns; - maxSpanY = - (ATLEAST_S && maxResizeHeight > 0) - ? getSpanY(widgetPadding, maxResizeHeight, smallestCellHeight) - : idp.numRows; - - // Use targetCellWidth/Height if it is within the min/max ranges and we're on S or above. - // Otherwise, fall back to minWidth/Height. - if (ATLEAST_S && targetCellWidth >= minSpanX && targetCellWidth <= maxSpanX - && targetCellHeight >= minSpanY && targetCellHeight <= maxSpanY) { - spanX = targetCellWidth; - spanY = targetCellHeight; - } else { - spanX = getSpanX(widgetPadding, minWidth, smallestCellWidth); - spanY = getSpanY(widgetPadding, minHeight, smallestCellHeight); - } + this.minSpanX = minSpanX; + this.minSpanY = minSpanY; + this.maxSpanX = maxSpanX; + this.maxSpanY = maxSpanY; + this.spanX = spanX; + this.spanY = spanY; } - private int getSpanX(Rect widgetPadding, int widgetWidth, float cellWidth) { + private int getSpanX(Rect widgetPadding, int widgetWidth, int cellSpacing, float cellWidth) { return Math.max(1, (int) Math.ceil( - (widgetWidth + widgetPadding.left + widgetPadding.right) / cellWidth)); + (widgetWidth + widgetPadding.left + widgetPadding.right + cellSpacing) / (cellWidth + + cellSpacing))); } - private int getSpanY(Rect widgetPadding, int widgetHeight, float cellHeight) { + private int getSpanY(Rect widgetPadding, int widgetHeight, int cellSpacing, float cellHeight) { return Math.max(1, (int) Math.ceil( - (widgetHeight + widgetPadding.top + widgetPadding.bottom) / cellHeight)); + (widgetHeight + widgetPadding.top + widgetPadding.bottom + cellSpacing) / ( + cellHeight + cellSpacing))); } public String getLabel(PackageManager packageManager) { From 45ecd6aa7d9e90548ebd447c9ad4fa671689c1a1 Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Wed, 26 May 2021 00:02:21 -0700 Subject: [PATCH 5/5] Add missing call to finish the home animation - This reset the task view's show-screenshot state to show the snapshot the next time the task view is visible Fixes: 186143625 Test: Enter pip w/ autoenter pip app, swipe up to overview Change-Id: I6a1ec3d0654a33b228f97a6009145450e72e8d48 --- .../src/com/android/quickstep/AbsSwipeUpHandler.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java index e0f430d6cf..c09620268e 100644 --- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java +++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java @@ -82,6 +82,7 @@ import com.android.launcher3.DeviceProfile; import com.android.launcher3.R; import com.android.launcher3.Utilities; import com.android.launcher3.anim.AnimationSuccessListener; +import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.logging.StatsLogManager; import com.android.launcher3.logging.StatsLogManager.StatsLogger; import com.android.launcher3.statemanager.BaseState; @@ -1213,20 +1214,22 @@ public abstract class AbsSwipeUpHandler, && (windowRotation == ROTATION_90 || windowRotation == ROTATION_270)) { swipePipToHomeAnimator.setFromRotation(mTaskViewSimulator, windowRotation); } + AnimatorPlaybackController activityAnimationToHome = + homeAnimFactory.createActivityAnimationToHome(); swipePipToHomeAnimator.addListener(new AnimatorListenerAdapter() { private boolean mHasAnimationEnded; @Override public void onAnimationStart(Animator animation) { if (mHasAnimationEnded) return; - // Ensure Launcher ends in NORMAL state, we intentionally skip other callbacks - // since they are not relevant in this swipe-pip-to-home case. - homeAnimFactory.createActivityAnimationToHome().dispatchOnStart(); + // Ensure Launcher ends in NORMAL state + activityAnimationToHome.dispatchOnStart(); } @Override public void onAnimationEnd(Animator animation) { if (mHasAnimationEnded) return; mHasAnimationEnded = true; + activityAnimationToHome.getAnimationPlayer().end(); if (mRecentsAnimationController == null) { // If the recents animation is interrupted, we still end the running // animation (not canceled) so this is still called. In that case, we can