From 2d1a69e58bd4619f58d7d1db622160bd6ff01a5d Mon Sep 17 00:00:00 2001 From: Vinit Nayak Date: Mon, 25 Apr 2022 19:55:31 +0000 Subject: [PATCH 1/9] Revert "Revert "Use new onStartSplitLegacy when starting split f..." Revert submission 17918609-revert-17779173-startSplitLegacy-OOWPZEFFGI Reason for revert: Running through TH Reverted Changes: I6d81e0584:Revert "Use new onStartSplitLegacy when starting s... I754bc308f:Revert "Remove check for preventing re-parenting n... Change-Id: I6eea82f34b3680020b49ec7fe19eb61cc68286a5 --- .../quickstep/RecentsAnimationCallbacks.java | 3 +-- .../com/android/quickstep/SystemUiProxy.java | 17 +++++++++++++---- .../android/quickstep/TaskAnimationManager.java | 5 +++-- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java b/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java index fe31f1d8bb..51ae56b96d 100644 --- a/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java +++ b/quickstep/src/com/android/quickstep/RecentsAnimationCallbacks.java @@ -104,8 +104,7 @@ public class RecentsAnimationCallbacks implements .map(RemoteAnimationTargetCompat::unwrap) .toArray(RemoteAnimationTarget[]::new); - RemoteAnimationTarget[] nonAppTargets = - mSystemUiProxy.onGoingToRecentsLegacy(mCancelled, nonHomeApps); + RemoteAnimationTarget[] nonAppTargets = mSystemUiProxy.onGoingToRecentsLegacy(nonHomeApps); RecentsAnimationTargets targets = new RecentsAnimationTargets(appTargets, wallpaperTargets, RemoteAnimationTargetCompat.wrap(nonAppTargets), diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java index 5ef89d309a..5e12f319ba 100644 --- a/quickstep/src/com/android/quickstep/SystemUiProxy.java +++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java @@ -676,14 +676,12 @@ public class SystemUiProxy implements ISystemUiProxy, DisplayController.DisplayI * Call this when going to recents so that shell can set-up and provide appropriate leashes * for animation (eg. DividerBar). * - * @param cancel true if recents starting is being cancelled. * @return RemoteAnimationTargets of windows that need to animate but only exist in shell. */ - public RemoteAnimationTarget[] onGoingToRecentsLegacy(boolean cancel, - RemoteAnimationTarget[] apps) { + public RemoteAnimationTarget[] onGoingToRecentsLegacy(RemoteAnimationTarget[] apps) { if (mSplitScreen != null) { try { - return mSplitScreen.onGoingToRecentsLegacy(cancel, apps); + return mSplitScreen.onGoingToRecentsLegacy(apps); } catch (RemoteException e) { Log.w(TAG, "Failed call onGoingToRecentsLegacy"); } @@ -691,6 +689,17 @@ public class SystemUiProxy implements ISystemUiProxy, DisplayController.DisplayI return null; } + public RemoteAnimationTarget[] onStartingSplitLegacy(RemoteAnimationTarget[] apps) { + if (mSplitScreen != null) { + try { + return mSplitScreen.onStartingSplitLegacy(apps); + } catch (RemoteException e) { + Log.w(TAG, "Failed call onStartingSplitLegacy"); + } + } + return null; + } + // // One handed // diff --git a/quickstep/src/com/android/quickstep/TaskAnimationManager.java b/quickstep/src/com/android/quickstep/TaskAnimationManager.java index f094d712a1..2565674763 100644 --- a/quickstep/src/com/android/quickstep/TaskAnimationManager.java +++ b/quickstep/src/com/android/quickstep/TaskAnimationManager.java @@ -177,8 +177,9 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn ((RecentsActivity) activityInterface.getCreatedActivity()).startHome(); return; } - RemoteAnimationTarget[] nonAppTargets = SystemUiProxy.INSTANCE.get(mCtx) - .onGoingToRecentsLegacy(false, nonHomeApps); + + RemoteAnimationTarget[] nonAppTargets = + SystemUiProxy.INSTANCE.getNoCreate().onStartingSplitLegacy(nonHomeApps); if (ENABLE_QUICKSTEP_LIVE_TILE.get() && activityInterface.isInLiveTileMode() && activityInterface.getCreatedActivity() != null) { From 023537038dbd65f33f08e899b5597a82dd814b68 Mon Sep 17 00:00:00 2001 From: Tracy Zhou Date: Thu, 14 Apr 2022 13:29:59 -0700 Subject: [PATCH 2/9] Originate split select animation from the original icon view instead of the split menu icon Bug: 226395821 Test: https://recall.googleplex.com/projects/f46cfe9c-8076-4efe-bf8a-b1cc4f1f5e1b/sessions/ed355c4f-b9d3-4b85-870f-2decb0b786db Change-Id: I7277a9de212328d6f580bff5d28338ea0c058d99 --- .../launcher3/popup/QuickstepSystemShortcut.java | 3 ++- .../com/android/quickstep/views/FloatingTaskView.java | 7 +++++++ .../src/com/android/quickstep/views/RecentsView.java | 11 +++++------ 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/quickstep/src/com/android/launcher3/popup/QuickstepSystemShortcut.java b/quickstep/src/com/android/launcher3/popup/QuickstepSystemShortcut.java index 86310fa14f..4e59790771 100644 --- a/quickstep/src/com/android/launcher3/popup/QuickstepSystemShortcut.java +++ b/quickstep/src/com/android/launcher3/popup/QuickstepSystemShortcut.java @@ -70,7 +70,8 @@ public interface QuickstepSystemShortcut { RecentsView recentsView = mTarget.getOverviewPanel(); recentsView.initiateSplitSelect( - new SplitSelectSource(view, new BitmapDrawable(bitmap), intent, mPosition)); + new SplitSelectSource(mOriginalView, new BitmapDrawable(bitmap), intent, + mPosition)); } } diff --git a/quickstep/src/com/android/quickstep/views/FloatingTaskView.java b/quickstep/src/com/android/quickstep/views/FloatingTaskView.java index 54420de6cb..c980d1eac2 100644 --- a/quickstep/src/com/android/quickstep/views/FloatingTaskView.java +++ b/quickstep/src/com/android/quickstep/views/FloatingTaskView.java @@ -196,6 +196,13 @@ public class FloatingTaskView extends FrameLayout { 0, 1, ACCEL); animation.addFloat(mThumbnailView, LauncherAnimUtils.VIEW_ALPHA, 1, 0, DEACCEL_3); + } else if (isStagedTask) { + // Fade in the placeholder view when split is initiated from homescreen / all apps + // icons. + if (mSplitPlaceholderView.getAlpha() == 0) { + animation.addFloat(mSplitPlaceholderView, SplitPlaceholderView.ALPHA_FLOAT, + 0.3f, 1, ACCEL); + } } MultiValueUpdateListener listener = new MultiValueUpdateListener() { diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index 49bf827cf9..01b06cbb76 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -2737,16 +2737,15 @@ public abstract class RecentsView Date: Thu, 14 Apr 2022 17:51:59 +0100 Subject: [PATCH 3/9] Tune AllApps dismiss animation - Avoid overriding interpolator in AllAppsTransitionController.setStateWithAnimation as it's no longer needed and it'll wrongly override interpolator for ANIM_ALL_APPS_FADE - Override ANIM_ALL_APPS_FADE to FINAL_FRAME in QuickstepAtomicAnimationFactory for tap deadzone to dismiss animation, also added EMPHASIZED_ACCELERATE for the dismiss animation - Tuned dismiss animation across form factors to 300ms Fix: 220336617 Test: manual Change-Id: I4b3e827b503dcb1dd39f0bd99d4c1dd5ffdba0f3 --- .../taskbar/TaskbarStashController.java | 5 +++-- .../allapps/TaskbarAllAppsSlideInView.java | 16 +++++++++++----- .../allapps/TaskbarAllAppsViewController.java | 5 +++-- .../uioverrides/RecentsViewStateController.java | 2 +- .../uioverrides/states/AllAppsState.java | 4 ++-- .../states/OverviewModalTaskState.java | 2 +- .../uioverrides/states/OverviewState.java | 2 +- .../states/QuickstepAtomicAnimationFactory.java | 16 ++++++++++++---- .../NoButtonNavbarToOverviewTouchController.java | 2 +- .../PortraitStatesTouchController.java | 11 +++++------ .../fallback/FallbackRecentsStateController.java | 2 +- .../android/quickstep/fallback/RecentsState.java | 2 +- .../quickstep/util/OverviewToHomeAnim.java | 2 +- .../com/android/quickstep/views/RecentsView.java | 3 ++- src/com/android/launcher3/LauncherState.java | 2 +- src/com/android/launcher3/Workspace.java | 2 +- .../allapps/AllAppsTransitionController.java | 2 -- .../android/launcher3/anim/Interpolators.java | 7 ------- .../PinShortcutRequestActivityInfo.java | 3 ++- .../launcher3/statemanager/BaseState.java | 2 +- .../launcher3/statemanager/StateManager.java | 4 ++-- src/com/android/launcher3/states/HintState.java | 2 +- .../launcher3/states/SpringLoadedState.java | 2 +- .../launcher3/views/AbstractSlideInView.java | 6 +++++- .../uioverrides/states/AllAppsState.java | 4 ++-- .../uioverrides/states/OverviewState.java | 2 +- 26 files changed, 62 insertions(+), 50 deletions(-) diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java index f34759d700..3489ae695f 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java @@ -17,6 +17,7 @@ package com.android.launcher3.taskbar; import static android.view.HapticFeedbackConstants.LONG_PRESS; +import static com.android.launcher3.LauncherState.ALL_APPS; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_LONGPRESS_HIDE; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_LONGPRESS_SHOW; import static com.android.launcher3.taskbar.Utilities.appendFlag; @@ -34,7 +35,6 @@ import android.view.WindowInsets; import com.android.launcher3.DeviceProfile; import com.android.launcher3.Utilities; -import com.android.launcher3.taskbar.allapps.TaskbarAllAppsSlideInView; import com.android.launcher3.testing.TestProtocol; import com.android.launcher3.util.MultiValueAlpha.AlphaProperty; import com.android.quickstep.AnimatedFloat; @@ -564,7 +564,8 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba updateStateForFlag(FLAG_STASHED_IN_APP_ALL_APPS, false); if (applyState) { - applyState(TaskbarAllAppsSlideInView.DEFAULT_CLOSE_DURATION); + applyState(ALL_APPS.getTransitionDuration( + mControllers.taskbarActivityContext, false /* isToState */)); } } diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java index a37ebac2c3..2d7ce3245a 100644 --- a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java +++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java @@ -15,13 +15,16 @@ */ package com.android.launcher3.taskbar.allapps; +import static com.android.launcher3.LauncherState.ALL_APPS; import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE; +import static com.android.systemui.animation.Interpolators.EMPHASIZED_ACCELERATE; import android.animation.PropertyValuesHolder; import android.content.Context; import android.graphics.Rect; import android.util.AttributeSet; import android.view.MotionEvent; +import android.view.animation.Interpolator; import com.android.launcher3.DeviceProfile; import com.android.launcher3.Insettable; @@ -33,9 +36,6 @@ import java.util.Optional; /** Wrapper for taskbar all apps with slide-in behavior. */ public class TaskbarAllAppsSlideInView extends AbstractSlideInView implements Insettable, DeviceProfile.OnDeviceProfileChangeListener { - static final int DEFAULT_OPEN_DURATION = 500; - public static final int DEFAULT_CLOSE_DURATION = 200; - private TaskbarAllAppsContainerView mAppsView; private OnCloseListener mOnCloseBeginListener; private float mShiftRange; @@ -61,7 +61,8 @@ public class TaskbarAllAppsSlideInView extends AbstractSlideInView { AbstractFloatingView.closeOpenContainer( mContext, AbstractFloatingView.TYPE_ACTION_POPUP); diff --git a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java index 86f26c3673..00a98c0647 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java @@ -118,7 +118,7 @@ public final class RecentsViewStateController extends if (toState == OVERVIEW_SPLIT_SELECT) { // Animation to "dismiss" selected taskView PendingAnimation splitSelectInitAnimation = mRecentsView.createSplitSelectInitAnimation( - toState.getTransitionDuration(mLauncher)); + toState.getTransitionDuration(mLauncher, true /* isToState */)); // Add properties to shift remaining taskViews to get out of placeholder view splitSelectInitAnimation.setFloat(mRecentsView, taskViewsFloat.first, toState.getSplitSelectTranslation(mLauncher), LINEAR); diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java b/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java index cd14b3f75c..44583f11dd 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java +++ b/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java @@ -37,8 +37,8 @@ public class AllAppsState extends LauncherState { } @Override - public int getTransitionDuration(Context context) { - return 150; + public int getTransitionDuration(Context context, boolean isToState) { + return isToState ? 500 : 300; } @Override diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java index 6f084a1f97..0c49e5fc69 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java +++ b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewModalTaskState.java @@ -40,7 +40,7 @@ public class OverviewModalTaskState extends OverviewState { } @Override - public int getTransitionDuration(Context launcher) { + public int getTransitionDuration(Context launcher, boolean isToState) { return 300; } diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java index 236454e161..53a54446de 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java +++ b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java @@ -56,7 +56,7 @@ public class OverviewState extends LauncherState { } @Override - public int getTransitionDuration(Context context) { + public int getTransitionDuration(Context context, boolean isToState) { // In gesture modes, overview comes in all the way from the side, so give it more time. return DisplayController.getNavigationMode(context).hasGestures ? 380 : 250; } diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java b/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java index b1d83e7c31..b5b03a1ec6 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java +++ b/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java @@ -42,6 +42,7 @@ import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SC import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_X; import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_Y; import static com.android.launcher3.states.StateAnimationConfig.ANIM_SCRIM_FADE; +import static com.android.launcher3.states.StateAnimationConfig.ANIM_VERTICAL_PROGRESS; import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_FADE; import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_SCALE; import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_TRANSLATE; @@ -50,6 +51,8 @@ import static com.android.launcher3.uioverrides.touchcontrollers.PortraitStatesT import static com.android.launcher3.uioverrides.touchcontrollers.PortraitStatesTouchController.ALL_APPS_SCRIM_OPAQUE_THRESHOLD; import static com.android.launcher3.uioverrides.touchcontrollers.PortraitStatesTouchController.ALL_APPS_SCRIM_VISIBLE_THRESHOLD; import static com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY; +import static com.android.systemui.animation.Interpolators.EMPHASIZED_ACCELERATE; +import static com.android.systemui.animation.Interpolators.EMPHASIZED_DECELERATE; import android.animation.ValueAnimator; @@ -179,12 +182,17 @@ public class QuickstepAtomicAnimationFactory extends } config.duration = Math.max(config.duration, mHintToNormalDuration); } else if (fromState == ALL_APPS && toState == NORMAL) { - config.setInterpolator(ANIM_ALL_APPS_FADE, Interpolators.clampToProgress(DEACCEL, - 1 - ALL_APPS_CONTENT_FADE_MAX_CLAMPING_THRESHOLD, - 1 - ALL_APPS_CONTENT_FADE_MIN_CLAMPING_THRESHOLD)); - config.setInterpolator(ANIM_SCRIM_FADE, Interpolators.clampToProgress(DEACCEL, + boolean isTablet = mActivity.getDeviceProfile().isTablet; + config.setInterpolator(ANIM_ALL_APPS_FADE, + isTablet ? FINAL_FRAME : Interpolators.clampToProgress(LINEAR, + 1 - ALL_APPS_CONTENT_FADE_MAX_CLAMPING_THRESHOLD, + 1 - ALL_APPS_CONTENT_FADE_MIN_CLAMPING_THRESHOLD)); + config.setInterpolator(ANIM_SCRIM_FADE, Interpolators.clampToProgress(LINEAR, 1 - ALL_APPS_SCRIM_OPAQUE_THRESHOLD, 1 - ALL_APPS_SCRIM_VISIBLE_THRESHOLD)); + config.setInterpolator(ANIM_VERTICAL_PROGRESS, EMPHASIZED_ACCELERATE); + } else if (fromState == NORMAL && toState == ALL_APPS) { + config.setInterpolator(ANIM_VERTICAL_PROGRESS, EMPHASIZED_DECELERATE); } } } diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java index 7ec12439cb..4da1d41091 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/NoButtonNavbarToOverviewTouchController.java @@ -180,7 +180,7 @@ public class NoButtonNavbarToOverviewTouchController extends PortraitStatesTouch // Normally we compute the duration based on the velocity and distance to the given // state, but since the hint state tracks the entire screen without a clear endpoint, we // need to manually set the duration to a reasonable value. - animator.setDuration(HINT_STATE.getTransitionDuration(mLauncher)); + animator.setDuration(HINT_STATE.getTransitionDuration(mLauncher, true /* isToState */)); } } diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java index 27a55c3ff3..1504c12d71 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java @@ -21,10 +21,9 @@ import static com.android.launcher3.AbstractFloatingView.getTopOpenViewWithType; import static com.android.launcher3.LauncherState.ALL_APPS; import static com.android.launcher3.LauncherState.NORMAL; import static com.android.launcher3.LauncherState.OVERVIEW; -import static com.android.launcher3.anim.Interpolators.ACCEL; -import static com.android.launcher3.anim.Interpolators.DEACCEL; import static com.android.launcher3.anim.Interpolators.FINAL_FRAME; import static com.android.launcher3.anim.Interpolators.INSTANT; +import static com.android.launcher3.anim.Interpolators.LINEAR; import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE; import static com.android.launcher3.states.StateAnimationConfig.ANIM_SCRIM_FADE; @@ -131,10 +130,10 @@ public class PortraitStatesTouchController extends AbstractStateChangeTouchContr boolean isTablet = mLauncher.getDeviceProfile().isTablet; builder.setInterpolator(ANIM_ALL_APPS_FADE, isTablet ? INSTANT - : Interpolators.clampToProgress(ACCEL, + : Interpolators.clampToProgress(LINEAR, ALL_APPS_CONTENT_FADE_MIN_CLAMPING_THRESHOLD, ALL_APPS_CONTENT_FADE_MAX_CLAMPING_THRESHOLD)); - builder.setInterpolator(ANIM_SCRIM_FADE, Interpolators.clampToProgress(ACCEL, + builder.setInterpolator(ANIM_SCRIM_FADE, Interpolators.clampToProgress(LINEAR, ALL_APPS_SCRIM_VISIBLE_THRESHOLD, ALL_APPS_SCRIM_OPAQUE_THRESHOLD)); return builder; @@ -145,10 +144,10 @@ public class PortraitStatesTouchController extends AbstractStateChangeTouchContr boolean isTablet = mLauncher.getDeviceProfile().isTablet; builder.setInterpolator(ANIM_ALL_APPS_FADE, isTablet ? FINAL_FRAME - : Interpolators.clampToProgress(DEACCEL, + : Interpolators.clampToProgress(LINEAR, 1 - ALL_APPS_CONTENT_FADE_MAX_CLAMPING_THRESHOLD, 1 - ALL_APPS_CONTENT_FADE_MIN_CLAMPING_THRESHOLD)); - builder.setInterpolator(ANIM_SCRIM_FADE, Interpolators.clampToProgress(DEACCEL, + builder.setInterpolator(ANIM_SCRIM_FADE, Interpolators.clampToProgress(LINEAR, 1 - ALL_APPS_SCRIM_OPAQUE_THRESHOLD, 1 - ALL_APPS_SCRIM_VISIBLE_THRESHOLD)); return builder; diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java index 5094d49200..f68bbbce62 100644 --- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java +++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java @@ -112,7 +112,7 @@ public class FallbackRecentsStateController implements StateHandler taskViewsFloat = diff --git a/quickstep/src/com/android/quickstep/fallback/RecentsState.java b/quickstep/src/com/android/quickstep/fallback/RecentsState.java index 9705bb6fd5..77db6b79f4 100644 --- a/quickstep/src/com/android/quickstep/fallback/RecentsState.java +++ b/quickstep/src/com/android/quickstep/fallback/RecentsState.java @@ -77,7 +77,7 @@ public class RecentsState implements BaseState { } @Override - public int getTransitionDuration(Context context) { + public int getTransitionDuration(Context context, boolean isToState) { return 250; } diff --git a/quickstep/src/com/android/quickstep/util/OverviewToHomeAnim.java b/quickstep/src/com/android/quickstep/util/OverviewToHomeAnim.java index 5cf4f0b97f..3cec1a4f1a 100644 --- a/quickstep/src/com/android/quickstep/util/OverviewToHomeAnim.java +++ b/quickstep/src/com/android/quickstep/util/OverviewToHomeAnim.java @@ -82,7 +82,7 @@ public class OverviewToHomeAnim { // WorkspaceRevealAnim handles the depth, so don't interfere. config.animFlags |= StateAnimationConfig.SKIP_DEPTH_CONTROLLER; } - config.duration = startState.getTransitionDuration(mLauncher); + config.duration = startState.getTransitionDuration(mLauncher, false /* isToState */); AnimatorSet stateAnim = stateManager.createAtomicAnimation( startState, NORMAL, config); stateAnim.addListener(new AnimationSuccessListener() { diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index 71b2cea444..41b3f59e30 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -4059,7 +4059,8 @@ public abstract class RecentsView { FLAG_DISABLE_RESTORE | FLAG_WORKSPACE_ICONS_CAN_BE_DRAGGED | FLAG_HIDE_BACK_BUTTON | FLAG_HAS_SYS_UI_SCRIM) { @Override - public int getTransitionDuration(Context context) { + public int getTransitionDuration(Context context, boolean isToState) { // Arbitrary duration, when going to NORMAL we use the state we're coming from instead. return 0; } diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java index 78771ce84a..836d4b8fc8 100644 --- a/src/com/android/launcher3/Workspace.java +++ b/src/com/android/launcher3/Workspace.java @@ -2118,7 +2118,7 @@ public class Workspace extends PagedView final Runnable onCompleteCallback = onCompleteRunnable; mLauncher.getDragController().animateDragViewToOriginalPosition( /* onComplete= */ callbackList::executeAllAndDestroy, cell, - SPRING_LOADED.getTransitionDuration(mLauncher)); + SPRING_LOADED.getTransitionDuration(mLauncher, true /* isToState */)); mLauncher.getStateManager().goToState(NORMAL, /* delay= */ 0, onCompleteCallback == null ? null diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java index 637a4189b8..8d2b268817 100644 --- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java +++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java @@ -254,8 +254,6 @@ public class AllAppsTransitionController anim.setInterpolator(verticalProgressInterpolator); anim.addListener(getProgressAnimatorListener()); builder.add(anim); - // Use ANIM_VERTICAL_PROGRESS's interpolator to determine state transition threshold. - builder.setInterpolator(verticalProgressInterpolator); setAlphas(toState, config, builder); diff --git a/src/com/android/launcher3/anim/Interpolators.java b/src/com/android/launcher3/anim/Interpolators.java index 5a46ce1b18..4ff5d5e973 100644 --- a/src/com/android/launcher3/anim/Interpolators.java +++ b/src/com/android/launcher3/anim/Interpolators.java @@ -47,13 +47,6 @@ public class Interpolators { public static final Interpolator DEACCEL_2_5 = new DecelerateInterpolator(2.5f); public static final Interpolator DEACCEL_3 = new DecelerateInterpolator(3f); - /** - * The decelerating emphasized interpolator. Used for hero / emphasized movement of content that - * is appearing e.g. when coming from off screen - */ - public static final Interpolator EMPHASIZED_DECELERATE = new PathInterpolator( - 0.05f, 0.7f, 0.1f, 1f); - public static final Interpolator ACCEL_DEACCEL = new AccelerateDecelerateInterpolator(); public static final Interpolator FAST_OUT_SLOW_IN = new PathInterpolator(0.4f, 0f, 0.2f, 1f); diff --git a/src/com/android/launcher3/dragndrop/PinShortcutRequestActivityInfo.java b/src/com/android/launcher3/dragndrop/PinShortcutRequestActivityInfo.java index 29e7c1854d..f9916d0b3b 100644 --- a/src/com/android/launcher3/dragndrop/PinShortcutRequestActivityInfo.java +++ b/src/com/android/launcher3/dragndrop/PinShortcutRequestActivityInfo.java @@ -87,7 +87,8 @@ class PinShortcutRequestActivityInfo extends ShortcutConfigActivityInfo { // Total duration for the drop animation to complete. long duration = mContext.getResources().getInteger(R.integer.config_dropAnimMaxDuration) + LauncherAnimUtils.SPRING_LOADED_EXIT_DELAY + - LauncherState.SPRING_LOADED.getTransitionDuration(Launcher.getLauncher(mContext)); + LauncherState.SPRING_LOADED.getTransitionDuration(Launcher.getLauncher(mContext), + true /* isToState */); // Delay the actual accept() call until the drop animation is complete. return PinRequestHelper.createWorkspaceItemFromPinItemRequest( mContext, mRequest, duration); diff --git a/src/com/android/launcher3/statemanager/BaseState.java b/src/com/android/launcher3/statemanager/BaseState.java index 122573cfa1..4a68dda331 100644 --- a/src/com/android/launcher3/statemanager/BaseState.java +++ b/src/com/android/launcher3/statemanager/BaseState.java @@ -36,7 +36,7 @@ public interface BaseState { /** * @return How long the animation to this state should take (or from this state to NORMAL). */ - int getTransitionDuration(Context context); + int getTransitionDuration(Context context, boolean isToState); /** * Returns the state to go back to from this state diff --git a/src/com/android/launcher3/statemanager/StateManager.java b/src/com/android/launcher3/statemanager/StateManager.java index 1767939114..2aa9ddeb50 100644 --- a/src/com/android/launcher3/statemanager/StateManager.java +++ b/src/com/android/launcher3/statemanager/StateManager.java @@ -253,8 +253,8 @@ public class StateManager> { // Since state mBaseState can be reached from multiple states, just assume that the // transition plays in reverse and use the same duration as previous state. mConfig.duration = state == mBaseState - ? fromState.getTransitionDuration(mActivity) - : state.getTransitionDuration(mActivity); + ? fromState.getTransitionDuration(mActivity, false /* isToState */) + : state.getTransitionDuration(mActivity, true /* isToState */); prepareForAtomicAnimation(fromState, state, mConfig); AnimatorSet animation = createAnimationToNewWorkspaceInternal(state).buildAnim(); if (listener != null) { diff --git a/src/com/android/launcher3/states/HintState.java b/src/com/android/launcher3/states/HintState.java index 8b520165ce..4cfced8561 100644 --- a/src/com/android/launcher3/states/HintState.java +++ b/src/com/android/launcher3/states/HintState.java @@ -43,7 +43,7 @@ public class HintState extends LauncherState { } @Override - public int getTransitionDuration(Context context) { + public int getTransitionDuration(Context context, boolean isToState) { return 80; } diff --git a/src/com/android/launcher3/states/SpringLoadedState.java b/src/com/android/launcher3/states/SpringLoadedState.java index e311bc8740..15cdc20cef 100644 --- a/src/com/android/launcher3/states/SpringLoadedState.java +++ b/src/com/android/launcher3/states/SpringLoadedState.java @@ -39,7 +39,7 @@ public class SpringLoadedState extends LauncherState { } @Override - public int getTransitionDuration(Context context) { + public int getTransitionDuration(Context context, boolean isToState) { return 150; } diff --git a/src/com/android/launcher3/views/AbstractSlideInView.java b/src/com/android/launcher3/views/AbstractSlideInView.java index ed31e8d130..47503b118e 100644 --- a/src/com/android/launcher3/views/AbstractSlideInView.java +++ b/src/com/android/launcher3/views/AbstractSlideInView.java @@ -231,13 +231,17 @@ public abstract class AbstractSlideInView if (mSwipeDetector.isIdleState()) { mOpenCloseAnimator .setDuration(defaultDuration) - .setInterpolator(Interpolators.ACCEL); + .setInterpolator(getIdleInterpolator()); } else { mOpenCloseAnimator.setInterpolator(mScrollInterpolator); } mOpenCloseAnimator.start(); } + protected Interpolator getIdleInterpolator() { + return Interpolators.ACCEL; + } + protected void onCloseComplete() { mIsOpen = false; getPopupContainer().removeView(this); diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/states/AllAppsState.java b/src_ui_overrides/com/android/launcher3/uioverrides/states/AllAppsState.java index 8a435c9647..2f8e6806e0 100644 --- a/src_ui_overrides/com/android/launcher3/uioverrides/states/AllAppsState.java +++ b/src_ui_overrides/com/android/launcher3/uioverrides/states/AllAppsState.java @@ -39,8 +39,8 @@ public class AllAppsState extends LauncherState { } @Override - public int getTransitionDuration(Context context) { - return 320; + public int getTransitionDuration(Context context, boolean isToState) { + return isToState ? 500 : 300; } @Override diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/states/OverviewState.java b/src_ui_overrides/com/android/launcher3/uioverrides/states/OverviewState.java index d1543175f4..7a228c42b8 100644 --- a/src_ui_overrides/com/android/launcher3/uioverrides/states/OverviewState.java +++ b/src_ui_overrides/com/android/launcher3/uioverrides/states/OverviewState.java @@ -34,7 +34,7 @@ public class OverviewState extends LauncherState { } @Override - public int getTransitionDuration(Context context) { + public int getTransitionDuration(Context context, boolean isToState) { return 250; } From c0b30dc2661eb44911b8556c4f0f237e02c6c04c Mon Sep 17 00:00:00 2001 From: Schneider Victor-tulias Date: Mon, 7 Mar 2022 12:49:56 -0800 Subject: [PATCH 4/9] Fix taskbar 3-button truncation on rotate - Fixed truncation issue in overview and home on rotation - Fixed 3 buttons translating incorrectly when switching to/from overview Fixes: 205057824 Fixes: 215482458 Test: Manual Change-Id: I0b89010a2b6ed03a34c3443fc6e1edc81f8d9f20 Merged-In: I0b89010a2b6ed03a34c3443fc6e1edc81f8d9f20 (cherry picked from commit 8aa99c72b1291b66f68f58fc899825b373bf2c22) --- .../taskbar/LauncherTaskbarUIController.java | 37 +++++++++------ .../launcher3/taskbar/TaskbarControllers.java | 3 ++ .../TaskbarLauncherStateController.java | 46 +++++++++++++++++++ .../taskbar/TaskbarStashController.java | 2 +- .../taskbar/TaskbarUIController.java | 9 ++++ .../taskbar/TaskbarViewController.java | 4 +- .../uioverrides/states/OverviewState.java | 10 +++- 7 files changed, 95 insertions(+), 16 deletions(-) diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java index 793d98704c..11dbe45207 100644 --- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java +++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java @@ -43,6 +43,7 @@ import com.android.launcher3.util.OnboardingPrefs; import com.android.quickstep.AnimatedFloat; import com.android.quickstep.RecentsAnimationCallbacks; +import java.io.PrintWriter; import java.util.Arrays; import java.util.Set; import java.util.stream.Stream; @@ -57,7 +58,12 @@ public class LauncherTaskbarUIController extends TaskbarUIController { private final BaseQuickstepLauncher mLauncher; private final DeviceProfile.OnDeviceProfileChangeListener mOnDeviceProfileChangeListener = - this::onStashedInAppChanged; + dp -> { + onStashedInAppChanged(dp); + if (mControllers != null && mControllers.taskbarViewController != null) { + mControllers.taskbarViewController.onRotationChanged(dp); + } + }; // Initialized in init. private AnimatedFloat mTaskbarOverrideBackgroundAlpha; @@ -65,15 +71,6 @@ public class LauncherTaskbarUIController extends TaskbarUIController { private final TaskbarLauncherStateController mTaskbarLauncherStateController = new TaskbarLauncherStateController(); - private final DeviceProfile.OnDeviceProfileChangeListener mProfileChangeListener = - new DeviceProfile.OnDeviceProfileChangeListener() { - @Override - public void onDeviceProfileChanged(DeviceProfile dp) { - mControllers.taskbarViewController.onRotationChanged( - mLauncher.getDeviceProfile()); - } - }; - public LauncherTaskbarUIController(BaseQuickstepLauncher launcher) { mLauncher = launcher; } @@ -93,7 +90,10 @@ public class LauncherTaskbarUIController extends TaskbarUIController { onStashedInAppChanged(mLauncher.getDeviceProfile()); mLauncher.addOnDeviceProfileChangeListener(mOnDeviceProfileChangeListener); - mLauncher.addOnDeviceProfileChangeListener(mProfileChangeListener); + } + + public boolean supportsVisualStashing() { + return mControllers.taskbarStashController.supportsVisualStashing(); } @Override @@ -102,9 +102,8 @@ public class LauncherTaskbarUIController extends TaskbarUIController { onLauncherResumedOrPaused(false); mTaskbarLauncherStateController.onDestroy(); - mLauncher.removeOnDeviceProfileChangeListener(mOnDeviceProfileChangeListener); mLauncher.setTaskbarUIController(null); - mLauncher.removeOnDeviceProfileChangeListener(mProfileChangeListener); + mLauncher.removeOnDeviceProfileChangeListener(mOnDeviceProfileChangeListener); updateTaskTransitionSpec(true); } @@ -271,4 +270,16 @@ public class LauncherTaskbarUIController extends TaskbarUIController { // gesture ends, start drawing taskbar's background again since launcher might stop drawing. forceHideBackground(inProgress); } + + @Override + public void dumpLogs(String prefix, PrintWriter pw) { + super.dumpLogs(prefix, pw); + + pw.println(String.format( + "%s\tmTaskbarOverrideBackgroundAlpha=%.2f", + prefix, + mTaskbarOverrideBackgroundAlpha.value)); + + mTaskbarLauncherStateController.dumpLogs(prefix + "\t", pw); + } } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java index ff08e3dda7..e4c96b2faa 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java @@ -187,9 +187,12 @@ public class TaskbarControllers { return; } + pw.println(String.format( + "%s\tmAreAllControllersInitialized=%b", prefix, mAreAllControllersInitialized)); for (LoggableTaskbarController controller : mControllersToLog) { controller.dumpLogs(prefix + "\t", pw); } + uiController.dumpLogs(prefix + "\t", pw); rotationButtonController.dumpLogs(prefix + "\t", pw); } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java index 36e642075f..138fb991f4 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java @@ -42,7 +42,9 @@ import com.android.quickstep.views.RecentsView; import com.android.systemui.animation.ViewRootSync; import com.android.systemui.shared.recents.model.ThumbnailData; +import java.io.PrintWriter; import java.util.HashMap; +import java.util.StringJoiner; import java.util.function.Consumer; import java.util.function.Supplier; @@ -476,4 +478,48 @@ import java.util.function.Supplier; controller.applyState(); } } + + private static String getStateString(int flags) { + StringJoiner str = new StringJoiner("|"); + str.add((flags & FLAG_RESUMED) != 0 ? "FLAG_RESUMED" : ""); + str.add((flags & FLAG_RECENTS_ANIMATION_RUNNING) != 0 + ? "FLAG_RECENTS_ANIMATION_RUNNING" : ""); + str.add((flags & FLAG_TRANSITION_STATE_RUNNING) != 0 + ? "FLAG_TRANSITION_STATE_RUNNING" : ""); + return str.toString(); + } + + protected void dumpLogs(String prefix, PrintWriter pw) { + pw.println(prefix + "TaskbarLauncherStateController:"); + + pw.println(String.format( + "%s\tmIconAlignmentForResumedState=%.2f", + prefix, + mIconAlignmentForResumedState.value)); + pw.println(String.format( + "%s\tmIconAlignmentForGestureState=%.2f", + prefix, + mIconAlignmentForGestureState.value)); + pw.println(String.format( + "%s\tmIconAlignmentForLauncherState=%.2f", + prefix, + mIconAlignmentForLauncherState.value)); + pw.println(String.format( + "%s\tmTaskbarBackgroundAlpha=%.2f", prefix, mTaskbarBackgroundAlpha.value)); + pw.println(String.format( + "%s\tmIconAlphaForHome=%.2f", prefix, mIconAlphaForHome.getValue())); + pw.println(String.format("%s\tmPrevState=%s", prefix, getStateString(mPrevState))); + pw.println(String.format("%s\tmState=%s", prefix, getStateString(mState))); + pw.println(String.format("%s\tmLauncherState=%s", prefix, mLauncherState)); + pw.println(String.format( + "%s\tmIsAnimatingToLauncherViaGesture=%b", + prefix, + mIsAnimatingToLauncherViaGesture)); + pw.println(String.format( + "%s\tmIsAnimatingToLauncherViaResume=%b", + prefix, + mIsAnimatingToLauncherViaResume)); + pw.println(String.format( + "%s\tmShouldDelayLauncherStateAnim=%b", prefix, mShouldDelayLauncherStateAnim)); + } } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java index f34759d700..c92feed46f 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java @@ -275,7 +275,7 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba return !mIsStashed && isInApp(); } - private boolean isInApp() { + public boolean isInApp() { return hasAnyFlag(FLAGS_IN_APP); } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java index d5c399b619..6c2d179510 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java @@ -22,6 +22,7 @@ import androidx.annotation.CallSuper; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.ItemInfoWithIcon; +import java.io.PrintWriter; import java.util.stream.Stream; /** @@ -86,4 +87,12 @@ public class TaskbarUIController { stashController.applyState(); } } + + @CallSuper + protected void dumpLogs(String prefix, PrintWriter pw) { + pw.println(String.format( + "%sTaskbarUIController: using an instance of %s", + prefix, + getClass().getSimpleName())); + } } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java index 6416720962..6967cc5969 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java @@ -289,10 +289,12 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar } public void onRotationChanged(DeviceProfile deviceProfile) { - if (areIconsVisible()) { + if (mControllers.taskbarStashController.isInApp()) { // We only translate on rotation when on home return; } + mActivity.setTaskbarWindowHeight( + deviceProfile.taskbarSize + deviceProfile.getTaskbarOffsetY()); mTaskbarNavButtonTranslationY.updateValue(-deviceProfile.getTaskbarOffsetY()); } diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java index 236454e161..2ec8d9db65 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java +++ b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java @@ -22,10 +22,12 @@ import android.content.Context; import android.graphics.Rect; import android.os.SystemProperties; +import com.android.launcher3.BaseQuickstepLauncher; import com.android.launcher3.DeviceProfile; import com.android.launcher3.Launcher; import com.android.launcher3.LauncherState; import com.android.launcher3.R; +import com.android.launcher3.taskbar.LauncherTaskbarUIController; import com.android.launcher3.util.DisplayController; import com.android.launcher3.util.Themes; import com.android.quickstep.util.LayoutUtils; @@ -93,7 +95,13 @@ public class OverviewState extends LauncherState { @Override public boolean isTaskbarStashed(Launcher launcher) { - return true; + if (launcher instanceof BaseQuickstepLauncher) { + LauncherTaskbarUIController uiController = + ((BaseQuickstepLauncher) launcher).getTaskbarUIController(); + + return uiController != null && uiController.supportsVisualStashing(); + } + return super.isTaskbarStashed(launcher); } @Override From 9b6babf8391a9f59e4b832493b68812a6c8af446 Mon Sep 17 00:00:00 2001 From: Schneider Victor-tulias Date: Thu, 24 Mar 2022 14:47:32 -0700 Subject: [PATCH 5/9] Translate the 3 navigation buttons to/from their in-app position when animating to/from the -1 screen, all apps and widgets. Bug: 221455508 Test: opened all apps, widgets, -1 screen, notifications shade and keyboard in various combinations and orders; locked screen, launched app, returned home with the back/home buttons, opened overview Change-Id: Ia0b406aacf72b34bd6b7ff1c01278ab6895a7da4 Merged-In: Ia0b406aacf72b34bd6b7ff1c01278ab6895a7da4 (cherry picked from commit 9c1a452a1d2663b183524b0efb9887d388b0c901) --- .../launcher3/BaseQuickstepLauncher.java | 25 ++++++ .../taskbar/DesktopTaskbarUIController.java | 6 ++ .../taskbar/LauncherTaskbarUIController.java | 81 ++++++++++++++++++- .../taskbar/NavbarButtonsViewController.java | 42 +++++++--- .../taskbar/TaskbarActivityContext.java | 2 +- .../launcher3/taskbar/TaskbarControllers.java | 17 +++- .../launcher3/taskbar/TaskbarManager.java | 3 + .../launcher3/taskbar/TaskbarSharedState.java | 1 - .../taskbar/TaskbarStashController.java | 6 +- .../taskbar/TaskbarUIController.java | 5 ++ .../taskbar/TaskbarViewController.java | 4 + .../allapps/TaskbarAllAppsController.java | 15 ++-- src/com/android/launcher3/Launcher.java | 18 +++++ .../allapps/AllAppsTransitionController.java | 1 + .../launcher3/widget/BaseWidgetSheet.java | 8 ++ 15 files changed, 205 insertions(+), 29 deletions(-) diff --git a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java index 6abcbd5504..2239102c4d 100644 --- a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java +++ b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java @@ -24,6 +24,9 @@ import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TI import static com.android.launcher3.config.FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE; import static com.android.launcher3.model.data.ItemInfo.NO_MATCHING_ID; import static com.android.launcher3.popup.QuickstepSystemShortcut.getSplitSelectShortcutByPosition; +import static com.android.launcher3.taskbar.LauncherTaskbarUIController.ALL_APPS_PAGE_PROGRESS_INDEX; +import static com.android.launcher3.taskbar.LauncherTaskbarUIController.MINUS_ONE_PAGE_PROGRESS_INDEX; +import static com.android.launcher3.taskbar.LauncherTaskbarUIController.WIDGETS_PAGE_PROGRESS_INDEX; import static com.android.launcher3.util.DisplayController.CHANGE_ACTIVE_SCREEN; import static com.android.launcher3.util.DisplayController.CHANGE_NAVIGATION_MODE; import static com.android.launcher3.util.DisplayController.NavigationMode.TWO_BUTTONS; @@ -229,6 +232,28 @@ public abstract class BaseQuickstepLauncher extends Launcher { public void onScrollChanged(float progress) { super.onScrollChanged(progress); mDepthController.onOverlayScrollChanged(progress); + onTaskbarInAppDisplayProgressUpdate(progress, MINUS_ONE_PAGE_PROGRESS_INDEX); + } + + @Override + public void onAllAppsTransition(float progress) { + super.onAllAppsTransition(progress); + onTaskbarInAppDisplayProgressUpdate(progress, ALL_APPS_PAGE_PROGRESS_INDEX); + } + + @Override + public void onWidgetsTransition(float progress) { + super.onWidgetsTransition(progress); + onTaskbarInAppDisplayProgressUpdate(progress, WIDGETS_PAGE_PROGRESS_INDEX); + } + + private void onTaskbarInAppDisplayProgressUpdate(float progress, int flag) { + if (mTaskbarManager == null + || mTaskbarManager.getCurrentActivityContext() == null + || mTaskbarUIController == null) { + return; + } + mTaskbarUIController.onTaskbarInAppDisplayProgressUpdate(progress, flag); } @Override diff --git a/quickstep/src/com/android/launcher3/taskbar/DesktopTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/DesktopTaskbarUIController.java index cf562482ed..e2359c0d5e 100644 --- a/quickstep/src/com/android/launcher3/taskbar/DesktopTaskbarUIController.java +++ b/quickstep/src/com/android/launcher3/taskbar/DesktopTaskbarUIController.java @@ -39,4 +39,10 @@ public class DesktopTaskbarUIController extends TaskbarUIController { protected void onDestroy() { mLauncher.getHotseat().setIconsAlpha(1f); } + + @Override + /** Disable taskbar stashing in desktop environment. */ + public boolean supportsVisualStashing() { + return false; + } } diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java index 11dbe45207..a3e8b5ccfd 100644 --- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java +++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java @@ -22,6 +22,7 @@ import android.animation.Animator; import android.annotation.ColorInt; import android.os.RemoteException; import android.util.Log; +import android.util.SparseArray; import android.view.MotionEvent; import android.view.TaskTransitionSpec; import android.view.WindowManagerGlobal; @@ -55,6 +56,13 @@ public class LauncherTaskbarUIController extends TaskbarUIController { private static final String TAG = "TaskbarUIController"; + public static final int MINUS_ONE_PAGE_PROGRESS_INDEX = 0; + public static final int ALL_APPS_PAGE_PROGRESS_INDEX = 1; + public static final int WIDGETS_PAGE_PROGRESS_INDEX = 2; + public static final int SYSUI_SURFACE_PROGRESS_INDEX = 3; + + private final SparseArray mTaskbarInAppDisplayProgress = new SparseArray<>(4); + private final BaseQuickstepLauncher mLauncher; private final DeviceProfile.OnDeviceProfileChangeListener mOnDeviceProfileChangeListener = @@ -92,10 +100,6 @@ public class LauncherTaskbarUIController extends TaskbarUIController { mLauncher.addOnDeviceProfileChangeListener(mOnDeviceProfileChangeListener); } - public boolean supportsVisualStashing() { - return mControllers.taskbarStashController.supportsVisualStashing(); - } - @Override protected void onDestroy() { super.onDestroy(); @@ -271,6 +275,53 @@ public class LauncherTaskbarUIController extends TaskbarUIController { forceHideBackground(inProgress); } + /** + * Animates Taskbar elements during a transition to a Launcher state that should use in-app + * layouts. + * + * @param progress [0, 1] + * 0 => use home layout + * 1 => use in-app layout + */ + public void onTaskbarInAppDisplayProgressUpdate(float progress, int progressIndex) { + if (mControllers == null) { + // This method can be called before init() is called. + return; + } + mTaskbarInAppDisplayProgress.put(progressIndex, progress); + if (!mControllers.taskbarStashController.isInApp() + && !mTaskbarLauncherStateController.isAnimatingToLauncher()) { + // Only animate the nav buttons while home and not animating home, otherwise let + // the TaskbarViewController handle it. + mControllers.navbarButtonsViewController + .getTaskbarNavButtonTranslationYForInAppDisplay() + .updateValue(mLauncher.getDeviceProfile().getTaskbarOffsetY() + * getInAppDisplayProgress()); + } + } + + /** Returns true iff any in-app display progress > 0. */ + public boolean shouldUseInAppLayout() { + return getInAppDisplayProgress() > 0; + } + + private float getInAppDisplayProgress(int index) { + if (!mTaskbarInAppDisplayProgress.contains(index)) { + mTaskbarInAppDisplayProgress.put(index, 0f); + } + return mTaskbarInAppDisplayProgress.get(index); + } + + private float getInAppDisplayProgress() { + return Stream.of( + getInAppDisplayProgress(MINUS_ONE_PAGE_PROGRESS_INDEX), + getInAppDisplayProgress(ALL_APPS_PAGE_PROGRESS_INDEX), + getInAppDisplayProgress(WIDGETS_PAGE_PROGRESS_INDEX), + getInAppDisplayProgress(SYSUI_SURFACE_PROGRESS_INDEX)) + .max(Float::compareTo) + .get(); + } + @Override public void dumpLogs(String prefix, PrintWriter pw) { super.dumpLogs(prefix, pw); @@ -280,6 +331,28 @@ public class LauncherTaskbarUIController extends TaskbarUIController { prefix, mTaskbarOverrideBackgroundAlpha.value)); + pw.println(String.format("%s\tTaskbar in-app display progress:", prefix)); + if (mControllers == null) { + pw.println(String.format("%s\t\tMissing mControllers", prefix)); + } else { + pw.println(String.format( + "%s\t\tprogress at MINUS_ONE_PAGE_PROGRESS_INDEX=%.2f", + prefix, + getInAppDisplayProgress(MINUS_ONE_PAGE_PROGRESS_INDEX))); + pw.println(String.format( + "%s\t\tprogress at ALL_APPS_PAGE_PROGRESS_INDEX=%.2f", + prefix, + getInAppDisplayProgress(ALL_APPS_PAGE_PROGRESS_INDEX))); + pw.println(String.format( + "%s\t\tprogress at WIDGETS_PAGE_PROGRESS_INDEX=%.2f", + prefix, + getInAppDisplayProgress(WIDGETS_PAGE_PROGRESS_INDEX))); + pw.println(String.format( + "%s\t\tprogress at SYSUI_SURFACE_PROGRESS_INDEX=%.2f", + prefix, + getInAppDisplayProgress(SYSUI_SURFACE_PROGRESS_INDEX))); + } + mTaskbarLauncherStateController.dumpLogs(prefix + "\t", pw); } } diff --git a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java index f65b907668..349dd0a8f6 100644 --- a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java +++ b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java @@ -16,6 +16,7 @@ package com.android.launcher3.taskbar; import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X; +import static com.android.launcher3.taskbar.LauncherTaskbarUIController.SYSUI_SURFACE_PROGRESS_INDEX; import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_A11Y; import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_BACK; import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_HOME; @@ -126,11 +127,13 @@ public class NavbarButtonsViewController implements TaskbarControllers.LoggableT private final AnimatedFloat mTaskbarNavButtonTranslationY = new AnimatedFloat( this::updateNavButtonTranslationY); + private final AnimatedFloat mTaskbarNavButtonTranslationYForInAppDisplay = new AnimatedFloat( + this::updateNavButtonTranslationY); private final AnimatedFloat mTaskbarNavButtonTranslationYForIme = new AnimatedFloat( this::updateNavButtonTranslationY); - // Only applies to mTaskbarNavButtonTranslationY - private final AnimatedFloat mNavButtonTranslationYMultiplier = new AnimatedFloat( - this::updateNavButtonTranslationY); + // Used for System UI state updates that should translate the nav button for in-app display. + private final AnimatedFloat mNavButtonInAppDisplayProgressForSysui = new AnimatedFloat( + this::updateNavButtonInAppDisplayProgressForSysui); private final AnimatedFloat mTaskbarNavButtonDarkIntensity = new AnimatedFloat( this::updateNavButtonDarkIntensity); private final AnimatedFloat mNavButtonDarkIntensityMultiplier = new AnimatedFloat( @@ -173,7 +176,6 @@ public class NavbarButtonsViewController implements TaskbarControllers.LoggableT public void init(TaskbarControllers controllers) { mControllers = controllers; mNavButtonsView.getLayoutParams().height = mContext.getDeviceProfile().taskbarSize; - mNavButtonTranslationYMultiplier.value = 1; boolean isThreeButtonNav = mContext.isThreeButtonNav(); mIsImeRenderingNavButtons = @@ -205,9 +207,9 @@ public class NavbarButtonsViewController implements TaskbarControllers.LoggableT // Make sure to remove nav bar buttons translation when notification shade is expanded or // IME is showing (add separate translation for IME). int flagsToRemoveTranslation = FLAG_NOTIFICATION_SHADE_EXPANDED | FLAG_IME_VISIBLE; - mPropertyHolders.add(new StatePropertyHolder(mNavButtonTranslationYMultiplier, + mPropertyHolders.add(new StatePropertyHolder(mNavButtonInAppDisplayProgressForSysui, flags -> (flags & flagsToRemoveTranslation) != 0, AnimatedFloat.VALUE, - 0, 1)); + 1, 0)); // Center nav buttons in new height for IME. float transForIme = (mContext.getDeviceProfile().taskbarSize - mControllers.taskbarInsetsController.getTaskbarHeightForIme()) / 2f; @@ -526,6 +528,11 @@ public class NavbarButtonsViewController implements TaskbarControllers.LoggableT return mTaskbarNavButtonTranslationY; } + /** Use to set the translationY for the all nav+contextual buttons when in Launcher */ + public AnimatedFloat getTaskbarNavButtonTranslationYForInAppDisplay() { + return mTaskbarNavButtonTranslationYForInAppDisplay; + } + /** Use to set the dark intensity for the all nav+contextual buttons */ public AnimatedFloat getTaskbarNavButtonDarkIntensity() { return mTaskbarNavButtonDarkIntensity; @@ -554,11 +561,26 @@ public class NavbarButtonsViewController implements TaskbarControllers.LoggableT } } + private void updateNavButtonInAppDisplayProgressForSysui() { + TaskbarUIController uiController = mControllers.uiController; + if (uiController instanceof LauncherTaskbarUIController) { + ((LauncherTaskbarUIController) uiController).onTaskbarInAppDisplayProgressUpdate( + mNavButtonInAppDisplayProgressForSysui.value, SYSUI_SURFACE_PROGRESS_INDEX); + } + } + private void updateNavButtonTranslationY() { - float normalTranslationY = mTaskbarNavButtonTranslationY.value - * mNavButtonTranslationYMultiplier.value; - float otherTranslationY = mTaskbarNavButtonTranslationYForIme.value; - mNavButtonsView.setTranslationY(normalTranslationY + otherTranslationY); + final float normalTranslationY = mTaskbarNavButtonTranslationY.value; + final float imeAdjustmentTranslationY = mTaskbarNavButtonTranslationYForIme.value; + TaskbarUIController uiController = mControllers.uiController; + final float inAppDisplayAdjustmentTranslationY = + (uiController instanceof LauncherTaskbarUIController + && ((LauncherTaskbarUIController) uiController).shouldUseInAppLayout()) + ? mTaskbarNavButtonTranslationYForInAppDisplay.value : 0; + + mNavButtonsView.setTranslationY(normalTranslationY + + imeAdjustmentTranslationY + + inAppDisplayAdjustmentTranslationY); } private void updateNavButtonDarkIntensity() { diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java index b349637c6b..2f322199f3 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java @@ -199,7 +199,7 @@ public class TaskbarActivityContext extends BaseTaskbarContext { new TaskbarInsetsController(this)); } - public void init(TaskbarSharedState sharedState) { + public void init(@NonNull TaskbarSharedState sharedState) { mLastRequestedNonFullscreenHeight = getDefaultTaskbarWindowHeight(); mWindowLayoutParams = createDefaultWindowLayoutParams(); diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java index e4c96b2faa..449e0a7311 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java @@ -61,6 +61,8 @@ public class TaskbarControllers { private boolean mAreAllControllersInitialized; private final List mPostInitCallbacks = new ArrayList<>(); + @Nullable private TaskbarSharedState mSharedState = null; + public TaskbarControllers(TaskbarActivityContext taskbarActivityContext, TaskbarDragController taskbarDragController, TaskbarNavButtonController navButtonController, @@ -104,8 +106,9 @@ public class TaskbarControllers { * TaskbarControllers instance, but should be careful to only access things that were created * in constructors for now, as some controllers may still be waiting for init(). */ - public void init(TaskbarSharedState sharedState) { + public void init(@NonNull TaskbarSharedState sharedState) { mAreAllControllersInitialized = false; + mSharedState = sharedState; taskbarDragController.init(this); navbarButtonsViewController.init(this); @@ -116,11 +119,11 @@ public class TaskbarControllers { taskbarUnfoldAnimationController.init(this); taskbarKeyguardController.init(navbarButtonsViewController); stashedHandleViewController.init(this); - taskbarStashController.init(this, sharedState); + taskbarStashController.init(this, sharedState.setupUIVisible); taskbarEduController.init(this); taskbarPopupController.init(this); taskbarForceVisibleImmersiveController.init(this); - taskbarAllAppsController.init(this, sharedState); + taskbarAllAppsController.init(this, sharedState.allAppsVisible); navButtonController.init(this); taskbarInsetsController.init(this); @@ -139,6 +142,12 @@ public class TaskbarControllers { mPostInitCallbacks.clear(); } + @Nullable + public TaskbarSharedState getSharedState() { + // This should only be null if called before init() and after destroy(). + return mSharedState; + } + public void onConfigurationChanged(@Config int configChanges) { navbarButtonsViewController.onConfigurationChanged(configChanges); } @@ -147,6 +156,8 @@ public class TaskbarControllers { * Cleans up all controllers. */ public void onDestroy() { + mSharedState = null; + navbarButtonsViewController.onDestroy(); uiController.onDestroy(); rotationButtonController.onDestroy(); diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java index e02a9d77c1..2e37170952 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java @@ -194,6 +194,9 @@ public class TaskbarManager { * Sets a {@link StatefulActivity} to act as taskbar callback */ public void setActivity(@NonNull StatefulActivity activity) { + if (mActivity == activity) { + return; + } mActivity = activity; mUnfoldProgressProvider.setSourceProvider(getUnfoldTransitionProgressProviderForActivity( activity)); diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarSharedState.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarSharedState.java index a5c55b0027..87b3789740 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarSharedState.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarSharedState.java @@ -25,5 +25,4 @@ public class TaskbarSharedState { public boolean setupUIVisible = false; public boolean allAppsVisible = false; - } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java index c92feed46f..c07ba2d327 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java @@ -167,7 +167,7 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba mStashedHeight = mActivity.getDeviceProfile().stashedTaskbarSize; } - public void init(TaskbarControllers controllers, TaskbarSharedState sharedState) { + public void init(TaskbarControllers controllers, boolean setupUIVisible) { mControllers = controllers; TaskbarDragLayerController dragLayerController = controllers.taskbarDragLayerController; @@ -188,7 +188,7 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba boolean isManuallyStashedInApp = supportsManualStashing() && mPrefs.getBoolean(SHARED_PREFS_STASHED_KEY, DEFAULT_STASHED_PREF); - boolean isInSetup = !mActivity.isUserSetupComplete() || sharedState.setupUIVisible; + boolean isInSetup = !mActivity.isUserSetupComplete() || setupUIVisible; updateStateForFlag(FLAG_STASHED_IN_APP_MANUAL, isManuallyStashedInApp); updateStateForFlag(FLAG_STASHED_IN_APP_SETUP, isInSetup); updateStateForFlag(FLAG_IN_SETUP, isInSetup); @@ -202,7 +202,7 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba * state. */ public boolean supportsVisualStashing() { - return !mActivity.isThreeButtonNav(); + return mControllers.uiController.supportsVisualStashing(); } /** diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java index 6c2d179510..fcc34c6d99 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java @@ -49,6 +49,11 @@ public class TaskbarUIController { return true; } + public boolean supportsVisualStashing() { + if (mControllers == null) return false; + return !mControllers.taskbarActivityContext.isThreeButtonNav(); + } + protected void onStashedInAppChanged() { } public Stream getAppIconsForEdu() { diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java index 6967cc5969..9b6cc66f03 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java @@ -73,6 +73,7 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar private final AnimatedFloat mTaskbarIconTranslationYForStash = new AnimatedFloat( this::updateTranslationY); private AnimatedFloat mTaskbarNavButtonTranslationY; + private AnimatedFloat mTaskbarNavButtonTranslationYForInAppDisplay; private final AnimatedFloat mThemeIconsBackground = new AnimatedFloat( this::updateIconsBackground); @@ -112,6 +113,8 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar } mTaskbarNavButtonTranslationY = controllers.navbarButtonsViewController.getTaskbarNavButtonTranslationY(); + mTaskbarNavButtonTranslationYForInAppDisplay = controllers.navbarButtonsViewController + .getTaskbarNavButtonTranslationYForInAppDisplay(); } public void onDestroy() { @@ -242,6 +245,7 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar int offsetY = launcherDp.getTaskbarOffsetY(); setter.setFloat(mTaskbarIconTranslationYForHome, VALUE, -offsetY, LINEAR); setter.setFloat(mTaskbarNavButtonTranslationY, VALUE, -offsetY, LINEAR); + setter.setFloat(mTaskbarNavButtonTranslationYForInAppDisplay, VALUE, offsetY, LINEAR); if (Utilities.isDarkTheme(mTaskbarView.getContext())) { setter.addFloat(mThemeIconsBackground, VALUE, 0f, 1f, LINEAR); diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java index 9fca8ebf8f..eaf93843ac 100644 --- a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java +++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java @@ -38,7 +38,6 @@ import com.android.launcher3.model.data.AppInfo; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.taskbar.TaskbarActivityContext; import com.android.launcher3.taskbar.TaskbarControllers; -import com.android.launcher3.taskbar.TaskbarSharedState; import com.android.systemui.shared.system.TaskStackChangeListener; import com.android.systemui.shared.system.TaskStackChangeListeners; @@ -72,7 +71,6 @@ public final class TaskbarAllAppsController implements OnDeviceProfileChangeList }; private TaskbarControllers mControllers; - private TaskbarSharedState mSharedState; /** Window context for all apps if it is open. */ private @Nullable TaskbarAllAppsContext mAllAppsContext; @@ -88,18 +86,17 @@ public final class TaskbarAllAppsController implements OnDeviceProfileChangeList } /** Initialize the controller. */ - public void init(TaskbarControllers controllers, TaskbarSharedState sharedState) { + public void init(TaskbarControllers controllers, boolean allAppsVisible) { if (!FeatureFlags.ENABLE_ALL_APPS_IN_TASKBAR.get()) { return; } mControllers = controllers; - mSharedState = sharedState; /* * Recreate All Apps if it was open in the previous Taskbar instance (e.g. the configuration * changed). */ - if (mSharedState.allAppsVisible) { + if (allAppsVisible) { show(false); } } @@ -141,7 +138,9 @@ public final class TaskbarAllAppsController implements OnDeviceProfileChangeList return; } mProxyView.show(); - mSharedState.allAppsVisible = true; + // mControllers and getSharedState should never be null here. Do not handle null-pointer + // to catch invalid states. + mControllers.getSharedState().allAppsVisible = true; mAllAppsContext = new TaskbarAllAppsContext(mTaskbarContext, this, @@ -176,7 +175,9 @@ public final class TaskbarAllAppsController implements OnDeviceProfileChangeList return; } mProxyView.close(false); - mSharedState.allAppsVisible = false; + // mControllers and getSharedState should never be null here. Do not handle null-pointer + // to catch invalid states. + mControllers.getSharedState().allAppsVisible = false; onDestroy(); } diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 4b42ecbae0..1c62ded7ab 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -3168,6 +3168,24 @@ public class Launcher extends StatefulActivity return new DragOptions(); } + /** + * Animates Launcher elements during a transition to the All Apps page. + * + * @param progress Transition progress from 0 to 1; where 0 => home and 1 => all apps. + */ + public void onAllAppsTransition(float progress) { + // No-Op + } + + /** + * Animates Launcher elements during a transition to the Widgets pages. + * + * @param progress Transition progress from 0 to 1; where 0 => home and 1 => widgets. + */ + public void onWidgetsTransition(float progress) { + // No-Op + } + private static class NonConfigInstance { public Configuration config; public Bitmap snapshot; diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java index 637a4189b8..bf34df11fc 100644 --- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java +++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java @@ -190,6 +190,7 @@ public class AllAppsTransitionController public void setProgress(float progress) { mProgress = progress; getAppsViewProgressTranslationY().set(mAppsView, mProgress * mShiftRange); + mLauncher.onAllAppsTransition(1 - progress); } public float getProgress() { diff --git a/src/com/android/launcher3/widget/BaseWidgetSheet.java b/src/com/android/launcher3/widget/BaseWidgetSheet.java index b12574f391..c7bb61207c 100644 --- a/src/com/android/launcher3/widget/BaseWidgetSheet.java +++ b/src/com/android/launcher3/widget/BaseWidgetSheet.java @@ -44,6 +44,7 @@ import com.android.launcher3.touch.ItemLongClickListener; import com.android.launcher3.util.SystemUiController; import com.android.launcher3.util.Themes; import com.android.launcher3.views.AbstractSlideInView; +import com.android.launcher3.views.ActivityContext; import com.android.launcher3.views.ArrowTipView; /** @@ -306,4 +307,11 @@ public abstract class BaseWidgetSheet extends AbstractSlideInView return mActivityContext.getSharedPrefs().getBoolean(KEY_WIDGETS_EDUCATION_TIP_SEEN, false) || Utilities.IS_RUNNING_IN_TEST_HARNESS; } + + @Override + protected void setTranslationShift(float translationShift) { + super.setTranslationShift(translationShift); + Launcher launcher = ActivityContext.lookupContext(getContext()); + launcher.onWidgetsTransition(1 - translationShift); + } } From 811e76353aada3b8271832e20852f0243024e0eb Mon Sep 17 00:00:00 2001 From: Justin Weir Date: Mon, 2 May 2022 15:28:44 -0400 Subject: [PATCH 6/9] Ensure log buffers are dumped to file on uncaught exceptions Update PluginManagerWrapper according to changes in ag/17915248 Bug: 213884413 Test: manually verified, added tests, and ran atest Change-Id: If829fc33769819624530f766178689ecf0374926 --- .../uioverrides/plugins/PluginManagerWrapper.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/quickstep/src/com/android/launcher3/uioverrides/plugins/PluginManagerWrapper.java b/quickstep/src/com/android/launcher3/uioverrides/plugins/PluginManagerWrapper.java index df0ac7ce22..fe0bca6646 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/plugins/PluginManagerWrapper.java +++ b/quickstep/src/com/android/launcher3/uioverrides/plugins/PluginManagerWrapper.java @@ -33,12 +33,12 @@ import com.android.systemui.shared.plugins.PluginInstance; import com.android.systemui.shared.plugins.PluginManager; import com.android.systemui.shared.plugins.PluginManagerImpl; import com.android.systemui.shared.plugins.PluginPrefs; +import com.android.systemui.shared.system.UncaughtExceptionPreHandlerManager; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.Optional; import java.util.Set; public class PluginManagerWrapper { @@ -48,6 +48,9 @@ public class PluginManagerWrapper { public static final String PLUGIN_CHANGED = PluginManager.PLUGIN_CHANGED; + private static final UncaughtExceptionPreHandlerManager UNCAUGHT_EXCEPTION_PRE_HANDLER_MANAGER = + new UncaughtExceptionPreHandlerManager(); + private final Context mContext; private final PluginManager mPluginManager; private final PluginEnablerImpl mPluginEnabler; @@ -67,7 +70,7 @@ public class PluginManagerWrapper { mPluginManager = new PluginManagerImpl(c, instanceManagerFactory, Utilities.IS_DEBUG_DEVICE, - Optional.ofNullable(Thread.getDefaultUncaughtExceptionHandler()), mPluginEnabler, + UNCAUGHT_EXCEPTION_PRE_HANDLER_MANAGER, mPluginEnabler, new PluginPrefs(c), privilegedPlugins); } From 7bf873063465a5ed1c20d194a6db7f1ade13b293 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Mon, 2 May 2022 13:16:57 -0700 Subject: [PATCH 7/9] Fixing wrong window insets estimation Launcher was estimating the landscape insets incorrectly causing the UI to get reloaded if device is rotated. This also caused widgets to be refetched as a result of grid size change Bug: 218067434 Test: Verified locally that the window bounds do not change Change-Id: Ia7228296c78ea3056f4859e43696d4bfd9522d3c --- src/com/android/launcher3/ResourceUtils.java | 4 ++ .../util/window/WindowManagerProxy.java | 42 ++++++++++++++----- .../TestWindowManagerProxy.java | 9 +++- 3 files changed, 43 insertions(+), 12 deletions(-) diff --git a/src/com/android/launcher3/ResourceUtils.java b/src/com/android/launcher3/ResourceUtils.java index 1c36db1048..f709acabed 100644 --- a/src/com/android/launcher3/ResourceUtils.java +++ b/src/com/android/launcher3/ResourceUtils.java @@ -31,6 +31,10 @@ public class ResourceUtils { public static final String NAVBAR_HEIGHT = "navigation_bar_height"; public static final String NAVBAR_HEIGHT_LANDSCAPE = "navigation_bar_height_landscape"; + public static final String STATUS_BAR_HEIGHT = "status_bar_height"; + public static final String STATUS_BAR_HEIGHT_LANDSCAPE = "status_bar_height_landscape"; + public static final String STATUS_BAR_HEIGHT_PORTRAIT = "status_bar_height_portrait"; + public static int getNavbarSize(String resName, Resources res) { return getDimenByName(resName, res, DEFAULT_NAVBAR_VALUE); } diff --git a/src/com/android/launcher3/util/window/WindowManagerProxy.java b/src/com/android/launcher3/util/window/WindowManagerProxy.java index 61b7fa106d..92f718ef45 100644 --- a/src/com/android/launcher3/util/window/WindowManagerProxy.java +++ b/src/com/android/launcher3/util/window/WindowManagerProxy.java @@ -22,6 +22,9 @@ import static com.android.launcher3.ResourceUtils.INVALID_RESOURCE_HANDLE; import static com.android.launcher3.ResourceUtils.NAVBAR_HEIGHT; import static com.android.launcher3.ResourceUtils.NAVBAR_HEIGHT_LANDSCAPE; import static com.android.launcher3.ResourceUtils.NAVBAR_LANDSCAPE_LEFT_RIGHT_SIZE; +import static com.android.launcher3.ResourceUtils.STATUS_BAR_HEIGHT; +import static com.android.launcher3.ResourceUtils.STATUS_BAR_HEIGHT_LANDSCAPE; +import static com.android.launcher3.ResourceUtils.STATUS_BAR_HEIGHT_PORTRAIT; import static com.android.launcher3.Utilities.dpiFromPx; import static com.android.launcher3.util.MainThreadInitializedObject.forOverride; import static com.android.launcher3.util.RotationUtils.deltaRotation; @@ -152,20 +155,26 @@ public class WindowManagerProxy implements ResourceBasedOverride { boolean isTablet = config.smallestScreenWidthDp > MIN_TABLET_WIDTH; boolean isGesture = isGestureNav(context); + boolean isPortrait = config.screenHeightDp > config.screenWidthDp; int bottomNav = isTablet ? 0 - : (config.screenHeightDp > config.screenWidthDp - ? getDimenByName(NAVBAR_HEIGHT, systemRes) + : (isPortrait + ? getDimenByName(systemRes, NAVBAR_HEIGHT) : (isGesture - ? getDimenByName(NAVBAR_HEIGHT_LANDSCAPE, systemRes) + ? getDimenByName(systemRes, NAVBAR_HEIGHT_LANDSCAPE) : 0)); Insets newNavInsets = Insets.of(navInsets.left, navInsets.top, navInsets.right, bottomNav); insetsBuilder.setInsets(WindowInsets.Type.navigationBars(), newNavInsets); insetsBuilder.setInsetsIgnoringVisibility(WindowInsets.Type.navigationBars(), newNavInsets); Insets statusBarInsets = oldInsets.getInsets(WindowInsets.Type.statusBars()); - int statusBarHeight = getDimenByName("status_bar_height", systemRes); + + + int statusBarHeight = getDimenByName(systemRes, + (isPortrait) ? STATUS_BAR_HEIGHT_PORTRAIT : STATUS_BAR_HEIGHT_LANDSCAPE, + STATUS_BAR_HEIGHT); + Insets newStatusBarInsets = Insets.of( statusBarInsets.left, Math.max(statusBarInsets.top, statusBarHeight), @@ -221,23 +230,26 @@ public class WindowManagerProxy implements ResourceBasedOverride { boolean isTabletOrGesture = isTablet || (Utilities.ATLEAST_R && isGestureNav(context)); - int statusBarHeight = getDimenByName("status_bar_height", systemRes); + int statusBarHeightPortrait = getDimenByName(systemRes, + STATUS_BAR_HEIGHT_PORTRAIT, STATUS_BAR_HEIGHT); + int statusBarHeightLandscape = getDimenByName(systemRes, + STATUS_BAR_HEIGHT_LANDSCAPE, STATUS_BAR_HEIGHT); int navBarHeightPortrait, navBarHeightLandscape, navbarWidthLandscape; navBarHeightPortrait = isTablet ? (mTaskbarDrawnInProcess ? 0 : systemRes.getDimensionPixelSize(R.dimen.taskbar_size)) - : getDimenByName(NAVBAR_HEIGHT, systemRes); + : getDimenByName(systemRes, NAVBAR_HEIGHT); navBarHeightLandscape = isTablet ? (mTaskbarDrawnInProcess ? 0 : systemRes.getDimensionPixelSize(R.dimen.taskbar_size)) : (isTabletOrGesture - ? getDimenByName(NAVBAR_HEIGHT_LANDSCAPE, systemRes) : 0); + ? getDimenByName(systemRes, NAVBAR_HEIGHT_LANDSCAPE) : 0); navbarWidthLandscape = isTabletOrGesture ? 0 - : getDimenByName(NAVBAR_LANDSCAPE_LEFT_RIGHT_SIZE, systemRes); + : getDimenByName(systemRes, NAVBAR_LANDSCAPE_LEFT_RIGHT_SIZE); WindowBounds[] result = new WindowBounds[4]; Point tempSize = new Point(); @@ -247,13 +259,15 @@ public class WindowManagerProxy implements ResourceBasedOverride { rotateSize(tempSize, rotationChange); Rect bounds = new Rect(0, 0, tempSize.x, tempSize.y); - int navBarHeight, navbarWidth; + int navBarHeight, navbarWidth, statusBarHeight; if (tempSize.y > tempSize.x) { navBarHeight = navBarHeightPortrait; navbarWidth = 0; + statusBarHeight = statusBarHeightPortrait; } else { navBarHeight = navBarHeightLandscape; navbarWidth = navbarWidthLandscape; + statusBarHeight = statusBarHeightLandscape; } Rect insets = new Rect(safeCutout); @@ -276,10 +290,18 @@ public class WindowManagerProxy implements ResourceBasedOverride { /** * Wrapper around the utility method for easier emulation */ - protected int getDimenByName(String resName, Resources res) { + protected int getDimenByName(Resources res, String resName) { return ResourceUtils.getDimenByName(resName, res, 0); } + /** + * Wrapper around the utility method for easier emulation + */ + protected int getDimenByName(Resources res, String resName, String fallback) { + int dimen = ResourceUtils.getDimenByName(resName, res, -1); + return dimen > -1 ? dimen : getDimenByName(res, fallback); + } + protected boolean isGestureNav(Context context) { return ResourceUtils.getIntegerByName("config_navBarInteractionMode", context.getResources(), INVALID_RESOURCE_HANDLE) == 2; diff --git a/tests/src/com/android/launcher3/deviceemulator/TestWindowManagerProxy.java b/tests/src/com/android/launcher3/deviceemulator/TestWindowManagerProxy.java index ca2f81e377..cbea688a9a 100644 --- a/tests/src/com/android/launcher3/deviceemulator/TestWindowManagerProxy.java +++ b/tests/src/com/android/launcher3/deviceemulator/TestWindowManagerProxy.java @@ -43,9 +43,14 @@ public class TestWindowManagerProxy extends WindowManagerProxy { } @Override - protected int getDimenByName(String resName, Resources res) { + protected int getDimenByName(Resources res, String resName) { Integer mock = mDevice.resourceOverrides.get(resName); - return mock != null ? mock : super.getDimenByName(resName, res); + return mock != null ? mock : super.getDimenByName(res, resName); + } + + @Override + protected int getDimenByName(Resources res, String resName, String fallback) { + return getDimenByName(res, resName); } @Override From e7b977ddd515ed6e6aa80739e47197505f1ab668 Mon Sep 17 00:00:00 2001 From: Jon Miranda Date: Mon, 2 May 2022 15:31:21 -0700 Subject: [PATCH 8/9] Fix all app button taskbar animation in LTR and RTL. Bug: 225154998 Test: Open app, view taskbar, go back to home Repeat for both RTL, LTR Change-Id: Ifdc8074bef6e5f5a447a1f4110ccb387b18a7ea9 --- .../android/launcher3/taskbar/TaskbarViewController.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java index 6416720962..ae9f655d5f 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java @@ -258,12 +258,14 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar View child = mTaskbarView.getChildAt(i); int positionInHotseat = -1; - if (FeatureFlags.ENABLE_ALL_APPS_IN_TASKBAR.get() && i == count - 1) { + boolean isRtl = Utilities.isRtl(child.getResources()); + if (FeatureFlags.ENABLE_ALL_APPS_IN_TASKBAR.get() + && ((isRtl && i == 0) || (!isRtl && i == count - 1))) { // Note that there is no All Apps button in the hotseat, this position is only used // as its convenient for animation purposes. - positionInHotseat = Utilities.isRtl(child.getResources()) + positionInHotseat = isRtl ? -1 - : mActivity.getDeviceProfile().inv.numShownHotseatIcons; + : mActivity.getDeviceProfile().numShownHotseatIcons; setter.setViewAlpha(child, 0, LINEAR); } else if (child.getTag() instanceof ItemInfo) { From 32084d49d3e278b3e92c0c12e925ce2a53958ac3 Mon Sep 17 00:00:00 2001 From: Sunny Goyal Date: Mon, 2 May 2022 10:00:07 -0700 Subject: [PATCH 9/9] Replacing ItemInfoMatcher with predicate This removed unnecessary componentName lookups when it is not required. Many checks just rely on IDs and userHandle Bug: 231153610 Test: Presubmit Change-Id: Ief93954abc5861062a9f55dc2ef181d3de106c62 --- .../HotseatPredictionController.java | 6 +- .../taskbar/TaskbarDragController.java | 5 +- .../taskbar/TaskbarModelCallbacks.java | 7 +- .../launcher3/taskbar/TaskbarView.java | 9 ++- .../taskbar/TaskbarViewController.java | 5 +- .../uioverrides/QuickstepLauncher.java | 4 +- src/com/android/launcher3/Launcher.java | 15 ++-- src/com/android/launcher3/Workspace.java | 9 +-- .../allapps/AlphabeticalAppsList.java | 48 +++++------- .../allapps/BaseAllAppsContainerView.java | 19 ++--- .../launcher3/allapps/WorkProfileManager.java | 8 +- .../launcher3/dragndrop/DragController.java | 12 +-- .../android/launcher3/model/AllAppsList.java | 7 +- .../launcher3/model/BaseModelUpdateTask.java | 4 +- .../android/launcher3/model/BgDataModel.java | 4 +- .../android/launcher3/model/ModelWriter.java | 6 +- .../launcher3/model/PackageUpdatedTask.java | 7 +- .../launcher3/util/ItemInfoMatcher.java | 78 +++++++------------ 18 files changed, 106 insertions(+), 147 deletions(-) diff --git a/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java b/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java index 62a8da787d..05b81671c3 100644 --- a/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java +++ b/quickstep/src/com/android/launcher3/hybridhotseat/HotseatPredictionController.java @@ -55,13 +55,13 @@ import com.android.launcher3.popup.SystemShortcut; import com.android.launcher3.touch.ItemLongClickListener; import com.android.launcher3.uioverrides.PredictedAppIcon; import com.android.launcher3.uioverrides.QuickstepLauncher; -import com.android.launcher3.util.ItemInfoMatcher; import com.android.launcher3.util.OnboardingPrefs; import com.android.launcher3.views.Snackbar; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.function.Predicate; import java.util.stream.Collectors; /** @@ -480,8 +480,8 @@ public class HotseatPredictionController implements DragController.DragListener, * * @param matcher filter matching items that have been removed */ - public void onModelItemsRemoved(ItemInfoMatcher matcher) { - if (mPredictedItems.removeIf(matcher::matchesInfo)) { + public void onModelItemsRemoved(Predicate matcher) { + if (mPredictedItems.removeIf(matcher)) { fillGapsWithPrediction(true); } } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java index 5c10565dc1..c522888fce 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java @@ -73,6 +73,7 @@ import com.android.systemui.shared.recents.model.Task; import java.io.PrintWriter; import java.util.Arrays; import java.util.Collections; +import java.util.function.Predicate; /** * Handles long click on Taskbar items to start a system drag and drop operation. @@ -439,12 +440,12 @@ public class TaskbarDragController extends DragController im target = taskbarViewController.getAllAppsButtonView(); } else if (item.container >= 0) { // Since folders close when the drag starts, target the folder icon instead. - ItemInfoMatcher matcher = ItemInfoMatcher.forFolderMatch( + Predicate matcher = ItemInfoMatcher.forFolderMatch( ItemInfoMatcher.ofItemIds(IntSet.wrap(item.id))); target = taskbarViewController.getFirstIconMatch(matcher); } else if (item.itemType == ITEM_TYPE_DEEP_SHORTCUT) { // Find first icon with same package/user as the deep shortcut. - ItemInfoMatcher packageUserMatcher = ItemInfoMatcher.ofPackages( + Predicate packageUserMatcher = ItemInfoMatcher.ofPackages( Collections.singleton(item.getTargetPackage()), item.user); target = taskbarViewController.getFirstIconMatch(packageUserMatcher); } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java index 62392eea29..75881a31f2 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java @@ -36,6 +36,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.function.Predicate; /** * Launcher model Callbacks for rendering taskbar. @@ -126,16 +127,16 @@ public class TaskbarModelCallbacks implements } @Override - public void bindWorkspaceComponentsRemoved(ItemInfoMatcher matcher) { + public void bindWorkspaceComponentsRemoved(Predicate matcher) { if (handleItemsRemoved(matcher)) { commitItemsToUI(); } } - private boolean handleItemsRemoved(ItemInfoMatcher matcher) { + private boolean handleItemsRemoved(Predicate matcher) { boolean modified = false; for (int i = mHotseatItems.size() - 1; i >= 0; i--) { - if (matcher.matchesInfo(mHotseatItems.valueAt(i))) { + if (matcher.test(mHotseatItems.valueAt(i))) { modified = true; mHotseatItems.removeAt(i); } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java index 7548398be2..6f88d649fb 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java @@ -41,12 +41,13 @@ import com.android.launcher3.model.data.FolderInfo; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.uioverrides.ApiWrapper; -import com.android.launcher3.util.ItemInfoMatcher; import com.android.launcher3.util.LauncherBindableItemsContainer; import com.android.launcher3.views.ActivityContext; import com.android.launcher3.views.AllAppsButton; import com.android.launcher3.views.DoubleShadowBubbleTextView; +import java.util.function.Predicate; + /** * Hosts the Taskbar content such as Hotseat and Recent Apps. Drawn on top of other apps. */ @@ -424,8 +425,8 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar * Finds the first icon to match one of the given matchers, from highest to lowest priority. * @return The first match, or All Apps button if no match was found. */ - public View getFirstMatch(ItemInfoMatcher... matchers) { - for (ItemInfoMatcher matcher : matchers) { + public View getFirstMatch(Predicate... matchers) { + for (Predicate matcher : matchers) { for (int i = 0; i < getChildCount(); i++) { View item = getChildAt(i); if (!(item.getTag() instanceof ItemInfo)) { @@ -433,7 +434,7 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar continue; } ItemInfo info = (ItemInfo) item.getTag(); - if (matcher.matchesInfo(info)) { + if (matcher.test(info)) { return item; } } diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java index 6416720962..0cc3590641 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java @@ -47,6 +47,7 @@ import com.android.launcher3.util.MultiValueAlpha; import com.android.quickstep.AnimatedFloat; import java.io.PrintWriter; +import java.util.function.Predicate; /** * Handles properties/data collection, then passes the results to TaskbarView to render. @@ -309,8 +310,8 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar * 2) FolderIcon of the Folder containing the given icon * 3) All Apps button */ - public View getFirstIconMatch(ItemInfoMatcher matcher) { - ItemInfoMatcher folderMatcher = ItemInfoMatcher.forFolderMatch(matcher); + public View getFirstIconMatch(Predicate matcher) { + Predicate folderMatcher = ItemInfoMatcher.forFolderMatch(matcher); return mTaskbarView.getFirstMatch(matcher, folderMatcher); } diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java index 7c52e806cb..4bb43431bc 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java +++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java @@ -70,7 +70,6 @@ import com.android.launcher3.uioverrides.touchcontrollers.TransposedQuickSwitchT import com.android.launcher3.uioverrides.touchcontrollers.TwoButtonNavbarTouchController; import com.android.launcher3.util.DisplayController; import com.android.launcher3.util.DisplayController.NavigationMode; -import com.android.launcher3.util.ItemInfoMatcher; import com.android.launcher3.util.PendingRequestArgs; import com.android.launcher3.util.TouchController; import com.android.launcher3.util.UiThreadHelper; @@ -86,6 +85,7 @@ import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Objects; +import java.util.function.Predicate; import java.util.stream.Stream; public class QuickstepLauncher extends BaseQuickstepLauncher { @@ -245,7 +245,7 @@ public class QuickstepLauncher extends BaseQuickstepLauncher { } @Override - public void bindWorkspaceComponentsRemoved(ItemInfoMatcher matcher) { + public void bindWorkspaceComponentsRemoved(Predicate matcher) { super.bindWorkspaceComponentsRemoved(matcher); mHotseatPredictionController.onModelItemsRemoved(matcher); } diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 4b42ecbae0..3164db206d 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -182,7 +182,6 @@ import com.android.launcher3.util.ActivityTracker; import com.android.launcher3.util.ComponentKey; import com.android.launcher3.util.IntArray; import com.android.launcher3.util.IntSet; -import com.android.launcher3.util.ItemInfoMatcher; import com.android.launcher3.util.OnboardingPrefs; import com.android.launcher3.util.PackageManagerHelper; import com.android.launcher3.util.PackageUserKey; @@ -2739,9 +2738,9 @@ public class Launcher extends StatefulActivity */ public View getFirstMatchForAppClose(int preferredItemId, String packageName, UserHandle user, boolean supportsAllAppsState) { - final ItemInfoMatcher preferredItem = (info, cn) -> + final Predicate preferredItem = info -> info != null && info.id == preferredItemId; - final ItemInfoMatcher packageAndUserAndApp = (info, cn) -> + final Predicate packageAndUserAndApp = info -> info != null && info.itemType == ITEM_TYPE_APPLICATION && info.user.equals(user) @@ -2770,8 +2769,8 @@ public class Launcher extends StatefulActivity * @param operators List of operators, in order starting from best matching operator. */ private static View getFirstMatch(Iterable containers, - final ItemInfoMatcher... operators) { - for (ItemInfoMatcher operator : operators) { + final Predicate... operators) { + for (Predicate operator : operators) { for (ViewGroup container : containers) { View match = mapOverViewGroup(container, operator); if (match != null) { @@ -2786,11 +2785,11 @@ public class Launcher extends StatefulActivity * Returns the first view matching the operator in the given ViewGroups, or null if none. * Forward iteration matters. */ - private static View mapOverViewGroup(ViewGroup container, ItemInfoMatcher op) { + private static View mapOverViewGroup(ViewGroup container, Predicate op) { final int itemCount = container.getChildCount(); for (int itemIdx = 0; itemIdx < itemCount; itemIdx++) { View item = container.getChildAt(itemIdx); - if (op.matchesInfo((ItemInfo) item.getTag())) { + if (op.test((ItemInfo) item.getTag())) { return item; } } @@ -2887,7 +2886,7 @@ public class Launcher extends StatefulActivity * package-removal should clear all items by package name. */ @Override - public void bindWorkspaceComponentsRemoved(final ItemInfoMatcher matcher) { + public void bindWorkspaceComponentsRemoved(Predicate matcher) { mWorkspace.removeItemsByMatcher(matcher); mDragController.onAppsRemoved(matcher); PopupContainerWithArrow.dismissInvalidPopup(this); diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java index 78771ce84a..14320eb28b 100644 --- a/src/com/android/launcher3/Workspace.java +++ b/src/com/android/launcher3/Workspace.java @@ -102,7 +102,6 @@ import com.android.launcher3.util.Executors; import com.android.launcher3.util.IntArray; import com.android.launcher3.util.IntSet; import com.android.launcher3.util.IntSparseArrayMap; -import com.android.launcher3.util.ItemInfoMatcher; import com.android.launcher3.util.LauncherBindableItemsContainer; import com.android.launcher3.util.OverlayEdgeEffect; import com.android.launcher3.util.PackageUserKey; @@ -3235,7 +3234,7 @@ public class Workspace extends PagedView * as a part of an update, this is called to ensure that other widgets and application * shortcuts are not removed. */ - public void removeItemsByMatcher(final ItemInfoMatcher matcher) { + public void removeItemsByMatcher(final Predicate matcher) { for (CellLayout layout : getWorkspaceAndHotseatCellLayouts()) { ShortcutAndWidgetContainer container = layout.getShortcutsAndWidgets(); // Iterate in reverse order as we are removing items @@ -3243,7 +3242,7 @@ public class Workspace extends PagedView View child = container.getChildAt(i); ItemInfo info = (ItemInfo) child.getTag(); - if (matcher.matchesInfo(info)) { + if (matcher.test(info)) { layout.removeViewInLayout(child); if (child instanceof DropTarget) { mDragController.removeDropTarget((DropTarget) child); @@ -3251,7 +3250,7 @@ public class Workspace extends PagedView } else if (child instanceof FolderIcon) { FolderInfo folderInfo = (FolderInfo) info; List matches = folderInfo.contents.stream() - .filter(matcher::matchesInfo) + .filter(matcher) .collect(Collectors.toList()); if (!matches.isEmpty()) { folderInfo.removeAll(matches, false); @@ -3330,7 +3329,7 @@ public class Workspace extends PagedView * * @param matcher the matcher generated by the caller. */ - public void persistRemoveItemsByMatcher(ItemInfoMatcher matcher) { + public void persistRemoveItemsByMatcher(Predicate matcher) { mLauncher.getModelWriter().deleteItemsFromDatabase(matcher); removeItemsByMatcher(matcher); } diff --git a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java index 2a16210861..cdaf80a804 100644 --- a/src/com/android/launcher3/allapps/AlphabeticalAppsList.java +++ b/src/com/android/launcher3/allapps/AlphabeticalAppsList.java @@ -21,17 +21,18 @@ import android.content.Context; import com.android.launcher3.allapps.BaseAllAppsAdapter.AdapterItem; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.model.data.AppInfo; -import com.android.launcher3.util.ItemInfoMatcher; +import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.util.LabelComparator; import com.android.launcher3.views.ActivityContext; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.Locale; -import java.util.Map; import java.util.Objects; import java.util.TreeMap; +import java.util.function.Predicate; +import java.util.stream.Collectors; +import java.util.stream.Stream; /** * The alphabetically sorted list of applications. @@ -82,7 +83,7 @@ public class AlphabeticalAppsList implement private AppInfoComparator mAppNameComparator; private final int mNumAppsPerRowAllApps; private int mNumAppRowsInAdapter; - private ItemInfoMatcher mItemFilter; + private Predicate mItemFilter; public AlphabeticalAppsList(Context context, AllAppsStore appsStore, WorkAdapterProvider adapterProvider) { @@ -94,7 +95,7 @@ public class AlphabeticalAppsList implement mAllAppsStore.addUpdateListener(this); } - public void updateItemFilter(ItemInfoMatcher itemFilter) { + public void updateItemFilter(Predicate itemFilter) { this.mItemFilter = itemFilter; onAppsUpdated(); } @@ -200,13 +201,11 @@ public class AlphabeticalAppsList implement // Sort the list of apps mApps.clear(); - for (AppInfo app : mAllAppsStore.getApps()) { - if (mItemFilter == null || mItemFilter.matches(app, null) || hasFilter()) { - mApps.add(app); - } + Stream appSteam = Stream.of(mAllAppsStore.getApps()); + if (!hasFilter() && mItemFilter != null) { + appSteam = appSteam.filter(mItemFilter); } - - Collections.sort(mApps, mAppNameComparator); + appSteam = appSteam.sorted(mAppNameComparator); // As a special case for some languages (currently only Simplified Chinese), we may need to // coalesce sections @@ -215,27 +214,16 @@ public class AlphabeticalAppsList implement if (localeRequiresSectionSorting) { // Compute the section headers. We use a TreeMap with the section name comparator to // ensure that the sections are ordered when we iterate over it later - TreeMap> sectionMap = new TreeMap<>(new LabelComparator()); - for (AppInfo info : mApps) { - // Add the section to the cache - String sectionName = info.sectionName; - - // Add it to the mapping - ArrayList sectionApps = sectionMap.get(sectionName); - if (sectionApps == null) { - sectionApps = new ArrayList<>(); - sectionMap.put(sectionName, sectionApps); - } - sectionApps.add(info); - } - - // Add each of the section apps to the list in order - mApps.clear(); - for (Map.Entry> entry : sectionMap.entrySet()) { - mApps.addAll(entry.getValue()); - } + appSteam = appSteam.collect(Collectors.groupingBy( + info -> info.sectionName, + () -> new TreeMap<>(new LabelComparator()), + Collectors.toCollection(ArrayList::new))) + .values() + .stream() + .flatMap(ArrayList::stream); } + appSteam.forEachOrdered(mApps::add); // Recompose the set of adapter items from the current set of apps if (mSearchResults.isEmpty()) { updateAdapterItems(); diff --git a/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java b/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java index f913aa9093..891fe8f53c 100644 --- a/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java +++ b/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java @@ -58,7 +58,7 @@ import com.android.launcher3.Utilities; import com.android.launcher3.allapps.search.SearchAdapterProvider; import com.android.launcher3.keyboard.FocusedItemDecorator; import com.android.launcher3.model.StringCache; -import com.android.launcher3.model.data.AppInfo; +import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.util.ItemInfoMatcher; import com.android.launcher3.util.Themes; import com.android.launcher3.views.ActivityContext; @@ -69,6 +69,8 @@ import com.android.launcher3.workprofile.PersonalWorkSlidingTabStrip.OnActivePag import java.util.Arrays; import java.util.List; +import java.util.function.Predicate; +import java.util.stream.Stream; /** * Base all apps view container. @@ -91,7 +93,7 @@ public abstract class BaseAllAppsContainerView mAH; - protected final ItemInfoMatcher mPersonalMatcher = ItemInfoMatcher.ofUser( + protected final Predicate mPersonalMatcher = ItemInfoMatcher.ofUser( Process.myUserHandle()); private final SearchAdapterProvider mMainAdapterProvider; private final AllAppsStore mAllAppsStore = new AllAppsStore(); @@ -229,17 +231,10 @@ public abstract class BaseAllAppsContainerView matcher) { mAppsList.updateItemFilter(matcher); mRecyclerView = (AllAppsRecyclerView) rv; mRecyclerView.setEdgeEffectFactory(createEdgeEffectFactory()); diff --git a/src/com/android/launcher3/allapps/WorkProfileManager.java b/src/com/android/launcher3/allapps/WorkProfileManager.java index 6203cead2d..c5b02dd1f5 100644 --- a/src/com/android/launcher3/allapps/WorkProfileManager.java +++ b/src/com/android/launcher3/allapps/WorkProfileManager.java @@ -27,7 +27,6 @@ import android.os.UserHandle; import android.os.UserManager; import android.util.Log; import android.view.ViewGroup; -import android.view.WindowInsets; import androidx.annotation.IntDef; import androidx.annotation.Nullable; @@ -35,11 +34,12 @@ import androidx.annotation.RequiresApi; import com.android.launcher3.R; import com.android.launcher3.config.FeatureFlags; -import com.android.launcher3.util.ItemInfoMatcher; +import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.workprofile.PersonalWorkSlidingTabStrip; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.function.Predicate; /** * Companion class for {@link BaseAllAppsContainerView} to manage work tab and personal tab @@ -70,7 +70,7 @@ public class WorkProfileManager implements PersonalWorkSlidingTabStrip.OnActiveP private final BaseAllAppsContainerView mAllApps; private final WorkAdapterProvider mAdapterProvider; - private final ItemInfoMatcher mMatcher; + private final Predicate mMatcher; private WorkModeSwitch mWorkModeSwitch; @@ -176,7 +176,7 @@ public class WorkProfileManager implements PersonalWorkSlidingTabStrip.OnActiveP return mAdapterProvider; } - public ItemInfoMatcher getMatcher() { + public Predicate getMatcher() { return mMatcher; } diff --git a/src/com/android/launcher3/dragndrop/DragController.java b/src/com/android/launcher3/dragndrop/DragController.java index fdb27998de..35cdfef465 100644 --- a/src/com/android/launcher3/dragndrop/DragController.java +++ b/src/com/android/launcher3/dragndrop/DragController.java @@ -18,7 +18,6 @@ package com.android.launcher3.dragndrop; import static com.android.launcher3.Utilities.ATLEAST_Q; -import android.content.ComponentName; import android.graphics.Point; import android.graphics.Rect; import android.graphics.drawable.Drawable; @@ -36,12 +35,12 @@ import com.android.launcher3.logging.InstanceId; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.testing.TestProtocol; -import com.android.launcher3.util.ItemInfoMatcher; import com.android.launcher3.util.TouchController; import com.android.launcher3.views.ActivityContext; import java.util.ArrayList; import java.util.Optional; +import java.util.function.Predicate; /** * Class for initiating a drag within a view or across multiple views. @@ -275,15 +274,12 @@ public abstract class DragController protected abstract void exitDrag(); - public void onAppsRemoved(ItemInfoMatcher matcher) { + public void onAppsRemoved(Predicate matcher) { // Cancel the current drag if we are removing an app that we are dragging if (mDragObject != null) { ItemInfo dragInfo = mDragObject.dragInfo; - if (dragInfo instanceof WorkspaceItemInfo) { - ComponentName cn = dragInfo.getTargetComponent(); - if (cn != null && matcher.matches(dragInfo, cn)) { - cancelDrag(); - } + if (dragInfo instanceof WorkspaceItemInfo && matcher.test(dragInfo)) { + cancelDrag(); } } } diff --git a/src/com/android/launcher3/model/AllAppsList.java b/src/com/android/launcher3/model/AllAppsList.java index b8c9762c24..4875d83942 100644 --- a/src/com/android/launcher3/model/AllAppsList.java +++ b/src/com/android/launcher3/model/AllAppsList.java @@ -36,9 +36,9 @@ import com.android.launcher3.compat.AlphabeticIndexCompat; import com.android.launcher3.icons.IconCache; import com.android.launcher3.model.BgDataModel.Callbacks; import com.android.launcher3.model.data.AppInfo; +import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.pm.PackageInstallInfo; import com.android.launcher3.util.FlagOp; -import com.android.launcher3.util.ItemInfoMatcher; import com.android.launcher3.util.PackageManagerHelper; import com.android.launcher3.util.SafeCloseable; @@ -47,6 +47,7 @@ import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.function.Consumer; +import java.util.function.Predicate; /** @@ -257,11 +258,11 @@ public class AllAppsList { /** * Updates the disabled flags of apps matching {@param matcher} based on {@param op}. */ - public void updateDisabledFlags(ItemInfoMatcher matcher, FlagOp op) { + public void updateDisabledFlags(Predicate matcher, FlagOp op) { final List data = this.data; for (int i = data.size() - 1; i >= 0; i--) { AppInfo info = data.get(i); - if (matcher.matches(info, info.componentName)) { + if (matcher.test(info)) { info.runtimeStatusFlags = op.apply(info.runtimeStatusFlags); mDataChanged = true; } diff --git a/src/com/android/launcher3/model/BaseModelUpdateTask.java b/src/com/android/launcher3/model/BaseModelUpdateTask.java index a3a471775c..832c1dd166 100644 --- a/src/com/android/launcher3/model/BaseModelUpdateTask.java +++ b/src/com/android/launcher3/model/BaseModelUpdateTask.java @@ -27,7 +27,6 @@ import com.android.launcher3.model.data.AppInfo; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.util.ComponentKey; -import com.android.launcher3.util.ItemInfoMatcher; import com.android.launcher3.widget.model.WidgetsListBaseEntry; import java.util.ArrayList; @@ -35,6 +34,7 @@ import java.util.HashMap; import java.util.List; import java.util.Objects; import java.util.concurrent.Executor; +import java.util.function.Predicate; import java.util.stream.Collectors; /** @@ -128,7 +128,7 @@ public abstract class BaseModelUpdateTask implements ModelUpdateTask { scheduleCallbackTask(c -> c.bindAllWidgets(widgets)); } - public void deleteAndBindComponentsRemoved(final ItemInfoMatcher matcher) { + public void deleteAndBindComponentsRemoved(final Predicate matcher) { getModelWriter().deleteItemsFromDatabase(matcher); // Call the components-removed callback diff --git a/src/com/android/launcher3/model/BgDataModel.java b/src/com/android/launcher3/model/BgDataModel.java index 866d18a86b..d52537e074 100644 --- a/src/com/android/launcher3/model/BgDataModel.java +++ b/src/com/android/launcher3/model/BgDataModel.java @@ -50,7 +50,6 @@ import com.android.launcher3.util.ComponentKey; import com.android.launcher3.util.IntArray; import com.android.launcher3.util.IntSet; import com.android.launcher3.util.IntSparseArrayMap; -import com.android.launcher3.util.ItemInfoMatcher; import com.android.launcher3.util.RunnableList; import com.android.launcher3.widget.model.WidgetsListBaseEntry; @@ -66,6 +65,7 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.function.Consumer; +import java.util.function.Predicate; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -495,7 +495,7 @@ public class BgDataModel { default void bindWorkspaceItemsChanged(List updated) { } default void bindWidgetsRestored(ArrayList widgets) { } default void bindRestoreItemsChange(HashSet updates) { } - default void bindWorkspaceComponentsRemoved(ItemInfoMatcher matcher) { } + default void bindWorkspaceComponentsRemoved(Predicate matcher) { } default void bindAllWidgets(List widgets) { } default void onInitialBindComplete(IntSet boundPages, RunnableList pendingTasks) { diff --git a/src/com/android/launcher3/model/ModelWriter.java b/src/com/android/launcher3/model/ModelWriter.java index 94e06d16ce..015abe94bc 100644 --- a/src/com/android/launcher3/model/ModelWriter.java +++ b/src/com/android/launcher3/model/ModelWriter.java @@ -53,6 +53,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.function.Predicate; import java.util.function.Supplier; import java.util.stream.Collectors; import java.util.stream.StreamSupport; @@ -278,10 +279,9 @@ public class ModelWriter { /** * Removes all the items from the database matching {@param matcher}. */ - public void deleteItemsFromDatabase(ItemInfoMatcher matcher) { + public void deleteItemsFromDatabase(Predicate matcher) { deleteItemsFromDatabase(StreamSupport.stream(mBgDataModel.itemsIdMap.spliterator(), false) - .filter(matcher::matchesInfo) - .collect(Collectors.toList())); + .filter(matcher).collect(Collectors.toList())); } /** diff --git a/src/com/android/launcher3/model/PackageUpdatedTask.java b/src/com/android/launcher3/model/PackageUpdatedTask.java index d47edff223..239dd4565a 100644 --- a/src/com/android/launcher3/model/PackageUpdatedTask.java +++ b/src/com/android/launcher3/model/PackageUpdatedTask.java @@ -57,6 +57,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.function.Predicate; /** * Handles updates due to changes in package manager (app installed/updated/removed) @@ -95,7 +96,7 @@ public class PackageUpdatedTask extends BaseModelUpdateTask { final int N = packages.length; final FlagOp flagOp; final HashSet packageSet = new HashSet<>(Arrays.asList(packages)); - final ItemInfoMatcher matcher = mOp == OP_USER_AVAILABILITY_CHANGE + final Predicate matcher = mOp == OP_USER_AVAILABILITY_CHANGE ? ItemInfoMatcher.ofUser(mUser) // We want to update all packages for this user : ItemInfoMatcher.ofPackages(packageSet, mUser); final HashSet removedComponents = new HashSet<>(); @@ -206,7 +207,7 @@ public class PackageUpdatedTask extends BaseModelUpdateTask { } ComponentName cn = si.getTargetComponent(); - if (cn != null && matcher.matches(si, cn)) { + if (cn != null && matcher.test(si)) { String packageName = cn.getPackageName(); if (si.hasStatusFlag(WorkspaceItemInfo.FLAG_SUPPORTS_WEB_UI)) { @@ -336,7 +337,7 @@ public class PackageUpdatedTask extends BaseModelUpdateTask { } if (!removedPackages.isEmpty() || !removedComponents.isEmpty()) { - ItemInfoMatcher removeMatch = ItemInfoMatcher.ofPackages(removedPackages, mUser) + Predicate removeMatch = ItemInfoMatcher.ofPackages(removedPackages, mUser) .or(ItemInfoMatcher.ofComponents(removedComponents, mUser)) .and(ItemInfoMatcher.ofItemIds(forceKeepShortcuts).negate()); deleteAndBindComponentsRemoved(removeMatch); diff --git a/src/com/android/launcher3/util/ItemInfoMatcher.java b/src/com/android/launcher3/util/ItemInfoMatcher.java index 7917410b3b..b6af3140fa 100644 --- a/src/com/android/launcher3/util/ItemInfoMatcher.java +++ b/src/com/android/launcher3/util/ItemInfoMatcher.java @@ -19,6 +19,8 @@ package com.android.launcher3.util; import android.content.ComponentName; import android.os.UserHandle; +import androidx.annotation.NonNull; + import com.android.launcher3.LauncherSettings.Favorites; import com.android.launcher3.model.data.FolderInfo; import com.android.launcher3.model.data.ItemInfo; @@ -27,90 +29,64 @@ import com.android.launcher3.shortcuts.ShortcutKey; import java.util.Collection; import java.util.HashSet; import java.util.Set; +import java.util.function.Predicate; /** * A utility class to check for {@link ItemInfo} */ -public interface ItemInfoMatcher { +public abstract class ItemInfoMatcher { /** * Empty component used for match testing */ - ComponentName EMPTY_COMPONENT = new ComponentName("", ""); + private static final ComponentName EMPTY_COMPONENT = new ComponentName("", ""); - boolean matches(ItemInfo info, ComponentName cn); - - /** - * Returns true if the itemInfo matches this check - */ - default boolean matchesInfo(ItemInfo info) { - if (info != null) { - ComponentName cn = info.getTargetComponent(); - return matches(info, cn != null ? cn : EMPTY_COMPONENT); - } else { - return false; - } + public static Predicate ofUser(UserHandle user) { + return info -> info != null && info.user.equals(user); } - /** - * Returns a new matcher with returns true if either this or {@param matcher} returns true. - */ - default ItemInfoMatcher or(ItemInfoMatcher matcher) { - return (info, cn) -> matches(info, cn) || matcher.matches(info, cn); + public static Predicate ofComponents( + HashSet components, UserHandle user) { + return info -> info != null && info.user.equals(user) + && components.contains(getNonNullComponent(info)); } - /** - * Returns a new matcher with returns true if both this and {@param matcher} returns true. - */ - default ItemInfoMatcher and(ItemInfoMatcher matcher) { - return (info, cn) -> matches(info, cn) && matcher.matches(info, cn); + public static Predicate ofPackages(Set packageNames, UserHandle user) { + return info -> info != null && info.user.equals(user) + && packageNames.contains(getNonNullComponent(info).getPackageName()); } - /** - * Returns a new matcher with returns the opposite value of this. - */ - default ItemInfoMatcher negate() { - return (info, cn) -> !matches(info, cn); - } - - static ItemInfoMatcher ofUser(UserHandle user) { - return (info, cn) -> info.user.equals(user); - } - - static ItemInfoMatcher ofComponents(HashSet components, UserHandle user) { - return (info, cn) -> components.contains(cn) && info.user.equals(user); - } - - static ItemInfoMatcher ofPackages(Set packageNames, UserHandle user) { - return (info, cn) -> packageNames.contains(cn.getPackageName()) && info.user.equals(user); - } - - static ItemInfoMatcher ofShortcutKeys(Set keys) { - return (info, cn) -> info.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT + public static Predicate ofShortcutKeys(Set keys) { + return info -> info != null && info.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT && keys.contains(ShortcutKey.fromItemInfo(info)); } /** * Returns a matcher for items within folders. */ - static ItemInfoMatcher forFolderMatch(ItemInfoMatcher childOperator) { - return (info, cn) -> info instanceof FolderInfo && ((FolderInfo) info).contents.stream() - .anyMatch(childOperator::matchesInfo); + public static Predicate forFolderMatch(Predicate childOperator) { + return info -> info instanceof FolderInfo && ((FolderInfo) info).contents.stream() + .anyMatch(childOperator); } /** * Returns a matcher for items with provided ids */ - static ItemInfoMatcher ofItemIds(IntSet ids) { - return (info, cn) -> ids.contains(info.id); + public static Predicate ofItemIds(IntSet ids) { + return info -> info != null && ids.contains(info.id); } /** * Returns a matcher for items with provided items */ - static ItemInfoMatcher ofItems(Collection items) { + public static Predicate ofItems(Collection items) { IntSet ids = new IntSet(); items.forEach(item -> ids.add(item.id)); return ofItemIds(ids); } + + private static ComponentName getNonNullComponent(@NonNull ItemInfo info) { + ComponentName cn = info.getTargetComponent(); + return cn != null ? cn : EMPTY_COMPONENT; + } }