From c6995f3eb21ab1d1a0dd548d49c5758343a3d608 Mon Sep 17 00:00:00 2001 From: Samuel Fufa Date: Tue, 23 Mar 2021 11:06:09 -0500 Subject: [PATCH 01/21] [Search] Resolve work/personal tab overlap with A-Z list This issue was caused due to launcher falling out of sync with DEVICE_SEARCH_FLAG. This change makes AllApps views agnostic of search input type when rendering layout. Bug: 182591985 Test: local Change-Id: Ic015b68e110eea9ab5184325f2a3633a5c7d15cc --- res/layout/all_apps_tabs.xml | 1 + .../android/launcher3/allapps/AllAppsContainerView.java | 4 ---- src/com/android/launcher3/allapps/AllAppsPagedView.java | 6 ------ .../android/launcher3/allapps/FloatingHeaderView.java | 9 +++------ 4 files changed, 4 insertions(+), 16 deletions(-) diff --git a/res/layout/all_apps_tabs.xml b/res/layout/all_apps_tabs.xml index c684881195..2accd2d21f 100644 --- a/res/layout/all_apps_tabs.xml +++ b/res/layout/all_apps_tabs.xml @@ -26,6 +26,7 @@ android:clipChildren="true" android:clipToPadding="false" android:descendantFocusability="afterDescendants" + android:paddingTop="@dimen/all_apps_header_top_padding" launcher:pageIndicator="@+id/tabs" > diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java index 591de043d2..bf0a88f33f 100644 --- a/src/com/android/launcher3/allapps/AllAppsContainerView.java +++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java @@ -583,10 +583,6 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo int padding = mHeader.getMaxTranslation(); for (int i = 0; i < mAH.length; i++) { mAH[i].padding.top = padding; - if (FeatureFlags.ENABLE_DEVICE_SEARCH.get() && mUsingTabs) { - //add extra space between tabs and recycler view - mAH[i].padding.top += mLauncher.getDeviceProfile().edgeMarginPx; - } mAH[i].applyPadding(); } } diff --git a/src/com/android/launcher3/allapps/AllAppsPagedView.java b/src/com/android/launcher3/allapps/AllAppsPagedView.java index 14e3b5140f..3cc9ce6806 100644 --- a/src/com/android/launcher3/allapps/AllAppsPagedView.java +++ b/src/com/android/launcher3/allapps/AllAppsPagedView.java @@ -23,8 +23,6 @@ import android.util.AttributeSet; import com.android.launcher3.Launcher; import com.android.launcher3.PagedView; -import com.android.launcher3.R; -import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.workprofile.PersonalWorkPagedView; /** @@ -43,10 +41,6 @@ public class AllAppsPagedView extends PersonalWorkPagedView { public AllAppsPagedView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); - int topPadding = FeatureFlags.ENABLE_DEVICE_SEARCH.get() ? 0 - : context.getResources().getDimensionPixelOffset( - R.dimen.all_apps_header_top_padding); - setPadding(0, topPadding, 0, 0); } @Override diff --git a/src/com/android/launcher3/allapps/FloatingHeaderView.java b/src/com/android/launcher3/allapps/FloatingHeaderView.java index 86f330c88d..733d867e4d 100644 --- a/src/com/android/launcher3/allapps/FloatingHeaderView.java +++ b/src/com/android/launcher3/allapps/FloatingHeaderView.java @@ -106,8 +106,8 @@ public class FloatingHeaderView extends LinearLayout implements public FloatingHeaderView(@NonNull Context context, @Nullable AttributeSet attrs) { super(context, attrs); - mHeaderTopPadding = FeatureFlags.ENABLE_DEVICE_SEARCH.get() ? 0 : - context.getResources().getDimensionPixelSize(R.dimen.all_apps_header_top_padding); + mHeaderTopPadding = context.getResources() + .getDimensionPixelSize(R.dimen.all_apps_header_top_padding); } @Override @@ -125,7 +125,6 @@ public class FloatingHeaderView extends LinearLayout implements } } mFixedRows = rows.toArray(new FloatingHeaderRow[rows.size()]); - setPadding(0, mHeaderTopPadding, 0, 0); mAllRows = mFixedRows; } @@ -243,9 +242,7 @@ public class FloatingHeaderView extends LinearLayout implements public int getMaxTranslation() { if (mMaxTranslation == 0 && mTabsHidden) { - int paddingOffset = getResources().getDimensionPixelSize( - R.dimen.all_apps_search_bar_bottom_padding); - return FeatureFlags.ENABLE_DEVICE_SEARCH.get() ? 0 : paddingOffset; + return getResources().getDimensionPixelSize(R.dimen.all_apps_search_bar_bottom_padding); } else if (mMaxTranslation > 0 && mTabsHidden) { return mMaxTranslation + getPaddingTop(); } else { From 284aaba153530e318130720e98afd7683a590b00 Mon Sep 17 00:00:00 2001 From: Alex Johnston Date: Tue, 23 Mar 2021 13:46:11 +0000 Subject: [PATCH 02/21] Block recent work profile apps content capture Stop data exposure of work profile by blocking content capture of recents apps when the work profile is locked. Manual testing steps * Set up work profile * Set personal and work pattern * Open work app, enter work pattern and verify content capture is possible * Lock device * Go to Recents and select already opened work app. Verify content capture is not possible until work pattern is entered. Bug: 168802517 Test: manual testing Change-Id: I3e6ba1d8645335785e8e26cdc895ea9c0017a0fd --- .../src/com/android/quickstep/TaskOverlayFactoryGo.java | 2 +- quickstep/src/com/android/quickstep/TaskOverlayFactory.java | 2 +- .../src/com/android/quickstep/views/TaskThumbnailView.java | 5 +++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java b/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java index b102a394f6..ea808c66f5 100644 --- a/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java +++ b/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java @@ -78,7 +78,7 @@ public final class TaskOverlayFactoryGo extends TaskOverlayFactory { } getActionsView().updateDisabledFlags(DISABLED_ROTATED, rotated); - boolean isAllowedByPolicy = thumbnail.isRealSnapshot; + boolean isAllowedByPolicy = mThumbnailView.isRealSnapshot(); getActionsView().setCallbacks(new OverlayUICallbacksGoImpl(isAllowedByPolicy, task)); } diff --git a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java index 0d2c42e3b0..3d98b9c5bc 100644 --- a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java +++ b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java @@ -152,7 +152,7 @@ public class TaskOverlayFactory implements ResourceBasedOverride { if (thumbnail != null) { getActionsView().updateDisabledFlags(DISABLED_ROTATED, rotated); - boolean isAllowedByPolicy = thumbnail.isRealSnapshot; + boolean isAllowedByPolicy = mThumbnailView.isRealSnapshot(); getActionsView().setCallbacks(new OverlayUICallbacksImpl(isAllowedByPolicy, task)); } } diff --git a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java index 3bd883ddc4..f94acf8bb9 100644 --- a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java +++ b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java @@ -445,13 +445,14 @@ public class TaskThumbnailView extends View implements PluginListener Date: Mon, 22 Mar 2021 15:59:38 -0700 Subject: [PATCH 03/21] Remove MultiValueAlpha Mode, as all usages are BLEND Test: Compiles, works as before Bug: 182512211 Change-Id: I79ee683720cdc697d91e7587d8fab4fd2645ba0d --- .../launcher3/util/MultiValueAlpha.java | 31 ++----------------- 1 file changed, 2 insertions(+), 29 deletions(-) diff --git a/src/com/android/launcher3/util/MultiValueAlpha.java b/src/com/android/launcher3/util/MultiValueAlpha.java index 0ea0290a8b..5be95292b4 100644 --- a/src/com/android/launcher3/util/MultiValueAlpha.java +++ b/src/com/android/launcher3/util/MultiValueAlpha.java @@ -42,43 +42,16 @@ public class MultiValueAlpha { } }; - /** - * Determines how each alpha should factor into the final alpha. - */ - public enum Mode { - BLEND() { - @Override - public float calculateNewAlpha(float currentAlpha, float otherAlpha) { - return currentAlpha * otherAlpha; - } - }, - - MAX() { - @Override - public float calculateNewAlpha(float currentAlpha, float otherAlpha) { - return Math.max(currentAlpha, otherAlpha); - } - }; - - protected abstract float calculateNewAlpha(float currentAlpha, float otherAlpha); - } - private final View mView; private final AlphaProperty[] mMyProperties; - private final Mode mMode; private int mValidMask; // Whether we should change from INVISIBLE to VISIBLE and vice versa at low alpha values. private boolean mUpdateVisibility; public MultiValueAlpha(View view, int size) { - this(view, size, Mode.BLEND); - } - - public MultiValueAlpha(View view, int size, Mode mode) { mView = view; mMyProperties = new AlphaProperty[size]; - mMode = mode; mValidMask = 0; for (int i = 0; i < size; i++) { @@ -124,7 +97,7 @@ public class MultiValueAlpha { mOthers = 1; for (AlphaProperty prop : mMyProperties) { if (prop != this) { - mOthers = mMode.calculateNewAlpha(mOthers, prop.mValue); + mOthers *= prop.mValue; } } } @@ -134,7 +107,7 @@ public class MultiValueAlpha { mValidMask = mMyMask; mValue = value; - mView.setAlpha(mMode.calculateNewAlpha(mOthers, mValue)); + mView.setAlpha(mOthers * mValue); if (mUpdateVisibility) { AlphaUpdateListener.updateVisibility(mView); } From e63bd38a55e262ea98d2bbcea45ecef0fbd3e931 Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Mon, 22 Mar 2021 17:19:41 -0700 Subject: [PATCH 04/21] Remove dead taskbar code Test: Works as before Bug: 182512211 Change-Id: Id4c979f2924f9ae6881a9bed18bcc52fbd80c05b --- .../launcher3/BaseQuickstepLauncher.java | 4 - .../taskbar/TaskbarActivityContext.java | 12 +-- .../launcher3/taskbar/TaskbarController.java | 68 +++--------- .../taskbar/TaskbarDragController.java | 33 ------ .../taskbar/TaskbarDragListener.java | 101 ------------------ .../taskbar/TaskbarStateHandler.java | 10 +- .../taskbar/TaskbarVisibilityController.java | 18 +--- .../QuickstepAtomicAnimationFactory.java | 16 --- .../util/StaggeredWorkspaceAnim.java | 4 +- .../launcher3/AbstractFloatingView.java | 7 -- .../WorkspaceStateTransitionAnimation.java | 4 +- .../states/StateAnimationConfig.java | 8 +- 12 files changed, 28 insertions(+), 257 deletions(-) delete mode 100644 quickstep/src/com/android/launcher3/taskbar/TaskbarDragListener.java diff --git a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java index 9ab49cebfa..6ba74145b2 100644 --- a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java +++ b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java @@ -338,10 +338,6 @@ public abstract class BaseQuickstepLauncher extends Launcher @Override public void onDragLayerHierarchyChanged() { onLauncherStateOrFocusChanged(); - - if (mTaskbarController != null) { - mTaskbarController.onLauncherDragLayerHierarchyChanged(); - } } @Override diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java index fc5e2c1740..5513c1658c 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java @@ -35,14 +35,13 @@ public class TaskbarActivityContext extends ContextWrapper implements ActivityCo private final DeviceProfile mDeviceProfile; private final LayoutInflater mLayoutInflater; private final TaskbarContainerView mTaskbarContainerView; - private final float mIconScale; public TaskbarActivityContext(BaseQuickstepLauncher launcher) { super(launcher); mDeviceProfile = launcher.getDeviceProfile().copy(this); float taskbarIconSize = getResources().getDimension(R.dimen.taskbar_icon_size); - mIconScale = taskbarIconSize / mDeviceProfile.iconSizePx; - mDeviceProfile.updateIconSize(mIconScale, getResources()); + float iconScale = taskbarIconSize / mDeviceProfile.iconSizePx; + mDeviceProfile.updateIconSize(iconScale, getResources()); mLayoutInflater = LayoutInflater.from(this).cloneInContext(this); @@ -73,11 +72,4 @@ public class TaskbarActivityContext extends ContextWrapper implements ActivityCo public Rect getFolderBoundingBox() { return mTaskbarContainerView.getFolderBoundingBox(); } - - /** - * @return The ratio of taskbar icon size vs normal workspace/hotseat icon size. - */ - public float getTaskbarIconScale() { - return mIconScale; - } } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarController.java index abf6d54146..eccc41bfe2 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarController.java @@ -151,13 +151,22 @@ public class TaskbarController { ActivityManagerWrapper.getInstance().startActivityFromRecents(task.key, ActivityOptions.makeBasic()); } else if (tag instanceof FolderInfo) { - if (mLauncher.hasBeenResumed()) { - FolderInfo folderInfo = (FolderInfo) tag; - onClickedOnFolderFromHome(folderInfo); - } else { - FolderIcon folderIcon = (FolderIcon) view; - onClickedOnFolderInApp(folderIcon); - } + FolderIcon folderIcon = (FolderIcon) view; + Folder folder = folderIcon.getFolder(); + + setTaskbarWindowFullscreen(true); + + mTaskbarContainerView.post(() -> { + folder.animateOpen(); + + folder.iterateOverItems((itemInfo, itemView) -> { + itemView.setOnClickListener(getItemOnClickListener()); + itemView.setOnLongClickListener(getItemOnLongClickListener()); + // To play haptic when dragging, like other Taskbar items do. + itemView.setHapticFeedbackEnabled(true); + return false; + }); + }); } else { ItemClickHandler.INSTANCE.onClick(view); } @@ -167,44 +176,9 @@ public class TaskbarController { }; } - // Open the real folder in Launcher. - private void onClickedOnFolderFromHome(FolderInfo folderInfo) { - alignRealHotseatWithTaskbar(); - - FolderIcon folderIcon = (FolderIcon) mLauncher.getHotseat() - .getFirstItemMatch((info, v) -> info == folderInfo); - folderIcon.post(folderIcon::performClick); - } - - // Open the Taskbar folder, and handle clicks on folder items. - private void onClickedOnFolderInApp(FolderIcon folderIcon) { - Folder folder = folderIcon.getFolder(); - - setTaskbarWindowFullscreen(true); - - mTaskbarContainerView.post(() -> { - folder.animateOpen(); - - folder.iterateOverItems((itemInfo, itemView) -> { - itemView.setOnClickListener(getItemOnClickListener()); - itemView.setOnLongClickListener(getItemOnLongClickListener()); - // To play haptic when dragging, like other Taskbar items do. - itemView.setHapticFeedbackEnabled(true); - return false; - }); - }); - } - @Override public View.OnLongClickListener getItemOnLongClickListener() { - return view -> { - if (mLauncher.hasBeenResumed() && view.getTag() instanceof ItemInfo) { - // TODO: remove this path - return mDragController.startWorkspaceDragOnLongClick(view); - } else { - return mDragController.startSystemDragOnLongClick(view); - } - }; + return mDragController::startSystemDragOnLongClick; } @Override @@ -509,14 +483,6 @@ public class TaskbarController { mTaskbarViewOnHome.getHeight() - hotseatBounds.bottom); } - /** - * A view was added or removed from DragLayer, check if we need to hide our hotseat copy and - * show the real one instead. - */ - public void onLauncherDragLayerHierarchyChanged() { - // TODO: remove, as this is a no-op now - } - private void updateWhichTaskbarViewIsVisible() { boolean isInApp = !mLauncher.hasBeenResumed() || mIsAnimatingToLauncher || mIsAnimatingToApp; diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java index f51e49837d..5eb34cb360 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java @@ -33,7 +33,6 @@ import com.android.launcher3.BaseQuickstepLauncher; import com.android.launcher3.BubbleTextView; import com.android.launcher3.LauncherSettings; import com.android.launcher3.R; -import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.systemui.shared.recents.model.Task; import com.android.systemui.shared.system.ClipDescriptionCompat; @@ -125,38 +124,6 @@ public class TaskbarDragController { return false; } - /** - * Starts a drag and drop operation that controls a real Workspace (Hotseat) view. - * @param view The Taskbar item that was long clicked. - * @return Whether {@link View#startDragAndDrop} started successfully. - */ - protected boolean startWorkspaceDragOnLongClick(View view) { - View.DragShadowBuilder transparentShadowBuilder = new View.DragShadowBuilder(view) { - private static final int ARBITRARY_SHADOW_SIZE = 10; - - @Override - public void onDrawShadow(Canvas canvas) { - } - - @Override - public void onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint) { - outShadowSize.set(ARBITRARY_SHADOW_SIZE, ARBITRARY_SHADOW_SIZE); - outShadowTouchPoint.set(ARBITRARY_SHADOW_SIZE / 2, ARBITRARY_SHADOW_SIZE / 2); - } - }; - - TaskbarDragListener taskbarDragListener = new TaskbarDragListener(mLauncher, - (ItemInfo) view.getTag()); - if (view.startDragAndDrop(new ClipData("", new String[] {taskbarDragListener.getMimeType()}, - new ClipData.Item("")), - transparentShadowBuilder, null /* localState */, View.DRAG_FLAG_GLOBAL)) { - view.setOnDragListener(getDraggedViewDragListener()); - taskbarDragListener.init(mLauncher.getDragLayer()); - return true; - } - return false; - } - /** * Hide the original Taskbar item while it is being dragged. */ diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragListener.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragListener.java deleted file mode 100644 index dc27df1909..0000000000 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragListener.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * 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.taskbar; - -import android.content.ClipDescription; -import android.graphics.Point; -import android.view.DragEvent; -import android.view.View; - -import com.android.launcher3.BaseQuickstepLauncher; -import com.android.launcher3.dragndrop.DragLayer; -import com.android.launcher3.dragndrop.DragOptions; -import com.android.launcher3.model.data.ItemInfo; - -import java.util.UUID; - -/** - * Listens to system drag and drop events initated by the Taskbar, and forwards them to Launcher's - * internal DragController to move Hotseat items. - */ -public class TaskbarDragListener implements View.OnDragListener { - - private static final String MIME_TYPE_PREFIX = "com.android.launcher3.taskbar.drag_and_drop/"; - - private final BaseQuickstepLauncher mLauncher; - private final ItemInfo mDraggedItem; - // Randomly generated id used to verify the drag event. - private final String mId; - - // Initialized in init(). - DragLayer mDragLayer; - - /** - * @param draggedItem The info of the item that was long clicked, which we will use to find - * the equivalent match on Hotseat to drag internally. - */ - public TaskbarDragListener(BaseQuickstepLauncher launcher, ItemInfo draggedItem) { - mLauncher = launcher; - mDraggedItem = draggedItem; - mId = UUID.randomUUID().toString(); - } - - protected void init(DragLayer dragLayer) { - mDragLayer = dragLayer; - mDragLayer.setOnDragListener(this); - // Temporarily disable haptics, as system will already play one when drag and drop starts. - mDragLayer.setHapticFeedbackEnabled(false); - } - - private void cleanup() { - mDragLayer.setOnDragListener(null); - mLauncher.setNextWorkspaceDragOptions(null); - mDragLayer.setHapticFeedbackEnabled(true); - } - - /** - * Returns a randomly generated id used to verify the drag event. - */ - protected String getMimeType() { - return MIME_TYPE_PREFIX + mId; - } - - @Override - public boolean onDrag(View dragLayer, DragEvent dragEvent) { - ClipDescription clipDescription = dragEvent.getClipDescription(); - if (dragEvent.getAction() == DragEvent.ACTION_DRAG_STARTED) { - if (clipDescription == null || !clipDescription.hasMimeType(getMimeType())) { - // We didn't initiate this drag, ignore. - cleanup(); - return false; - } - View hotseatView = mLauncher.getHotseat().getFirstItemMatch( - (info, view) -> info == mDraggedItem); - if (hotseatView == null) { - cleanup(); - return false; - } - DragOptions dragOptions = new DragOptions(); - dragOptions.simulatedDndStartPoint = new Point((int) dragEvent.getX(), - (int) dragEvent.getY()); - mLauncher.setNextWorkspaceDragOptions(dragOptions); - hotseatView.performLongClick(); - } else if (dragEvent.getAction() == DragEvent.ACTION_DRAG_ENDED) { - cleanup(); - } - return mLauncher.getDragController().onDragEvent(dragEvent); - } -} diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStateHandler.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStateHandler.java index b4b5d8b3fe..0a3819dad5 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStateHandler.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStateHandler.java @@ -16,14 +16,12 @@ package com.android.launcher3.taskbar; import static com.android.launcher3.LauncherState.TASKBAR; -import static com.android.launcher3.states.StateAnimationConfig.ANIM_TASKBAR_FADE; -import static com.android.launcher3.states.StateAnimationConfig.SKIP_TASKBAR; +import static com.android.launcher3.anim.Interpolators.LINEAR; import androidx.annotation.Nullable; import com.android.launcher3.BaseQuickstepLauncher; import com.android.launcher3.LauncherState; -import com.android.launcher3.anim.Interpolators; import com.android.launcher3.anim.PendingAnimation; import com.android.launcher3.statemanager.StateManager; import com.android.launcher3.states.StateAnimationConfig; @@ -65,13 +63,9 @@ public class TaskbarStateHandler implements StateManager.StateHandler Date: Tue, 23 Mar 2021 15:35:46 -0700 Subject: [PATCH 05/21] Fix taskbar crash after cleanup - Set LayoutTransition after adding initial views - End running transitions in cleanup - Only run update listener if LayoutTransition is active Test: No crash after taskbar cleanup() Bug: 182512211 Change-Id: I1049857935d09235388c1ef1fe4d89ef53b79aa5 --- .../launcher3/taskbar/TaskbarView.java | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java index 3567c17afa..21a2d512ab 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java @@ -120,11 +120,6 @@ public class TaskbarView extends LinearLayout implements FolderIcon.FolderIconPa } protected void init(int numHotseatIcons, int numRecentIcons) { - mLayoutTransition = new LayoutTransition(); - addUpdateListenerForAllLayoutTransitions( - () -> mControllerCallbacks.onItemPositionsChanged(this)); - setLayoutTransition(mLayoutTransition); - mHotseatStartIndex = 0; mHotseatEndIndex = mHotseatStartIndex + numHotseatIcons - 1; updateHotseatItems(new ItemInfo[numHotseatIcons]); @@ -135,6 +130,14 @@ public class TaskbarView extends LinearLayout implements FolderIcon.FolderIconPa mRecentsStartIndex = dividerIndex + 1; mRecentsEndIndex = mRecentsStartIndex + numRecentIcons - 1; updateRecentTasks(new Task[numRecentIcons]); + + mLayoutTransition = new LayoutTransition(); + addUpdateListenerForAllLayoutTransitions(() -> { + if (getLayoutTransition() == mLayoutTransition) { + mControllerCallbacks.onItemPositionsChanged(this); + } + }); + setLayoutTransition(mLayoutTransition); } private void addUpdateListenerForAllLayoutTransitions(Runnable onUpdate) { @@ -159,10 +162,20 @@ public class TaskbarView extends LinearLayout implements FolderIcon.FolderIconPa } protected void cleanup() { + endAllLayoutTransitionAnimators(); + setLayoutTransition(null); removeAllViews(); mHotseatRecentsDivider = null; } + private void endAllLayoutTransitionAnimators() { + mLayoutTransition.getAnimator(LayoutTransition.CHANGE_APPEARING).end(); + mLayoutTransition.getAnimator(LayoutTransition.CHANGE_DISAPPEARING).end(); + mLayoutTransition.getAnimator(LayoutTransition.CHANGING).end(); + mLayoutTransition.getAnimator(LayoutTransition.APPEARING).end(); + mLayoutTransition.getAnimator(LayoutTransition.DISAPPEARING).end(); + } + /** * Sets the alpha of the background color behind all the Taskbar contents. * @param alpha 0 is fully transparent, 1 is fully opaque. From 2cff164be23f13246b7ad7512b241d7e9fd26433 Mon Sep 17 00:00:00 2001 From: Alina Zaidi Date: Wed, 24 Mar 2021 09:52:45 +0000 Subject: [PATCH 06/21] Clear focus from search bar whenever a header is clicked in search adapter. Test: Manually checked Bug: 183398749 Change-Id: Ie91312ae1e62c6427e3397d1e5f60bc812a790ee --- .../widget/picker/WidgetsListAdapterTest.java | 2 +- ...WidgetsListHeaderViewHolderBinderTest.java | 3 ++- ...sListSearchHeaderViewHolderBinderTest.java | 3 ++- .../WidgetsListTableViewHolderBinderTest.java | 3 ++- .../widget/picker/WidgetsFullSheet.java | 13 +++++++-- .../widget/picker/WidgetsListAdapter.java | 9 ++++++- .../search/LauncherWidgetsSearchBar.java | 5 ++++ .../picker/search/WidgetsSearchBar.java | 5 ++++ .../search/WidgetsSearchBarController.java | 17 +++++++----- .../search/WidgetsSearchBarUIHelper.java | 27 +++++++++++++++++++ 10 files changed, 74 insertions(+), 13 deletions(-) create mode 100644 src/com/android/launcher3/widget/picker/search/WidgetsSearchBarUIHelper.java diff --git a/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsListAdapterTest.java b/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsListAdapterTest.java index e1214ff39f..6b5678cb8a 100644 --- a/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsListAdapterTest.java +++ b/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsListAdapterTest.java @@ -82,7 +82,7 @@ public final class WidgetsListAdapterTest { mTestProfile.numColumns = 5; mUserHandle = Process.myUserHandle(); mAdapter = new WidgetsListAdapter(mContext, mMockLayoutInflater, mMockWidgetCache, - mIconCache, null, null); + mIconCache, null, null, null); mAdapter.registerAdapterDataObserver(mListener); doAnswer(invocation -> ((ComponentWithLabel) invocation.getArgument(0)) diff --git a/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsListHeaderViewHolderBinderTest.java b/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsListHeaderViewHolderBinderTest.java index 84a03d572c..12a092dafe 100644 --- a/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsListHeaderViewHolderBinderTest.java +++ b/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsListHeaderViewHolderBinderTest.java @@ -105,7 +105,8 @@ public final class WidgetsListHeaderViewHolderBinderTest { mWidgetPreviewLoader, mIconCache, /* iconClickListener= */ view -> {}, - /* iconLongClickListener= */ view -> false); + /* iconLongClickListener= */ view -> false, + /* searchBarUIHelper= */ null); mViewHolderBinder = new WidgetsListHeaderViewHolderBinder( LayoutInflater.from(mTestActivity), mOnHeaderClickListener, widgetsListAdapter); } diff --git a/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsListSearchHeaderViewHolderBinderTest.java b/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsListSearchHeaderViewHolderBinderTest.java index 075c58db6b..e09034132c 100644 --- a/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsListSearchHeaderViewHolderBinderTest.java +++ b/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsListSearchHeaderViewHolderBinderTest.java @@ -105,7 +105,8 @@ public final class WidgetsListSearchHeaderViewHolderBinderTest { mWidgetPreviewLoader, mIconCache, /* iconClickListener= */ view -> {}, - /* iconLongClickListener= */ view -> false); + /* iconLongClickListener= */ view -> false, + /* searchBarUIHelper= */ null); mViewHolderBinder = new WidgetsListSearchHeaderViewHolderBinder( LayoutInflater.from(mTestActivity), mOnHeaderClickListener, widgetsListAdapter); } diff --git a/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinderTest.java b/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinderTest.java index 0c6e71711d..0935d1cfc4 100644 --- a/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinderTest.java +++ b/robolectric_tests/src/com/android/launcher3/widget/picker/WidgetsListTableViewHolderBinderTest.java @@ -111,7 +111,8 @@ public final class WidgetsListTableViewHolderBinderTest { mWidgetPreviewLoader, mIconCache, /* iconClickListener= */ view -> {}, - /* iconLongClickListener= */ view -> false); + /* iconLongClickListener= */ view -> false, + /* searchBarUIHelper= */ null); mViewHolderBinder = new WidgetsListTableViewHolderBinder( mContext, LayoutInflater.from(mTestActivity), diff --git a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java index dc7d341546..29c00b209f 100644 --- a/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java +++ b/src/com/android/launcher3/widget/picker/WidgetsFullSheet.java @@ -58,6 +58,7 @@ import com.android.launcher3.widget.LauncherAppWidgetHost.ProviderChangedListene import com.android.launcher3.widget.model.WidgetsListBaseEntry; import com.android.launcher3.widget.picker.search.SearchModeListener; import com.android.launcher3.widget.picker.search.WidgetsSearchBar; +import com.android.launcher3.widget.picker.search.WidgetsSearchBarUIHelper; import com.android.launcher3.widget.util.WidgetsTableUtils; import com.android.launcher3.workprofile.PersonalWorkPagedView; import com.android.launcher3.workprofile.PersonalWorkSlidingTabStrip.OnActivePageChangedListener; @@ -71,7 +72,8 @@ import java.util.function.Predicate; */ public class WidgetsFullSheet extends BaseWidgetSheet implements Insettable, ProviderChangedListener, OnActivePageChangedListener, - WidgetsRecyclerView.HeaderViewDimensionsProvider, SearchModeListener { + WidgetsRecyclerView.HeaderViewDimensionsProvider, SearchModeListener, + WidgetsSearchBarUIHelper { private static final String TAG = WidgetsFullSheet.class.getSimpleName(); private static final long DEFAULT_OPEN_DURATION = 267; @@ -561,6 +563,11 @@ public class WidgetsFullSheet extends BaseWidgetSheet getWindowInsetsController().hide(WindowInsets.Type.ime()); } + @Override + public void clearSearchBarFocus() { + mSearchAndRecommendationViewHolder.mSearchBar.clearSearchBarFocus(); + } + /** A holder class for holding adapters & their corresponding recycler view. */ private final class AdapterHolder { static final int PRIMARY = 0; @@ -583,7 +590,9 @@ public class WidgetsFullSheet extends BaseWidgetSheet apps.getWidgetCache(), apps.getIconCache(), /* iconClickListener= */ WidgetsFullSheet.this, - /* iconLongClickListener= */ WidgetsFullSheet.this); + /* iconLongClickListener= */ WidgetsFullSheet.this, + /* WidgetsSearchBarUIHelper= */ + mAdapterType == SEARCH ? WidgetsFullSheet.this : null); mWidgetsListAdapter.setHasStableIds(true); switch (mAdapterType) { case PRIMARY: diff --git a/src/com/android/launcher3/widget/picker/WidgetsListAdapter.java b/src/com/android/launcher3/widget/picker/WidgetsListAdapter.java index d841c64a3c..d9c9d4d71b 100644 --- a/src/com/android/launcher3/widget/picker/WidgetsListAdapter.java +++ b/src/com/android/launcher3/widget/picker/WidgetsListAdapter.java @@ -41,6 +41,7 @@ import com.android.launcher3.widget.model.WidgetsListBaseEntry; import com.android.launcher3.widget.model.WidgetsListContentEntry; import com.android.launcher3.widget.model.WidgetsListHeaderEntry; import com.android.launcher3.widget.model.WidgetsListSearchHeaderEntry; +import com.android.launcher3.widget.picker.search.WidgetsSearchBarUIHelper; import java.util.ArrayList; import java.util.Arrays; @@ -69,6 +70,7 @@ public class WidgetsListAdapter extends Adapter implements OnHeaderC private static final int VIEW_TYPE_WIDGETS_HEADER = R.id.view_type_widgets_header; private static final int VIEW_TYPE_WIDGETS_SEARCH_HEADER = R.id.view_type_widgets_search_header; + @Nullable private final WidgetsSearchBarUIHelper mSearchBarUIHelper; private final WidgetsDiffReporter mDiffReporter; private final SparseArray mViewHolderBinders = new SparseArray<>(); private final WidgetsListTableViewHolderBinder mWidgetsListTableViewHolderBinder; @@ -88,7 +90,9 @@ public class WidgetsListAdapter extends Adapter implements OnHeaderC public WidgetsListAdapter(Context context, LayoutInflater layoutInflater, WidgetPreviewLoader widgetPreviewLoader, IconCache iconCache, - OnClickListener iconClickListener, OnLongClickListener iconLongClickListener) { + OnClickListener iconClickListener, OnLongClickListener iconLongClickListener, + @Nullable WidgetsSearchBarUIHelper searchBarUIHelper) { + mSearchBarUIHelper = searchBarUIHelper; mDiffReporter = new WidgetsDiffReporter(iconCache, this); mWidgetsListTableViewHolderBinder = new WidgetsListTableViewHolderBinder(context, layoutInflater, iconClickListener, iconLongClickListener, @@ -237,6 +241,9 @@ public class WidgetsListAdapter extends Adapter implements OnHeaderC @Override public void onHeaderClicked(boolean showWidgets, PackageUserKey packageUserKey) { + if (mSearchBarUIHelper != null) { + mSearchBarUIHelper.clearSearchBarFocus(); + } if (showWidgets) { mWidgetsContentVisiblePackageUserKey = packageUserKey; updateVisibleEntries(); diff --git a/src/com/android/launcher3/widget/picker/search/LauncherWidgetsSearchBar.java b/src/com/android/launcher3/widget/picker/search/LauncherWidgetsSearchBar.java index cc336196ae..56a08b16fb 100644 --- a/src/com/android/launcher3/widget/picker/search/LauncherWidgetsSearchBar.java +++ b/src/com/android/launcher3/widget/picker/search/LauncherWidgetsSearchBar.java @@ -79,4 +79,9 @@ public class LauncherWidgetsSearchBar extends LinearLayout implements WidgetsSea super.onDetachedFromWindow(); mController.onDestroy(); } + + @Override + public void clearSearchBarFocus() { + mController.clearFocus(); + } } diff --git a/src/com/android/launcher3/widget/picker/search/WidgetsSearchBar.java b/src/com/android/launcher3/widget/picker/search/WidgetsSearchBar.java index ef7bf23226..3ac82c0ca7 100644 --- a/src/com/android/launcher3/widget/picker/search/WidgetsSearchBar.java +++ b/src/com/android/launcher3/widget/picker/search/WidgetsSearchBar.java @@ -34,6 +34,11 @@ public interface WidgetsSearchBar { */ void reset(); + /** + * Clears focus from search bar. + */ + void clearSearchBarFocus(); + /** * Sets the vertical location, in pixels, of this search bar relative to its top position. */ diff --git a/src/com/android/launcher3/widget/picker/search/WidgetsSearchBarController.java b/src/com/android/launcher3/widget/picker/search/WidgetsSearchBarController.java index 60110977ed..d35a75b80a 100644 --- a/src/com/android/launcher3/widget/picker/search/WidgetsSearchBarController.java +++ b/src/com/android/launcher3/widget/picker/search/WidgetsSearchBarController.java @@ -103,8 +103,7 @@ public class WidgetsSearchBarController implements TextWatcher, public void clearSearchResult() { mSearchAlgorithm.cancel(/* interruptActiveRequests= */ true); mInput.getText().clear(); - mInput.clearFocus(); - mInput.hideKeyboard(); + clearFocus(); mSearchModeListener.exitSearchMode(); } @@ -117,18 +116,24 @@ public class WidgetsSearchBarController implements TextWatcher, @Override public boolean onBackKey() { - mInput.clearFocus(); - mInput.hideKeyboard(); + clearFocus(); return true; } @Override public boolean onKey(View view, int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_ENTER && event.getAction() == KeyEvent.ACTION_UP) { - mInput.clearFocus(); - mInput.hideKeyboard(); + clearFocus(); return true; } return false; } + + /** + * Clears focus from edit text. + */ + public void clearFocus() { + mInput.clearFocus(); + mInput.hideKeyboard(); + } } diff --git a/src/com/android/launcher3/widget/picker/search/WidgetsSearchBarUIHelper.java b/src/com/android/launcher3/widget/picker/search/WidgetsSearchBarUIHelper.java new file mode 100644 index 0000000000..edfdc655ed --- /dev/null +++ b/src/com/android/launcher3/widget/picker/search/WidgetsSearchBarUIHelper.java @@ -0,0 +1,27 @@ +/* + * 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.picker.search; + +/** + * UI helper for {@link WidgetsSearchBar}. + */ +public interface WidgetsSearchBarUIHelper { + /** + * Clears focus from the search bar. + */ + void clearSearchBarFocus(); +} From 375a1bbb929ae5ce723e3466d8f0ea6d2a71f5de Mon Sep 17 00:00:00 2001 From: Jon Spivack Date: Wed, 24 Mar 2021 04:01:26 -0700 Subject: [PATCH 07/21] TaskOverlayFactoryGo: Minor updates for testability Made a few things public and marked them as @VisibleForTesting. Bug: 179738220 Test: atest -v LauncherGoGoogleRoboTests Change-Id: I231316ecf9282ad4d54038e218f44f062b3fa413 --- .../android/quickstep/TaskOverlayFactoryGo.java | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java b/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java index 36a4e7fa35..3a473449ae 100644 --- a/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java +++ b/go/quickstep/src/com/android/quickstep/TaskOverlayFactoryGo.java @@ -36,6 +36,8 @@ import android.os.SystemClock; import android.text.TextUtils; import android.util.Log; +import androidx.annotation.VisibleForTesting; + import com.android.launcher3.R; import com.android.quickstep.views.OverviewActionsView; import com.android.quickstep.views.TaskThumbnailView; @@ -51,6 +53,7 @@ public final class TaskOverlayFactoryGo extends TaskOverlayFactory { public static final String ACTION_SEARCH = "com.android.quickstep.ACTION_SEARCH"; public static final String ELAPSED_NANOS = "niu_actions_elapsed_realtime_nanos"; public static final String ACTIONS_URL = "niu_actions_app_url"; + private static final String ASSIST_KEY_CONTENT = "content"; private static final String TAG = "TaskOverlayFactoryGo"; // Empty constructor required for ResourceBasedOverride @@ -68,8 +71,6 @@ public final class TaskOverlayFactoryGo extends TaskOverlayFactory { * @param The type of View in which the overlay will be placed */ public static final class TaskOverlayGo extends TaskOverlay { - private static final String ASSIST_KEY_CONTENT = "content"; - private String mNIUPackageName; private int mTaskId; private Bundle mAssistData; @@ -122,7 +123,11 @@ public final class TaskOverlayFactoryGo extends TaskOverlayFactory { }); } - private void sendNIUIntent(String actionType) { + /** + * Creates and sends an Intent corresponding to the button that was clicked + */ + @VisibleForTesting + public void sendNIUIntent(String actionType) { Intent intent = createNIUIntent(actionType); mImageApi.shareAsDataWithExplicitIntent(/* crop */ null, intent); } @@ -178,6 +183,11 @@ public final class TaskOverlayFactoryGo extends TaskOverlayFactory { } } } + + @VisibleForTesting + public void setImageActionsAPI(ImageActionsApi imageActionsApi) { + mImageApi = imageActionsApi; + } } /** From 73c8a366a86aef554f6588eb44c68955cb23b338 Mon Sep 17 00:00:00 2001 From: Yogisha Dixit Date: Sun, 21 Mar 2021 20:10:06 +0000 Subject: [PATCH 08/21] Add a button for reconfiguring widgets. Test: manual Bug: 183316993 Change-Id: I17bec121e3d07d65979c2b92c285e487a7d64d65 --- res/drawable/gm_edit_24.xml | 10 ++++++ .../widget_reconfigure_button_frame.xml | 32 +++++++++++++++++++ res/layout/app_widget_resize_frame.xml | 12 +++++++ res/values/dimens.xml | 6 ++++ .../launcher3/AppWidgetResizeFrame.java | 25 +++++++++++++++ .../widget/LauncherAppWidgetProviderInfo.java | 4 +++ 6 files changed, 89 insertions(+) create mode 100644 res/drawable/gm_edit_24.xml create mode 100644 res/drawable/widget_reconfigure_button_frame.xml diff --git a/res/drawable/gm_edit_24.xml b/res/drawable/gm_edit_24.xml new file mode 100644 index 0000000000..59a0dc2faf --- /dev/null +++ b/res/drawable/gm_edit_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/res/drawable/widget_reconfigure_button_frame.xml b/res/drawable/widget_reconfigure_button_frame.xml new file mode 100644 index 0000000000..37d93ade95 --- /dev/null +++ b/res/drawable/widget_reconfigure_button_frame.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + diff --git a/res/layout/app_widget_resize_frame.xml b/res/layout/app_widget_resize_frame.xml index 671dbc63c0..53db5edd8a 100644 --- a/res/layout/app_widget_resize_frame.xml +++ b/res/layout/app_widget_resize_frame.xml @@ -73,5 +73,17 @@ android:src="@drawable/ic_widget_resize_handle" android:tint="?android:attr/colorAccent" /> + + \ No newline at end of file diff --git a/res/values/dimens.xml b/res/values/dimens.xml index cf830c7ed4..c051d6d4e6 100644 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -56,6 +56,12 @@ 24dp 22dp + + 14dp + 6dp + 32dp + 36dp + 6dp 8dp diff --git a/src/com/android/launcher3/AppWidgetResizeFrame.java b/src/com/android/launcher3/AppWidgetResizeFrame.java index ab9178556e..5d41bb5c3e 100644 --- a/src/com/android/launcher3/AppWidgetResizeFrame.java +++ b/src/com/android/launcher3/AppWidgetResizeFrame.java @@ -22,6 +22,7 @@ import android.util.SizeF; import android.view.KeyEvent; import android.view.MotionEvent; import android.view.View; +import android.widget.ImageButton; import android.widget.ImageView; import androidx.annotation.Nullable; @@ -74,6 +75,7 @@ public class AppWidgetResizeFrame extends AbstractFloatingView implements View.O private LauncherAppWidgetHostView mWidgetView; private CellLayout mCellLayout; private DragLayer mDragLayer; + private ImageButton mReconfigureButton; private Rect mWidgetPadding; @@ -211,6 +213,17 @@ public class AppWidgetResizeFrame extends AbstractFloatingView implements View.O mDragHandles[INDEX_RIGHT].setVisibility(GONE); } + mReconfigureButton = (ImageButton) findViewById(R.id.widget_reconfigure_button); + if (info.isReconfigurable()) { + mReconfigureButton.setVisibility(VISIBLE); + mReconfigureButton.setOnClickListener(view -> mLauncher + .getAppWidgetHost() + .startConfigActivity( + mLauncher, + mWidgetView.getAppWidgetId(), + Launcher.REQUEST_RECONFIGURE_APPWIDGET)); + } + // When we create the resize frame, we first mark all cells as unoccupied. The appropriate // cells (same if not resized, or different) will be marked as occupied when the resize // frame is dismissed. @@ -582,6 +595,13 @@ public class AppWidgetResizeFrame extends AbstractFloatingView implements View.O return false; } + private boolean isTouchOnReconfigureButton(MotionEvent ev) { + int xFrame = (int) ev.getX() - getLeft(); + int yFrame = (int) ev.getY() - getTop(); + mReconfigureButton.getHitRect(sTmpRect); + return sTmpRect.contains(xFrame, yFrame); + } + @Override public boolean onControllerTouchEvent(MotionEvent ev) { int action = ev.getAction(); @@ -609,6 +629,11 @@ public class AppWidgetResizeFrame extends AbstractFloatingView implements View.O if (ev.getAction() == MotionEvent.ACTION_DOWN && handleTouchDown(ev)) { return true; } + // Keep the resize frame open but let a click on the reconfigure button fall through to the + // button's OnClickListener. + if (isTouchOnReconfigureButton(ev)) { + return false; + } close(false); return false; } diff --git a/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfo.java b/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfo.java index 8689fbfd3c..ad61495de8 100644 --- a/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfo.java +++ b/src/com/android/launcher3/widget/LauncherAppWidgetProviderInfo.java @@ -139,6 +139,10 @@ public class LauncherAppWidgetProviderInfo extends AppWidgetProviderInfo } } + public boolean isReconfigurable() { + return configure != null && (getWidgetFeatures() & WIDGET_FEATURE_RECONFIGURABLE) != 0; + } + @Override public final ComponentName getComponent() { return provider; From 334efebaba9f17d9fc79bfdee1a610d6d626dc7c Mon Sep 17 00:00:00 2001 From: Zak Cohen Date: Fri, 19 Mar 2021 16:42:07 -0700 Subject: [PATCH 09/21] Overview - Adds first pass at making landscape layout real. Adds dynamic sizing to margins around task view, also creates space in the overview actions view in landscape to make space for the proactive chips if needed. Bug: 182529089 Test: Local build and run on two devices Change-Id: I447de3564a3249ede4e8e8a4d3e5d1c177f6be61 --- .../res/layout/overview_clear_all_button.xml | 3 +- quickstep/res/layout/task.xml | 5 +-- quickstep/res/values-land/dimens.xml | 2 ++ quickstep/res/values/dimens.xml | 4 --- .../quickstep/BaseActivityInterface.java | 26 ++++++++------- .../quickstep/util/TaskViewSimulator.java | 6 ++-- .../quickstep/views/ClearAllButton.java | 15 ++++++--- .../quickstep/views/OverviewActionsView.java | 13 ++++++++ .../android/quickstep/views/RecentsView.java | 18 +++++------ .../android/quickstep/views/TaskMenuView.java | 7 ++-- .../com/android/quickstep/views/TaskView.java | 32 +++++++++---------- res/values/dimens.xml | 4 +++ src/com/android/launcher3/DeviceProfile.java | 9 ++++++ 13 files changed, 87 insertions(+), 57 deletions(-) diff --git a/quickstep/res/layout/overview_clear_all_button.xml b/quickstep/res/layout/overview_clear_all_button.xml index 34ff91df9a..c61610a438 100644 --- a/quickstep/res/layout/overview_clear_all_button.xml +++ b/quickstep/res/layout/overview_clear_all_button.xml @@ -22,5 +22,4 @@ android:layout_height="wrap_content" android:text="@string/recents_clear_all" android:textColor="?attr/workspaceTextColor" - android:textSize="14sp" - android:translationY="@dimen/task_thumbnail_half_top_margin" /> \ No newline at end of file + android:textSize="14sp" /> \ No newline at end of file diff --git a/quickstep/res/layout/task.xml b/quickstep/res/layout/task.xml index 0f9a6aad6f..7e5b85c41d 100644 --- a/quickstep/res/layout/task.xml +++ b/quickstep/res/layout/task.xml @@ -13,6 +13,8 @@ See the License for the specific language governing permissions and limitations under the License. --> + + android:layout_height="match_parent"/> 24dp + + 8dp \ No newline at end of file diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml index 755bce8612..0ff11c5f5e 100644 --- a/quickstep/res/values/dimens.xml +++ b/quickstep/res/values/dimens.xml @@ -15,11 +15,7 @@ --> - - 80dp - 40dp 48dp - 16dp 2dp diff --git a/quickstep/src/com/android/quickstep/BaseActivityInterface.java b/quickstep/src/com/android/quickstep/BaseActivityInterface.java index 5942b3aaf4..462630cac3 100644 --- a/quickstep/src/com/android/quickstep/BaseActivityInterface.java +++ b/quickstep/src/com/android/quickstep/BaseActivityInterface.java @@ -201,14 +201,18 @@ public abstract class BaseActivityInterface 0 ? endTranslation : 0; } + + /** + * Get the Y translation that is set in the original layout position, before scrolling. + */ + private float getOriginalTranslationY() { + return mActivity.getDeviceProfile().overviewTaskThumbnailTopMarginPx / 2.0f; + } } diff --git a/quickstep/src/com/android/quickstep/views/OverviewActionsView.java b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java index 1241982040..6fcd54cf62 100644 --- a/quickstep/src/com/android/quickstep/views/OverviewActionsView.java +++ b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java @@ -29,6 +29,7 @@ import android.widget.FrameLayout; import androidx.annotation.IntDef; import androidx.annotation.Nullable; +import com.android.launcher3.DeviceProfile; import com.android.launcher3.Insettable; import com.android.launcher3.R; import com.android.launcher3.util.MultiValueAlpha; @@ -144,6 +145,7 @@ public class OverviewActionsView extends FrameLayo public void setInsets(Rect insets) { mInsets.set(insets); updateVerticalMargin(SysUINavigationMode.getMode(getContext())); + updateHorizontalPadding(); } public void updateHiddenFlags(@ActionsHiddenFlags int visibilityFlags, boolean enable) { @@ -187,6 +189,10 @@ public class OverviewActionsView extends FrameLayo return mMultiValueAlpha.getProperty(INDEX_FULLSCREEN_ALPHA); } + private void updateHorizontalPadding() { + setPadding(mInsets.left, 0, mInsets.right, 0); + } + /** Updates vertical margins for different navigation mode or configuration changes. */ public void updateVerticalMargin(Mode mode) { LayoutParams actionParams = (LayoutParams) findViewById( @@ -196,6 +202,13 @@ public class OverviewActionsView extends FrameLayo getBottomVerticalMargin(mode)); } + /** + * Set the device profile for this view to draw with. + */ + public void setDp(DeviceProfile dp) { + requestLayout(); + } + protected int getBottomVerticalMargin(Mode mode) { int bottomMargin; int orientation = getResources().getConfiguration().orientation; diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index 4d8176c7e5..d637bb4aca 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -310,7 +310,6 @@ public abstract class RecentsView extends PagedView protected final T mActivity; private final float mFastFlingVelocity; private final RecentsModel mModel; - private final int mTaskTopMargin; private final int mRowSpacing; private final ClearAllButton mClearAllButton; private final Rect mClearAllButtonDeadZoneRect = new Rect(); @@ -529,8 +528,6 @@ public abstract class RecentsView extends PagedView mIsRtl = mOrientationHandler.getRecentsRtlSetting(getResources()); setLayoutDirection(mIsRtl ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR); - mTaskTopMargin = getResources() - .getDimensionPixelSize(R.dimen.task_thumbnail_top_margin); mRowSpacing = getResources().getDimensionPixelSize(R.dimen.overview_grid_row_spacing); mSquaredTouchSlop = squaredTouchSlop(context); @@ -1066,7 +1063,9 @@ public abstract class RecentsView extends PagedView public void setInsets(Rect insets) { mInsets.set(insets); resetPaddingFromTaskSize(); - mLiveTileTaskViewSimulator.setDp(mActivity.getDeviceProfile()); + DeviceProfile dp = mActivity.getDeviceProfile(); + mLiveTileTaskViewSimulator.setDp(dp); + mActionsView.setDp(dp); } private void resetPaddingFromTaskSize() { @@ -1075,7 +1074,7 @@ public abstract class RecentsView extends PagedView mTaskWidth = mTempRect.width(); mTaskHeight = mTempRect.height(); - mTempRect.top -= mTaskTopMargin; + mTempRect.top -= dp.overviewTaskThumbnailTopMarginPx; setPadding(mTempRect.left - mInsets.left, mTempRect.top - mInsets.top, dp.widthPx - mInsets.right - mTempRect.right, dp.heightPx - mInsets.bottom - mTempRect.bottom); @@ -1602,7 +1601,8 @@ public abstract class RecentsView extends PagedView final int boxLength = Math.max(mTaskWidth, mTaskHeight); float availableHeight = mLastComputedGridSize.height(); float rowHeight = (availableHeight - mRowSpacing) / 2; - float gridScale = rowHeight / (boxLength + mTaskTopMargin); + int taskTopMargin = mActivity.getDeviceProfile().overviewTaskThumbnailTopMarginPx; + float gridScale = rowHeight / (boxLength + taskTopMargin); int topRowWidth = 0; int bottomRowWidth = 0; @@ -1635,7 +1635,7 @@ public abstract class RecentsView extends PagedView gridTranslations[i] -= taskGridHorizontalDiff; taskView.setGridOffsetTranslationX(taskGridHorizontalDiff); - float taskGridVerticalDiff = mLastComputedGridSize.top + mTaskTopMargin * gridScale + float taskGridVerticalDiff = mLastComputedGridSize.top + taskTopMargin * gridScale - mLastComputedTaskSize.top; // Off-set gap due to task scaling. @@ -1669,7 +1669,7 @@ public abstract class RecentsView extends PagedView bottomSet.add(i); // Move into bottom row. - float heightOffset = (boxLength + mTaskTopMargin) * gridScale + mRowSpacing; + float heightOffset = (boxLength + taskTopMargin) * gridScale + mRowSpacing; taskView.setGridTranslationY(heightOffset + taskGridVerticalDiff); // Move horizontally into empty space. @@ -2485,7 +2485,7 @@ public abstract class RecentsView extends PagedView if (child == mSplitHiddenTaskView) { int left = newScroll[i] + getPaddingStart(); - int topMargin = mSplitHiddenTaskView.getThumbnailTopMargin(); + int topMargin = mActivity.getDeviceProfile().overviewTaskThumbnailTopMarginPx; int top = -mSplitHiddenTaskView.getHeight() - locationOnScreen[1]; mSplitHiddenTaskView.layout(left, top, left + mSplitHiddenTaskView.getWidth(), diff --git a/quickstep/src/com/android/quickstep/views/TaskMenuView.java b/quickstep/src/com/android/quickstep/views/TaskMenuView.java index a5b7a5b575..a46daf38fd 100644 --- a/quickstep/src/com/android/quickstep/views/TaskMenuView.java +++ b/quickstep/src/com/android/quickstep/views/TaskMenuView.java @@ -58,7 +58,6 @@ public class TaskMenuView extends AbstractFloatingView { private static final int REVEAL_OPEN_DURATION = 150; private static final int REVEAL_CLOSE_DURATION = 100; - private final float mThumbnailTopMargin; private BaseDraggingActivity mActivity; private TextView mTaskName; private AnimatorSet mOpenCloseAnimator; @@ -73,7 +72,6 @@ public class TaskMenuView extends AbstractFloatingView { super(context, attrs, defStyleAttr); mActivity = BaseDraggingActivity.fromContext(context); - mThumbnailTopMargin = getResources().getDimension(R.dimen.task_thumbnail_top_margin); setClipToOutline(true); } @@ -123,14 +121,15 @@ public class TaskMenuView extends AbstractFloatingView { } public void setPosition(float x, float y, PagedOrientationHandler pagedOrientationHandler) { - float adjustedY = y + mThumbnailTopMargin; + int taskTopMargin = mActivity.getDeviceProfile().overviewTaskThumbnailTopMarginPx; + float adjustedY = y + taskTopMargin; // Changing pivot to make computations easier // NOTE: Changing the pivots means the rotated view gets rotated about the new pivots set, // which would render the X and Y position set here incorrect setPivotX(0); if (mActivity.getDeviceProfile().isTablet && FeatureFlags.ENABLE_OVERVIEW_GRID.get()) { // In tablet, set pivotY to original position without mThumbnailTopMargin adjustment. - setPivotY(-mThumbnailTopMargin); + setPivotY(-taskTopMargin); } else { setPivotY(0); } diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java index a2acab880f..be044e7c48 100644 --- a/quickstep/src/com/android/quickstep/views/TaskView.java +++ b/quickstep/src/com/android/quickstep/views/TaskView.java @@ -376,7 +376,8 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { mCurrentFullscreenParams = new FullscreenDrawParams(context); mDigitalWellBeingToast = new DigitalWellBeingToast(mActivity, this); - mOutlineProvider = new TaskOutlineProvider(getContext(), mCurrentFullscreenParams); + mOutlineProvider = new TaskOutlineProvider(getContext(), mCurrentFullscreenParams, + mActivity.getDeviceProfile().overviewTaskThumbnailTopMarginPx); setOutlineProvider(mOutlineProvider); } @@ -673,16 +674,12 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { } } - public int getThumbnailTopMargin() { - return (int) getResources().getDimension(R.dimen.task_thumbnail_top_margin); - } - public void setOrientationState(RecentsOrientedState orientationState) { PagedOrientationHandler orientationHandler = orientationState.getOrientationHandler(); boolean isRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL; LayoutParams snapshotParams = (LayoutParams) mSnapshotView.getLayoutParams(); - int thumbnailPadding = (int) getResources().getDimension(R.dimen.task_thumbnail_top_margin); - int taskIconMargin = (int) getResources().getDimension(R.dimen.task_icon_top_margin); + snapshotParams.topMargin = mActivity.getDeviceProfile().overviewTaskThumbnailTopMarginPx; + int taskIconMargin = mActivity.getDeviceProfile().overviewTaskMarginPx; int taskIconHeight = (int) getResources().getDimension(R.dimen.task_thumbnail_icon_size); LayoutParams iconParams = (LayoutParams) mIconView.getLayoutParams(); switch (orientationHandler.getRotation()) { @@ -694,7 +691,7 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { break; case ROTATION_180: iconParams.gravity = BOTTOM | CENTER_HORIZONTAL; - iconParams.bottomMargin = -thumbnailPadding; + iconParams.bottomMargin = -snapshotParams.topMargin; iconParams.leftMargin = iconParams.rightMargin = 0; iconParams.topMargin = taskIconMargin; break; @@ -711,6 +708,7 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { iconParams.topMargin = taskIconMargin; break; } + mSnapshotView.setLayoutParams(snapshotParams); mIconView.setLayoutParams(iconParams); mIconView.setRotation(orientationHandler.getDegreesRotated()); @@ -1083,17 +1081,17 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { private static final class TaskOutlineProvider extends ViewOutlineProvider { - private final int mMarginTop; + private int mMarginTop; private FullscreenDrawParams mFullscreenParams; - TaskOutlineProvider(Context context, FullscreenDrawParams fullscreenParams) { - mMarginTop = context.getResources().getDimensionPixelSize( - R.dimen.task_thumbnail_top_margin); + TaskOutlineProvider(Context context, FullscreenDrawParams fullscreenParams, int topMargin) { + mMarginTop = topMargin; mFullscreenParams = fullscreenParams; } - public void setFullscreenParams(FullscreenDrawParams params) { + public void updateParams(FullscreenDrawParams params, int topMargin) { mFullscreenParams = params; + mMarginTop = topMargin; } @Override @@ -1216,7 +1214,9 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { } thumbnail.setFullscreenParams(mCurrentFullscreenParams); - mOutlineProvider.setFullscreenParams(mCurrentFullscreenParams); + mOutlineProvider.updateParams( + mCurrentFullscreenParams, + mActivity.getDeviceProfile().overviewTaskThumbnailTopMarginPx); invalidateOutline(); } @@ -1238,8 +1238,8 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { void updateTaskSize() { ViewGroup.LayoutParams params = getLayoutParams(); if (mActivity.getDeviceProfile().isTablet && FeatureFlags.ENABLE_OVERVIEW_GRID.get()) { - final int thumbnailPadding = (int) getResources().getDimension( - R.dimen.task_thumbnail_top_margin); + final int thumbnailPadding = + mActivity.getDeviceProfile().overviewTaskThumbnailTopMarginPx; Rect lastComputedTaskSize = getRecentsView().getLastComputedTaskSize(); int taskWidth = lastComputedTaskSize.width(); diff --git a/res/values/dimens.xml b/res/values/dimens.xml index cf830c7ed4..d54e3a142c 100644 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -286,4 +286,8 @@ 16dp + + 0dp + 0dp + diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java index fa19ee6918..09f4cde195 100644 --- a/src/com/android/launcher3/DeviceProfile.java +++ b/src/com/android/launcher3/DeviceProfile.java @@ -151,6 +151,10 @@ public class DeviceProfile { public int allAppsIconDrawablePaddingPx; public float allAppsIconTextSizePx; + // Overview + public int overviewTaskThumbnailTopMarginPx; + public int overviewTaskMarginPx; + // Widgets public final PointF appWidgetScale = new PointF(1.0f, 1.0f); @@ -297,6 +301,11 @@ public class DeviceProfile { : (hotseatBarTopPaddingPx + hotseatBarBottomPaddingPx + (isScalableGrid ? 0 : hotseatExtraVerticalSize))); + + overviewTaskMarginPx = res.getDimensionPixelSize(R.dimen.overview_task_margin); + overviewTaskThumbnailTopMarginPx = res.getDimensionPixelSize( + R.dimen.task_thumbnail_icon_size) + 2 * overviewTaskMarginPx; + // Calculate all of the remaining variables. extraSpace = updateAvailableDimensions(res); // Now that we have all of the variables calculated, we can tune certain sizes. From 02c4f65e67a30d7d3baaba7f7dd4aedfe7416bed Mon Sep 17 00:00:00 2001 From: Steven Ng Date: Wed, 24 Mar 2021 14:51:19 +0000 Subject: [PATCH 10/21] Fix scrolling in WidgetsBottomSheet Popup container shouldn't intercept the scroll event if its child scroll view isn't scrolled to the top yet. Test: manual Bug: 183599207 Change-Id: I434ba5e91b154e9862f22c08cd01c9d459e6707b --- .../launcher3/widget/WidgetsBottomSheet.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/com/android/launcher3/widget/WidgetsBottomSheet.java b/src/com/android/launcher3/widget/WidgetsBottomSheet.java index 2fda86c89c..bbb0d92eac 100644 --- a/src/com/android/launcher3/widget/WidgetsBottomSheet.java +++ b/src/com/android/launcher3/widget/WidgetsBottomSheet.java @@ -26,6 +26,7 @@ import android.util.IntProperty; import android.util.Pair; import android.view.Gravity; import android.view.LayoutInflater; +import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.animation.Interpolator; @@ -152,6 +153,19 @@ public class WidgetsBottomSheet extends BaseWidgetSheet implements Insettable { }); } + @Override + public boolean onControllerInterceptTouchEvent(MotionEvent ev) { + if (ev.getAction() == MotionEvent.ACTION_DOWN) { + mNoIntercept = false; + ScrollView scrollView = findViewById(R.id.widgets_table_scroll_view); + if (getPopupContainer().isEventOverView(scrollView, ev) + && scrollView.getScrollY() > 0) { + mNoIntercept = true; + } + } + return super.onControllerInterceptTouchEvent(ev); + } + protected WidgetCell addItemCell(ViewGroup parent) { WidgetCell widget = (WidgetCell) LayoutInflater.from(getContext()) .inflate(R.layout.widget_cell, parent, false); From 6151a34543be100447f8821d23acf0632e754749 Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Wed, 24 Mar 2021 10:01:44 -0700 Subject: [PATCH 11/21] Fix activity NPE when clearing flags - If the activity is already destroyed then skip setting flags Bug: 183400378 Test: Just adding a null check Change-Id: Id2fddb5adb3b68302fb58fce340abd29237ca731 --- quickstep/src/com/android/quickstep/views/RecentsView.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index 4d8176c7e5..3cdb1dcc3e 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -3160,7 +3160,9 @@ public abstract class RecentsView extends PagedView MAIN_EXECUTOR.execute(() -> { // Needed for activities that auto-enter PiP, which will not trigger a remote // animation to be created - mActivity.clearForceInvisibleFlag(STATE_HANDLER_INVISIBILITY_FLAGS); + if (mActivity != null) { + mActivity.clearForceInvisibleFlag(STATE_HANDLER_INVISIBILITY_FLAGS); + } }); } } From 387e65e3c4626bd9f623d22aac300b1301ef5d69 Mon Sep 17 00:00:00 2001 From: Jon Spivack Date: Wed, 24 Mar 2021 10:16:00 -0700 Subject: [PATCH 12/21] Change label for Search button in Go Overview The visual search button on the Recents screen (on Go devices) will be renamed to Lens. Bug: 183618164 Test: Manual Change-Id: I86371e604bd0204510737e5088c95404129818bb --- go/quickstep/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go/quickstep/res/values/strings.xml b/go/quickstep/res/values/strings.xml index 71e2f3a5c5..61c8cd9343 100644 --- a/go/quickstep/res/values/strings.xml +++ b/go/quickstep/res/values/strings.xml @@ -10,5 +10,5 @@ Translate - Search + Lens From 02e9f1e12f16456daf234c1e82ed43e26e1ef8b1 Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Mon, 22 Mar 2021 17:32:50 -0700 Subject: [PATCH 13/21] Slightly improve Taskbar animations to launcher - Move Taskbar scale to LauncherState - Rename TaskbarVisibilityController to TaskbarAnimationController and add mTaskbarScaleForLauncherState to TaskbarAnimationController - Set OverviewState#getTaskbarScale() = 1f so Taskbar doesn't scale up when going from an app to Overview - Increase home animation duration so Taskbar animation aligns better Test: Taskbar scales up when going home, doesn't scale up when going to overview Bug: 182512211 Change-Id: I6f448e76de98d7ff337ae93234d4bb7ce6254d50 --- .../launcher3/BaseQuickstepLauncher.java | 8 ++++ ...r.java => TaskbarAnimationController.java} | 31 ++++++++++--- .../launcher3/taskbar/TaskbarController.java | 46 +++++++++++-------- .../taskbar/TaskbarStateHandler.java | 5 ++ .../uioverrides/states/OverviewState.java | 5 ++ .../android/quickstep/AbsSwipeUpHandler.java | 5 +- .../util/StaggeredWorkspaceAnim.java | 9 ++-- src/com/android/launcher3/Launcher.java | 7 +++ src/com/android/launcher3/LauncherState.java | 4 ++ 9 files changed, 89 insertions(+), 31 deletions(-) rename quickstep/src/com/android/launcher3/taskbar/{TaskbarVisibilityController.java => TaskbarAnimationController.java} (76%) diff --git a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java index 6ba74145b2..085db6d7b6 100644 --- a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java +++ b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java @@ -335,6 +335,14 @@ public abstract class BaseQuickstepLauncher extends Launcher ? new float[] {1, 1} : new float[] {1.1f, 0}; } + @Override + public float getNormalTaskbarScale() { + if (mTaskbarController != null) { + return mTaskbarController.getTaskbarScaleOnHome(); + } + return super.getNormalTaskbarScale(); + } + @Override public void onDragLayerHierarchyChanged() { onLauncherStateOrFocusChanged(); diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarVisibilityController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarAnimationController.java similarity index 76% rename from quickstep/src/com/android/launcher3/taskbar/TaskbarVisibilityController.java rename to quickstep/src/com/android/launcher3/taskbar/TaskbarAnimationController.java index 8745a7c8d9..7c54e2d6b9 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarVisibilityController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarAnimationController.java @@ -20,20 +20,21 @@ import static com.android.launcher3.LauncherState.TASKBAR; import android.animation.Animator; import com.android.launcher3.BaseQuickstepLauncher; +import com.android.launcher3.Utilities; import com.android.quickstep.AnimatedFloat; import com.android.quickstep.SystemUiProxy; import com.android.systemui.shared.system.QuickStepContract; /** - * Works with TaskbarController to update the TaskbarView's alpha based on LauncherState, whether - * Launcher is in the foreground, etc. + * Works with TaskbarController to update the TaskbarView's visual properties based on factors such + * as LauncherState, whether Launcher is in the foreground, etc. */ -public class TaskbarVisibilityController { +public class TaskbarAnimationController { private static final long IME_VISIBILITY_ALPHA_DURATION = 120; private final BaseQuickstepLauncher mLauncher; - private final TaskbarController.TaskbarVisibilityControllerCallbacks mTaskbarCallbacks; + private final TaskbarController.TaskbarAnimationControllerCallbacks mTaskbarCallbacks; // Background alpha. private final AnimatedFloat mTaskbarBackgroundAlpha = new AnimatedFloat( @@ -45,8 +46,12 @@ public class TaskbarVisibilityController { private final AnimatedFloat mTaskbarVisibilityAlphaForIme = new AnimatedFloat( this::updateVisibilityAlpha); - public TaskbarVisibilityController(BaseQuickstepLauncher launcher, - TaskbarController.TaskbarVisibilityControllerCallbacks taskbarCallbacks) { + // Scale. + private final AnimatedFloat mTaskbarScaleForLauncherState = new AnimatedFloat( + this::updateScale); + + public TaskbarAnimationController(BaseQuickstepLauncher launcher, + TaskbarController.TaskbarAnimationControllerCallbacks taskbarCallbacks) { mLauncher = launcher; mTaskbarCallbacks = taskbarCallbacks; } @@ -72,6 +77,10 @@ public class TaskbarVisibilityController { return mTaskbarVisibilityAlphaForLauncherState; } + protected AnimatedFloat getTaskbarScaleForLauncherState() { + return mTaskbarScaleForLauncherState; + } + protected Animator createAnimToBackgroundAlpha(float toAlpha, long duration) { return mTaskbarBackgroundAlpha.animateToValue(mTaskbarBackgroundAlpha.value, toAlpha) .setDuration(duration); @@ -85,6 +94,7 @@ public class TaskbarVisibilityController { private void onTaskbarBackgroundAlphaChanged() { mTaskbarCallbacks.updateTaskbarBackgroundAlpha(mTaskbarBackgroundAlpha.value); updateVisibilityAlpha(); + updateScale(); } private void updateVisibilityAlpha() { @@ -101,6 +111,15 @@ public class TaskbarVisibilityController { setNavBarButtonAlpha(1f - taskbarAlpha); } + private void updateScale() { + // We use mTaskbarBackgroundAlpha as a proxy for whether Launcher is resumed/paused, the + // assumption being that Taskbar should always be at scale 1f regardless of the current + // LauncherState if Launcher is paused. + float scale = mTaskbarScaleForLauncherState.value; + scale = Utilities.mapRange(mTaskbarBackgroundAlpha.value, scale, 1f); + mTaskbarCallbacks.updateTaskbarScale(scale); + } + private void setNavBarButtonAlpha(float navBarAlpha) { SystemUiProxy.INSTANCE.get(mLauncher).setNavBarButtonAlpha(navBarAlpha, false); } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarController.java index eccc41bfe2..de23ad2efa 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarController.java @@ -19,8 +19,6 @@ import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; -import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY; -import static com.android.launcher3.anim.Interpolators.LINEAR; import static com.android.systemui.shared.system.WindowManagerWrapper.ITYPE_BOTTOM_TAPPABLE_ELEMENT; import static com.android.systemui.shared.system.WindowManagerWrapper.ITYPE_EXTRA_NAVIGATION_BAR; @@ -75,7 +73,7 @@ public class TaskbarController { // Layout width and height of the Taskbar in the default state. private final Point mTaskbarSize; private final TaskbarStateHandler mTaskbarStateHandler; - private final TaskbarVisibilityController mTaskbarVisibilityController; + private final TaskbarAnimationController mTaskbarAnimationController; private final TaskbarHotseatController mHotseatController; private final TaskbarRecentsController mRecentsController; private final TaskbarDragController mDragController; @@ -104,8 +102,8 @@ public class TaskbarController { mWindowManager = mLauncher.getWindowManager(); mTaskbarSize = new Point(MATCH_PARENT, mLauncher.getDeviceProfile().taskbarSize); mTaskbarStateHandler = mLauncher.getTaskbarStateHandler(); - mTaskbarVisibilityController = new TaskbarVisibilityController(mLauncher, - createTaskbarVisibilityControllerCallbacks()); + mTaskbarAnimationController = new TaskbarAnimationController(mLauncher, + createTaskbarAnimationControllerCallbacks()); mHotseatController = new TaskbarHotseatController(mLauncher, createTaskbarHotseatControllerCallbacks()); mRecentsController = new TaskbarRecentsController(mLauncher, @@ -113,8 +111,8 @@ public class TaskbarController { mDragController = new TaskbarDragController(mLauncher); } - private TaskbarVisibilityControllerCallbacks createTaskbarVisibilityControllerCallbacks() { - return new TaskbarVisibilityControllerCallbacks() { + private TaskbarAnimationControllerCallbacks createTaskbarAnimationControllerCallbacks() { + return new TaskbarAnimationControllerCallbacks() { @Override public void updateTaskbarBackgroundAlpha(float alpha) { mTaskbarViewInApp.setBackgroundAlpha(alpha); @@ -125,6 +123,12 @@ public class TaskbarController { mTaskbarContainerView.setAlpha(alpha); mTaskbarViewOnHome.setAlpha(alpha); } + + @Override + public void updateTaskbarScale(float scale) { + mTaskbarViewInApp.setScaleX(scale); + mTaskbarViewInApp.setScaleY(scale); + } }; } @@ -242,12 +246,10 @@ public class TaskbarController { mTaskbarContainerView.init(mTaskbarViewInApp); addToWindowManager(); mTaskbarStateHandler.setTaskbarCallbacks(createTaskbarStateHandlerCallbacks()); - mTaskbarVisibilityController.init(); + mTaskbarAnimationController.init(); mHotseatController.init(); mRecentsController.init(); - SCALE_PROPERTY.set(mTaskbarViewInApp, mLauncher.hasBeenResumed() - ? getTaskbarScaleOnHome() : 1f); updateWhichTaskbarViewIsVisible(); } @@ -255,7 +257,12 @@ public class TaskbarController { return new TaskbarStateHandlerCallbacks() { @Override public AnimatedFloat getAlphaTarget() { - return mTaskbarVisibilityController.getTaskbarVisibilityForLauncherState(); + return mTaskbarAnimationController.getTaskbarVisibilityForLauncherState(); + } + + @Override + public AnimatedFloat getScaleTarget() { + return mTaskbarAnimationController.getTaskbarScaleForLauncherState(); } }; } @@ -274,7 +281,7 @@ public class TaskbarController { mTaskbarContainerView.cleanup(); removeFromWindowManager(); mTaskbarStateHandler.setTaskbarCallbacks(null); - mTaskbarVisibilityController.cleanup(); + mTaskbarAnimationController.cleanup(); mHotseatController.cleanup(); mRecentsController.cleanup(); } @@ -342,12 +349,10 @@ public class TaskbarController { */ public Animator createAnimToLauncher(@Nullable LauncherState toState, long duration) { PendingAnimation anim = new PendingAnimation(duration); - anim.add(mTaskbarVisibilityController.createAnimToBackgroundAlpha(0, duration)); + anim.add(mTaskbarAnimationController.createAnimToBackgroundAlpha(0, duration)); if (toState != null) { mTaskbarStateHandler.setStateWithAnimation(toState, new StateAnimationConfig(), anim); } - anim.addFloat(mTaskbarViewInApp, SCALE_PROPERTY, mTaskbarViewInApp.getScaleX(), - getTaskbarScaleOnHome(), LINEAR); anim.addListener(new AnimatorListenerAdapter() { @Override @@ -368,8 +373,7 @@ public class TaskbarController { private Animator createAnimToApp(long duration) { PendingAnimation anim = new PendingAnimation(duration); - anim.add(mTaskbarVisibilityController.createAnimToBackgroundAlpha(1, duration)); - anim.addFloat(mTaskbarViewInApp, SCALE_PROPERTY, mTaskbarViewInApp.getScaleX(), 1f, LINEAR); + anim.add(mTaskbarAnimationController.createAnimToBackgroundAlpha(1, duration)); anim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animation) { @@ -390,7 +394,7 @@ public class TaskbarController { * Should be called when the IME visibility changes, so we can hide/show Taskbar accordingly. */ public void setIsImeVisible(boolean isImeVisible) { - mTaskbarVisibilityController.animateToVisibilityForIme(isImeVisible ? 0 : 1); + mTaskbarAnimationController.animateToVisibilityForIme(isImeVisible ? 0 : 1); } /** @@ -527,15 +531,17 @@ public class TaskbarController { */ protected interface TaskbarStateHandlerCallbacks { AnimatedFloat getAlphaTarget(); + AnimatedFloat getScaleTarget(); } /** - * Contains methods that TaskbarVisibilityController can call to interface with + * Contains methods that TaskbarAnimationController can call to interface with * TaskbarController. */ - protected interface TaskbarVisibilityControllerCallbacks { + protected interface TaskbarAnimationControllerCallbacks { void updateTaskbarBackgroundAlpha(float alpha); void updateTaskbarVisibilityAlpha(float alpha); + void updateTaskbarScale(float scale); } /** diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStateHandler.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStateHandler.java index 0a3819dad5..9fc7d995a7 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStateHandler.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStateHandler.java @@ -53,8 +53,10 @@ public class TaskbarStateHandler implements StateManager.StateHandler, STATE_LAUNCHER_PRESENT | STATE_LAUNCHER_DRAWN | STATE_LAUNCHER_STARTED; public static final long MAX_SWIPE_DURATION = 350; - public static final long MIN_OVERSHOOT_DURATION = 120; + public static final long HOME_DURATION = StaggeredWorkspaceAnim.DURATION_MS; public static final float MIN_PROGRESS_FOR_OVERVIEW = 0.7f; private static final float SWIPE_DURATION_MULTIPLIER = @@ -957,7 +958,7 @@ public abstract class AbsSwipeUpHandler, mInputConsumerProxy.enable(); } if (endTarget == HOME) { - duration = Math.max(MIN_OVERSHOOT_DURATION, duration); + duration = HOME_DURATION; } else if (endTarget == RECENTS) { if (mRecentsView != null) { int nearestPage = mRecentsView.getDestinationPage(); diff --git a/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java b/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java index d4ca31fbda..f68e936f7f 100644 --- a/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java +++ b/quickstep/src/com/android/quickstep/util/StaggeredWorkspaceAnim.java @@ -60,7 +60,10 @@ import com.android.systemui.plugins.ResourceProvider; public class StaggeredWorkspaceAnim { private static final int APP_CLOSE_ROW_START_DELAY_MS = 10; + // How long it takes to fade in each staggered row. private static final int ALPHA_DURATION_MS = 250; + // Should be used for animations running alongside this StaggeredWorkspaceAnim. + public static final int DURATION_MS = 250; private static final float MAX_VELOCITY_PX_PER_S = 22f; @@ -131,15 +134,15 @@ public class StaggeredWorkspaceAnim { } if (animateOverviewScrim) { - PendingAnimation pendingAnimation = new PendingAnimation(ALPHA_DURATION_MS); + PendingAnimation pendingAnimation = new PendingAnimation(DURATION_MS); addScrimAnimationForState(launcher, NORMAL, pendingAnimation); mAnimators.play(pendingAnimation.buildAnim()); } - addDepthAnimationForState(launcher, NORMAL, ALPHA_DURATION_MS); + addDepthAnimationForState(launcher, NORMAL, DURATION_MS); mAnimators.play(launcher.getDragLayer().getSysUiScrim().createSysuiMultiplierAnim(0f, 1f) - .setDuration(ALPHA_DURATION_MS)); + .setDuration(DURATION_MS)); mAnimators.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 89c0f6697e..8785fbc2b9 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -2763,6 +2763,13 @@ public class Launcher extends StatefulActivity implements Launche return new float[] {NO_SCALE, NO_OFFSET}; } + /** + * @see LauncherState#getTaskbarScale(Launcher) + */ + public float getNormalTaskbarScale() { + return 1f; + } + public static Launcher getLauncher(Context context) { return fromContext(context); } diff --git a/src/com/android/launcher3/LauncherState.java b/src/com/android/launcher3/LauncherState.java index 06bc4380fa..46bce937bf 100644 --- a/src/com/android/launcher3/LauncherState.java +++ b/src/com/android/launcher3/LauncherState.java @@ -176,6 +176,10 @@ public abstract class LauncherState implements BaseState { return launcher.getNormalOverviewScaleAndOffset(); } + public float getTaskbarScale(Launcher launcher) { + return launcher.getNormalTaskbarScale(); + } + public float getOverviewFullscreenProgress() { return 0; } From dedbc8ac36f674baa47694bc20a93f8ee2fe46cc Mon Sep 17 00:00:00 2001 From: Alex Chau Date: Wed, 17 Mar 2021 16:53:26 +0000 Subject: [PATCH 14/21] Remove grid scaling in Overveiw - Grid scaling has problem that scales task icon and menu, which makes it hard to control icon size and text size in the manula - Replaced the whole concept with dedicated Task size calculation in grid layout - Support different icon size in TaskView in grid and removed task_thumbnail_top_margin - Removed grid progress in TaskViewSimulator as well - Refactored how ClearAllButton scroll and translations are calcualted to align clear all properly in grid - Make page center calculation aware of PagedView pivot and scaling Bug: 174464863 Test: Manual on two screens Change-Id: I47b13ef6e55c6e16c52ea04225f5bde02ed82fc2 --- quickstep/res/values/dimens.xml | 1 + .../android/quickstep/AbsSwipeUpHandler.java | 11 +- .../quickstep/BaseActivityInterface.java | 86 ++++++---- .../com/android/quickstep/TaskViewUtils.java | 7 +- .../quickstep/util/TaskViewSimulator.java | 36 ---- .../quickstep/views/ClearAllButton.java | 66 ++++++-- .../android/quickstep/views/RecentsView.java | 158 +++++++++--------- .../com/android/quickstep/views/TaskView.java | 38 ++--- res/values/dimens.xml | 1 + src/com/android/launcher3/DeviceProfile.java | 11 +- src/com/android/launcher3/PagedView.java | 23 ++- .../android/launcher3/anim/Interpolators.java | 3 + .../touch/LandscapePagedViewHandler.java | 2 +- .../touch/PagedOrientationHandler.java | 2 +- .../touch/PortraitPagedViewHandler.java | 2 +- 15 files changed, 233 insertions(+), 214 deletions(-) diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml index 0ff11c5f5e..3036341dae 100644 --- a/quickstep/res/values/dimens.xml +++ b/quickstep/res/values/dimens.xml @@ -16,6 +16,7 @@ 48dp + 32dp 2dp diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java index b49282544d..f4ef1f7e47 100644 --- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java +++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java @@ -923,6 +923,9 @@ public abstract class AbsSwipeUpHandler, float currentShift = mCurrentShift.value; final GestureEndTarget endTarget = calculateEndTarget(velocity, endVelocity, isFling, isCancel); + // Set the state, but don't notify until the animation completes + mGestureState.setEndTarget(endTarget, false /* isAtomic */); + float endShift = endTarget.isLauncher ? 1 : 0; final float startShift; if (!isFling) { @@ -945,7 +948,7 @@ public abstract class AbsSwipeUpHandler, } Interpolator interpolator; S state = mActivityInterface.stateFromGestureEndTarget(endTarget); - if (state.displayOverviewTasksAsGrid(mActivity.getDeviceProfile())) { + if (state.displayOverviewTasksAsGrid(mDp)) { interpolator = ACCEL_DEACCEL; } else if (endTarget == RECENTS) { interpolator = OVERSHOOT_1_2; @@ -1055,8 +1058,6 @@ public abstract class AbsSwipeUpHandler, @UiThread private void animateToProgressInternal(float start, float end, long duration, Interpolator interpolator, GestureEndTarget target, PointF velocityPxPerMs) { - // Set the state, but don't notify until the animation completes - mGestureState.setEndTarget(target, false /* isAtomic */); maybeUpdateRecentsAttachedState(); // If we are transitioning to launcher, then listen for the activity to be restarted while @@ -1147,10 +1148,8 @@ public abstract class AbsSwipeUpHandler, }); animatorSet.play(windowAnim); S state = mActivityInterface.stateFromGestureEndTarget(mGestureState.getEndTarget()); - if (mRecentsView != null && state.displayOverviewTasksAsGrid( - mActivity.getDeviceProfile())) { + if (mRecentsView != null && state.displayOverviewTasksAsGrid(mDp)) { animatorSet.play(ObjectAnimator.ofFloat(mRecentsView, RECENTS_GRID_PROGRESS, 1)); - animatorSet.play(mTaskViewSimulator.gridProgress.animateToValue(0, 1)); } animatorSet.setDuration(duration).setInterpolator(interpolator); animatorSet.start(); diff --git a/quickstep/src/com/android/quickstep/BaseActivityInterface.java b/quickstep/src/com/android/quickstep/BaseActivityInterface.java index 462630cac3..0415009faf 100644 --- a/quickstep/src/com/android/quickstep/BaseActivityInterface.java +++ b/quickstep/src/com/android/quickstep/BaseActivityInterface.java @@ -31,6 +31,7 @@ import android.animation.Animator; import android.annotation.TargetApi; import android.content.Context; import android.content.res.Resources; +import android.graphics.PointF; import android.graphics.Rect; import android.os.Build; import android.view.Gravity; @@ -43,6 +44,7 @@ import com.android.launcher3.DeviceProfile; import com.android.launcher3.R; import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.anim.PendingAnimation; +import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.statehandlers.DepthController; import com.android.launcher3.statemanager.BaseState; import com.android.launcher3.statemanager.StatefulActivity; @@ -195,45 +197,53 @@ public abstract class BaseActivityInterface extends PagedView protected final Rect mTempRect = new Rect(); protected final RectF mTempRectF = new RectF(); private final PointF mTempPointF = new PointF(); + private float mFullscreenScale; private static final int DISMISS_TASK_DURATION = 300; private static final int ADDITION_TASK_DURATION = 200; @@ -741,7 +742,7 @@ public abstract class RecentsView extends PagedView int taskStart = mOrientationHandler.getChildStart(tv) + (int) tv.getOffsetAdjustment( mOverviewFullscreenEnabled, showAsGrid()); int taskSize = (int) (mOrientationHandler.getMeasuredSize(tv) * tv.getSizeAdjustment( - mOverviewFullscreenEnabled, showAsGrid())); + mOverviewFullscreenEnabled)); int taskEnd = taskStart + taskSize; return (taskStart >= start && taskStart <= end) || (taskEnd >= start && taskEnd <= end); @@ -1019,7 +1020,6 @@ public abstract class RecentsView extends PagedView mLiveTileTaskViewSimulator.taskSecondaryTranslation.value = 0; mLiveTileTaskViewSimulator.fullScreenProgress.value = 0; mLiveTileTaskViewSimulator.recentsViewScale.value = 1; - mLiveTileTaskViewSimulator.gridProgress.value = 0; } if (mRunningTaskTileHidden) { setRunningTaskHidden(mRunningTaskTileHidden); @@ -1091,6 +1091,10 @@ public abstract class RecentsView extends PagedView */ private void updateTaskSize() { final int taskCount = getTaskViewCount(); + if (taskCount == 0) { + return; + } + float accumulatedTranslationX = 0; float[] fullscreenTranslations = new float[taskCount]; int firstNonHomeTaskIndex = 0; @@ -1105,8 +1109,11 @@ public abstract class RecentsView extends PagedView taskView.updateTaskSize(); fullscreenTranslations[i] += accumulatedTranslationX; + // Compensate space caused by TaskView scaling. float widthDiff = taskView.getLayoutParams().width * (1 - taskView.getFullscreenScale()); + // Compensate page spacing widening caused by RecentsView scaling. + widthDiff += mPageSpacing * (1 - 1 / mFullscreenScale); float fullscreenTranslationX = mIsRtl ? widthDiff : -widthDiff; fullscreenTranslations[i] += fullscreenTranslationX; accumulatedTranslationX += fullscreenTranslationX; @@ -1180,13 +1187,13 @@ public abstract class RecentsView extends PagedView View page = getPageAt(i); mScrollState.updateInterpolation(mActivity.getDeviceProfile(), mOrientationHandler.getChildStartWithTranslation(page)); - ((PageCallbacks) page).onPageScroll(mScrollState); + ((PageCallbacks) page).onPageScroll(mScrollState, mOverviewGridEnabled); } } @Override protected int getDestinationPage(int scaledScroll) { - if (mGridProgress == 0) { + if (!showAsGrid()) { return super.getDestinationPage(scaledScroll); } @@ -1599,11 +1606,7 @@ public abstract class RecentsView extends PagedView } final int boxLength = Math.max(mTaskWidth, mTaskHeight); - float availableHeight = mLastComputedGridSize.height(); - float rowHeight = (availableHeight - mRowSpacing) / 2; int taskTopMargin = mActivity.getDeviceProfile().overviewTaskThumbnailTopMarginPx; - float gridScale = rowHeight / (boxLength + taskTopMargin); - int topRowWidth = 0; int bottomRowWidth = 0; float topAccumulatedTranslationX = 0; @@ -1621,43 +1624,17 @@ public abstract class RecentsView extends PagedView continue; } - taskView.setGridScale(gridScale); - - float scaledWidth = taskView.getLayoutParams().width * gridScale; - float taskGridHorizontalDiff; - if (mIsRtl) { - float taskRight = mLastComputedTaskSize.left + scaledWidth; - taskGridHorizontalDiff = mLastComputedGridSize.right - taskRight; - } else { - float taskLeft = mLastComputedTaskSize.right - scaledWidth; - taskGridHorizontalDiff = mLastComputedGridSize.left - taskLeft; - } - gridTranslations[i] -= taskGridHorizontalDiff; - taskView.setGridOffsetTranslationX(taskGridHorizontalDiff); - - float taskGridVerticalDiff = mLastComputedGridSize.top + taskTopMargin * gridScale - - mLastComputedTaskSize.top; - - // Off-set gap due to task scaling. - float widthDiff = taskView.getLayoutParams().width * (1 - gridScale); - float gridScaleTranslationX = mIsRtl ? widthDiff : -widthDiff; - gridTranslations[i] += gridScaleTranslationX; - - // Visible offset caused by having scaling pivot on top-right. - taskView.setNonRtlVisibleOffset(mIsRtl ? 0 : widthDiff); - if (topRowWidth <= bottomRowWidth) { gridTranslations[i] += topAccumulatedTranslationX; - topRowWidth += taskView.getLayoutParams().width * gridScale + mPageSpacing; + topRowWidth += taskView.getLayoutParams().width + mPageSpacing; topSet.add(i); - taskView.setGridTranslationY(taskGridVerticalDiff); + taskView.setGridTranslationY(0); // Move horizontally into empty space. float widthOffset = 0; for (int j = i - 1; bottomSet.contains(j); j--) { - widthOffset += getTaskViewAt(j).getLayoutParams().width * gridScale - + mPageSpacing; + widthOffset += getTaskViewAt(j).getLayoutParams().width + mPageSpacing; } float gridTranslationX = mIsRtl ? widthOffset : -widthOffset; @@ -1665,26 +1642,39 @@ public abstract class RecentsView extends PagedView topAccumulatedTranslationX += gridTranslationX; } else { gridTranslations[i] += bottomAccumulatedTranslationX; - bottomRowWidth += taskView.getLayoutParams().width * gridScale + mPageSpacing; + bottomRowWidth += taskView.getLayoutParams().width + mPageSpacing; bottomSet.add(i); // Move into bottom row. - float heightOffset = (boxLength + taskTopMargin) * gridScale + mRowSpacing; - taskView.setGridTranslationY(heightOffset + taskGridVerticalDiff); + float heightOffset = (boxLength + taskTopMargin) + mRowSpacing; + taskView.setGridTranslationY(heightOffset); // Move horizontally into empty space. float widthOffset = 0; for (int j = i - 1; topSet.contains(j); j--) { - widthOffset += getTaskViewAt(j).getLayoutParams().width * gridScale - + mPageSpacing; + widthOffset += getTaskViewAt(j).getLayoutParams().width + mPageSpacing; } float gridTranslationX = mIsRtl ? widthOffset : -widthOffset; gridTranslations[i] += gridTranslationX; bottomAccumulatedTranslationX += gridTranslationX; } - topAccumulatedTranslationX += gridScaleTranslationX; - bottomAccumulatedTranslationX += gridScaleTranslationX; + } + + // If the first non-home task does not take full width of task Rect, shift all tasks + // accordingly without affecting scrolls. + int firstTaskWidth = getTaskViewAt(firstNonHomeTaskIndex).getLayoutParams().width; + float firstNonHomeTaskOffset = firstTaskWidth == ViewGroup.LayoutParams.MATCH_PARENT ? 0 + : mTaskWidth - firstTaskWidth; + float offsetTranslation = mIsRtl ? firstNonHomeTaskOffset : -firstNonHomeTaskOffset; + + // We need to maintain first non-home task's grid translation at 0, now shift translation + // of all the TaskViews to achieve that. + for (int i = firstNonHomeTaskIndex; i < taskCount; i++) { + TaskView taskView = getTaskViewAt(i); + taskView.setGridTranslationX( + gridTranslations[i] - gridTranslations[firstNonHomeTaskIndex]); + taskView.setGridOffsetTranslationX(offsetTranslation); } // Use the accumulated translation of the longer row. @@ -1700,7 +1690,7 @@ public abstract class RecentsView extends PagedView shorterRowCompensation = bottomRowWidth - topRowWidth; } } else { - if (!topSet.contains(taskCount - 1)) { + if (bottomSet.contains(taskCount - 1)) { shorterRowCompensation = topRowWidth - bottomRowWidth; } } @@ -1721,14 +1711,14 @@ public abstract class RecentsView extends PagedView clearAllAccumulatedTranslation + clearAllShorterRowCompensation + clearAllShortTotalCompensation; - // We need to maintain first non-home task's grid translation at 0, now shift translation - // of all the TaskViews to achieve that. - for (int i = firstNonHomeTaskIndex; i < taskCount; i++) { - getTaskViewAt(i).setGridTranslationX( - gridTranslations[i] - gridTranslations[firstNonHomeTaskIndex]); - } mClearAllButton.setGridTranslationPrimary( clearAllTotalTranslationX - gridTranslations[firstNonHomeTaskIndex]); + mClearAllButton.setGridTranslationSecondary( + boxLength - mTaskHeight / 2f + mRowSpacing / 2f); + mClearAllButton.setGridScrollOffset( + mIsRtl ? mLastComputedTaskSize.left - mLastComputedGridSize.left + : mLastComputedTaskSize.right - mLastComputedGridSize.right); + mClearAllButton.setOffsetTranslationPrimary(offsetTranslation); setGridProgress(mGridProgress); } @@ -1753,7 +1743,6 @@ public abstract class RecentsView extends PagedView for (int i = 0; i < taskCount; i++) { getTaskViewAt(i).setGridProgress(gridProgress); } - mLiveTileTaskViewSimulator.gridProgress.value = gridProgress; mClearAllButton.setGridProgress(gridProgress); } @@ -1801,8 +1790,10 @@ public abstract class RecentsView extends PagedView /** * Updates the page UI based on scroll params. + * + * @param gridEnabled whether Overveiw is currently showing as 2 rows grid */ - default void onPageScroll(ScrollState scrollState) {} + default void onPageScroll(ScrollState scrollState, boolean gridEnabled) {} } public static class ScrollState extends CurveProperties { @@ -2297,7 +2288,7 @@ public abstract class RecentsView extends PagedView // Update the pivots such that when the task is scaled, it fills the full page getTaskSize(mTempRect); - getPagedViewOrientedState().getFullScreenScaleAndPivot( + mFullscreenScale = getPagedViewOrientedState().getFullScreenScaleAndPivot( mTempRect, mActivity.getDeviceProfile(), mTempPointF); setPivotX(mTempPointF.x); setPivotY(mTempPointF.y); @@ -2858,22 +2849,42 @@ public abstract class RecentsView extends PagedView @Override protected int computeMinScroll() { if (getTaskViewCount() > 0) { - if (mDisallowScrollToClearAll) { + if (mIsRtl && mDisallowScrollToClearAll) { // We aren't showing the clear all button, // so use the leftmost task as the min scroll. - if (mIsRtl) { - return getScrollForPage(indexOfChild(getTaskViewAt(getTaskViewCount() - 1))); - } - return getScrollForPage(mTaskViewStartIndex); + return getScrollForPage(indexOfChild(getTaskViewAt(getTaskViewCount() - 1))); } - if (mIsRtl) { - return getScrollForPage(indexOfChild(getTaskViewAt(getTaskViewCount() - 1)) + 1); - } - return getScrollForPage(mTaskViewStartIndex); + return getLeftMostChildScroll(); } return super.computeMinScroll(); } + /** + * Returns page scroll of the left most child. + */ + public int getLeftMostChildScroll() { + if (mIsRtl) { + return getScrollForPage(indexOfChild(getTaskViewAt(getTaskViewCount() - 1)) + 1); + } + return getScrollForPage(mTaskViewStartIndex); + } + + @Override + protected int computeMaxScroll() { + if (getTaskViewCount() > 0) { + if (!mIsRtl && mDisallowScrollToClearAll) { + // We aren't showing the clear all button, + // so use the rightmost task as the min scroll. + return getScrollForPage(indexOfChild(getTaskViewAt(getTaskViewCount() - 1))); + } + if (mIsRtl) { + return getScrollForPage(mTaskViewStartIndex); + } + return getScrollForPage(indexOfChild(getTaskViewAt(getTaskViewCount() - 1)) + 1); + } + return super.computeMaxScroll(); + } + @Override protected boolean getPageScrolls(int[] outPageScrolls, boolean layoutChildren, ComputePageScrollsLogic scrollLogic) { @@ -2919,26 +2930,7 @@ public abstract class RecentsView extends PagedView return super.getChildVisibleSize(index); } return (int) (super.getChildVisibleSize(index) * taskView.getSizeAdjustment( - mOverviewFullscreenEnabled, showAsGrid())); - } - - @Override - protected int computeMaxScroll() { - if (getTaskViewCount() > 0) { - if (mDisallowScrollToClearAll) { - // We aren't showing the clear all button, - // so use the rightmost task as the min scroll. - if (mIsRtl) { - return getScrollForPage(mTaskViewStartIndex); - } - return getScrollForPage(indexOfChild(getTaskViewAt(getTaskViewCount() - 1))); - } - if (mIsRtl) { - return getScrollForPage(mTaskViewStartIndex); - } - return getScrollForPage(indexOfChild(getTaskViewAt(getTaskViewCount() - 1)) + 1); - } - return super.computeMaxScroll(); + mOverviewFullscreenEnabled)); } public ClearAllButton getClearAllButton() { diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java index be044e7c48..d497a96edb 100644 --- a/quickstep/src/com/android/quickstep/views/TaskView.java +++ b/quickstep/src/com/android/quickstep/views/TaskView.java @@ -279,7 +279,6 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { private float mFullscreenProgress; private float mGridProgress; private float mFullscreenScale = 1; - private float mGridScale = 1; private final FullscreenDrawParams mCurrentFullscreenParams; private final StatefulActivity mActivity; @@ -298,7 +297,6 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { private float mGridTranslationY; // Offset translation does not affect scroll calculation. private float mGridOffsetTranslationX; - private float mNonRtlVisibleOffset; private ObjectAnimator mIconAndDimAnimator; private float mIconScaleAnimStartProgress = 0; @@ -678,9 +676,10 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { PagedOrientationHandler orientationHandler = orientationState.getOrientationHandler(); boolean isRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL; LayoutParams snapshotParams = (LayoutParams) mSnapshotView.getLayoutParams(); - snapshotParams.topMargin = mActivity.getDeviceProfile().overviewTaskThumbnailTopMarginPx; - int taskIconMargin = mActivity.getDeviceProfile().overviewTaskMarginPx; - int taskIconHeight = (int) getResources().getDimension(R.dimen.task_thumbnail_icon_size); + DeviceProfile deviceProfile = mActivity.getDeviceProfile(); + snapshotParams.topMargin = deviceProfile.overviewTaskThumbnailTopMarginPx; + int taskIconMargin = deviceProfile.overviewTaskMarginPx; + int taskIconHeight = deviceProfile.overviewTaskIconSizePx; LayoutParams iconParams = (LayoutParams) mIconView.getLayoutParams(); switch (orientationHandler.getRotation()) { case ROTATION_90: @@ -709,8 +708,11 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { break; } mSnapshotView.setLayoutParams(snapshotParams); + iconParams.width = iconParams.height = taskIconHeight; mIconView.setLayoutParams(iconParams); mIconView.setRotation(orientationHandler.getDegreesRotated()); + snapshotParams.topMargin = deviceProfile.overviewTaskThumbnailTopMarginPx; + mSnapshotView.setLayoutParams(snapshotParams); if (mMenuView != null) { mMenuView.onRotationChanged(); @@ -790,8 +792,8 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { @Override public void onRecycle() { - mFullscreenTranslationX = mGridTranslationX = mGridTranslationY = - mGridOffsetTranslationX = mBoxTranslationY = mNonRtlVisibleOffset = 0f; + mFullscreenTranslationX = mGridTranslationX = + mGridTranslationY = mGridOffsetTranslationX = mBoxTranslationY = 0f; resetViewTransforms(); // Clear any references to the thumbnail (it will be re-read either from the cache or the // system on next bind) @@ -801,7 +803,7 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { } @Override - public void onPageScroll(ScrollState scrollState) { + public void onPageScroll(ScrollState scrollState, boolean gridEnabled) { // Don't do anything if it's modal. if (mModalness > 0) { return; @@ -904,11 +906,6 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { return mFullscreenScale; } - public void setGridScale(float gridScale) { - mGridScale = gridScale; - applyScale(); - } - /** * Moves TaskView between carousel and 2 row grid. * @@ -925,8 +922,6 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { float scale = 1; float fullScreenProgress = EXAGGERATED_EASE.getInterpolation(mFullscreenProgress); scale *= Utilities.mapRange(fullScreenProgress, 1f, mFullscreenScale); - float gridProgress = ACCEL_DEACCEL.getInterpolation(mGridProgress); - scale *= Utilities.mapRange(gridProgress, 1f, mGridScale); setScaleX(scale); setScaleY(scale); } @@ -989,10 +984,6 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { applyTranslationX(); } - public void setNonRtlVisibleOffset(float nonRtlVisibleOffset) { - mNonRtlVisibleOffset = nonRtlVisibleOffset; - } - public float getScrollAdjustment(boolean fullscreenEnabled, boolean gridEnabled) { float scrollAdjustment = 0; if (fullscreenEnabled) { @@ -1004,22 +995,19 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable { return scrollAdjustment; } - public float getOffsetAdjustment(boolean fullscreenEnabled, boolean gridEnabled) { + public float getOffsetAdjustment(boolean fullscreenEnabled,boolean gridEnabled) { float offsetAdjustment = getScrollAdjustment(fullscreenEnabled, gridEnabled); if (gridEnabled) { - offsetAdjustment += mGridOffsetTranslationX + mNonRtlVisibleOffset; + offsetAdjustment += mGridOffsetTranslationX; } return offsetAdjustment; } - public float getSizeAdjustment(boolean fullscreenEnabled, boolean gridEnabled) { + public float getSizeAdjustment(boolean fullscreenEnabled) { float sizeAdjustment = 1; if (fullscreenEnabled) { sizeAdjustment *= mFullscreenScale; } - if (gridEnabled) { - sizeAdjustment *= mGridScale; - } return sizeAdjustment; } diff --git a/res/values/dimens.xml b/res/values/dimens.xml index 73af517e98..1fccdf34a6 100644 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -294,6 +294,7 @@ 0dp + 0dp 0dp diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java index 09f4cde195..58d612d014 100644 --- a/src/com/android/launcher3/DeviceProfile.java +++ b/src/com/android/launcher3/DeviceProfile.java @@ -152,8 +152,9 @@ public class DeviceProfile { public float allAppsIconTextSizePx; // Overview - public int overviewTaskThumbnailTopMarginPx; public int overviewTaskMarginPx; + public int overviewTaskIconSizePx; + public int overviewTaskThumbnailTopMarginPx; // Widgets public final PointF appWidgetScale = new PointF(1.0f, 1.0f); @@ -301,10 +302,12 @@ public class DeviceProfile { : (hotseatBarTopPaddingPx + hotseatBarBottomPaddingPx + (isScalableGrid ? 0 : hotseatExtraVerticalSize))); - overviewTaskMarginPx = res.getDimensionPixelSize(R.dimen.overview_task_margin); - overviewTaskThumbnailTopMarginPx = res.getDimensionPixelSize( - R.dimen.task_thumbnail_icon_size) + 2 * overviewTaskMarginPx; + overviewTaskIconSizePx = + isTablet && FeatureFlags.ENABLE_OVERVIEW_GRID.get() ? res.getDimensionPixelSize( + R.dimen.task_thumbnail_icon_size_grid) : res.getDimensionPixelSize( + R.dimen.task_thumbnail_icon_size); + overviewTaskThumbnailTopMarginPx = overviewTaskIconSizePx + overviewTaskMarginPx * 2; // Calculate all of the remaining variables. extraSpace = updateAvailableDimensions(res); diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java index 65fde8659a..76885ccbc8 100644 --- a/src/com/android/launcher3/PagedView.java +++ b/src/com/android/launcher3/PagedView.java @@ -1512,17 +1512,16 @@ public abstract class PagedView extends ViewGrou return getDestinationPage(mOrientationHandler.getPrimaryScroll(this)); } - protected int getDestinationPage(int scaledScroll) { - return getPageNearestToCenterOfScreen(scaledScroll); + protected int getDestinationPage(int primaryScroll) { + return getPageNearestToCenterOfScreen(primaryScroll); } public int getPageNearestToCenterOfScreen() { return getPageNearestToCenterOfScreen(mOrientationHandler.getPrimaryScroll(this)); } - private int getPageNearestToCenterOfScreen(int scaledScroll) { - int pageOrientationSize = mOrientationHandler.getMeasuredSize(this); - int screenCenter = scaledScroll + (pageOrientationSize / 2); + private int getPageNearestToCenterOfScreen(int primaryScroll) { + int screenCenter = getScreenCenter(primaryScroll); int minDistanceFromScreenCenter = Integer.MAX_VALUE; int minDistanceFromScreenCenterIndex = -1; final int childCount = getChildCount(); @@ -1538,18 +1537,26 @@ public abstract class PagedView extends ViewGrou } private int getDisplacementFromScreenCenter(int childIndex, int screenCenter) { - int childSize = getChildVisibleSize(childIndex); + int childSize = Math.round(getChildVisibleSize(childIndex)); int halfChildSize = (childSize / 2); int childCenter = getChildOffset(childIndex) + halfChildSize; return childCenter - screenCenter; } protected int getDisplacementFromScreenCenter(int childIndex) { - int pageOrientationSize = mOrientationHandler.getMeasuredSize(this); - int screenCenter = mOrientationHandler.getPrimaryScroll(this) + (pageOrientationSize / 2); + int primaryScroll = mOrientationHandler.getPrimaryScroll(this); + int screenCenter = getScreenCenter(primaryScroll); return getDisplacementFromScreenCenter(childIndex, screenCenter); } + private int getScreenCenter(int primaryScroll) { + float primaryScale = mOrientationHandler.getPrimaryScale(this); + float primaryPivot = mOrientationHandler.getPrimaryValue(getPivotX(), getPivotY()); + int pageOrientationSize = mOrientationHandler.getMeasuredSize(this); + return Math.round(primaryScroll + (pageOrientationSize / 2f - primaryPivot) / primaryScale + + primaryPivot); + } + protected void snapToDestination() { snapToPage(getDestinationPage(), getPageSnapDuration()); } diff --git a/src/com/android/launcher3/anim/Interpolators.java b/src/com/android/launcher3/anim/Interpolators.java index 6b9ed09c77..7980138370 100644 --- a/src/com/android/launcher3/anim/Interpolators.java +++ b/src/com/android/launcher3/anim/Interpolators.java @@ -77,6 +77,9 @@ public class Interpolators { public static final Interpolator TOUCH_RESPONSE_INTERPOLATOR = new PathInterpolator(0.3f, 0f, 0.1f, 1f); + public static final Interpolator TOUCH_RESPONSE_INTERPOLATOR_ACCEL_DEACCEL = + v -> ACCEL_DEACCEL.getInterpolation(TOUCH_RESPONSE_INTERPOLATOR.getInterpolation(v)); + /** * Inversion of ZOOM_OUT, compounded with an ease-out. diff --git a/src/com/android/launcher3/touch/LandscapePagedViewHandler.java b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java index c1cf0c8ec2..19dfe15f62 100644 --- a/src/com/android/launcher3/touch/LandscapePagedViewHandler.java +++ b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java @@ -136,7 +136,7 @@ public class LandscapePagedViewHandler implements PagedOrientationHandler { } @Override - public int getClearAllScrollOffset(View view, boolean isRtl) { + public int getClearAllSidePadding(View view, boolean isRtl) { return (isRtl ? view.getPaddingBottom() : - view.getPaddingTop()) / 2; } diff --git a/src/com/android/launcher3/touch/PagedOrientationHandler.java b/src/com/android/launcher3/touch/PagedOrientationHandler.java index fcfa205ed2..9140a04341 100644 --- a/src/com/android/launcher3/touch/PagedOrientationHandler.java +++ b/src/com/android/launcher3/touch/PagedOrientationHandler.java @@ -66,7 +66,7 @@ public interface PagedOrientationHandler { float getPrimaryVelocity(VelocityTracker velocityTracker, int pointerId); int getMeasuredSize(View view); float getPrimarySize(RectF rect); - int getClearAllScrollOffset(View view, boolean isRtl); + int getClearAllSidePadding(View view, boolean isRtl); int getSecondaryDimension(View view); FloatProperty getPrimaryViewTranslate(); FloatProperty getSecondaryViewTranslate(); diff --git a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java index 2bc2dc7d93..29be62733c 100644 --- a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java +++ b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java @@ -132,7 +132,7 @@ public class PortraitPagedViewHandler implements PagedOrientationHandler { } @Override - public int getClearAllScrollOffset(View view, boolean isRtl) { + public int getClearAllSidePadding(View view, boolean isRtl) { return (isRtl ? view.getPaddingRight() : - view.getPaddingLeft()) / 2; } From 177cff38fa2168b8e015b3fa68558dc0f8ecf864 Mon Sep 17 00:00:00 2001 From: Jon Spivack Date: Wed, 24 Mar 2021 11:47:54 -0700 Subject: [PATCH 15/21] Add OWNERS to Launcher3/go The code in this directory only impacts the Go Launcher variants, so it would make sense for the owners to be from the Go team. Bug: 183627385 Test: N/A Change-Id: Iab09be2d590d25bce6de07048befa2e832a54623 --- go/OWNERS | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 go/OWNERS diff --git a/go/OWNERS b/go/OWNERS new file mode 100644 index 0000000000..903b3c4ef4 --- /dev/null +++ b/go/OWNERS @@ -0,0 +1,2 @@ +rajekumar@google.com +spivack@google.com From c9e69fa98da5bb166edf0978bf45d3c1bfd952ab Mon Sep 17 00:00:00 2001 From: Jon Miranda Date: Mon, 22 Mar 2021 17:13:34 -0400 Subject: [PATCH 16/21] 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 --- res/values/attrs.xml | 1 + ...size_limits.xml => size_limits_80x104.xml} | 2 +- src/com/android/launcher3/DevicePaddings.java | 44 ++++++++++++++++--- src/com/android/launcher3/DeviceProfile.java | 27 +++++++++--- .../launcher3/InvariantDeviceProfile.java | 14 ++++-- 5 files changed, 74 insertions(+), 14 deletions(-) rename res/xml/{size_limits.xml => size_limits_80x104.xml} (97%) diff --git a/res/values/attrs.xml b/res/values/attrs.xml index 4078ef4092..f4a729f734 100644 --- a/res/values/attrs.xml +++ b/res/values/attrs.xml @@ -134,6 +134,7 @@ + diff --git a/res/xml/size_limits.xml b/res/xml/size_limits_80x104.xml similarity index 97% rename from res/xml/size_limits.xml rename to res/xml/size_limits_80x104.xml index ba570146de..e11bc5ecfa 100644 --- a/res/xml/size_limits.xml +++ b/res/xml/size_limits_80x104.xml @@ -38,7 +38,7 @@ + launcher:c="16dp"/> 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; + } } /** diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java index 58d612d014..1ce5f4dba6 100644 --- a/src/com/android/launcher3/DeviceProfile.java +++ b/src/com/android/launcher3/DeviceProfile.java @@ -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)); diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java index 348d9eef2c..3dbd4794a2 100644 --- a/src/com/android/launcher3/InvariantDeviceProfile.java +++ b/src/com/android/launcher3/InvariantDeviceProfile.java @@ -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 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 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(); From 7c43972c50b47d11bc9c83e7364586b3a045dbbc Mon Sep 17 00:00:00 2001 From: Alex Chau Date: Wed, 24 Mar 2021 11:32:44 +0000 Subject: [PATCH 17/21] Move numAllAppsColumns to displayOptions - Allow different number of columns per screen size Bug: 171915986 Test: Manual Change-Id: I7b7d518289ea56624dc87512f639e92f10f6b586 --- res/values/attrs.xml | 5 +++-- .../launcher3/InvariantDeviceProfile.java | 20 +++++++++++++------ 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/res/values/attrs.xml b/res/values/attrs.xml index 4078ef4092..1da6bc4e45 100644 --- a/res/values/attrs.xml +++ b/res/values/attrs.xml @@ -129,8 +129,6 @@ - - @@ -170,6 +168,9 @@ + + + diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java index 348d9eef2c..320b97c829 100644 --- a/src/com/android/launcher3/InvariantDeviceProfile.java +++ b/src/com/android/launcher3/InvariantDeviceProfile.java @@ -225,8 +225,13 @@ public class InvariantDeviceProfile { .add(myDisplayOption); result.iconSize = defaultDisplayOption.iconSize; result.landscapeIconSize = defaultDisplayOption.landscapeIconSize; - result.allAppsIconSize = Math.min( - defaultDisplayOption.allAppsIconSize, myDisplayOption.allAppsIconSize); + if (defaultDisplayOption.allAppsIconSize < myDisplayOption.allAppsIconSize) { + result.allAppsIconSize = defaultDisplayOption.allAppsIconSize; + result.numAllAppsColumns = defaultDisplayOption.numAllAppsColumns; + } else { + result.allAppsIconSize = myDisplayOption.allAppsIconSize; + result.numAllAppsColumns = myDisplayOption.numAllAppsColumns; + } result.minCellHeight = defaultDisplayOption.minCellHeight; result.minCellWidth = defaultDisplayOption.minCellWidth; result.borderSpacing = defaultDisplayOption.borderSpacing; @@ -278,7 +283,6 @@ public class InvariantDeviceProfile { demoModeLayoutId = closestProfile.demoModeLayoutId; numFolderRows = closestProfile.numFolderRows; numFolderColumns = closestProfile.numFolderColumns; - numAllAppsColumns = closestProfile.numAllAppsColumns; isScalable = closestProfile.isScalable; mExtraAttrs = closestProfile.extraAttrs; @@ -293,6 +297,7 @@ public class InvariantDeviceProfile { minCellHeight = displayOption.minCellHeight; minCellWidth = displayOption.minCellWidth; borderSpacing = displayOption.borderSpacing; + numAllAppsColumns = Math.round(displayOption.numAllAppsColumns); if (Utilities.isGridOptionsEnabled(context)) { allAppsIconSize = displayOption.allAppsIconSize; @@ -609,7 +614,6 @@ public class InvariantDeviceProfile { private final int numHotseatIcons; private final String dbFile; - private final int numAllAppsColumns; private final int defaultLayoutId; private final int demoModeLayoutId; @@ -636,8 +640,6 @@ public class InvariantDeviceProfile { R.styleable.GridDisplayOption_numFolderRows, numRows); numFolderColumns = a.getInt( R.styleable.GridDisplayOption_numFolderColumns, numColumns); - numAllAppsColumns = a.getInt( - R.styleable.GridDisplayOption_numAllAppsColumns, numColumns); isScalable = a.getBoolean( R.styleable.GridDisplayOption_isScalable, false); @@ -656,6 +658,7 @@ public class InvariantDeviceProfile { private final float minHeightDps; private final boolean canBeDefault; + private float numAllAppsColumns; private float minCellHeight; private float minCellWidth; private float borderSpacing; @@ -676,6 +679,8 @@ public class InvariantDeviceProfile { minHeightDps = a.getFloat(R.styleable.ProfileDisplayOption_minHeightDps, 0); canBeDefault = a.getBoolean( R.styleable.ProfileDisplayOption_canBeDefault, false); + numAllAppsColumns = a.getInt(R.styleable.ProfileDisplayOption_numAllAppsColumns, + grid.numColumns); minCellHeight = a.getFloat(R.styleable.ProfileDisplayOption_minCellHeightDps, 0); minCellWidth = a.getFloat(R.styleable.ProfileDisplayOption_minCellWidthDps, 0); @@ -702,12 +707,14 @@ public class InvariantDeviceProfile { minWidthDps = 0; minHeightDps = 0; canBeDefault = false; + numAllAppsColumns = 0; minCellHeight = 0; minCellWidth = 0; borderSpacing = 0; } private DisplayOption multiply(float w) { + numAllAppsColumns *= w; iconSize *= w; landscapeIconSize *= w; allAppsIconSize *= w; @@ -720,6 +727,7 @@ public class InvariantDeviceProfile { } private DisplayOption add(DisplayOption p) { + numAllAppsColumns += p.numAllAppsColumns; iconSize += p.iconSize; landscapeIconSize += p.landscapeIconSize; allAppsIconSize += p.allAppsIconSize; From e0b8c8396a1ffd1341841ea32ca9d08544aa0dbb Mon Sep 17 00:00:00 2001 From: Samuel Fufa Date: Wed, 24 Mar 2021 19:34:44 -0500 Subject: [PATCH 18/21] [String][Work profile] Update work profile strings Bug: 183517121 Test: Manual Change-Id: I334854170dca6ecf321da0ec2094ab993404c229 --- res/values/strings.xml | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/res/values/strings.xml b/res/values/strings.xml index 1eb123bb92..8faac48c8b 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -379,9 +379,18 @@ Work profile is paused - Work apps can\'t send you notifications, use your battery, or access your location + Work apps can’t send you notifications, use your battery, or access your location - Work profile is paused. Work apps can\’t send you notifications, use your battery, or access your location + Work profile is paused. Work apps can’t send you notifications, use your battery, or access your location + + Work apps are badged and visible to your IT admin + + Got it + + + Pause work apps + + Turn on Filter From 773050d228287b42e4a1beec2b89c6533e65c251 Mon Sep 17 00:00:00 2001 From: Tracy Zhou Date: Mon, 22 Mar 2021 19:47:46 -0700 Subject: [PATCH 19/21] Fix a memory leak Currently we pass a callback from AbsSwipeUpHandler to TaskAnimationManager to render task view launch animation, exposing the launcher activity to the static TouchInteractionService, which causes the leak. To not only fix the leak, but consider a better place for this functionality semantically, RecentsView is a better home. Fixes: 183458638 Test: Run presubmit Change-Id: Id35d0ad22005003d2516c34515a5cb338605be0b --- .../android/quickstep/AbsSwipeUpHandler.java | 108 ++---------------- .../quickstep/RecentsAnimationTargets.java | 9 -- .../quickstep/TaskAnimationManager.java | 49 +++++--- .../quickstep/util/InputConsumerProxy.java | 28 +++-- .../util/InputProxyHandlerFactory.java | 53 +++++++++ .../android/quickstep/views/RecentsView.java | 75 ++++++++++++ 6 files changed, 187 insertions(+), 135 deletions(-) create mode 100644 quickstep/src/com/android/quickstep/util/InputProxyHandlerFactory.java diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java index f4ef1f7e47..c91fa9fd5c 100644 --- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java +++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java @@ -22,7 +22,6 @@ import static android.widget.Toast.LENGTH_SHORT; import static com.android.launcher3.BaseActivity.INVISIBLE_BY_STATE_HANDLER; import static com.android.launcher3.BaseActivity.STATE_HANDLER_INVISIBILITY_FLAGS; -import static com.android.launcher3.QuickstepTransitionManager.RECENTS_LAUNCH_DURATION; import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL; import static com.android.launcher3.anim.Interpolators.DEACCEL; import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2; @@ -97,8 +96,8 @@ import com.android.quickstep.util.ActiveGestureLog; import com.android.quickstep.util.ActivityInitListener; import com.android.quickstep.util.AnimatorControllerWithResistance; import com.android.quickstep.util.InputConsumerProxy; +import com.android.quickstep.util.InputProxyHandlerFactory; import com.android.quickstep.util.MotionPauseDetector; -import com.android.quickstep.util.MultiValueUpdateListener; import com.android.quickstep.util.ProtoTracer; import com.android.quickstep.util.RecentsOrientedState; import com.android.quickstep.util.RectFSpringAnim; @@ -113,12 +112,10 @@ import com.android.systemui.shared.system.InputConsumerController; import com.android.systemui.shared.system.InteractionJankMonitorWrapper; import com.android.systemui.shared.system.LatencyTrackerCompat; import com.android.systemui.shared.system.RemoteAnimationTargetCompat; -import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams; import com.android.systemui.shared.system.TaskInfoCompat; import com.android.systemui.shared.system.TaskStackChangeListener; import java.util.ArrayList; -import java.util.Arrays; import java.util.function.Consumer; /** @@ -255,7 +252,10 @@ public abstract class AbsSwipeUpHandler, mActivityInterface = gestureState.getActivityInterface(); mActivityInitListener = mActivityInterface.createActivityInitListener(this::onActivityInit); mInputConsumerProxy = - new InputConsumerProxy(inputConsumer, this::createNewInputProxyHandler); + new InputConsumerProxy(inputConsumer, () -> { + endRunningWindowAnim(mGestureState.getEndTarget() == HOME /* cancel */); + endLauncherTransitionController(); + }, new InputProxyHandlerFactory(mActivityInterface, mGestureState)); mTaskAnimationManager = taskAnimationManager; mTouchTimeMs = touchTimeMs; mContinuingLastGesture = continuingLastGesture; @@ -783,19 +783,6 @@ public abstract class AbsSwipeUpHandler, handleNormalGestureEnd(endVelocity, isFling, velocity, false /* isCancel */); } - /** - * Called to create a input proxy for the running task - */ - @UiThread - protected InputConsumer createNewInputProxyHandler() { - endRunningWindowAnim(mGestureState.getEndTarget() == HOME /* cancel */); - endLauncherTransitionController(); - - StatefulActivity activity = mActivityInterface.getCreatedActivity(); - return activity == null ? InputConsumer.NO_OP - : new OverviewInputConsumer(mGestureState, activity, null, true); - } - private void endRunningWindowAnim(boolean cancel) { if (mRunningWindowAnim != null) { if (cancel) { @@ -1338,6 +1325,7 @@ public abstract class AbsSwipeUpHandler, mInputConsumerProxy.destroy(); mTaskAnimationManager.setLiveTileCleanUpHandler(null); } + mInputConsumerProxy.unregisterCallback(); endRunningWindowAnim(false /* cancel */); if (mGestureEndCallback != null) { @@ -1502,36 +1490,13 @@ public abstract class AbsSwipeUpHandler, protected abstract void finishRecentsControllerToHome(Runnable callback); - private final TaskStackChangeListener mLiveTileRestartListener = new TaskStackChangeListener() { - @Override - public void onActivityRestartAttempt(ActivityManager.RunningTaskInfo task, - boolean homeTaskVisible, boolean clearedTask, boolean wasVisible) { - if (mRecentsView.getRunningTaskIndex() != -1 - && mRecentsView.getRunningTaskId() == task.taskId - && mRecentsAnimationTargets.hasTask(task.taskId)) { - launchOtherTaskInLiveTileMode(task.taskId, mRecentsAnimationTargets.apps); - } - ActivityManagerWrapper.getInstance().unregisterTaskStackListener( - mLiveTileRestartListener); - } - }; - private void setupLauncherUiAfterSwipeUpToRecentsAnimation() { endLauncherTransitionController(); mActivityInterface.onSwipeUpToRecentsComplete(); mRecentsView.onSwipeUpAnimationSuccess(); if (LIVE_TILE.get()) { - mTaskAnimationManager.setLaunchOtherTaskInLiveTileModeHandler( - appearedTaskTarget -> { - RemoteAnimationTargetCompat[] apps = Arrays.copyOf( - mRecentsAnimationTargets.apps, - mRecentsAnimationTargets.apps.length + 1); - apps[apps.length - 1] = appearedTaskTarget; - launchOtherTaskInLiveTileMode(appearedTaskTarget.taskId, apps); - }); mTaskAnimationManager.setLiveTileCleanUpHandler(mInputConsumerProxy::destroy); - ActivityManagerWrapper.getInstance().registerTaskStackListener( - mLiveTileRestartListener); + mTaskAnimationManager.enableLiveTileRestartListener(); } SystemUiProxy.INSTANCE.get(mContext).onOverviewShown(false, TAG); @@ -1539,65 +1504,6 @@ public abstract class AbsSwipeUpHandler, reset(); } - private void launchOtherTaskInLiveTileMode(int taskId, RemoteAnimationTargetCompat[] apps) { - AnimatorSet anim = new AnimatorSet(); - TaskView taskView = mRecentsView.getTaskView(taskId); - if (taskView == null || !mRecentsView.isTaskViewVisible(taskView)) { - // TODO: Refine this animation. - SurfaceTransactionApplier surfaceApplier = - new SurfaceTransactionApplier(mActivity.getDragLayer()); - ValueAnimator appAnimator = ValueAnimator.ofFloat(0, 1); - appAnimator.setDuration(RECENTS_LAUNCH_DURATION); - appAnimator.setInterpolator(ACCEL_DEACCEL); - appAnimator.addUpdateListener(new MultiValueUpdateListener() { - @Override - public void onUpdate(float percent) { - SurfaceParams.Builder builder = new SurfaceParams.Builder( - apps[apps.length - 1].leash); - Matrix matrix = new Matrix(); - matrix.postScale(percent, percent); - matrix.postTranslate(mDp.widthPx * (1 - percent) / 2, - mDp.heightPx * (1 - percent) / 2); - builder.withAlpha(percent).withMatrix(matrix); - surfaceApplier.scheduleApply(builder.build()); - } - }); - anim.play(appAnimator); - } else { - TaskViewUtils.composeRecentsLaunchAnimator( - anim, taskView, apps, - mRecentsAnimationTargets.wallpapers, true /* launcherClosing */, - mActivity.getStateManager(), mRecentsView, - mActivityInterface.getDepthController()); - } - anim.addListener(new AnimatorListenerAdapter(){ - - @Override - public void onAnimationEnd(Animator animator) { - cleanUp(false); - } - - @Override - public void onAnimationCancel(Animator animator) { - cleanUp(true); - } - - private void cleanUp(boolean canceled) { - if (mRecentsAnimationController != null) { - mRecentsAnimationController.finish(false /* toRecents */, - null /* onFinishComplete */); - if (canceled) { - mRecentsAnimationController = null; - } else { - mActivityInterface.onLaunchTaskSuccess(); - } - ActiveGestureLog.INSTANCE.addLog("finishRecentsAnimation", false); - } - } - }); - anim.start(); - } - private static boolean isNotInRecents(RemoteAnimationTargetCompat app) { return app.isNotInRecents || app.activityType == ACTIVITY_TYPE_HOME; diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationTargets.java b/quickstep/src/com/android/quickstep/RecentsAnimationTargets.java index da0a66431e..718c5baa2c 100644 --- a/quickstep/src/com/android/quickstep/RecentsAnimationTargets.java +++ b/quickstep/src/com/android/quickstep/RecentsAnimationTargets.java @@ -41,13 +41,4 @@ public class RecentsAnimationTargets extends RemoteAnimationTargets { public boolean hasTargets() { return unfilteredApps.length != 0; } - - public boolean hasTask(int taskId) { - for (RemoteAnimationTargetCompat target : unfilteredApps) { - if (target.taskId == taskId) { - return true; - } - } - return false; - } } diff --git a/quickstep/src/com/android/quickstep/TaskAnimationManager.java b/quickstep/src/com/android/quickstep/TaskAnimationManager.java index 9a454f2bd7..b6dad2d385 100644 --- a/quickstep/src/com/android/quickstep/TaskAnimationManager.java +++ b/quickstep/src/com/android/quickstep/TaskAnimationManager.java @@ -17,10 +17,11 @@ package com.android.quickstep; import static com.android.launcher3.util.Executors.MAIN_EXECUTOR; import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR; -import static com.android.quickstep.GestureState.GestureEndTarget.RECENTS; import static com.android.quickstep.GestureState.STATE_RECENTS_ANIMATION_INITIALIZED; import static com.android.quickstep.GestureState.STATE_RECENTS_ANIMATION_STARTED; +import static com.android.quickstep.util.NavigationModeFeatureFlag.LIVE_TILE; +import android.app.ActivityManager; import android.content.Context; import android.content.Intent; import android.os.Bundle; @@ -31,13 +32,13 @@ import androidx.annotation.UiThread; import com.android.launcher3.Utilities; import com.android.launcher3.config.FeatureFlags; +import com.android.quickstep.views.RecentsView; import com.android.systemui.shared.recents.model.ThumbnailData; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.ActivityOptionsCompat; import com.android.systemui.shared.system.RemoteAnimationTargetCompat; import com.android.systemui.shared.system.RemoteTransitionCompat; - -import java.util.function.Consumer; +import com.android.systemui.shared.system.TaskStackChangeListener; public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAnimationListener { public static final boolean ENABLE_SHELL_TRANSITIONS = @@ -49,10 +50,24 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn // Temporary until we can hook into gesture state events private GestureState mLastGestureState; private RemoteAnimationTargetCompat mLastAppearedTaskTarget; - private Consumer mLaunchOtherTaskHandler; private Runnable mLiveTileCleanUpHandler; private Context mCtx; + private final TaskStackChangeListener mLiveTileRestartListener = new TaskStackChangeListener() { + @Override + public void onActivityRestartAttempt(ActivityManager.RunningTaskInfo task, + boolean homeTaskVisible, boolean clearedTask, boolean wasVisible) { + BaseActivityInterface activityInterface = mLastGestureState.getActivityInterface(); + if (LIVE_TILE.get() && activityInterface.isInLiveTileMode() + && activityInterface.getCreatedActivity() != null) { + RecentsView recentsView = activityInterface.getCreatedActivity().getOverviewPanel(); + recentsView.launchSideTaskInLiveTileModeForRestartedApp(task.taskId); + ActivityManagerWrapper.getInstance().unregisterTaskStackListener( + mLiveTileRestartListener); + } + } + }; + TaskAnimationManager(Context ctx) { mCtx = ctx; } @@ -114,9 +129,14 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn @Override public void onTaskAppeared(RemoteAnimationTargetCompat appearedTaskTarget) { - if (mLaunchOtherTaskHandler != null - && mLastGestureState.getEndTarget() == RECENTS) { - mLaunchOtherTaskHandler.accept(appearedTaskTarget); + BaseActivityInterface activityInterface = mLastGestureState.getActivityInterface(); + if (LIVE_TILE.get() && activityInterface.isInLiveTileMode() + && activityInterface.getCreatedActivity() != null) { + RecentsView recentsView = + activityInterface.getCreatedActivity().getOverviewPanel(); + RemoteAnimationTargetCompat[] apps = new RemoteAnimationTargetCompat[1]; + apps[0] = appearedTaskTarget; + recentsView.launchSideTaskInLiveTileMode(appearedTaskTarget.taskId, apps); return; } if (mController != null) { @@ -161,17 +181,12 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn return mCallbacks; } - /** - * The passed-in handler is used to render side task launch animation in recents in live tile - * mode. - */ - public void setLaunchOtherTaskInLiveTileModeHandler( - Consumer handler) { - mLaunchOtherTaskHandler = handler; + public void setLiveTileCleanUpHandler(Runnable cleanUpHandler) { + mLiveTileCleanUpHandler = cleanUpHandler; } - public void setLiveTileCleanUpHandler(Runnable runnable) { - mLiveTileCleanUpHandler = runnable; + public void enableLiveTileRestartListener() { + ActivityManagerWrapper.getInstance().registerTaskStackListener(mLiveTileRestartListener); } /** @@ -215,6 +230,7 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn mLiveTileCleanUpHandler.run(); mLiveTileCleanUpHandler = null; } + ActivityManagerWrapper.getInstance().unregisterTaskStackListener(mLiveTileRestartListener); // Release all the target leashes if (mTargets != null) { @@ -231,7 +247,6 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn mTargets = null; mLastGestureState = null; mLastAppearedTaskTarget = null; - mLaunchOtherTaskHandler = null; } public void dump() { diff --git a/quickstep/src/com/android/quickstep/util/InputConsumerProxy.java b/quickstep/src/com/android/quickstep/util/InputConsumerProxy.java index 3e87f48f02..2e5b33ae24 100644 --- a/quickstep/src/com/android/quickstep/util/InputConsumerProxy.java +++ b/quickstep/src/com/android/quickstep/util/InputConsumerProxy.java @@ -38,7 +38,8 @@ public class InputConsumerProxy { private static final String TAG = "InputConsumerProxy"; private final InputConsumerController mInputConsumerController; - private final Supplier mConsumerSupplier; + private Runnable mCallback; + private Supplier mConsumerSupplier; // The consumer is created lazily on demand. private InputConsumer mInputConsumer; @@ -48,8 +49,9 @@ public class InputConsumerProxy { private boolean mDestroyPending = false; public InputConsumerProxy(InputConsumerController inputConsumerController, - Supplier consumerSupplier) { + Runnable callback, Supplier consumerSupplier) { mInputConsumerController = inputConsumerController; + mCallback = callback; mConsumerSupplier = consumerSupplier; } @@ -64,9 +66,7 @@ public class InputConsumerProxy { if (ev instanceof MotionEvent) { onInputConsumerMotionEvent((MotionEvent) ev); } else if (ev instanceof KeyEvent) { - if (mInputConsumer == null) { - mInputConsumer = mConsumerSupplier.get(); - } + initInputConsumerIfNeeded(); mInputConsumer.onKeyEvent((KeyEvent) ev); return true; } @@ -89,9 +89,7 @@ public class InputConsumerProxy { if (action == ACTION_DOWN) { mTouchInProgress = true; - if (mInputConsumer == null) { - mInputConsumer = mConsumerSupplier.get(); - } + initInputConsumerIfNeeded(); } else if (action == ACTION_CANCEL || action == ACTION_UP) { // Finish any pending actions mTouchInProgress = false; @@ -115,4 +113,18 @@ public class InputConsumerProxy { mDestroyed = true; mInputConsumerController.setInputListener(null); } + + public void unregisterCallback() { + mCallback = null; + } + + private void initInputConsumerIfNeeded() { + if (mInputConsumer == null) { + if (mCallback != null) { + mCallback.run(); + } + mInputConsumer = mConsumerSupplier.get(); + mConsumerSupplier = null; + } + } } diff --git a/quickstep/src/com/android/quickstep/util/InputProxyHandlerFactory.java b/quickstep/src/com/android/quickstep/util/InputProxyHandlerFactory.java new file mode 100644 index 0000000000..8209c09304 --- /dev/null +++ b/quickstep/src/com/android/quickstep/util/InputProxyHandlerFactory.java @@ -0,0 +1,53 @@ +/* + * 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.quickstep.util; + +import androidx.annotation.UiThread; + +import com.android.launcher3.statemanager.StatefulActivity; +import com.android.quickstep.BaseActivityInterface; +import com.android.quickstep.GestureState; +import com.android.quickstep.InputConsumer; +import com.android.quickstep.inputconsumers.OverviewInputConsumer; + +import java.util.function.Supplier; + +/** + * A factory that creates a input consumer for + * {@link com.android.quickstep.util.InputConsumerProxy}. + */ +public class InputProxyHandlerFactory implements Supplier { + + private final BaseActivityInterface mActivityInterface; + private final GestureState mGestureState; + + @UiThread + public InputProxyHandlerFactory(BaseActivityInterface activityInterface, + GestureState gestureState) { + mActivityInterface = activityInterface; + mGestureState = gestureState; + } + + /** + * Called to create a input proxy for the running task + */ + @Override + public InputConsumer get() { + StatefulActivity activity = mActivityInterface.getCreatedActivity(); + return activity == null ? InputConsumer.NO_OP + : new OverviewInputConsumer(mGestureState, activity, null, true); + } +} diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index d357ebead0..769344080a 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -27,6 +27,7 @@ import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA; import static com.android.launcher3.LauncherState.BACKGROUND_APP; import static com.android.launcher3.LauncherState.OVERVIEW_MODAL_TASK; import static com.android.launcher3.LauncherState.OVERVIEW_SPLIT_SELECT; +import static com.android.launcher3.QuickstepTransitionManager.RECENTS_LAUNCH_DURATION; import static com.android.launcher3.Utilities.EDGE_NAV_BAR; import static com.android.launcher3.Utilities.mapToRange; import static com.android.launcher3.Utilities.squaredHypot; @@ -34,6 +35,7 @@ import static com.android.launcher3.Utilities.squaredTouchSlop; import static com.android.launcher3.anim.Interpolators.ACCEL; import static com.android.launcher3.anim.Interpolators.ACCEL_0_75; import static com.android.launcher3.anim.Interpolators.ACCEL_2; +import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL; import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN; import static com.android.launcher3.anim.Interpolators.LINEAR; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_CLEAR_ALL; @@ -50,6 +52,7 @@ import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NO_RECENTS; import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NO_TASKS; import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorSet; import android.animation.LayoutTransition; import android.animation.LayoutTransition.TransitionListener; @@ -61,6 +64,7 @@ import android.app.ActivityManager.RunningTaskInfo; import android.content.Context; import android.content.res.Configuration; import android.graphics.Canvas; +import android.graphics.Matrix; import android.graphics.Point; import android.graphics.PointF; import android.graphics.Rect; @@ -129,8 +133,11 @@ import com.android.quickstep.RecentsModel.TaskVisualsChangeListener; import com.android.quickstep.SystemUiProxy; import com.android.quickstep.TaskOverlayFactory; import com.android.quickstep.TaskThumbnailCache; +import com.android.quickstep.TaskViewUtils; import com.android.quickstep.ViewUtils; +import com.android.quickstep.util.ActiveGestureLog; import com.android.quickstep.util.LayoutUtils; +import com.android.quickstep.util.MultiValueUpdateListener; import com.android.quickstep.util.RecentsOrientedState; import com.android.quickstep.util.SplitScreenBounds; import com.android.quickstep.util.SurfaceTransactionApplier; @@ -142,6 +149,8 @@ import com.android.systemui.shared.recents.model.Task.TaskKey; import com.android.systemui.shared.recents.model.ThumbnailData; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.PackageManagerWrapper; +import com.android.systemui.shared.system.RemoteAnimationTargetCompat; +import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams; import com.android.systemui.shared.system.TaskStackChangeListener; import com.android.wm.shell.pip.IPipAnimationListener; @@ -715,6 +724,72 @@ public abstract class RecentsView extends PagedView super.draw(canvas); } + public void launchSideTaskInLiveTileModeForRestartedApp(int taskId) { + if (mRunningTaskId != -1 && mRunningTaskId == taskId && + getLiveTileParams().getTargetSet().findTask(taskId) != null) { + launchSideTaskInLiveTileMode(taskId, getLiveTileParams().getTargetSet().apps); + } + } + + public void launchSideTaskInLiveTileMode(int taskId, RemoteAnimationTargetCompat[] apps) { + AnimatorSet anim = new AnimatorSet(); + TaskView taskView = getTaskView(taskId); + if (taskView == null || !isTaskViewVisible(taskView)) { + // TODO: Refine this animation. + SurfaceTransactionApplier surfaceApplier = + new SurfaceTransactionApplier(mActivity.getDragLayer()); + ValueAnimator appAnimator = ValueAnimator.ofFloat(0, 1); + appAnimator.setDuration(RECENTS_LAUNCH_DURATION); + appAnimator.setInterpolator(ACCEL_DEACCEL); + appAnimator.addUpdateListener(new MultiValueUpdateListener() { + @Override + public void onUpdate(float percent) { + SurfaceParams.Builder builder = new SurfaceParams.Builder( + apps[apps.length - 1].leash); + Matrix matrix = new Matrix(); + matrix.postScale(percent, percent); + matrix.postTranslate(mActivity.getDeviceProfile().widthPx * (1 - percent) / 2, + mActivity.getDeviceProfile().heightPx * (1 - percent) / 2); + builder.withAlpha(percent).withMatrix(matrix); + surfaceApplier.scheduleApply(builder.build()); + } + }); + anim.play(appAnimator); + } else { + TaskViewUtils.composeRecentsLaunchAnimator( + anim, taskView, apps, + mLiveTileParams.getTargetSet().wallpapers, true /* launcherClosing */, + mActivity.getStateManager(), this, + getDepthController()); + } + anim.addListener(new AnimatorListenerAdapter(){ + + @Override + public void onAnimationEnd(Animator animator) { + cleanUp(false); + } + + @Override + public void onAnimationCancel(Animator animator) { + cleanUp(true); + } + + private void cleanUp(boolean canceled) { + if (mRecentsAnimationController != null) { + mRecentsAnimationController.finish(false /* toRecents */, + null /* onFinishComplete */); + if (canceled) { + mRecentsAnimationController = null; + } else { + mSizeStrategy.onLaunchTaskSuccess(); + } + ActiveGestureLog.INSTANCE.addLog("finishRecentsAnimation", false); + } + } + }); + anim.start(); + } + private void updateTaskStartIndex(View affectingView) { if (!(affectingView instanceof TaskView) && !(affectingView instanceof ClearAllButton)) { int childCount = getChildCount(); From a750f8cdcab8c244e1b206f5ea004e78f8babcb4 Mon Sep 17 00:00:00 2001 From: Pierre Barbier de Reuille Date: Thu, 25 Mar 2021 11:01:06 +0000 Subject: [PATCH 20/21] Correct RoundedCorner enforcements. The feature status will not, in the end, depend on the widget, so removed the argument. Bug: 183097166 Test: Manual test Change-Id: I977e775072cf1724f3e31b848d3ac4c862d23e00 --- .../launcher3/widget/LauncherAppWidgetHostView.java | 5 +++-- .../launcher3/widget/RoundedCornerEnforcement.java | 8 ++------ 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java b/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java index 2e542edf76..687318f775 100644 --- a/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java +++ b/src/com/android/launcher3/widget/LauncherAppWidgetHostView.java @@ -497,12 +497,13 @@ public class LauncherAppWidgetHostView extends NavigableAppWidgetHostView @UiThread private void enforceRoundedCorners() { - if (mEnforcedCornerRadius <= 0 || !RoundedCornerEnforcement.isRoundedCornerEnabled(this)) { + if (mEnforcedCornerRadius <= 0 || !RoundedCornerEnforcement.isRoundedCornerEnabled()) { resetRoundedCorners(); return; } View background = RoundedCornerEnforcement.findBackground(this); - if (RoundedCornerEnforcement.hasAppWidgetOptedOut(this, background)) { + if (background == null + || RoundedCornerEnforcement.hasAppWidgetOptedOut(this, background)) { resetRoundedCorners(); return; } diff --git a/src/com/android/launcher3/widget/RoundedCornerEnforcement.java b/src/com/android/launcher3/widget/RoundedCornerEnforcement.java index 99eccd1303..1e46ffd30c 100644 --- a/src/com/android/launcher3/widget/RoundedCornerEnforcement.java +++ b/src/com/android/launcher3/widget/RoundedCornerEnforcement.java @@ -72,12 +72,8 @@ public class RoundedCornerEnforcement { } /** Check if the app widget is in the deny list. */ - public static boolean isRoundedCornerEnabled(@NonNull View view) { - if (!Utilities.ATLEAST_S || !FeatureFlags.ENABLE_ENFORCED_ROUNDED_CORNERS.get()) { - return false; - } - // Here we need to test if the view's component is in the (to be created) deny list. - return true; + public static boolean isRoundedCornerEnabled() { + return Utilities.ATLEAST_S && FeatureFlags.ENABLE_ENFORCED_ROUNDED_CORNERS.get(); } /** From adc23265dc00c881b303aabe4d7d5609f710f029 Mon Sep 17 00:00:00 2001 From: Pierre Barbier de Reuille Date: Thu, 25 Mar 2021 11:01:34 +0000 Subject: [PATCH 21/21] Added rounded corner to bitmap Widget Preview This applies to the widget picker and the initial Widget drop. Bug: 183615331 Test: Manually using top preinstalled widgets Change-Id: Ib7ce422dc485396c2aceec6f43e83529d642ecc7 --- .../android/launcher3/FastBitmapDrawable.java | 18 ++++++++++++++++++ .../widget/PendingItemDragHelper.java | 9 ++++++++- .../android/launcher3/widget/WidgetCell.java | 6 +++++- 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/com/android/launcher3/FastBitmapDrawable.java b/src/com/android/launcher3/FastBitmapDrawable.java index b1fe4a235c..0027a50d95 100644 --- a/src/com/android/launcher3/FastBitmapDrawable.java +++ b/src/com/android/launcher3/FastBitmapDrawable.java @@ -28,6 +28,7 @@ import android.graphics.ColorFilter; import android.graphics.ColorMatrix; import android.graphics.ColorMatrixColorFilter; import android.graphics.Paint; +import android.graphics.Path; import android.graphics.PixelFormat; import android.graphics.Rect; import android.graphics.drawable.Drawable; @@ -61,6 +62,8 @@ public class FastBitmapDrawable extends Drawable { private boolean mIsPressed; private boolean mIsDisabled; private float mDisabledAlpha = 1f; + private float mRoundedCornersRadius = 0f; + private final Path mClipPath = new Path(); // Animator and properties for the fast bitmap drawable's scale private static final Property SCALE @@ -102,6 +105,13 @@ public class FastBitmapDrawable extends Drawable { @Override public final void draw(Canvas canvas) { + if (mRoundedCornersRadius > 0) { + float radius = mRoundedCornersRadius * mScale; + mClipPath.reset(); + mClipPath.addRoundRect(0, 0, getIntrinsicWidth(), getIntrinsicHeight(), + radius, radius, Path.Direction.CCW); + canvas.clipPath(mClipPath); + } if (mScale != 1f) { int count = canvas.save(); Rect bounds = getBounds(); @@ -164,6 +174,14 @@ public class FastBitmapDrawable extends Drawable { return mScale; } + public void setRoundedCornersRadius(float radius) { + mRoundedCornersRadius = radius; + } + + public float getRoundedCornersRadius() { + return mRoundedCornersRadius; + } + @Override public int getIntrinsicWidth() { return mBitmap.getWidth(); diff --git a/src/com/android/launcher3/widget/PendingItemDragHelper.java b/src/com/android/launcher3/widget/PendingItemDragHelper.java index 247a748ba6..08bb66211c 100644 --- a/src/com/android/launcher3/widget/PendingItemDragHelper.java +++ b/src/com/android/launcher3/widget/PendingItemDragHelper.java @@ -54,10 +54,13 @@ public class PendingItemDragHelper extends DragPreviewProvider { @Nullable private RemoteViews mRemoteViewsPreview; @Nullable private LauncherAppWidgetHostView mAppWidgetHostViewPreview; + private final float mEnforcedRoundedCornersForWidget; public PendingItemDragHelper(View view) { super(view); mAddInfo = (PendingAddItemInfo) view.getTag(); + mEnforcedRoundedCornersForWidget = RoundedCornerEnforcement.computeEnforcedRadius( + view.getContext()); } /** @@ -115,10 +118,14 @@ public class PendingItemDragHelper extends DragPreviewProvider { .addDragListener(new AppWidgetHostViewDragListener(launcher)); } if (preview == null) { - preview = new FastBitmapDrawable( + FastBitmapDrawable p = new FastBitmapDrawable( app.getWidgetCache().generateWidgetPreview(launcher, createWidgetInfo.info, maxWidth, null, previewSizeBeforeScale).first); + if (RoundedCornerEnforcement.isRoundedCornerEnabled()) { + p.setRoundedCornersRadius(mEnforcedRoundedCornersForWidget); + } + preview = p; } if (previewSizeBeforeScale[0] < previewBitmapWidth) { diff --git a/src/com/android/launcher3/widget/WidgetCell.java b/src/com/android/launcher3/widget/WidgetCell.java index 1b0e1ce0b2..2b4b9ea55e 100644 --- a/src/com/android/launcher3/widget/WidgetCell.java +++ b/src/com/android/launcher3/widget/WidgetCell.java @@ -94,6 +94,7 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener { protected final BaseActivity mActivity; protected final DeviceProfile mDeviceProfile; private final CheckLongPressHelper mLongPressHelper; + private final float mEnforcedCornerRadius; private RemoteViews mPreview; private LauncherAppWidgetHostView mAppWidgetHostViewPreview; @@ -118,6 +119,7 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener { setWillNotDraw(false); setClipToPadding(false); setAccessibilityDelegate(mActivity.getAccessibilityDelegate()); + mEnforcedCornerRadius = RoundedCornerEnforcement.computeEnforcedRadius(context); } private void setContainerWidth() { @@ -245,7 +247,9 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener { } public void applyPreview(Bitmap bitmap) { - applyPreview(new FastBitmapDrawable(bitmap)); + FastBitmapDrawable drawable = new FastBitmapDrawable(bitmap); + drawable.setRoundedCornersRadius(mEnforcedCornerRadius); + applyPreview(drawable); } private void applyPreview(Drawable drawable) {