Merge "Fixing pressHome when a context menu is visible" into ub-launcher3-qt-dev
diff --git a/quickstep/AndroidManifest.xml b/quickstep/AndroidManifest.xml
index a38979d..332e0fa 100644
--- a/quickstep/AndroidManifest.xml
+++ b/quickstep/AndroidManifest.xml
@@ -84,6 +84,11 @@
android:clearTaskOnLaunch="true"
android:exported="false" />
+ <activity android:name="com.android.quickstep.LockScreenRecentsActivity"
+ android:theme="@android:style/Theme.NoDisplay"
+ android:showOnLockScreen="true"
+ android:directBootAware="true" />
+
</application>
</manifest>
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/FlingAndHoldTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/FlingAndHoldTouchController.java
index 7a6cd2d..e3e339a 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/FlingAndHoldTouchController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/FlingAndHoldTouchController.java
@@ -22,6 +22,7 @@
import static com.android.launcher3.LauncherStateManager.ANIM_ALL;
import static com.android.launcher3.LauncherStateManager.ATOMIC_OVERVIEW_PEEK_COMPONENT;
import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -34,8 +35,10 @@
import com.android.launcher3.LauncherState;
import com.android.launcher3.anim.AnimatorSetBuilder;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
+import com.android.quickstep.OverviewInteractionState;
import com.android.quickstep.util.MotionPauseDetector;
import com.android.quickstep.views.RecentsView;
+import com.android.systemui.shared.system.QuickStepContract;
/**
* Touch controller which handles swipe and hold to go to Overview
@@ -99,7 +102,8 @@
* having it as part of the existing animation to the target state.
*/
private boolean handlingOverviewAnim() {
- return mStartState == NORMAL;
+ int stateFlags = OverviewInteractionState.INSTANCE.get(mLauncher).getSystemUiStateFlags();
+ return mStartState == NORMAL && (stateFlags & SYSUI_STATE_OVERVIEW_DISABLED) == 0;
}
@Override
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java
index e1dd124..18b8af4 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/touchcontrollers/QuickSwitchTouchController.java
@@ -30,6 +30,7 @@
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.util.SystemUiController.UI_STATE_OVERVIEW;
import static com.android.quickstep.views.RecentsView.UPDATE_SYSUI_FLAGS_THRESHOLD;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
import android.view.MotionEvent;
@@ -44,10 +45,12 @@
import com.android.launcher3.touch.SwipeDetector;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
+import com.android.quickstep.OverviewInteractionState;
import com.android.quickstep.SysUINavigationMode;
import com.android.quickstep.SysUINavigationMode.Mode;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
+import com.android.systemui.shared.system.QuickStepContract;
/**
* Handles quick switching to a recent task from the home screen.
@@ -80,6 +83,10 @@
@Override
protected LauncherState getTargetState(LauncherState fromState, boolean isDragTowardPositive) {
+ int stateFlags = OverviewInteractionState.INSTANCE.get(mLauncher).getSystemUiStateFlags();
+ if ((stateFlags & SYSUI_STATE_OVERVIEW_DISABLED) != 0) {
+ return NORMAL;
+ }
return isDragTowardPositive ? QUICK_SWITCH : NORMAL;
}
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 4b2e487..00e4a9d 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/LauncherActivityControllerHelper.java
@@ -30,6 +30,7 @@
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
+import android.animation.TimeInterpolator;
import android.content.Context;
import android.graphics.Rect;
import android.graphics.RectF;
@@ -68,6 +69,8 @@
*/
public final class LauncherActivityControllerHelper implements ActivityControlHelper<Launcher> {
+ private Runnable mAdjustInterpolatorsRunnable;
+
@Override
public int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context, Rect outRect) {
LayoutUtils.calculateLauncherTaskSize(context, dp, outRect);
@@ -194,6 +197,13 @@
}
@Override
+ public void adjustActivityControllerInterpolators() {
+ if (mAdjustInterpolatorsRunnable != null) {
+ mAdjustInterpolatorsRunnable.run();
+ }
+ }
+
+ @Override
public void onTransitionCancelled() {
activity.getStateManager().goToState(startState, false /* animate */);
}
@@ -275,6 +285,7 @@
playScaleDownAnim(anim, activity, fromState, endState);
anim.setDuration(transitionLength * 2);
+ anim.setInterpolator(LINEAR);
AnimatorPlaybackController controller =
AnimatorPlaybackController.wrap(anim, transitionLength * 2);
activity.getStateManager().setCurrentUserControlledAnimation(controller);
@@ -291,7 +302,6 @@
Animator shiftAnim = new SpringObjectAnimator<>(activity.getAllAppsController(),
"allAppsSpringFromACH", activity.getAllAppsController().getShiftRange(),
SPRING_DAMPING_RATIO, SPRING_STIFFNESS, progressValues);
- shiftAnim.setInterpolator(LINEAR);
return shiftAnim;
}
@@ -310,19 +320,37 @@
= fromState.getOverviewScaleAndTranslation(launcher);
LauncherState.ScaleAndTranslation endScaleAndTranslation
= endState.getOverviewScaleAndTranslation(launcher);
+ float fromTranslationY = fromScaleAndTranslation.translationY;
+ float endTranslationY = endScaleAndTranslation.translationY;
float fromFullscreenProgress = fromState.getOverviewFullscreenProgress();
float endFullscreenProgress = endState.getOverviewFullscreenProgress();
Animator scale = ObjectAnimator.ofFloat(recentsView, SCALE_PROPERTY,
fromScaleAndTranslation.scale, endScaleAndTranslation.scale);
Animator translateY = ObjectAnimator.ofFloat(recentsView, TRANSLATION_Y,
- fromScaleAndTranslation.translationY, endScaleAndTranslation.translationY);
+ fromTranslationY, endTranslationY);
Animator applyFullscreenProgress = ObjectAnimator.ofFloat(recentsView,
RecentsView.FULLSCREEN_PROGRESS, fromFullscreenProgress, endFullscreenProgress);
- scale.setInterpolator(LINEAR);
- translateY.setInterpolator(LINEAR);
- applyFullscreenProgress.setInterpolator(LINEAR);
anim.playTogether(scale, translateY, applyFullscreenProgress);
+
+ mAdjustInterpolatorsRunnable = () -> {
+ // Adjust the translateY interpolator to account for the running task's top inset.
+ // When progress <= 1, this is handled by each task view as they set their fullscreen
+ // progress. However, once we go to progress > 1, fullscreen progress stays at 0, so
+ // recents as a whole needs to translate further to keep up with the app window.
+ TaskView runningTaskView = recentsView.getRunningTaskView();
+ if (runningTaskView == null) {
+ runningTaskView = recentsView.getTaskViewAt(recentsView.getCurrentPage());
+ }
+ TimeInterpolator oldInterpolator = translateY.getInterpolator();
+ Rect fallbackInsets = launcher.getDeviceProfile().getInsets();
+ float extraTranslationY = runningTaskView.getThumbnail().getInsets(fallbackInsets).top;
+ float normalizedTranslationY = extraTranslationY / (fromTranslationY - endTranslationY);
+ translateY.setInterpolator(t -> {
+ float newT = oldInterpolator.getInterpolation(t);
+ return newT <= 1f ? newT : newT + normalizedTranslationY * (newT - 1);
+ });
+ };
}
@Override
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/LockScreenRecentsActivity.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/LockScreenRecentsActivity.java
new file mode 100644
index 0000000..65f323c
--- /dev/null
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/LockScreenRecentsActivity.java
@@ -0,0 +1,31 @@
+/*
+ * 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.quickstep;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+/**
+ * Empty activity to start a recents transition
+ */
+public class LockScreenRecentsActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ finish();
+ }
+}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
index 6ba1bf5..7563c3f 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
@@ -22,8 +22,11 @@
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SYSUI_PROXY;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_CLICKABLE;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_HOME_DISABLED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NAV_BAR_HIDDEN;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_PINNING;
import android.annotation.TargetApi;
import android.app.ActivityManager;
@@ -79,6 +82,7 @@
import com.android.systemui.shared.system.InputChannelCompat.InputEventReceiver;
import com.android.systemui.shared.system.InputConsumerController;
import com.android.systemui.shared.system.InputMonitorCompat;
+import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.shared.system.QuickStepContract.SystemUiStateFlags;
import java.io.FileDescriptor;
@@ -197,6 +201,8 @@
public void onSystemUiStateChanged(int stateFlags) {
mSystemUiStateFlags = stateFlags;
+ mOverviewInteractionState.setSystemUiStateFlags(stateFlags);
+ mOverviewComponentObserver.onSystemUiStateChanged(stateFlags);
}
/** Deprecated methods **/
@@ -464,22 +470,19 @@
private boolean validSystemUiFlags() {
return (mSystemUiStateFlags & SYSUI_STATE_NAV_BAR_HIDDEN) == 0
- && (mSystemUiStateFlags & SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED) == 0;
- }
-
- private boolean topTaskLocked() {
- return ActivityManagerWrapper.getInstance().isLockToAppActive();
+ && (mSystemUiStateFlags & SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED) == 0
+ && ((mSystemUiStateFlags & SYSUI_STATE_HOME_DISABLED) == 0
+ || (mSystemUiStateFlags & SYSUI_STATE_OVERVIEW_DISABLED) == 0);
}
private InputConsumer newConsumer(boolean useSharedState, MotionEvent event) {
- boolean topTaskLocked = topTaskLocked();
- boolean isInValidSystemUiState = validSystemUiFlags() && !topTaskLocked;
+ boolean isInValidSystemUiState = validSystemUiFlags();
if (!mIsUserUnlocked) {
if (isInValidSystemUiState) {
// This handles apps launched in direct boot mode (e.g. dialer) as well as apps
// launched while device is locked even after exiting direct boot mode (e.g. camera).
- return new DeviceLockedInputConsumer(this);
+ return createDeviceLockedInputConsumer(mAM.getRunningTask(0));
} else {
return InputConsumer.NO_OP;
}
@@ -490,13 +493,15 @@
if (mMode == Mode.NO_BUTTON) {
final ActivityControlHelper activityControl =
mOverviewComponentObserver.getActivityControlHelper();
- if (mAssistantAvailable && !topTaskLocked
- && AssistantTouchConsumer.withinTouchRegion(this, event)) {
+ if (mAssistantAvailable
+ && !QuickStepContract.isAssistantGestureDisabled(mSystemUiStateFlags)
+ && AssistantTouchConsumer.withinTouchRegion(this, event)
+ && !ActivityManagerWrapper.getInstance().isLockToAppActive()) {
base = new AssistantTouchConsumer(this, mISystemUiProxy, activityControl, base,
mInputMonitorCompat);
}
- if (ActivityManagerWrapper.getInstance().isScreenPinningActive()) {
+ if ((mSystemUiStateFlags & SYSUI_STATE_SCREEN_PINNING) != 0) {
// Note: we only allow accessibility to wrap this, and it replaces the previous
// base input consumer (which should be NO_OP anyway since topTaskLocked == true).
base = new ScreenPinnedInputConsumer(this, mISystemUiProxy, activityControl);
@@ -512,16 +517,15 @@
}
private InputConsumer newBaseConsumer(boolean useSharedState, MotionEvent event) {
- if (mKM.isDeviceLocked()) {
- // This handles apps launched in direct boot mode (e.g. dialer) as well as apps launched
- // while device is locked even after exiting direct boot mode (e.g. camera).
- return new DeviceLockedInputConsumer(this);
- }
-
final RunningTaskInfo runningTaskInfo = mAM.getRunningTask(0);
if (!useSharedState) {
mSwipeSharedState.clearAllState();
}
+ if (mKM.isDeviceLocked()) {
+ // This handles apps launched in direct boot mode (e.g. dialer) as well as apps launched
+ // while device is locked even after exiting direct boot mode (e.g. camera).
+ return createDeviceLockedInputConsumer(runningTaskInfo);
+ }
final ActivityControlHelper activityControl =
mOverviewComponentObserver.getActivityControlHelper();
@@ -559,6 +563,15 @@
mSwipeSharedState, mInputMonitorCompat, mSwipeTouchRegion);
}
+ private InputConsumer createDeviceLockedInputConsumer(RunningTaskInfo taskInfo) {
+ if (mMode == Mode.NO_BUTTON && taskInfo != null) {
+ return new DeviceLockedInputConsumer(this, mSwipeSharedState, mInputMonitorCompat,
+ mSwipeTouchRegion, taskInfo.taskId);
+ } else {
+ return InputConsumer.NO_OP;
+ }
+ }
+
/**
* To be called by the consumer when it's no longer active.
*/
@@ -585,17 +598,14 @@
// Dump everything
pw.println("TouchState:");
pw.println(" navMode=" + mMode);
- pw.println(" validSystemUiFlags=" + validSystemUiFlags()
- + " flags=" + mSystemUiStateFlags);
- pw.println(" topTaskLocked=" + topTaskLocked());
+ pw.println(" validSystemUiFlags=" + validSystemUiFlags());
+ pw.println(" systemUiFlags=" + mSystemUiStateFlags);
+ pw.println(" systemUiFlagsDesc="
+ + QuickStepContract.getSystemUiStateString(mSystemUiStateFlags));
pw.println(" isDeviceLocked=" + mKM.isDeviceLocked());
- pw.println(" screenPinned=" +
- ActivityManagerWrapper.getInstance().isScreenPinningActive());
pw.println(" assistantAvailable=" + mAssistantAvailable);
- pw.println(" a11yClickable="
- + ((mSystemUiStateFlags & SYSUI_STATE_A11Y_BUTTON_CLICKABLE) != 0));
- pw.println(" a11yLongClickable="
- + ((mSystemUiStateFlags & SYSUI_STATE_A11Y_BUTTON_LONG_CLICKABLE) != 0));
+ pw.println(" assistantDisabled="
+ + QuickStepContract.isAssistantGestureDisabled(mSystemUiStateFlags));
pw.println(" resumed="
+ mOverviewComponentObserver.getActivityControlHelper().isResumed());
pw.println(" useSharedState=" + mConsumer.useSharedSwipeState());
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 ffef1cf..ca966c8 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java
@@ -39,6 +39,7 @@
import static com.android.quickstep.WindowTransformSwipeHandler.GestureEndTarget.NEW_TASK;
import static com.android.quickstep.WindowTransformSwipeHandler.GestureEndTarget.RECENTS;
import static com.android.quickstep.views.RecentsView.UPDATE_SYSUI_FLAGS_THRESHOLD;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
import android.animation.Animator;
import android.animation.AnimatorSet;
@@ -105,6 +106,7 @@
import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.InputConsumerController;
import com.android.systemui.shared.system.LatencyTrackerCompat;
+import com.android.systemui.shared.system.QuickStepContract;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat;
import com.android.systemui.shared.system.WindowCallbacksCompat;
@@ -217,6 +219,12 @@
private static final long SHELF_ANIM_DURATION = 120;
public static final long RECENTS_ATTACH_DURATION = 300;
+ // Start resisting when swiping past this factor of mTransitionDragLength.
+ private static final float DRAG_LENGTH_FACTOR_START_PULLBACK = 1.4f;
+ // This is how far down we can scale down, where 0f is full screen and 1f is recents.
+ private static final float DRAG_LENGTH_FACTOR_MAX_PULLBACK = 1.8f;
+ private static final Interpolator PULLBACK_INTERPOLATOR = DEACCEL;
+
/**
* Used as the page index for logging when we return to the last task at the end of the gesture.
*/
@@ -231,7 +239,10 @@
private RunningWindowAnim mRunningWindowAnim;
private boolean mIsShelfPeeking;
private DeviceProfile mDp;
+ // The distance needed to drag to reach the task size in recents.
private int mTransitionDragLength;
+ // How much further we can drag past recents, as a factor of mTransitionDragLength.
+ private float mDragLengthFactor = 1;
// Shift in the range of [0, 1].
// 0 => preview snapShot is completely visible, and hotseat is completely translated down
@@ -375,6 +386,10 @@
mTransitionDragLength = mActivityControlHelper.getSwipeUpDestinationAndLength(
dp, mContext, tempRect);
mClipAnimationHelper.updateTargetRect(tempRect);
+ if (mMode == Mode.NO_BUTTON) {
+ // We can drag all the way to the top of the screen.
+ mDragLengthFactor = (float) dp.heightPx / mTransitionDragLength;
+ }
}
private long getFadeInDuration() {
@@ -546,11 +561,18 @@
public void updateDisplacement(float displacement) {
// We are moving in the negative x/y direction
displacement = -displacement;
- if (displacement > mTransitionDragLength && mTransitionDragLength > 0) {
- mCurrentShift.updateValue(1);
+ if (displacement > mTransitionDragLength * mDragLengthFactor && mTransitionDragLength > 0) {
+ mCurrentShift.updateValue(mDragLengthFactor);
} else {
float translation = Math.max(displacement, 0);
float shift = mTransitionDragLength == 0 ? 0 : translation / mTransitionDragLength;
+ if (shift > DRAG_LENGTH_FACTOR_START_PULLBACK) {
+ float pullbackProgress = Utilities.getProgress(shift,
+ DRAG_LENGTH_FACTOR_START_PULLBACK, mDragLengthFactor);
+ pullbackProgress = PULLBACK_INTERPOLATOR.getInterpolation(pullbackProgress);
+ shift = DRAG_LENGTH_FACTOR_START_PULLBACK + pullbackProgress
+ * (DRAG_LENGTH_FACTOR_MAX_PULLBACK - DRAG_LENGTH_FACTOR_START_PULLBACK);
+ }
mCurrentShift.updateValue(shift);
}
}
@@ -638,6 +660,8 @@
private void onAnimatorPlaybackControllerCreated(AnimatorPlaybackController anim) {
mLauncherTransitionController = anim;
+ mLauncherTransitionController.dispatchSetInterpolator(t -> t * mDragLengthFactor);
+ mAnimationFactory.adjustActivityControllerInterpolators();
mLauncherTransitionController.dispatchOnStart();
updateLauncherTransitionProgress();
}
@@ -690,7 +714,9 @@
if (mGestureEndTarget == HOME) {
return;
}
- float progress = mCurrentShift.value;
+ // Normalize the progress to 0 to 1, as the animation controller will clamp it to that
+ // anyway. The controller mimics the drag length factor by applying it to its interpolators.
+ float progress = mCurrentShift.value / mDragLengthFactor;
mLauncherTransitionController.setPlayFraction(
progress <= mShiftAtGestureStart || mShiftAtGestureStart >= 1
? 0 : (progress - mShiftAtGestureStart) / (1 - mShiftAtGestureStart));
@@ -835,16 +861,9 @@
}
}
- @UiThread
- private void handleNormalGestureEnd(float endVelocity, boolean isFling, PointF velocity,
+ private GestureEndTarget calculateEndTarget(PointF velocity, float endVelocity, boolean isFling,
boolean isCancel) {
- PointF velocityPxPerMs = new PointF(velocity.x / 1000, velocity.y / 1000);
- long duration = MAX_SWIPE_DURATION;
- float currentShift = mCurrentShift.value;
final GestureEndTarget endTarget;
- float endShift;
- final float startShift;
- Interpolator interpolator = DEACCEL;
final boolean goingToNewTask;
if (mRecentsView != null) {
if (!mRecentsAnimationWrapper.hasTargets()) {
@@ -859,7 +878,7 @@
} else {
goingToNewTask = false;
}
- final boolean reachedOverviewThreshold = currentShift >= MIN_PROGRESS_FOR_OVERVIEW;
+ final boolean reachedOverviewThreshold = mCurrentShift.value >= MIN_PROGRESS_FOR_OVERVIEW;
if (!isFling) {
if (isCancel) {
endTarget = LAST_TASK;
@@ -869,7 +888,7 @@
} else if (goingToNewTask) {
endTarget = NEW_TASK;
} else {
- endTarget = currentShift < MIN_PROGRESS_FOR_OVERVIEW ? LAST_TASK : HOME;
+ endTarget = !reachedOverviewThreshold ? LAST_TASK : HOME;
}
} else {
endTarget = reachedOverviewThreshold && mGestureStarted
@@ -878,12 +897,6 @@
? NEW_TASK
: LAST_TASK;
}
- endShift = endTarget.endShift;
- long expectedDuration = Math.abs(Math.round((endShift - currentShift)
- * MAX_SWIPE_DURATION * SWIPE_DURATION_MULTIPLIER));
- duration = Math.min(MAX_SWIPE_DURATION, expectedDuration);
- startShift = currentShift;
- interpolator = endTarget == RECENTS ? OVERSHOOT_1_2 : DEACCEL;
} else {
if (mMode == Mode.NO_BUTTON && endVelocity < 0 && !mIsShelfPeeking) {
// If swiping at a diagonal, base end target on the faster velocity.
@@ -896,9 +909,36 @@
} else {
endTarget = goingToNewTask ? NEW_TASK : LAST_TASK;
}
- endShift = endTarget.endShift;
+ }
+
+ int stateFlags = OverviewInteractionState.INSTANCE.get(mActivity).getSystemUiStateFlags();
+ if ((stateFlags & SYSUI_STATE_OVERVIEW_DISABLED) != 0
+ && (endTarget == RECENTS || endTarget == LAST_TASK)) {
+ return LAST_TASK;
+ }
+ return endTarget;
+ }
+
+ @UiThread
+ private void handleNormalGestureEnd(float endVelocity, boolean isFling, PointF velocity,
+ boolean isCancel) {
+ PointF velocityPxPerMs = new PointF(velocity.x / 1000, velocity.y / 1000);
+ long duration = MAX_SWIPE_DURATION;
+ float currentShift = mCurrentShift.value;
+ final GestureEndTarget endTarget = calculateEndTarget(velocity, endVelocity,
+ isFling, isCancel);
+ float endShift = endTarget.endShift;
+ final float startShift;
+ Interpolator interpolator = DEACCEL;
+ if (!isFling) {
+ long expectedDuration = Math.abs(Math.round((endShift - currentShift)
+ * MAX_SWIPE_DURATION * SWIPE_DURATION_MULTIPLIER));
+ duration = Math.min(MAX_SWIPE_DURATION, expectedDuration);
+ startShift = currentShift;
+ interpolator = endTarget == RECENTS ? OVERSHOOT_1_2 : DEACCEL;
+ } else {
startShift = Utilities.boundToRange(currentShift - velocityPxPerMs.y
- * SINGLE_FRAME_MS / mTransitionDragLength, 0, 1);
+ * SINGLE_FRAME_MS / mTransitionDragLength, 0, mDragLengthFactor);
float minFlingVelocity = mContext.getResources()
.getDimension(R.dimen.quickstep_fling_min_velocity);
if (Math.abs(endVelocity) > minFlingVelocity && mTransitionDragLength > 0) {
@@ -1057,6 +1097,7 @@
mLauncherTransitionController.getAnimationPlayer().end();
} else {
mLauncherTransitionController.dispatchSetInterpolator(adjustedInterpolator);
+ mAnimationFactory.adjustActivityControllerInterpolators();
mLauncherTransitionController.getAnimationPlayer().setDuration(duration);
if (QUICKSTEP_SPRINGS.get()) {
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java
index d01b5ec..db2af59 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/DeviceLockedInputConsumer.java
@@ -15,26 +15,102 @@
*/
package com.android.quickstep.inputconsumers;
+import static android.view.MotionEvent.ACTION_CANCEL;
+import static android.view.MotionEvent.ACTION_POINTER_DOWN;
+import static android.view.MotionEvent.ACTION_UP;
+
import static com.android.launcher3.Utilities.squaredHypot;
import static com.android.launcher3.Utilities.squaredTouchSlop;
+import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
+import static com.android.quickstep.WindowTransformSwipeHandler.MIN_PROGRESS_FOR_OVERVIEW;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.graphics.Point;
import android.graphics.PointF;
+import android.graphics.Rect;
+import android.graphics.RectF;
import android.view.MotionEvent;
+import android.view.VelocityTracker;
+import android.view.ViewConfiguration;
+import android.view.WindowManager;
+
+import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
+import com.android.quickstep.LockScreenRecentsActivity;
+import com.android.quickstep.MultiStateCallback;
+import com.android.quickstep.SwipeSharedState;
+import com.android.quickstep.util.ClipAnimationHelper;
+import com.android.quickstep.util.RecentsAnimationListenerSet;
+import com.android.quickstep.util.SwipeAnimationTargetSet;
+import com.android.systemui.shared.system.ActivityManagerWrapper;
+import com.android.systemui.shared.system.BackgroundExecutor;
+import com.android.systemui.shared.system.InputMonitorCompat;
+import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
/**
* A dummy input consumer used when the device is still locked, e.g. from secure camera.
*/
-public class DeviceLockedInputConsumer implements InputConsumer {
+public class DeviceLockedInputConsumer implements InputConsumer,
+ SwipeAnimationTargetSet.SwipeAnimationListener {
+
+ private static final float SCALE_DOWN = 0.75f;
+
+ private static final String[] STATE_NAMES = DEBUG_STATES ? new String[2] : null;
+ private static int getFlagForIndex(int index, String name) {
+ if (DEBUG_STATES) {
+ STATE_NAMES[index] = name;
+ }
+ return 1 << index;
+ }
+
+ private static final int STATE_TARGET_RECEIVED =
+ getFlagForIndex(0, "STATE_TARGET_RECEIVED");
+ private static final int STATE_HANDLER_INVALIDATED =
+ getFlagForIndex(1, "STATE_HANDLER_INVALIDATED");
private final Context mContext;
private final float mTouchSlopSquared;
- private final PointF mTouchDown = new PointF();
+ private final SwipeSharedState mSwipeSharedState;
+ private final InputMonitorCompat mInputMonitorCompat;
- public DeviceLockedInputConsumer(Context context) {
+ private final PointF mTouchDown = new PointF();
+ private final ClipAnimationHelper mClipAnimationHelper;
+ private final ClipAnimationHelper.TransformParams mTransformParams;
+ private final Point mDisplaySize;
+ private final MultiStateCallback mStateCallback;
+ private final RectF mSwipeTouchRegion;
+ public final int mRunningTaskId;
+
+ private VelocityTracker mVelocityTracker;
+ private float mProgress;
+
+ private boolean mThresholdCrossed = false;
+
+ private SwipeAnimationTargetSet mTargetSet;
+
+ public DeviceLockedInputConsumer(Context context, SwipeSharedState swipeSharedState,
+ InputMonitorCompat inputMonitorCompat, RectF swipeTouchRegion, int runningTaskId) {
mContext = context;
mTouchSlopSquared = squaredTouchSlop(context);
+ mSwipeSharedState = swipeSharedState;
+ mClipAnimationHelper = new ClipAnimationHelper(context);
+ mTransformParams = new ClipAnimationHelper.TransformParams();
+ mInputMonitorCompat = inputMonitorCompat;
+ mSwipeTouchRegion = swipeTouchRegion;
+ mRunningTaskId = runningTaskId;
+
+ // Do not use DeviceProfile as the user data might be locked
+ mDisplaySize = new Point();
+ context.getSystemService(WindowManager.class).getDefaultDisplay().getRealSize(mDisplaySize);
+
+ // Init states
+ mStateCallback = new MultiStateCallback(STATE_NAMES);
+ mStateCallback.addCallback(STATE_TARGET_RECEIVED | STATE_HANDLER_INVALIDATED,
+ this::endRemoteAnimation);
+
+ mVelocityTracker = VelocityTracker.obtain();
}
@Override
@@ -44,17 +120,137 @@
@Override
public void onMotionEvent(MotionEvent ev) {
+ if (mVelocityTracker == null) {
+ return;
+ }
+ mVelocityTracker.addMovement(ev);
+
float x = ev.getX();
float y = ev.getY();
- if (ev.getAction() == MotionEvent.ACTION_DOWN) {
- mTouchDown.set(x, y);
- } else if (ev.getAction() == MotionEvent.ACTION_MOVE) {
- if (squaredHypot(x - mTouchDown.x, y - mTouchDown.y) > mTouchSlopSquared) {
+ switch (ev.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ mTouchDown.set(x, y);
+ break;
+ case ACTION_POINTER_DOWN: {
+ if (!mThresholdCrossed) {
+ // Cancel interaction in case of multi-touch interaction
+ int ptrIdx = ev.getActionIndex();
+ if (!mSwipeTouchRegion.contains(ev.getX(ptrIdx), ev.getY(ptrIdx))) {
+ int action = ev.getAction();
+ ev.setAction(ACTION_CANCEL);
+ finishTouchTracking(ev);
+ ev.setAction(action);
+ }
+ }
+ break;
+ }
+ case MotionEvent.ACTION_MOVE: {
+ if (!mThresholdCrossed) {
+ if (squaredHypot(x - mTouchDown.x, y - mTouchDown.y) > mTouchSlopSquared) {
+ startRecentsTransition();
+ }
+ } else {
+ float dy = Math.max(mTouchDown.y - y, 0);
+ mProgress = dy / mDisplaySize.y;
+ mTransformParams.setProgress(mProgress);
+ if (mTargetSet != null) {
+ mClipAnimationHelper.applyTransform(mTargetSet, mTransformParams);
+ }
+ }
+ break;
+ }
+ case MotionEvent.ACTION_CANCEL:
+ case MotionEvent.ACTION_UP:
+ finishTouchTracking(ev);
+ break;
+ }
+ }
+
+ /**
+ * Called when the gesture has ended. Does not correlate to the completion of the interaction as
+ * the animation can still be running.
+ */
+ private void finishTouchTracking(MotionEvent ev) {
+ mStateCallback.setState(STATE_HANDLER_INVALIDATED);
+ if (mThresholdCrossed && ev.getAction() == ACTION_UP) {
+ mVelocityTracker.computeCurrentVelocity(1000,
+ ViewConfiguration.get(mContext).getScaledMaximumFlingVelocity());
+
+ float velocityY = mVelocityTracker.getYVelocity();
+ float flingThreshold = mContext.getResources()
+ .getDimension(R.dimen.quickstep_fling_threshold_velocity);
+
+ boolean dismissTask;
+ if (Math.abs(velocityY) > flingThreshold) {
+ // Is fling
+ dismissTask = velocityY < 0;
+ } else {
+ dismissTask = mProgress >= (1 - MIN_PROGRESS_FOR_OVERVIEW);
+ }
+ if (dismissTask) {
// For now, just start the home intent so user is prompted to unlock the device.
mContext.startActivity(new Intent(Intent.ACTION_MAIN)
.addCategory(Intent.CATEGORY_HOME)
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
}
}
+ mVelocityTracker.recycle();
+ mVelocityTracker = null;
+ }
+
+ private void startRecentsTransition() {
+ mThresholdCrossed = true;
+ RecentsAnimationListenerSet newListenerSet =
+ mSwipeSharedState.newRecentsAnimationListenerSet();
+ newListenerSet.addListener(this);
+ Intent intent = new Intent(Intent.ACTION_MAIN)
+ .addCategory(Intent.CATEGORY_DEFAULT)
+ .setComponent(new ComponentName(mContext, LockScreenRecentsActivity.class))
+ .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+
+ mInputMonitorCompat.pilferPointers();
+ BackgroundExecutor.get().submit(
+ () -> ActivityManagerWrapper.getInstance().startRecentsActivity(
+ intent, null, newListenerSet, null, null));
+ }
+
+ @Override
+ public void onRecentsAnimationStart(SwipeAnimationTargetSet targetSet) {
+ mTargetSet = targetSet;
+
+ Rect displaySize = new Rect(0, 0, mDisplaySize.x, mDisplaySize.y);
+ RemoteAnimationTargetCompat targetCompat = targetSet.findTask(mRunningTaskId);
+ if (targetCompat != null) {
+ mClipAnimationHelper.updateSource(displaySize, targetCompat);
+ }
+
+ Utilities.scaleRectAboutCenter(displaySize, SCALE_DOWN);
+ displaySize.offsetTo(displaySize.left, 0);
+ mClipAnimationHelper.updateTargetRect(displaySize);
+ mClipAnimationHelper.applyTransform(mTargetSet, mTransformParams);
+
+ mStateCallback.setState(STATE_TARGET_RECEIVED);
+ }
+
+ @Override
+ public void onRecentsAnimationCanceled() {
+ mTargetSet = null;
+ }
+
+ private void endRemoteAnimation() {
+ if (mTargetSet != null) {
+ mTargetSet.finishController(
+ false /* toRecents */, null /* callback */, false /* sendUserLeaveHint */);
+ }
+ }
+
+ @Override
+ public void onConsumerAboutToBeSwitched() {
+ mStateCallback.setState(STATE_HANDLER_INVALIDATED);
+ }
+
+ @Override
+ public boolean allowInterceptByParent() {
+ return !mThresholdCrossed;
}
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ClipAnimationHelper.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ClipAnimationHelper.java
index c164a24..e2fb602 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ClipAnimationHelper.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/ClipAnimationHelper.java
@@ -23,7 +23,6 @@
import android.annotation.TargetApi;
import android.content.Context;
-import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Matrix.ScaleToFit;
import android.graphics.Rect;
@@ -160,14 +159,16 @@
public RectF applyTransform(RemoteAnimationTargetSet targetSet, TransformParams params,
boolean launcherOnTop) {
+ float progress = params.progress;
if (params.currentRect == null) {
RectF currentRect;
mTmpRectF.set(mTargetRect);
Utilities.scaleRectFAboutCenter(mTmpRectF, params.offsetScale);
- float progress = params.progress;
currentRect = mRectFEvaluator.evaluate(progress, mSourceRect, mTmpRectF);
currentRect.offset(params.offsetX, 0);
+ // Don't clip past progress > 1.
+ progress = Math.min(1, progress);
final RectF sourceWindowClipInsets = params.forLiveTile
? mSourceWindowClipInsetsForLiveTile : mSourceWindowClipInsets;
mClipRectF.left = sourceWindowClipInsets.left * progress;
@@ -189,7 +190,7 @@
float alpha = 1f;
int layer = RemoteAnimationProvider.getLayer(app, mBoostModeTargetLayers);
float cornerRadius = 0f;
- float scale = params.currentRect.width() / crop.width();
+ float scale = Math.max(params.currentRect.width(), mTargetRect.width()) / crop.width();
if (app.mode == targetSet.targetMode) {
if (app.activityType != RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME) {
mTmpMatrix.setRectToRect(mSourceRect, params.currentRect, ScaleToFit.FILL);
@@ -198,7 +199,7 @@
if (mSupportsRoundedCornersOnWindows) {
float windowCornerRadius = mUseRoundedCornersOnWindows
? mWindowCornerRadius : 0;
- cornerRadius = Utilities.mapRange(params.progress, windowCornerRadius,
+ cornerRadius = Utilities.mapRange(progress, windowCornerRadius,
mTaskCornerRadius);
mCurrentCornerRadius = cornerRadius;
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
index 053b738..3364377 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/TaskView.java
@@ -633,6 +633,7 @@
* @param progress: 0 = show icon and no insets; 1 = don't show icon and show full insets.
*/
public void setFullscreenProgress(float progress) {
+ progress = Utilities.boundToRange(progress, 0, 1);
if (progress == mFullscreenProgress) {
return;
}
diff --git a/quickstep/res/layout/task.xml b/quickstep/res/layout/task.xml
index ba4ea8b..1869188 100644
--- a/quickstep/res/layout/task.xml
+++ b/quickstep/res/layout/task.xml
@@ -44,7 +44,7 @@
<FrameLayout
android:id="@+id/proactive_suggest_container"
android:layout_width="match_parent"
- android:layout_height="48dp"
+ android:layout_height="wrap_content"
android:gravity="center"
android:visibility="gone"
/>
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java
index 0c29fcf..6030cea 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java
@@ -26,6 +26,7 @@
import static com.android.launcher3.anim.Interpolators.DEACCEL;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.config.FeatureFlags.QUICKSTEP_SPRINGS;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
import android.animation.TimeInterpolator;
import android.animation.ValueAnimator;
@@ -46,9 +47,11 @@
import com.android.launcher3.uioverrides.states.OverviewState;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
+import com.android.quickstep.OverviewInteractionState;
import com.android.quickstep.RecentsModel;
import com.android.quickstep.TouchInteractionService;
import com.android.quickstep.util.LayoutUtils;
+import com.android.systemui.shared.system.QuickStepContract;
/**
* Touch controller for handling various state transitions in portrait UI.
@@ -135,7 +138,10 @@
} else if (fromState == OVERVIEW) {
return isDragTowardPositive ? ALL_APPS : NORMAL;
} else if (fromState == NORMAL && isDragTowardPositive) {
+ int stateFlags = OverviewInteractionState.INSTANCE.get(mLauncher)
+ .getSystemUiStateFlags();
return mAllowDragToOverview && TouchInteractionService.isConnected()
+ && (stateFlags & SYSUI_STATE_OVERVIEW_DISABLED) == 0
? OVERVIEW : ALL_APPS;
}
return fromState;
diff --git a/quickstep/src/com/android/quickstep/ActivityControlHelper.java b/quickstep/src/com/android/quickstep/ActivityControlHelper.java
index 17f88c9..b0acd9b 100644
--- a/quickstep/src/com/android/quickstep/ActivityControlHelper.java
+++ b/quickstep/src/com/android/quickstep/ActivityControlHelper.java
@@ -118,6 +118,8 @@
void createActivityController(long transitionLength);
+ default void adjustActivityControllerInterpolators() { }
+
default void onTransitionCancelled() { }
default void setShelfState(ShelfAnimState animState, Interpolator interpolator,
diff --git a/quickstep/src/com/android/quickstep/OverviewComponentObserver.java b/quickstep/src/com/android/quickstep/OverviewComponentObserver.java
index a2f07e3..b5da836 100644
--- a/quickstep/src/com/android/quickstep/OverviewComponentObserver.java
+++ b/quickstep/src/com/android/quickstep/OverviewComponentObserver.java
@@ -22,6 +22,7 @@
import static com.android.launcher3.util.PackageManagerHelper.getPackageFilter;
import static com.android.systemui.shared.system.PackageManagerWrapper.ACTION_PREFERRED_ACTIVITY_CHANGED;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_HOME_DISABLED;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
@@ -32,6 +33,7 @@
import com.android.systemui.shared.system.PackageManagerWrapper;
+import com.android.systemui.shared.system.QuickStepContract;
import java.util.ArrayList;
/**
@@ -56,6 +58,7 @@
private String mUpdateRegisteredPackage;
private ActivityControlHelper mActivityControlHelper;
private Intent mOverviewIntent;
+ private int mSystemUiStateFlags;
public OverviewComponentObserver(Context context) {
mContext = context;
@@ -71,6 +74,15 @@
updateOverviewTargets();
}
+ public void onSystemUiStateChanged(int stateFlags) {
+ boolean homeDisabledChanged = (mSystemUiStateFlags & SYSUI_STATE_HOME_DISABLED)
+ != (stateFlags & SYSUI_STATE_HOME_DISABLED);
+ mSystemUiStateFlags = stateFlags;
+ if (homeDisabledChanged) {
+ updateOverviewTargets();
+ }
+ }
+
/**
* Update overview intent and {@link ActivityControlHelper} based off the current launcher home
* component.
@@ -81,7 +93,8 @@
final String overviewIntentCategory;
ComponentName overviewComponent;
- if (defaultHome == null || mMyHomeComponent.equals(defaultHome)) {
+ if ((mSystemUiStateFlags & SYSUI_STATE_HOME_DISABLED) == 0 &&
+ (defaultHome == null || mMyHomeComponent.equals(defaultHome))) {
// User default home is same as out home app. Use Overview integrated in Launcher.
overviewComponent = mMyHomeComponent;
mActivityControlHelper = new LauncherActivityControllerHelper();
diff --git a/quickstep/src/com/android/quickstep/OverviewInteractionState.java b/quickstep/src/com/android/quickstep/OverviewInteractionState.java
index 79d922c..78b48d7 100644
--- a/quickstep/src/com/android/quickstep/OverviewInteractionState.java
+++ b/quickstep/src/com/android/quickstep/OverviewInteractionState.java
@@ -53,6 +53,8 @@
private ISystemUiProxy mISystemUiProxy;
private float mBackButtonAlpha = 1;
+ private int mSystemUiStateFlags;
+
private OverviewInteractionState(Context context) {
mContext = context;
@@ -83,6 +85,14 @@
mBgHandler.obtainMessage(MSG_SET_PROXY, proxy).sendToTarget();
}
+ public void setSystemUiStateFlags(int stateFlags) {
+ mSystemUiStateFlags = stateFlags;
+ }
+
+ public int getSystemUiStateFlags() {
+ return mSystemUiStateFlags;
+ }
+
private boolean handleUiMessage(Message msg) {
if (msg.what == MSG_SET_BACK_BUTTON_ALPHA) {
mBackButtonAlpha = (float) msg.obj;
diff --git a/src/com/android/launcher3/allapps/DiscoveryBounce.java b/src/com/android/launcher3/allapps/DiscoveryBounce.java
index 1d62b43..8c59626 100644
--- a/src/com/android/launcher3/allapps/DiscoveryBounce.java
+++ b/src/com/android/launcher3/allapps/DiscoveryBounce.java
@@ -30,6 +30,9 @@
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.Launcher;
+import com.android.launcher3.LauncherState;
+import com.android.launcher3.LauncherStateManager;
+import com.android.launcher3.LauncherStateManager.StateListener;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.compat.UserManagerCompat;
@@ -52,6 +55,16 @@
private final Launcher mLauncher;
private final Animator mDiscoBounceAnimation;
+ private final StateListener mStateListener = new StateListener() {
+ @Override
+ public void onStateTransitionStart(LauncherState toState) {
+ handleClose(false);
+ }
+
+ @Override
+ public void onStateTransitionComplete(LauncherState finalState) {}
+ };
+
public DiscoveryBounce(Launcher launcher, float delta) {
super(launcher, null);
mLauncher = launcher;
@@ -67,6 +80,7 @@
}
});
mDiscoBounceAnimation.addListener(controller.getProgressAnimatorListener());
+ launcher.getStateManager().addStateListener(mStateListener);
}
@Override
@@ -105,6 +119,7 @@
// Reset the all-apps progress to what ever it was previously.
mLauncher.getAllAppsController().setProgress(mLauncher.getStateManager()
.getState().getVerticalProgress(mLauncher));
+ mLauncher.getStateManager().removeStateListener(mStateListener);
}
}