diff options
20 files changed, 280 insertions, 65 deletions
diff --git a/go/quickstep/src/com/android/quickstep/TouchInteractionService.java b/go/quickstep/src/com/android/quickstep/TouchInteractionService.java index 89a845426..80e1325f6 100644 --- a/go/quickstep/src/com/android/quickstep/TouchInteractionService.java +++ b/go/quickstep/src/com/android/quickstep/TouchInteractionService.java @@ -30,7 +30,6 @@ import android.view.MotionEvent; import com.android.systemui.shared.recents.IOverviewProxy; import com.android.systemui.shared.recents.ISystemUiProxy; -import com.android.systemui.shared.system.NavigationBarCompat.HitTarget; /** * Service connected by system-UI for handling touch interaction. @@ -38,8 +37,6 @@ import com.android.systemui.shared.system.NavigationBarCompat.HitTarget; @TargetApi(Build.VERSION_CODES.O) public class TouchInteractionService extends Service { - public static final int EDGE_NAV_BAR = 1 << 8; - private static final String TAG = "TouchInteractionService"; private final IBinder mMyBinder = new IOverviewProxy.Stub() { diff --git a/go/quickstep/src/com/android/quickstep/views/IconRecentsView.java b/go/quickstep/src/com/android/quickstep/views/IconRecentsView.java index 8976c4474..5bb4c5aaa 100644 --- a/go/quickstep/src/com/android/quickstep/views/IconRecentsView.java +++ b/go/quickstep/src/com/android/quickstep/views/IconRecentsView.java @@ -89,6 +89,7 @@ public final class IconRecentsView extends FrameLayout { private RecyclerView mTaskRecyclerView; private View mEmptyView; private View mContentView; + private View mClearAllView; private boolean mTransitionedFromApp; public IconRecentsView(Context context, AttributeSet attrs) { @@ -125,10 +126,20 @@ public final class IconRecentsView extends FrameLayout { updateContentViewVisibility(); } }); + mClearAllView = findViewById(R.id.clear_all_button); + mClearAllView.setOnClickListener(v -> animateClearAllTasks()); + } + } + - View clearAllView = findViewById(R.id.clear_all_button); - clearAllView.setOnClickListener(v -> animateClearAllTasks()); + @Override + public void setEnabled(boolean enabled) { + super.setEnabled(enabled); + TaskItemView[] itemViews = getTaskViews(); + for (TaskItemView itemView : itemViews) { + itemView.setEnabled(enabled); } + mClearAllView.setEnabled(enabled); } /** @@ -204,6 +215,7 @@ public final class IconRecentsView extends FrameLayout { * Clear all tasks and animate out. */ private void animateClearAllTasks() { + setEnabled(false); TaskItemView[] itemViews = getTaskViews(); AnimatorSet clearAnim = new AnimatorSet(); @@ -249,6 +261,7 @@ public final class IconRecentsView extends FrameLayout { itemView.setTranslationX(0); itemView.setAlpha(1.0f); } + setEnabled(true); mContentView.setVisibility(GONE); mTaskActionController.clearAllTasks(); } diff --git a/iconloaderlib/src/com/android/launcher3/icons/BaseIconFactory.java b/iconloaderlib/src/com/android/launcher3/icons/BaseIconFactory.java index 96b0a9e25..ab4b64cbf 100644 --- a/iconloaderlib/src/com/android/launcher3/icons/BaseIconFactory.java +++ b/iconloaderlib/src/com/android/launcher3/icons/BaseIconFactory.java @@ -61,6 +61,7 @@ public class BaseIconFactory implements AutoCloseable { mCanvas = new Canvas(); mCanvas.setDrawFilter(new PaintFlagsDrawFilter(DITHER_FLAG, FILTER_BITMAP_FLAG)); + clear(); } protected void clear() { @@ -114,11 +115,6 @@ public class BaseIconFactory implements AutoCloseable { } public BitmapInfo createBadgedIconBitmap(Drawable icon, UserHandle user, - boolean shrinkNonAdaptiveIcons, boolean isInstantApp) { - return createBadgedIconBitmap(icon, user, shrinkNonAdaptiveIcons, isInstantApp, null); - } - - public BitmapInfo createBadgedIconBitmap(Drawable icon, UserHandle user, int iconAppTargetSdk) { return createBadgedIconBitmap(icon, user, iconAppTargetSdk, false); } diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsUiFactory.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsUiFactory.java index 36014a9b5..f507d0f9d 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsUiFactory.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsUiFactory.java @@ -30,6 +30,7 @@ import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.uioverrides.touchcontrollers.FlingAndHoldTouchController; import com.android.launcher3.uioverrides.touchcontrollers.LandscapeEdgeSwipeController; +import com.android.launcher3.uioverrides.touchcontrollers.NavBarToHomeTouchController; import com.android.launcher3.uioverrides.touchcontrollers.OverviewToAllAppsTouchController; import com.android.launcher3.uioverrides.touchcontrollers.PortraitStatesTouchController; import com.android.launcher3.uioverrides.touchcontrollers.StatusBarTouchController; @@ -64,6 +65,7 @@ public abstract class RecentsUiFactory { list.add(launcher.getDragController()); if (mode == Mode.NO_BUTTON) { list.add(new QuickSwitchTouchController(launcher)); + list.add(new NavBarToHomeTouchController(launcher)); list.add(new FlingAndHoldTouchController(launcher)); } else { if (launcher.getDeviceProfile().isVerticalBarLayout()) { diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java new file mode 100644 index 000000000..673beff85 --- /dev/null +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/NavBarToHomeTouchController.java @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.launcher3.uioverrides.touchcontrollers; + +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.allapps.AllAppsTransitionController.ALL_APPS_PROGRESS; +import static com.android.launcher3.anim.Interpolators.DEACCEL_3; + +import android.animation.Animator; +import android.animation.AnimatorSet; +import android.animation.ObjectAnimator; +import android.view.MotionEvent; +import android.view.View; +import android.view.animation.Interpolator; + +import com.android.launcher3.Launcher; +import com.android.launcher3.LauncherState; +import com.android.launcher3.LauncherStateManager.AnimationConfig; +import com.android.launcher3.Utilities; +import com.android.launcher3.allapps.AllAppsTransitionController; +import com.android.launcher3.anim.AnimatorPlaybackController; +import com.android.launcher3.anim.AnimatorSetBuilder; +import com.android.launcher3.anim.Interpolators; +import com.android.launcher3.touch.AbstractStateChangeTouchController; +import com.android.launcher3.touch.SwipeDetector; +import com.android.launcher3.userevent.nano.LauncherLogProto; +import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch; +import com.android.quickstep.views.RecentsView; + +/** + * Handles swiping up on the nav bar to go home from overview or all apps. + */ +public class NavBarToHomeTouchController extends AbstractStateChangeTouchController { + + private static final Interpolator PULLBACK_INTERPOLATOR = DEACCEL_3; + + public NavBarToHomeTouchController(Launcher launcher) { + super(launcher, SwipeDetector.VERTICAL); + } + + @Override + protected boolean canInterceptTouch(MotionEvent ev) { + boolean cameFromNavBar = (ev.getEdgeFlags() & Utilities.EDGE_NAV_BAR) != 0; + return cameFromNavBar && (mLauncher.isInState(OVERVIEW) || mLauncher.isInState(ALL_APPS)); + } + + @Override + protected LauncherState getTargetState(LauncherState fromState, boolean isDragTowardPositive) { + return isDragTowardPositive ? NORMAL : fromState; + } + + @Override + protected float initCurrentAnimation(int animComponents) { + long accuracy = (long) (getShiftRange() * 2); + final AnimatorSet anim; + if (mFromState == OVERVIEW) { + anim = new AnimatorSet(); + RecentsView recentsView = mLauncher.getOverviewPanel(); + float pullbackDistance = recentsView.getPaddingStart() / 2; + if (!recentsView.isRtl()) { + pullbackDistance = -pullbackDistance; + } + anim.play(ObjectAnimator.ofFloat(recentsView, View.TRANSLATION_X, pullbackDistance)); + anim.setInterpolator(PULLBACK_INTERPOLATOR); + } else { // if (mFromState == ALL_APPS) + AnimatorSetBuilder builder = new AnimatorSetBuilder(); + AllAppsTransitionController allAppsController = mLauncher.getAllAppsController(); + final float pullbackDistance = mLauncher.getDeviceProfile().allAppsIconSizePx / 2; + Animator allAppsProgress = ObjectAnimator.ofFloat(allAppsController, ALL_APPS_PROGRESS, + -pullbackDistance / allAppsController.getShiftRange()); + allAppsProgress.setInterpolator(PULLBACK_INTERPOLATOR); + builder.play(allAppsProgress); + // Slightly fade out all apps content to further distinguish from scrolling. + builder.setInterpolator(AnimatorSetBuilder.ANIM_ALL_APPS_FADE, Interpolators + .mapToProgress(PULLBACK_INTERPOLATOR, 0, 0.5f)); + AnimationConfig config = new AnimationConfig(); + config.duration = accuracy; + allAppsController.setAlphas(mToState.getVisibleElements(mLauncher), config, builder); + anim = builder.build(); + } + anim.setDuration(accuracy); + mCurrentAnimation = AnimatorPlaybackController.wrap(anim, accuracy, this::clearState); + return -1 / getShiftRange(); + } + + @Override + public void onDragStart(boolean start) { + super.onDragStart(start); + mStartContainerType = LauncherLogProto.ContainerType.NAVBAR; + } + + @Override + public void onDragEnd(float velocity, boolean fling) { + final int logAction = fling ? Touch.FLING : Touch.SWIPE; + float interpolatedProgress = PULLBACK_INTERPOLATOR.getInterpolation( + mCurrentAnimation.getProgressFraction()); + if (interpolatedProgress >= SUCCESS_TRANSITION_PROGRESS || velocity < 0 && fling) { + mLauncher.getStateManager().goToState(mToState, true, + () -> onSwipeInteractionCompleted(mToState, logAction)); + } else { + // Quickly return to the state we came from (we didn't move far). + AnimatorPlaybackController anim = mLauncher.getStateManager() + .createAnimationToNewWorkspace(mFromState, 80); + anim.setEndAction(() -> onSwipeInteractionCompleted(mFromState, logAction)); + anim.start(); + } + mCurrentAnimation.dispatchOnCancel(); + } + + @Override + protected int getDirectionForLog() { + return LauncherLogProto.Action.Direction.UP; + } + + @Override + protected boolean goingBetweenNormalAndOverview(LauncherState fromState, + LauncherState toState) { + // We don't want to create an atomic animation to/from overview. + return false; + } + + @Override + protected int getLogContainerTypeForNormalState() { + return LauncherLogProto.ContainerType.NAVBAR; + } +} diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityControllerHelper.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityControllerHelper.java index ef46b3b0d..73fcf78b8 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityControllerHelper.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/FallbackActivityControllerHelper.java @@ -16,6 +16,7 @@ package com.android.quickstep; import static com.android.launcher3.anim.Interpolators.LINEAR; +import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON; import static com.android.quickstep.views.RecentsView.CONTENT_ALPHA; import android.animation.Animator; @@ -59,7 +60,8 @@ public final class FallbackActivityControllerHelper implements @Override public int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context, Rect outRect) { LayoutUtils.calculateFallbackTaskSize(context, dp, outRect); - if (dp.isVerticalBarLayout()) { + if (dp.isVerticalBarLayout() + && SysUINavigationMode.INSTANCE.get(context).getMode() != NO_BUTTON) { Rect targetInsets = dp.getInsets(); int hotseatInset = dp.isSeascape() ? targetInsets.left : targetInsets.right; return dp.hotseatBarSizePx + hotseatInset; diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java index 69f3338e1..df2b687b2 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java @@ -24,6 +24,7 @@ import static com.android.launcher3.allapps.AllAppsTransitionController.SPRING_D import static com.android.launcher3.allapps.AllAppsTransitionController.SPRING_STIFFNESS; import static com.android.launcher3.anim.Interpolators.DEACCEL_3; import static com.android.launcher3.anim.Interpolators.LINEAR; +import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; @@ -74,7 +75,8 @@ public final class LauncherActivityControllerHelper implements ActivityControlHe @Override public int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context, Rect outRect) { LayoutUtils.calculateLauncherTaskSize(context, dp, outRect); - if (dp.isVerticalBarLayout()) { + if (dp.isVerticalBarLayout() + && SysUINavigationMode.INSTANCE.get(context).getMode() != NO_BUTTON) { Rect targetInsets = dp.getInsets(); int hotseatInset = dp.isSeascape() ? targetInsets.left : targetInsets.right; return dp.hotseatBarSizePx + hotseatInset; diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/OtherActivityInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/OtherActivityInputConsumer.java index c8dcf8068..63c2e5dd4 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/OtherActivityInputConsumer.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/OtherActivityInputConsumer.java @@ -24,6 +24,7 @@ import static android.view.MotionEvent.INVALID_POINTER_ID; import static com.android.launcher3.util.RaceConditionTracker.ENTER; import static com.android.launcher3.util.RaceConditionTracker.EXIT; import static com.android.launcher3.Utilities.EDGE_NAV_BAR; +import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON; import static com.android.quickstep.TouchInteractionService.TOUCH_INTERACTION_LOG; import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS; @@ -284,11 +285,13 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC } private boolean isNavBarOnRight() { - return mDisplayRotation == Surface.ROTATION_90 && mStableInsets.right > 0; + return SysUINavigationMode.INSTANCE.get(getBaseContext()).getMode() != NO_BUTTON + && mDisplayRotation == Surface.ROTATION_90 && mStableInsets.right > 0; } private boolean isNavBarOnLeft() { - return mDisplayRotation == Surface.ROTATION_270 && mStableInsets.left > 0; + return SysUINavigationMode.INSTANCE.get(getBaseContext()).getMode() != NO_BUTTON + && mDisplayRotation == Surface.ROTATION_270 && mStableInsets.left > 0; } private void startTouchTrackingForWindowAnimation(long touchTimeMs) { diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java index 10180f586..b1db78083 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java @@ -203,6 +203,11 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> private static final long SHELF_ANIM_DURATION = 120; + /** + * Used as the page index for logging when we return to the last task at the end of the gesture. + */ + private static final int LOG_NO_OP_PAGE_INDEX = -1; + private final ClipAnimationHelper mClipAnimationHelper; private final ClipAnimationHelper.TransformParams mTransformParams; @@ -245,6 +250,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> private boolean mPassedOverviewThreshold; private boolean mGestureStarted; private int mLogAction = Touch.SWIPE; + private int mLogDirection = Direction.UP; private final RecentsAnimationWrapper mRecentsAnimationWrapper; @@ -692,6 +698,12 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> setStateOnUiThread(STATE_GESTURE_COMPLETED); mLogAction = isFling ? Touch.FLING : Touch.SWIPE; + boolean isVelocityVertical = Math.abs(velocity.y) > Math.abs(velocity.x); + if (isVelocityVertical) { + mLogDirection = velocity.y < 0 ? Direction.UP : Direction.DOWN; + } else { + mLogDirection = velocity.x < 0 ? Direction.LEFT : Direction.RIGHT; + } handleNormalGestureEnd(endVelocity, isFling, velocity); } @@ -824,19 +836,15 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> // We probably never received an animation controller, skip logging. return; } - boolean toLauncher = endTarget.isLauncher; - final int direction; - if (dp.isVerticalBarLayout()) { - direction = (dp.isSeascape() ^ toLauncher) ? Direction.LEFT : Direction.RIGHT; - } else { - direction = toLauncher ? Direction.UP : Direction.DOWN; - } + int pageIndex = endTarget == LAST_TASK + ? LOG_NO_OP_PAGE_INDEX + : mRecentsView.getNextPage(); UserEventDispatcher.newInstance(mContext).logStateChangeAction( - mLogAction, direction, + mLogAction, mLogDirection, ContainerType.NAVBAR, ContainerType.APP, endTarget.containerType, - 0); + pageIndex); } /** Animates to the given progress, where 0 is the current app and 1 is overview. */ diff --git a/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java b/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java index 8633b21a1..f5ac9c94e 100644 --- a/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java +++ b/quickstep/tests/src/com/android/quickstep/NavigationModeSwitchRule.java @@ -17,7 +17,6 @@ package com.android.quickstep; import static androidx.test.InstrumentationRegistry.getInstrumentation; - import static com.android.quickstep.NavigationModeSwitchRule.Mode.ALL; import static com.android.quickstep.NavigationModeSwitchRule.Mode.THREE_BUTTON; import static com.android.quickstep.NavigationModeSwitchRule.Mode.TWO_BUTTON; @@ -27,22 +26,17 @@ import static com.android.systemui.shared.system.QuickStepContract.NAV_BAR_MODE_ import android.content.Context; import android.util.Log; - import androidx.test.uiautomator.UiDevice; - import com.android.launcher3.tapl.LauncherInstrumentation; import com.android.launcher3.tapl.TestHelpers; -import com.android.systemui.shared.system.QuickStepContract; - -import org.junit.Assert; -import org.junit.rules.TestRule; -import org.junit.runner.Description; -import org.junit.runners.model.Statement; - import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import org.junit.Assert; +import org.junit.rules.TestRule; +import org.junit.runner.Description; +import org.junit.runners.model.Statement; /** * Test rule that allows executing a test with Quickstep on and then Quickstep off. @@ -78,9 +72,9 @@ public class NavigationModeSwitchRule implements TestRule { @Override public void evaluate() throws Throwable { final Context context = getInstrumentation().getContext(); - final String prevOverlayPkg = QuickStepContract.isGesturalMode(context) + final String prevOverlayPkg = LauncherInstrumentation.isGesturalMode(context) ? NAV_BAR_MODE_GESTURAL_OVERLAY - : QuickStepContract.isSwipeUpMode(context) + : LauncherInstrumentation.isSwipeUpMode(context) ? NAV_BAR_MODE_2BUTTON_OVERLAY : NAV_BAR_MODE_3BUTTON_OVERLAY; final LauncherInstrumentation.NavigationModel originalMode = diff --git a/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java b/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java index 554aef4b7..dc83e8763 100644 --- a/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java +++ b/quickstep/tests/src/com/android/quickstep/StartLauncherViaGestureTests.java @@ -96,6 +96,7 @@ public class StartLauncherViaGestureTests extends AbstractQuickStepTest { } @Test + @Ignore // b/129723135 @NavigationModeSwitch public void testStressSwipeToOverview() { for (int i = 0; i < STRESS_REPEAT_COUNT; ++i) { diff --git a/src/com/android/launcher3/LauncherAppState.java b/src/com/android/launcher3/LauncherAppState.java index 7bb60714f..dc275161d 100644 --- a/src/com/android/launcher3/LauncherAppState.java +++ b/src/com/android/launcher3/LauncherAppState.java @@ -131,6 +131,7 @@ public class LauncherAppState { if ((changeFlags & CHANGE_FLAG_ICON_PARAMS) != 0) { LauncherIcons.clearPool(); mIconCache.updateIconParams(idp.fillResIconDpi, idp.iconBitmapSize); + mWidgetCache.refresh(); } mModel.forceReload(); diff --git a/src/com/android/launcher3/LauncherStateManager.java b/src/com/android/launcher3/LauncherStateManager.java index 5f7538b40..5b654d8f3 100644 --- a/src/com/android/launcher3/LauncherStateManager.java +++ b/src/com/android/launcher3/LauncherStateManager.java @@ -17,6 +17,7 @@ package com.android.launcher3; import static android.view.View.VISIBLE; + import static com.android.launcher3.LauncherState.NORMAL; import static com.android.launcher3.LauncherState.OVERVIEW; import static com.android.launcher3.LauncherState.OVERVIEW_PEEK; @@ -29,7 +30,6 @@ import static com.android.launcher3.anim.Interpolators.ACCEL; import static com.android.launcher3.anim.Interpolators.DEACCEL; import static com.android.launcher3.anim.Interpolators.DEACCEL_1_7; import static com.android.launcher3.anim.Interpolators.INSTANT; -import static com.android.launcher3.anim.Interpolators.NEVER; import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2; import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_7; import static com.android.launcher3.anim.Interpolators.clampToProgress; @@ -41,6 +41,8 @@ import android.animation.AnimatorSet; import android.os.Handler; import android.os.Looper; +import androidx.annotation.IntDef; + import com.android.launcher3.anim.AnimationSuccessListener; import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.anim.AnimatorSetBuilder; @@ -52,8 +54,6 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; -import androidx.annotation.IntDef; - /** * TODO: figure out what kind of tests we can write for this * @@ -326,7 +326,8 @@ public class LauncherStateManager { } else if (fromState == NORMAL && toState == OVERVIEW_PEEK) { builder.setInterpolator(ANIM_OVERVIEW_FADE, INSTANT); } else if (fromState == OVERVIEW_PEEK && toState == NORMAL) { - builder.setInterpolator(ANIM_OVERVIEW_FADE, NEVER); + // Keep fully visible until the very end (when overview is offscreen) to make invisible. + builder.setInterpolator(ANIM_OVERVIEW_FADE, t -> t < 1 ? 0 : 1); } } diff --git a/src/com/android/launcher3/TestProtocol.java b/src/com/android/launcher3/TestProtocol.java index 49a736eed..7d3715ef1 100644 --- a/src/com/android/launcher3/TestProtocol.java +++ b/src/com/android/launcher3/TestProtocol.java @@ -33,6 +33,27 @@ public final class TestProtocol { public static final int ALL_APPS_STATE_ORDINAL = 5; public static final int BACKGROUND_APP_STATE_ORDINAL = 6; + public static String stateOrdinalToString(int ordinal) { + switch (ordinal) { + case NORMAL_STATE_ORDINAL: + return "Normal"; + case SPRING_LOADED_STATE_ORDINAL: + return "SpringLoaded"; + case OVERVIEW_STATE_ORDINAL: + return "Overview"; + case OVERVIEW_PEEK_STATE_ORDINAL: + return "OverviewPeek"; + case QUICK_SWITCH_STATE_ORDINAL: + return "QuickSwitch"; + case ALL_APPS_STATE_ORDINAL: + return "AllApps"; + case BACKGROUND_APP_STATE_ORDINAL: + return "Background"; + default: + return null; + } + } + public static final String TEST_INFO_RESPONSE_FIELD = "response"; public static final String REQUEST_HOME_TO_OVERVIEW_SWIPE_HEIGHT = "home-to-overview-swipe-height"; diff --git a/src/com/android/launcher3/WidgetPreviewLoader.java b/src/com/android/launcher3/WidgetPreviewLoader.java index 050849cc2..6d1bc1a9c 100644 --- a/src/com/android/launcher3/WidgetPreviewLoader.java +++ b/src/com/android/launcher3/WidgetPreviewLoader.java @@ -24,6 +24,7 @@ import android.graphics.drawable.Drawable; import android.os.AsyncTask; import android.os.CancellationSignal; import android.os.Handler; +import android.os.Process; import android.os.UserHandle; import android.util.Log; import android.util.LongSparseArray; @@ -73,7 +74,6 @@ public class WidgetPreviewLoader { private final Context mContext; private final IconCache mIconCache; private final UserManagerCompat mUserManager; - private final AppWidgetManagerCompat mWidgetManager; private final CacheDb mDb; private final MainThreadExecutor mMainThreadExecutor = new MainThreadExecutor(); @@ -82,7 +82,6 @@ public class WidgetPreviewLoader { public WidgetPreviewLoader(Context context, IconCache iconCache) { mContext = context; mIconCache = iconCache; - mWidgetManager = AppWidgetManagerCompat.getInstance(context); mUserManager = UserManagerCompat.getInstance(context); mDb = new CacheDb(context); mWorkerHandler = new Handler(LauncherModel.getWorkerLooper()); @@ -107,6 +106,10 @@ public class WidgetPreviewLoader { return signal; } + public void refresh() { + mDb.clear(); + + } /** * The DB holds the generated previews for various components. Previews can also have different * sizes (landscape vs portrait). @@ -474,8 +477,9 @@ public class WidgetPreviewLoader { RectF boxRect = drawBoxWithShadow(c, size, size); LauncherIcons li = LauncherIcons.obtain(mContext); - Bitmap icon = li.createScaledBitmapWithoutShadow( - mutateOnMainThread(info.getFullResIcon(mIconCache)), 0); + Bitmap icon = li.createBadgedIconBitmap( + mutateOnMainThread(info.getFullResIcon(mIconCache)), + Process.myUserHandle(), 0).icon; li.recycle(); Rect src = new Rect(0, 0, icon.getWidth(), icon.getHeight()); diff --git a/src/com/android/launcher3/anim/Interpolators.java b/src/com/android/launcher3/anim/Interpolators.java index 217b6db2c..b169cb80b 100644 --- a/src/com/android/launcher3/anim/Interpolators.java +++ b/src/com/android/launcher3/anim/Interpolators.java @@ -58,7 +58,6 @@ public class Interpolators { public static final Interpolator EXAGGERATED_EASE; public static final Interpolator INSTANT = t -> 1; - public static final Interpolator NEVER = t -> 0; private static final int MIN_SETTLE_DURATION = 200; private static final float OVERSHOOT_FACTOR = 0.9f; diff --git a/src/com/android/launcher3/logging/LoggerUtils.java b/src/com/android/launcher3/logging/LoggerUtils.java index 4ef86265f..d208077d5 100644 --- a/src/com/android/launcher3/logging/LoggerUtils.java +++ b/src/com/android/launcher3/logging/LoggerUtils.java @@ -15,7 +15,8 @@ */ package com.android.launcher3.logging; -import android.content.Context; +import static com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType.NAVBAR; + import android.util.ArrayMap; import android.util.SparseArray; import android.view.View; @@ -97,7 +98,8 @@ public class LoggerUtils { case Target.Type.CONTAINER: str = getFieldName(t.containerType, ContainerType.class); if (t.containerType == ContainerType.WORKSPACE || - t.containerType == ContainerType.HOTSEAT) { + t.containerType == ContainerType.HOTSEAT || + t.containerType == NAVBAR) { str += " id=" + t.pageIndex; } else if (t.containerType == ContainerType.FOLDER) { str += " grid(" + t.gridX + "," + t.gridY+ ")"; diff --git a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java index c403e76ee..0274de35c 100644 --- a/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java +++ b/src/com/android/launcher3/touch/AbstractStateChangeTouchController.java @@ -224,7 +224,8 @@ public abstract class AbstractStateChangeTouchController return true; } - private boolean goingBetweenNormalAndOverview(LauncherState fromState, LauncherState toState) { + protected boolean goingBetweenNormalAndOverview(LauncherState fromState, + LauncherState toState) { return (fromState == NORMAL || fromState == OVERVIEW) && (toState == NORMAL || toState == OVERVIEW) && mPendingAnimation == null; @@ -242,7 +243,7 @@ public abstract class AbstractStateChangeTouchController mStartContainerType = LauncherLogProto.ContainerType.ALLAPPS; } else if (mStartState == NORMAL) { mStartContainerType = getLogContainerTypeForNormalState(); - } else if (mStartState == OVERVIEW){ + } else if (mStartState == OVERVIEW){ mStartContainerType = LauncherLogProto.ContainerType.TASKSWITCHER; } if (mCurrentAnimation == null) { diff --git a/src/com/android/launcher3/widget/WidgetsRecyclerView.java b/src/com/android/launcher3/widget/WidgetsRecyclerView.java index 641183a01..c15557beb 100644 --- a/src/com/android/launcher3/widget/WidgetsRecyclerView.java +++ b/src/com/android/launcher3/widget/WidgetsRecyclerView.java @@ -56,11 +56,6 @@ public class WidgetsRecyclerView extends BaseRecyclerView implements OnItemTouch addOnItemTouchListener(this); } - public WidgetsRecyclerView(Context context, AttributeSet attrs, int defStyleAttr, - int defStyleRes) { - this(context, attrs, defStyleAttr); - } - @Override protected void onFinishInflate() { super.onFinishInflate(); diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java index 00257a5d1..a4b417192 100644 --- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java +++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java @@ -16,27 +16,26 @@ package com.android.launcher3.tapl; -import static com.android.launcher3.TestProtocol.BACKGROUND_APP_STATE_ORDINAL; - import android.app.ActivityManager; import android.app.Instrumentation; import android.app.UiAutomation; import android.content.ContentResolver; import android.content.Context; import android.content.pm.PackageManager; +import android.content.res.Resources; import android.graphics.Point; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Parcelable; import android.os.SystemClock; +import android.text.TextUtils; import android.util.Log; import android.view.InputDevice; import android.view.MotionEvent; import android.view.Surface; import android.view.ViewConfiguration; import android.view.accessibility.AccessibilityEvent; - import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.test.uiautomator.By; @@ -45,18 +44,15 @@ import androidx.test.uiautomator.Configurator; import androidx.test.uiautomator.UiDevice; import androidx.test.uiautomator.UiObject2; import androidx.test.uiautomator.Until; - import com.android.launcher3.TestProtocol; import com.android.systemui.shared.system.QuickStepContract; - -import org.junit.Assert; - import java.io.IOException; import java.lang.ref.WeakReference; import java.util.Deque; import java.util.LinkedList; import java.util.List; import java.util.concurrent.TimeoutException; +import org.junit.Assert; /** * The main tapl object. The only object that can be explicitly constructed by the using code. It @@ -65,6 +61,8 @@ import java.util.concurrent.TimeoutException; public final class LauncherInstrumentation { private static final String TAG = "Tapl"; + private static final String NAV_BAR_INTERACTION_MODE_RES_NAME = + "config_navBarInteractionMode"; private static final int ZERO_BUTTON_STEPS_FROM_BACKGROUND_TO_HOME = 20; // Types for launcher containers that the user is interacting with. "Background" is a @@ -171,11 +169,11 @@ public final class LauncherInstrumentation { // Workaround, use constructed context because both the instrumentation context and the // app context are not constructed with resources that take overlays into account final Context ctx = baseContext.createPackageContext("android", 0); - if (QuickStepContract.isGesturalMode(ctx)) { + if (isGesturalMode(ctx)) { return NavigationModel.ZERO_BUTTON; - } else if (QuickStepContract.isSwipeUpMode(ctx)) { + } else if (isSwipeUpMode(ctx)) { return NavigationModel.TWO_BUTTON; - } else if (QuickStepContract.isLegacyMode(ctx)) { + } else if (isLegacyMode(ctx)) { return NavigationModel.THREE_BUTTON; } else { fail("Can't detect navigation mode"); @@ -225,6 +223,12 @@ public final class LauncherInstrumentation { } } + private void assertEquals(String message, String expected, String actual) { + if (!TextUtils.equals(expected, actual)) { + fail(message + " expected: '" + expected + "' but was: '" + actual + "'"); + } + } + void assertNotEquals(String message, int unexpected, int actual) { if (unexpected == actual) { failEquals(message, actual); @@ -539,8 +543,9 @@ public final class LauncherInstrumentation { event -> TestProtocol.SWITCHED_TO_STATE_MESSAGE.equals(event.getClassName()), "Swipe failed to receive an event for the swipe end: " + startX + ", " + startY + ", " + endX + ", " + endY); - assertEquals("Swipe switched launcher to a wrong state", - expectedState, parcel.getInt(TestProtocol.STATE_FIELD)); + assertEquals("Swipe switched launcher to a wrong state;", + TestProtocol.stateOrdinalToString(expectedState), + TestProtocol.stateOrdinalToString(parcel.getInt(TestProtocol.STATE_FIELD))); } void waitForIdle() { @@ -595,6 +600,33 @@ public final class LauncherInstrumentation { } } + public static boolean isGesturalMode(Context context) { + return QuickStepContract.isGesturalMode( + getSystemIntegerRes(context, NAV_BAR_INTERACTION_MODE_RES_NAME)); + } + + public static boolean isSwipeUpMode(Context context) { + return QuickStepContract.isSwipeUpMode( + getSystemIntegerRes(context, NAV_BAR_INTERACTION_MODE_RES_NAME)); + } + + public static boolean isLegacyMode(Context context) { + return QuickStepContract.isLegacyMode( + getSystemIntegerRes(context, NAV_BAR_INTERACTION_MODE_RES_NAME)); + } + + private static int getSystemIntegerRes(Context context, String resName) { + Resources res = context.getResources(); + int resId = res.getIdentifier(resName, "integer", "android"); + + if (resId != 0) { + return res.getInteger(resId); + } else { + Log.e(TAG, "Failed to get system resource ID. Incompatible framework version?"); + return -1; + } + } + static void sleep(int duration) { try { Thread.sleep(duration); |