From d4488bfd729b9ed29c5a1d5022b29e7d4a1a3f0e Mon Sep 17 00:00:00 2001 From: "Liam, Lee Pong Lam" Date: Tue, 24 Sep 2024 22:10:48 +0000 Subject: [PATCH 01/10] Implement focus state on personal/work tab button figma: https://www.figma.com/design/ccBEWEnusF6lE4edgCw7bG/Android-Interactions-Library?node-id=6315-109525&node-type=frame&t=SBKtwrMnJ0ppeUxa-0 result: https://photos.app.goo.gl/LEWF6tsKz3BXXWuv5 hsv: https://hsv.googleplex.com/4794951907934208 Bug: 327430110 Flag: EXEMPT bugfix Test: Manual Change-Id: Ia953c92f30cbd65a83f8e60e8bb2d4b17073b369 --- res/drawable/all_apps_tabs_background.xml | 51 ++++++++----------- .../all_apps_tabs_background_selected.xml | 27 ++++++++++ ..._apps_tabs_background_selected_focused.xml | 37 ++++++++++++++ .../all_apps_tabs_background_unselected.xml | 27 ++++++++++ ...pps_tabs_background_unselected_focused.xml | 37 ++++++++++++++ res/layout/all_apps_personal_work_tabs.xml | 4 +- res/values/dimens.xml | 4 ++ 7 files changed, 154 insertions(+), 33 deletions(-) create mode 100644 res/drawable/all_apps_tabs_background_selected.xml create mode 100644 res/drawable/all_apps_tabs_background_selected_focused.xml create mode 100644 res/drawable/all_apps_tabs_background_unselected.xml create mode 100644 res/drawable/all_apps_tabs_background_unselected_focused.xml diff --git a/res/drawable/all_apps_tabs_background.xml b/res/drawable/all_apps_tabs_background.xml index 62927afeb7..d200b9f961 100644 --- a/res/drawable/all_apps_tabs_background.xml +++ b/res/drawable/all_apps_tabs_background.xml @@ -13,36 +13,25 @@ See the License for the specific language governing permissions and limitations under the License. --> - - - - - - - - - - - - - - - - + + + + + + + + + - - - - - - - - + - - \ No newline at end of file + + + + + + + + + + \ No newline at end of file diff --git a/res/drawable/all_apps_tabs_background_selected.xml b/res/drawable/all_apps_tabs_background_selected.xml new file mode 100644 index 0000000000..47f95dd745 --- /dev/null +++ b/res/drawable/all_apps_tabs_background_selected.xml @@ -0,0 +1,27 @@ + + + + + + + + + \ No newline at end of file diff --git a/res/drawable/all_apps_tabs_background_selected_focused.xml b/res/drawable/all_apps_tabs_background_selected_focused.xml new file mode 100644 index 0000000000..e3d86c04fe --- /dev/null +++ b/res/drawable/all_apps_tabs_background_selected_focused.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/res/drawable/all_apps_tabs_background_unselected.xml b/res/drawable/all_apps_tabs_background_unselected.xml new file mode 100644 index 0000000000..ab592a8304 --- /dev/null +++ b/res/drawable/all_apps_tabs_background_unselected.xml @@ -0,0 +1,27 @@ + + + + + + + + + \ No newline at end of file diff --git a/res/drawable/all_apps_tabs_background_unselected_focused.xml b/res/drawable/all_apps_tabs_background_unselected_focused.xml new file mode 100644 index 0000000000..0016102ef0 --- /dev/null +++ b/res/drawable/all_apps_tabs_background_unselected_focused.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/res/layout/all_apps_personal_work_tabs.xml b/res/layout/all_apps_personal_work_tabs.xml index e04b207a3e..ecc5a1404a 100644 --- a/res/layout/all_apps_personal_work_tabs.xml +++ b/res/layout/all_apps_personal_work_tabs.xml @@ -21,8 +21,8 @@ android:layout_width="match_parent" android:layout_height="@dimen/all_apps_header_pill_height" android:layout_gravity="center_horizontal" - android:paddingTop="@dimen/all_apps_tabs_vertical_padding" - android:paddingBottom="@dimen/all_apps_tabs_vertical_padding" + android:paddingTop="@dimen/all_apps_tabs_vertical_padding_focus" + android:paddingBottom="@dimen/all_apps_tabs_vertical_padding_focus" android:layout_marginTop="@dimen/all_apps_tabs_margin_top" android:orientation="horizontal" style="@style/TextHeadline" diff --git a/res/values/dimens.xml b/res/values/dimens.xml index f8c075fa5f..d1e905da48 100644 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -126,6 +126,10 @@ 20dp 4dp 6dp + 1dp + 5dp + 3dp + 2dp 8dp 2dp 128dp From 2f3a57eb5dc138609e35c30ed742311a3939a6b7 Mon Sep 17 00:00:00 2001 From: mattsziklay Date: Tue, 1 Oct 2024 13:58:45 -0700 Subject: [PATCH 02/10] Add split instructions view to desktop split. Fixes issues with desktop split caused by the instructions view not being present. Makes desktop split select more uniform with other split select transitions. Fix: 369961040 Fix: 370038890 Test: Manual Flag: EXEMPT bug fix Change-Id: Icfc6228f3e2692fda59ce5ab7c847ebe5314b25e --- .../util/SplitSelectStateController.java | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java index 8f579e2371..511c989928 100644 --- a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java +++ b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java @@ -77,6 +77,7 @@ import com.android.launcher3.logging.StatsLogManager; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.statehandlers.DepthController; import com.android.launcher3.statemanager.StateManager; +import com.android.launcher3.taskbar.LauncherTaskbarUIController; import com.android.launcher3.testing.TestLogging; import com.android.launcher3.testing.shared.TestProtocol; import com.android.launcher3.uioverrides.QuickstepLauncher; @@ -943,7 +944,16 @@ public class SplitSelectStateController { anim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationStart(Animator animation) { - controller.finish(true /* toRecents */, null /* onFinishComplete */, + controller.finish( + true /* toRecents */, + () -> { + LauncherTaskbarUIController controller = + mLauncher.getTaskbarUIController(); + if (controller != null) { + controller.updateTaskbarLauncherStateGoingHome(); + } + + }, false /* sendUserLeaveHint */); } @Override @@ -951,7 +961,16 @@ public class SplitSelectStateController { SystemUiProxy.INSTANCE.get(mLauncher.getApplicationContext()) .onDesktopSplitSelectAnimComplete(mTaskInfo); } + @Override + public void onAnimationCancel(Animator animation) { + mLauncher.getDragLayer().removeView(floatingTaskView); + getSplitAnimationController() + .removeSplitInstructionsView(mLauncher); + resetState(); + } }); + anim.add(getSplitAnimationController() + .getShowSplitInstructionsAnim(mLauncher).buildAnim()); anim.buildAnim().start(); } } From a909cc2dd7cbc909e3a60d1ac2e242bf6681d7a3 Mon Sep 17 00:00:00 2001 From: Fengjiang Li Date: Wed, 2 Oct 2024 13:28:02 -0700 Subject: [PATCH 03/10] [NPE] Fix NPE of TaskInfo in FloatingWidgetView#getDefaultBackgroundColor Fix: 370315165 Flag: NONE - prod crash Test: presubmit Change-Id: I50e71f0611fc9c664cfe51fbe9c3fc21462e10ed --- .../quickstep/views/FloatingWidgetView.java | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/quickstep/src/com/android/quickstep/views/FloatingWidgetView.java b/quickstep/src/com/android/quickstep/views/FloatingWidgetView.java index bdca596a92..b719ee5b73 100644 --- a/quickstep/src/com/android/quickstep/views/FloatingWidgetView.java +++ b/quickstep/src/com/android/quickstep/views/FloatingWidgetView.java @@ -18,6 +18,7 @@ package com.android.quickstep.views; import android.animation.Animator; import android.animation.Animator.AnimatorListener; import android.annotation.TargetApi; +import android.app.TaskInfo; import android.content.Context; import android.graphics.Matrix; import android.graphics.RectF; @@ -333,11 +334,16 @@ public class FloatingWidgetView extends FrameLayout implements AnimatorListener, * context's theme background color. */ public static int getDefaultBackgroundColor( - Context context, RemoteAnimationTarget target) { - return (target != null && target.taskInfo != null - && target.taskInfo.taskDescription != null) - ? target.taskInfo.taskDescription.getBackgroundColor() - : Themes.getColorBackground(context); + Context context, @Nullable RemoteAnimationTarget target) { + final int fallbackColor = Themes.getColorBackground(context); + if (target == null) { + return fallbackColor; + } + final TaskInfo taskInfo = target.taskInfo; + if (taskInfo == null) { + return fallbackColor; + } + return taskInfo.taskDescription.getBackgroundColor(); } private static void getRelativePosition(View descendant, View ancestor, RectF position) { From d0ce1d3c5023a4854be7162a0f8c6fca3c238fa0 Mon Sep 17 00:00:00 2001 From: Rajeev Kumar Date: Thu, 3 Oct 2024 15:26:28 -0700 Subject: [PATCH 04/10] Get rid of unused PopupDataProvider field and also add method to Share class to be able to pass mock StatsLogManager from unit tests. Bug: 371327013 Fixes: 371327013 Flag: EXEMPT bugfix Test: atest com.android.launcher3.AppSharingTest Change-Id: I2267b2ba5bbc997e36440881f0228e2b3099a09d --- .../src/com/android/launcher3/AppSharing.java | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/go/quickstep/src/com/android/launcher3/AppSharing.java b/go/quickstep/src/com/android/launcher3/AppSharing.java index e15b132f94..a97feccfe1 100644 --- a/go/quickstep/src/com/android/launcher3/AppSharing.java +++ b/go/quickstep/src/com/android/launcher3/AppSharing.java @@ -37,12 +37,13 @@ import android.widget.Toast; import androidx.core.content.FileProvider; +import com.android.internal.annotations.VisibleForTesting; +import com.android.launcher3.logging.StatsLogManager; import com.android.launcher3.model.AppShareabilityChecker; import com.android.launcher3.model.AppShareabilityJobService; import com.android.launcher3.model.AppShareabilityManager; import com.android.launcher3.model.AppShareabilityManager.ShareabilityStatus; import com.android.launcher3.model.data.ItemInfo; -import com.android.launcher3.popup.PopupDataProvider; import com.android.launcher3.popup.SystemShortcut; import com.android.launcher3.views.ActivityContext; @@ -114,17 +115,17 @@ public final class AppSharing { * The Share App system shortcut, used to initiate p2p sharing of a given app */ public final class Share extends SystemShortcut { - private final PopupDataProvider mPopupDataProvider; private final boolean mSharingEnabledForUser; private final Set mBoundViews = Collections.newSetFromMap(new WeakHashMap<>()); private boolean mIsEnabled = true; + private StatsLogManager mStatsLogManager; public Share(Launcher target, ItemInfo itemInfo, View originalView) { super(R.drawable.ic_share, R.string.app_share_drop_target_label, target, itemInfo, originalView); - mPopupDataProvider = target.getPopupDataProvider(); - + mStatsLogManager = ActivityContext.lookupContext(originalView.getContext()) + .getStatsLogManager(); mSharingEnabledForUser = bluetoothSharingEnabled(target); if (!mSharingEnabledForUser) { setEnabled(false); @@ -150,8 +151,7 @@ public final class AppSharing { @Override public void onClick(View view) { - ActivityContext.lookupContext(view.getContext()) - .getStatsLogManager().logger().log(LAUNCHER_SYSTEM_SHORTCUT_APP_SHARE_TAP); + mStatsLogManager.logger().log(LAUNCHER_SYSTEM_SHORTCUT_APP_SHARE_TAP); if (!mIsEnabled) { showCannotShareToast(view.getContext()); return; @@ -240,6 +240,11 @@ public final class AppSharing { public boolean isEnabled() { return mIsEnabled; } + + @VisibleForTesting + void setStatsLogManager(StatsLogManager statsLogManager) { + mStatsLogManager = statsLogManager; + } } /** From 989aa8ac836b2449225999488cf76c0821a3d4c8 Mon Sep 17 00:00:00 2001 From: mpodolian Date: Tue, 1 Oct 2024 16:55:24 -0700 Subject: [PATCH 05/10] 3 button nav is laid out correctly. Updated logic of laying out the 3 nav buttons container. Also updated placement of the hotseat, so it is not shifted on the phone. Test: Manual. Fold and unfold felix with and without bubbles. Reboot the devices and perform the same test. Fixes: 370773620 Flag: com.android.wm.shell.enable_bubble_bar Change-Id: I7d5ba51f7ded275f7456a8690d04001b9651f6c5 --- .../taskbar/NavbarButtonsViewController.java | 36 +++++++++++++--- .../taskbar/TaskbarActivityContext.java | 5 ++- .../launcher3/taskbar/TaskbarControllers.java | 5 ++- .../TaskbarLauncherStateController.java | 41 +++++++++++-------- .../taskbar/TaskbarViewController.java | 4 +- 5 files changed, 63 insertions(+), 28 deletions(-) diff --git a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java index 895535e5c7..d1725bc59b 100644 --- a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java +++ b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java @@ -406,6 +406,12 @@ public class NavbarButtonsViewController implements TaskbarControllers.LoggableT } }; mSeparateWindowParent.recreateControllers(); + if (BubbleBarController.isBubbleBarEnabled()) { + mNavButtonsView.addOnLayoutChangeListener( + (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> + onLayoutsUpdated() + ); + } } private void initButtons(ViewGroup navContainer, ViewGroup endContainer, @@ -1180,15 +1186,20 @@ public class NavbarButtonsViewController implements TaskbarControllers.LoggableT /** Adjusts navigation buttons layout accordingly to the bubble bar position. */ @Override public void onBubbleBarLocationUpdated(BubbleBarLocation location) { - cancelExistingNavBarAnimation(); - mBubbleBarTargetLocation = location; + boolean locationUpdated = location != mBubbleBarTargetLocation; + if (locationUpdated) { + cancelExistingNavBarAnimation(); + } else { + endExistingAnimation(); + } mNavButtonContainer.setTranslationX(getNavBarTranslationX(location)); - mNavButtonContainer.setAlpha(1); + mBubbleBarTargetLocation = location; } /** Animates navigation buttons accordingly to the bubble bar position. */ @Override public void onBubbleBarLocationAnimated(BubbleBarLocation location) { + if (location == mBubbleBarTargetLocation) return; cancelExistingNavBarAnimation(); mBubbleBarTargetLocation = location; int finalX = getNavBarTranslationX(location); @@ -1199,6 +1210,13 @@ public class NavbarButtonsViewController implements TaskbarControllers.LoggableT mNavBarLocationAnimator.start(); } + private void endExistingAnimation() { + if (mNavBarLocationAnimator != null) { + mNavBarLocationAnimator.end(); + mNavBarLocationAnimator = null; + } + } + private void cancelExistingNavBarAnimation() { if (mNavBarLocationAnimator != null) { mNavBarLocationAnimator.cancel(); @@ -1240,12 +1258,18 @@ public class NavbarButtonsViewController implements TaskbarControllers.LoggableT } /** Adjusts the navigation buttons layout position according to the bubble bar location. */ - public void onTaskbarLayoutChanged() { - if (mControllers.taskbarViewController.getIconLayoutBounds().isEmpty()) return; + public void onLayoutsUpdated() { + // no need to do anything if on phone, or if taskbar or navbar views were not placed on + // screen. + if (mContext.getDeviceProfile().isPhone + || mControllers.taskbarViewController.getIconLayoutBounds().isEmpty() + || mNavButtonsView.getWidth() == 0) { + return; + } if (enableBubbleBarInPersistentTaskBar() && mControllers.bubbleControllers.isPresent()) { if (mBubbleBarTargetLocation == null) { - // only set bubble bar location if it was not set before, e.g. at device boot + // only set bubble bar location if it was not set before mBubbleBarTargetLocation = mControllers.bubbleControllers.get() .bubbleBarViewController.getBubbleBarLocation(); } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java index a59445b9f6..46d063b0f3 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java @@ -278,7 +278,10 @@ public class TaskbarActivityContext extends BaseTaskbarContext { // If Bubble bar is present, TaskbarControllers depends on it so build it first. Optional bubbleControllersOptional = Optional.empty(); BubbleBarController.onTaskbarRecreated(); - if (BubbleBarController.isBubbleBarEnabled() && bubbleBarView != null) { + if (BubbleBarController.isBubbleBarEnabled() + && !mDeviceProfile.isPhone + && bubbleBarView != null + ) { Optional bubbleHandleController = Optional.empty(); Optional bubbleBarSwipeController = Optional.empty(); if (isTransientTaskbar) { diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java index 59746751a5..219a24a702 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java @@ -220,11 +220,12 @@ public class TaskbarControllers { uiController = newUiController; uiController.init(this); uiController.updateStateForSysuiFlags(mSharedState.sysuiStateFlags); - bubbleControllers.ifPresent(bubbleControllers -> { + // if bubble controllers are present take bubble bar location, else set it to null + bubbleControllers.ifPresentOrElse(bubbleControllers -> { BubbleBarLocation location = bubbleControllers.bubbleBarViewController.getBubbleBarLocation(); uiController.onBubbleBarLocationUpdated(location); - }); + }, () -> uiController.onBubbleBarLocationUpdated(null)); // Notify that the ui controller has changed navbarButtonsViewController.onUiControllerChanged(); } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java index 065646ad39..c35e6c93cb 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java @@ -845,43 +845,49 @@ public class TaskbarLauncherStateController { } /** Updates launcher home screen appearance accordingly to the bubble bar location. */ - public void onBubbleBarLocationChanged(BubbleBarLocation location, boolean animate) { - DeviceProfile deviceProfile = mLauncher.getDeviceProfile(); - if (mBubbleBarLocation == location) return; + public void onBubbleBarLocationChanged(@Nullable BubbleBarLocation location, boolean animate) { mBubbleBarLocation = location; + if (location == null) { + // bubble bar is not present, hence no location, resetting the hotseat + updateHotseatAndQsbTranslationX(0, animate); + mBubbleBarLocation = null; + return; + } + DeviceProfile deviceProfile = mLauncher.getDeviceProfile(); if (!deviceProfile.shouldAdjustHotseatOnBubblesLocationUpdate( mControllers.taskbarActivityContext)) { return; } - int targetX = 0; - if (mBubbleBarLocation != null) { - boolean isBubblesOnLeft = location.isOnLeft(isRtl(mLauncher.getResources())); - targetX = deviceProfile.getHotseatTranslationXForBubbleBar(/* isNavbarOnRight= */ - isBubblesOnLeft); - } + boolean isBubblesOnLeft = location.isOnLeft(isRtl(mLauncher.getResources())); + int targetX = deviceProfile + .getHotseatTranslationXForBubbleBar(/* isNavbarOnRight= */ isBubblesOnLeft); updateHotseatAndQsbTranslationX(targetX, animate); } + /** Used to translate hotseat and QSB to make room for bubbles. */ private void updateHotseatAndQsbTranslationX(float targetValue, boolean animate) { // cancel existing animation if (mHotseatTranslationXAnimation != null) { mHotseatTranslationXAnimation.cancel(); + mHotseatTranslationXAnimation = null; } - Runnable alignTaskbar = new Runnable() { + Runnable postAnimationAction = new Runnable() { @Override public void run() { + mHotseatTranslationXAnimation = null; // We only need to align the task bar when on launcher home screen if (mControllers.taskbarStashController.isOnHome()) { - DeviceProfile dp = mLauncher.getDeviceProfile(); - mControllers.taskbarViewController - .setLauncherIconAlignment(/* alignmentRatio = */ 1, dp); + mControllers.taskbarViewController.setLauncherIconAlignment( + /* alignmentRatio = */ 1, + mLauncher.getDeviceProfile() + ); } } }; Hotseat hotseat = mLauncher.getHotseat(); AnimatorSet translationXAnimation = new AnimatorSet(); - MultiProperty iconsTranslationX = hotseat.getIconsTranslationX( - Hotseat.ICONS_TRANSLATION_X_NAV_BAR_ALIGNMENT); + MultiProperty iconsTranslationX = mLauncher.getHotseat() + .getIconsTranslationX(Hotseat.ICONS_TRANSLATION_X_NAV_BAR_ALIGNMENT); if (animate) { translationXAnimation.playTogether(iconsTranslationX.animateToValue(targetValue)); } else { @@ -900,18 +906,17 @@ public class TaskbarLauncherStateController { } } if (!animate) { - alignTaskbar.run(); + postAnimationAction.run(); return; } mHotseatTranslationXAnimation = translationXAnimation; translationXAnimation.setStartDelay(FADE_OUT_ANIM_POSITION_DURATION_MS); translationXAnimation.setDuration(FADE_IN_ANIM_ALPHA_DURATION_MS); translationXAnimation.setInterpolator(Interpolators.EMPHASIZED); - translationXAnimation.addListener(AnimatorListeners.forEndCallback(alignTaskbar)); + translationXAnimation.addListener(AnimatorListeners.forEndCallback(postAnimationAction)); translationXAnimation.start(); } - private final class TaskBarRecentsAnimationListener implements RecentsAnimationCallbacks.RecentsAnimationListener { private final RecentsAnimationCallbacks mCallbacks; diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java index b495e7d80e..3dc1423b6b 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java @@ -159,7 +159,9 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar private final View.OnLayoutChangeListener mTaskbarViewLayoutChangeListener = (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> { updateTaskbarIconTranslationXForPinning(); - mControllers.navbarButtonsViewController.onTaskbarLayoutChanged(); + if (BubbleBarController.isBubbleBarEnabled()) { + mControllers.navbarButtonsViewController.onLayoutsUpdated(); + } }; // Animation to align icons with Launcher, created lazily. This allows the controller to be From e4b07471948c1e9374ce295886b3898de1a8f795 Mon Sep 17 00:00:00 2001 From: Jordan Silva Date: Fri, 4 Oct 2024 01:08:13 +0000 Subject: [PATCH 06/10] Update bug number for enable_large_desktop_windowing_tile Bug: 357860832 Change-Id: If208bfb26bd4e082bf5197b44f7270ee3e68ae39 Flag: com.android.launcher3.enable_large_desktop_windowing_tile Test: Gantry should update the bug reference --- aconfig/launcher_overview.aconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aconfig/launcher_overview.aconfig b/aconfig/launcher_overview.aconfig index 853faf8167..c59978f002 100644 --- a/aconfig/launcher_overview.aconfig +++ b/aconfig/launcher_overview.aconfig @@ -36,7 +36,7 @@ flag { name: "enable_large_desktop_windowing_tile" namespace: "launcher_overview" description: "Makes the desktop tiles larger and moves them to the front of the list in Overview." - bug: "353947137" + bug: "357860832" } flag { From b6ac8b2ae9e934f1800c8de252bf02c4535fbeb3 Mon Sep 17 00:00:00 2001 From: vinayjoglekar Date: Tue, 1 Oct 2024 16:42:03 -0700 Subject: [PATCH 07/10] Fix for recents button quick switch with only focus and desktop task This CL also fixes : Home -> Recents -> Recents opens the last large tile (Which was broken when there is desktop window tile in recents.) Test: Manual BUG: 365756337 Fix: 365756337 Flag: com.android.launcher3.enable_large_desktop_windowing_tile Change-Id: I0b8fe3a0a7074355f14ced23ae282fe2943d8ce9 --- .../quickstep/OverviewCommandHelper.kt | 35 +++++++++++++++---- .../android/quickstep/views/RecentsView.java | 14 ++++++++ 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/quickstep/src/com/android/quickstep/OverviewCommandHelper.kt b/quickstep/src/com/android/quickstep/OverviewCommandHelper.kt index a33e5c0fd2..461f963dc1 100644 --- a/quickstep/src/com/android/quickstep/OverviewCommandHelper.kt +++ b/quickstep/src/com/android/quickstep/OverviewCommandHelper.kt @@ -27,6 +27,7 @@ import androidx.annotation.BinderThread import androidx.annotation.UiThread import androidx.annotation.VisibleForTesting import com.android.internal.jank.Cuj +import com.android.launcher3.Flags.enableLargeDesktopWindowingTile import com.android.launcher3.Flags.enableOverviewCommandHelperTimeout import com.android.launcher3.PagedView import com.android.launcher3.logger.LauncherAtom @@ -215,13 +216,12 @@ constructor( } } TOGGLE -> { - val taskView = - if (recentsView.runningTaskView == null) { - recentsView.getTaskViewAt(0) - } else { - recentsView.nextTaskView ?: recentsView.runningTaskView - } - launchTask(recentsView, taskView, command, onCallbackResult) + launchTask( + recentsView, + getNextToggledTaskView(recentsView), + command, + onCallbackResult, + ) } HOME -> { recentsView.startHome() @@ -229,6 +229,27 @@ constructor( } } + private fun getNextToggledTaskView(recentsView: RecentsView<*, *>): TaskView? { + // When running task view is null we return last large taskView - typically focusView when + // grid only is not enabled else last desktop task view. + return if (recentsView.runningTaskView == null) { + recentsView.lastLargeTaskView ?: recentsView.getTaskViewAt(0) + } else { + if ( + enableLargeDesktopWindowingTile() && + recentsView.getTaskViewCount() == recentsView.largeTilesCount && + recentsView.runningTaskView === recentsView.lastLargeTaskView + ) { + // Enables the toggle when only large tiles are in recents view. + // We return previous because unlike small tiles, large tiles are always + // on the right hand side. + recentsView.previousTaskView ?: recentsView.runningTaskView + } else { + recentsView.nextTaskView ?: recentsView.runningTaskView + } + } + } + private fun launchTask( recents: RecentsView<*, *>, taskView: TaskView?, diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index 0d2acf0dab..a469743796 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -4567,6 +4567,20 @@ public abstract class RecentsView< return getTaskViewAt(getRunningTaskIndex() + 1); } + @Nullable + public TaskView getPreviousTaskView() { + return getTaskViewAt(getRunningTaskIndex() - 1); + } + + @Nullable + public TaskView getLastLargeTaskView() { + return mUtils.getLastLargeTaskView(getTaskViews()); + } + + public int getLargeTilesCount() { + return mUtils.getLargeTileCount(getTaskViews()); + } + @Nullable public TaskView getCurrentPageTaskView() { return getTaskViewAt(getCurrentPage()); From 06dbdcea4eab1d50270a3c548f6f30deeb029b76 Mon Sep 17 00:00:00 2001 From: Jordan Silva Date: Fri, 4 Oct 2024 07:28:09 +0000 Subject: [PATCH 08/10] Fix a bug where the last large task index was not being set correctly. This was causing the focused task shift to be calculated incorrectly, which was resulting in the focused task being shifted too far to the left. Bug: 330342294 Fix: 371490320 Flag: com.android.launcher3.enable_large_desktop_windowing_tile Test: Manual. Open 1 DesktopTask, 1 FocusedTask, 2 other tasks in the grid. Dismiss the focused task. The rebalance should work keeping the new focused task next to desktop task. Change-Id: If6f95814942c2cbadc30a0082649569f21dea60a --- quickstep/src/com/android/quickstep/views/RecentsView.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index 8b3ef04f8e..069cbd8933 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -3141,7 +3141,9 @@ public abstract class RecentsView< // Horizontal grid translation for each task float[] gridTranslations = new float[taskCount]; - int lastLargeTaskIndex = Integer.MAX_VALUE; + TaskView lastLargeTaskView = mUtils.getLastLargeTaskView(getTaskViews()); + int lastLargeTaskIndex = + (lastLargeTaskView == null) ? Integer.MAX_VALUE : indexOfChild(lastLargeTaskView); Set largeTasksIndices = new HashSet<>(); int focusedTaskShift = 0; int largeTaskWidthAndSpacing = 0; @@ -3177,7 +3179,6 @@ public abstract class RecentsView< taskView.setGridTranslationY((mLastComputedTaskSize.height() + taskTopMargin - taskView.getLayoutParams().height) / 2f); - lastLargeTaskIndex = i; largeTasksIndices.add(i); largeTaskWidthAndSpacing = taskWidthAndSpacing; From c407f1aa5aa0db23a2eb8d040de7f2bcefa27138 Mon Sep 17 00:00:00 2001 From: Jordan Silva Date: Fri, 4 Oct 2024 07:55:25 +0000 Subject: [PATCH 09/10] Fix a bug where the running task would be drawn below recents task When the live tile is the adjacent app to be launched, it will wrongly update the pivot and translate all the tasks to the side, resulting in a broken animation. This bug was introduced in ag/29639296, while fixing the launch of the the adjacent task while the live tile was in the center of the screen. To solve this excessive translation, we need to update pivot only when adjacent task is not a live tile. Bug: 361744056 Change-Id: I56cbabcc351b0becd791b58dd94f65cd0b533bc2 Test: Launch central/side large tile with different live tile combinations Flag: com.android.launcher3.enable_large_desktop_windowing_tile --- .../android/quickstep/views/RecentsView.java | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index 8b3ef04f8e..01930b3cbd 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -5418,6 +5418,7 @@ public abstract class RecentsView< int taskIndex = indexOfChild(taskView); int centerTaskIndex = getCurrentPage(); + boolean isRunningTask = taskView.isRunningTask(); float toScale = getMaxScaleForFullScreen(); boolean showAsGrid = showAsGrid(); @@ -5436,13 +5437,16 @@ public abstract class RecentsView< mTempPointF); setPivotX(mTempPointF.x); setPivotY(mTempPointF.y); - runActionOnRemoteHandles( - remoteTargetHandle -> { - remoteTargetHandle.getTaskViewSimulator().setPivotOverride( - mTempPointF); - remoteTargetHandle.getTaskViewSimulator().setDrawsBelowRecents( - false); - }); + + if (!isRunningTask) { + runActionOnRemoteHandles( + remoteTargetHandle -> { + remoteTargetHandle.getTaskViewSimulator().setPivotOverride( + mTempPointF); + remoteTargetHandle.getTaskViewSimulator().setDrawsBelowRecents( + false); + }); + } } }); } else if (!showAsGrid) { From 12aff98cd8ccb0637c8b290e469b06a04a7eb2e5 Mon Sep 17 00:00:00 2001 From: Schneider Victor-Tulias Date: Thu, 3 Oct 2024 11:25:08 -0400 Subject: [PATCH 10/10] Add a AbsSwipeUpHandlerTestCase for the RecentsWindowSwipeHandler - Added RecentsWindowSwipeHandlerTestCase - Slightly refactored AbsSwipeUpHandlerTestCase for simplicity Flag: EXEMPT adding test code Bug: 292269949 Test: RecentsWindowSwipeHandlerTestCase Change-Id: Iacd8ff8261ad262d4645ba97c35d296050e61195 --- .../quickstep/AbsSwipeUpHandlerTestCase.java | 38 ++++----- .../FallbackSwipeHandlerTestCase.java | 14 ++-- .../LauncherSwipeHandlerV2TestCase.java | 11 ++- .../RecentsWindowSwipeHandlerTestCase.java | 77 +++++++++++++++++++ 4 files changed, 107 insertions(+), 33 deletions(-) create mode 100644 quickstep/tests/multivalentTests/src/com/android/quickstep/RecentsWindowSwipeHandlerTestCase.java diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/AbsSwipeUpHandlerTestCase.java b/quickstep/tests/multivalentTests/src/com/android/quickstep/AbsSwipeUpHandlerTestCase.java index 87a7cdae14..3483723097 100644 --- a/quickstep/tests/multivalentTests/src/com/android/quickstep/AbsSwipeUpHandlerTestCase.java +++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/AbsSwipeUpHandlerTestCase.java @@ -20,7 +20,6 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -38,14 +37,13 @@ import android.view.SurfaceControl; import android.view.ViewTreeObserver; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.test.platform.app.InstrumentationRegistry; import com.android.launcher3.DeviceProfile; -import com.android.launcher3.Flags; import com.android.launcher3.LauncherRootView; import com.android.launcher3.dragndrop.DragLayer; import com.android.launcher3.statemanager.BaseState; -import com.android.launcher3.statemanager.StatefulActivity; import com.android.launcher3.statemanager.StatefulContainer; import com.android.launcher3.util.SystemUiController; import com.android.quickstep.fallback.window.RecentsWindowManager; @@ -65,11 +63,11 @@ import java.util.Collections; import java.util.HashMap; public abstract class AbsSwipeUpHandlerTestCase< - RECENTS_CONTAINER extends Context & RecentsViewContainer & StatefulContainer, - STATE extends BaseState, RECENTS_VIEW extends RecentsView, - ACTIVITY_TYPE extends StatefulActivity & RecentsViewContainer, - ACTIVITY_INTERFACE extends BaseActivityInterface, - SWIPE_HANDLER extends AbsSwipeUpHandler> { + STATE_TYPE extends BaseState, + RECENTS_CONTAINER extends Context & RecentsViewContainer & StatefulContainer, + RECENTS_VIEW extends RecentsView, + SWIPE_HANDLER extends AbsSwipeUpHandler, + CONTAINER_INTERFACE extends BaseContainerInterface> { protected final Context mContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); @@ -106,13 +104,12 @@ public abstract class AbsSwipeUpHandlerTestCase< /* minimizedHomeBounds= */ null, new Bundle()); - protected RecentsWindowManager mRecentsWindowManager; protected TaskAnimationManager mTaskAnimationManager; - @Mock protected ACTIVITY_INTERFACE mActivityInterface; + @Mock protected CONTAINER_INTERFACE mActivityInterface; @Mock protected ActivityInitListener mActivityInitListener; @Mock protected RecentsAnimationController mRecentsAnimationController; - @Mock protected STATE mState; + @Mock protected STATE_TYPE mState; @Mock protected ViewTreeObserver mViewTreeObserver; @Mock protected DragLayer mDragLayer; @Mock protected LauncherRootView mRootView; @@ -122,16 +119,6 @@ public abstract class AbsSwipeUpHandlerTestCase< @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule(); - @Before - public void setUpTaskAnimationManager() { - runOnMainSync(() -> { - if(Flags.enableFallbackOverviewInWindow()){ - mRecentsWindowManager = new RecentsWindowManager(mContext); - } - mTaskAnimationManager = new TaskAnimationManager(mContext, mRecentsWindowManager); - }); - } - @Before public void setUpRunningTaskInfo() { mRunningTaskInfo.baseIntent = new Intent(Intent.ACTION_MAIN) @@ -162,6 +149,7 @@ public abstract class AbsSwipeUpHandlerTestCase< @Before public void setUpRecentsContainer() { + mTaskAnimationManager = new TaskAnimationManager(mContext, getRecentsWindowManager()); RecentsViewContainer recentsContainer = getRecentsContainer(); RECENTS_VIEW recentsView = getRecentsView(); @@ -263,13 +251,12 @@ public abstract class AbsSwipeUpHandlerTestCase< private void onRecentsAnimationStart(SWIPE_HANDLER absSwipeUpHandler) { when(mActivityInterface.getOverviewWindowBounds(any(), any())).thenReturn(new Rect()); - doNothing().when(mActivityInterface).setOnDeferredActivityLaunchCallback(any()); runOnMainSync(() -> absSwipeUpHandler.onRecentsAnimationStart( mRecentsAnimationController, mRecentsAnimationTargets)); } - private static void runOnMainSync(Runnable runnable) { + protected static void runOnMainSync(Runnable runnable) { InstrumentationRegistry.getInstrumentation().runOnMainSync(runnable); } @@ -278,6 +265,11 @@ public abstract class AbsSwipeUpHandlerTestCase< return createSwipeHandler(SystemClock.uptimeMillis(), false); } + @Nullable + protected RecentsWindowManager getRecentsWindowManager() { + return null; + } + @NonNull protected abstract SWIPE_HANDLER createSwipeHandler( long touchTimeMs, boolean continuingLastGesture); diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/FallbackSwipeHandlerTestCase.java b/quickstep/tests/multivalentTests/src/com/android/quickstep/FallbackSwipeHandlerTestCase.java index 8d6906fca4..88197e5473 100644 --- a/quickstep/tests/multivalentTests/src/com/android/quickstep/FallbackSwipeHandlerTestCase.java +++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/FallbackSwipeHandlerTestCase.java @@ -16,6 +16,7 @@ package com.android.quickstep; +import androidx.annotation.NonNull; import androidx.test.filters.SmallTest; import com.android.launcher3.util.LauncherMultivalentJUnit; @@ -28,15 +29,14 @@ import org.mockito.Mock; @SmallTest @RunWith(LauncherMultivalentJUnit.class) public class FallbackSwipeHandlerTestCase extends AbsSwipeUpHandlerTestCase< - RecentsActivity, RecentsState, - FallbackRecentsView, RecentsActivity, - FallbackActivityInterface, - FallbackSwipeHandler> { + FallbackRecentsView, + FallbackSwipeHandler, + FallbackActivityInterface> { @Mock private RecentsActivity mRecentsActivity; - @Mock private FallbackRecentsView mRecentsView; + @Mock private FallbackRecentsView mRecentsView; @Override @@ -52,13 +52,15 @@ public class FallbackSwipeHandlerTestCase extends AbsSwipeUpHandlerTestCase< mInputConsumerController); } + @NonNull @Override protected RecentsActivity getRecentsContainer() { return mRecentsActivity; } + @NonNull @Override - protected FallbackRecentsView getRecentsView() { + protected FallbackRecentsView getRecentsView() { return mRecentsView; } } diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/LauncherSwipeHandlerV2TestCase.java b/quickstep/tests/multivalentTests/src/com/android/quickstep/LauncherSwipeHandlerV2TestCase.java index 653dc01306..ec1dc8b008 100644 --- a/quickstep/tests/multivalentTests/src/com/android/quickstep/LauncherSwipeHandlerV2TestCase.java +++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/LauncherSwipeHandlerV2TestCase.java @@ -19,6 +19,7 @@ package com.android.quickstep; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.when; +import androidx.annotation.NonNull; import androidx.test.filters.SmallTest; import com.android.launcher3.Hotseat; @@ -38,12 +39,11 @@ import org.mockito.Mock; @SmallTest @RunWith(LauncherMultivalentJUnit.class) public class LauncherSwipeHandlerV2TestCase extends AbsSwipeUpHandlerTestCase< - QuickstepLauncher, LauncherState, - RecentsView, QuickstepLauncher, - LauncherActivityInterface, - LauncherSwipeHandlerV2> { + RecentsView, + LauncherSwipeHandlerV2, + LauncherActivityInterface> { @Mock private QuickstepLauncher mQuickstepLauncher; @Mock private RecentsView mRecentsView; @@ -67,6 +67,7 @@ public class LauncherSwipeHandlerV2TestCase extends AbsSwipeUpHandlerTestCase< when(mWorkspace.getStateTransitionAnimation()).thenReturn(mTransitionAnimation); } + @NonNull @Override protected LauncherSwipeHandlerV2 createSwipeHandler( long touchTimeMs, boolean continuingLastGesture) { @@ -80,11 +81,13 @@ public class LauncherSwipeHandlerV2TestCase extends AbsSwipeUpHandlerTestCase< mInputConsumerController); } + @NonNull @Override protected QuickstepLauncher getRecentsContainer() { return mQuickstepLauncher; } + @NonNull @Override protected RecentsView getRecentsView() { return mRecentsView; diff --git a/quickstep/tests/multivalentTests/src/com/android/quickstep/RecentsWindowSwipeHandlerTestCase.java b/quickstep/tests/multivalentTests/src/com/android/quickstep/RecentsWindowSwipeHandlerTestCase.java new file mode 100644 index 0000000000..1bdf273ddf --- /dev/null +++ b/quickstep/tests/multivalentTests/src/com/android/quickstep/RecentsWindowSwipeHandlerTestCase.java @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2024 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; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.test.filters.SmallTest; + +import com.android.launcher3.util.LauncherMultivalentJUnit; +import com.android.quickstep.fallback.FallbackRecentsView; +import com.android.quickstep.fallback.RecentsState; +import com.android.quickstep.fallback.window.RecentsWindowManager; +import com.android.quickstep.fallback.window.RecentsWindowSwipeHandler; +import com.android.quickstep.views.RecentsViewContainer; + +import org.junit.runner.RunWith; +import org.mockito.Mock; + +@SmallTest +@RunWith(LauncherMultivalentJUnit.class) +public class RecentsWindowSwipeHandlerTestCase extends AbsSwipeUpHandlerTestCase< + RecentsState, + RecentsWindowManager, + FallbackRecentsView, + RecentsWindowSwipeHandler, + FallbackWindowInterface> { + + @Mock private RecentsWindowManager mRecentsWindowManager; + @Mock private FallbackRecentsView mRecentsView; + + @NonNull + @Override + protected RecentsWindowSwipeHandler createSwipeHandler(long touchTimeMs, + boolean continuingLastGesture) { + return new RecentsWindowSwipeHandler( + mContext, + mRecentsAnimationDeviceState, + mTaskAnimationManager, + mGestureState, + touchTimeMs, + continuingLastGesture, + mInputConsumerController, + mRecentsWindowManager); + } + + @Nullable + @Override + protected RecentsWindowManager getRecentsWindowManager() { + return mRecentsWindowManager; + } + + @NonNull + @Override + protected RecentsViewContainer getRecentsContainer() { + return mRecentsWindowManager; + } + + @NonNull + @Override + protected FallbackRecentsView getRecentsView() { + return mRecentsView; + } +}