Deleting Quickscrub related logic

Bug: 124255113
Change-Id: Ic5f2338f1e3ae0a0cfb08f822dee0e01ae54a7b0
This commit is contained in:
Sunny Goyal 2019-02-13 14:57:52 -08:00
parent 435041de60
commit 3f271d4b7f
30 changed files with 244 additions and 1659 deletions

View File

@ -28,18 +28,6 @@ public final class GoLauncherAppTransitionManagerImpl extends QuickstepAppTransi
return mLauncher.getStateManager().getState().overviewUi; return mLauncher.getStateManager().getState().overviewUi;
} }
@Override
protected boolean isQuickSwitchInProgress() {
// Go does not support quick scrub.
return false;
}
@Override
protected ActivityOptions getQuickSwitchActivityOptions() {
// Go does not support quick scrub.
return null;
}
@Override @Override
protected void composeRecentsLaunchAnimator(AnimatorSet anim, View v, protected void composeRecentsLaunchAnimator(AnimatorSet anim, View v,
RemoteAnimationTargetCompat[] targets, boolean launcherClosing) { RemoteAnimationTargetCompat[] targets, boolean launcherClosing) {

View File

@ -1,26 +0,0 @@
/*
* 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;
/**
* Extension of overview state used for QuickScrub. Same as {@link OverviewState} for Go as we do
* not support quickscrub.
*/
public final class FastOverviewState extends OverviewState {
public FastOverviewState(int id) {
super(id);
}
}

View File

@ -18,7 +18,6 @@ package com.android.quickstep;
import static com.android.launcher3.LauncherState.OVERVIEW; import static com.android.launcher3.LauncherState.OVERVIEW;
import android.app.ActivityManager;
import android.content.Context; import android.content.Context;
import android.graphics.Rect; import android.graphics.Rect;
@ -31,7 +30,6 @@ import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.dragndrop.DragLayer; import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.userevent.nano.LauncherLogProto; import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.util.MultiValueAlpha.AlphaProperty; import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
import com.android.quickstep.util.TransformedRect;
import com.android.quickstep.views.IconRecentsView; import com.android.quickstep.views.IconRecentsView;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat; import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
@ -51,18 +49,6 @@ public final class LauncherActivityControllerHelper implements ActivityControlHe
return null; return null;
} }
@Override
public void onQuickInteractionStart(Launcher activity, ActivityManager.RunningTaskInfo taskInfo,
boolean activityVisible, TouchInteractionLog touchInteractionLog) {
// Go does not have quick interactions.
}
@Override
public float getTranslationYForQuickScrub(TransformedRect targetRect, DeviceProfile dp,
Context context) {
// Go does not have quick scrub.
return 0;
}
@Override @Override
public void executeOnWindowAvailable(Launcher activity, Runnable action) { public void executeOnWindowAvailable(Launcher activity, Runnable action) {
@ -77,7 +63,7 @@ public final class LauncherActivityControllerHelper implements ActivityControlHe
@Override @Override
public int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context, public int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context,
int interactionType, TransformedRect outRect) { Rect outRect) {
// TODO Implement outRect depending on where the task should animate to. // TODO Implement outRect depending on where the task should animate to.
// Go does not support swipe up gesture. // Go does not support swipe up gesture.
return 0; return 0;
@ -101,8 +87,7 @@ public final class LauncherActivityControllerHelper implements ActivityControlHe
//TODO: Implement this based off where the recents view needs to be for app => recents anim. //TODO: Implement this based off where the recents view needs to be for app => recents anim.
return new AnimationFactory() { return new AnimationFactory() {
@Override @Override
public void createActivityController(long transitionLength, public void createActivityController(long transitionLength) {}
@TouchConsumer.InteractionType int interactionType) {}
@Override @Override
public void onTransitionCancelled() {} public void onTransitionCancelled() {}
@ -163,12 +148,6 @@ public final class LauncherActivityControllerHelper implements ActivityControlHe
return true; return true;
} }
@Override
public boolean deferStartingActivity(int downHitTarget) {
// Go only supports back to overview so we always defer starting activity.
return true;
}
@Override @Override
public boolean supportsLongSwipe(Launcher activity) { public boolean supportsLongSwipe(Launcher activity) {
// Go does not support long swipe from the app. // Go does not support long swipe from the app.

View File

@ -60,34 +60,17 @@ public final class LauncherAppTransitionManagerImpl extends QuickstepAppTransiti
&& findTaskViewToLaunch(mLauncher, v, targets) != null; && findTaskViewToLaunch(mLauncher, v, targets) != null;
} }
@Override
protected boolean isQuickSwitchInProgress() {
return mRecentsView.getQuickScrubController().isQuickSwitch();
}
@Override
protected ActivityOptions getQuickSwitchActivityOptions() {
return ActivityOptions.makeCustomAnimation(mLauncher, R.anim.no_anim,
R.anim.no_anim);
}
@Override @Override
protected void composeRecentsLaunchAnimator(@NonNull AnimatorSet anim, @NonNull View v, protected void composeRecentsLaunchAnimator(@NonNull AnimatorSet anim, @NonNull View v,
@NonNull RemoteAnimationTargetCompat[] targets, boolean launcherClosing) { @NonNull RemoteAnimationTargetCompat[] targets, boolean launcherClosing) {
RecentsView recentsView = mLauncher.getOverviewPanel(); RecentsView recentsView = mLauncher.getOverviewPanel();
boolean skipLauncherChanges = !launcherClosing; boolean skipLauncherChanges = !launcherClosing;
boolean isLaunchingFromQuickscrub =
recentsView.getQuickScrubController().isWaitingForTaskLaunch();
TaskView taskView = findTaskViewToLaunch(mLauncher, v, targets); TaskView taskView = findTaskViewToLaunch(mLauncher, v, targets);
int duration = isLaunchingFromQuickscrub
? RECENTS_QUICKSCRUB_LAUNCH_DURATION
: RECENTS_LAUNCH_DURATION;
ClipAnimationHelper helper = new ClipAnimationHelper(mLauncher); ClipAnimationHelper helper = new ClipAnimationHelper(mLauncher);
anim.play(getRecentsWindowAnimator(taskView, skipLauncherChanges, targets, helper) anim.play(getRecentsWindowAnimator(taskView, skipLauncherChanges, targets, helper)
.setDuration(duration)); .setDuration(RECENTS_LAUNCH_DURATION));
Animator childStateAnimation = null; Animator childStateAnimation = null;
// Found a visible recents task that matches the opening app, lets launch the app from there // Found a visible recents task that matches the opening app, lets launch the app from there
@ -96,7 +79,7 @@ public final class LauncherAppTransitionManagerImpl extends QuickstepAppTransiti
if (launcherClosing) { if (launcherClosing) {
launcherAnim = recentsView.createAdjacentPageAnimForTaskLaunch(taskView, helper); launcherAnim = recentsView.createAdjacentPageAnimForTaskLaunch(taskView, helper);
launcherAnim.setInterpolator(Interpolators.TOUCH_RESPONSE_INTERPOLATOR); launcherAnim.setInterpolator(Interpolators.TOUCH_RESPONSE_INTERPOLATOR);
launcherAnim.setDuration(duration); launcherAnim.setDuration(RECENTS_LAUNCH_DURATION);
// Make sure recents gets fixed up by resetting task alphas and scales, etc. // Make sure recents gets fixed up by resetting task alphas and scales, etc.
windowAnimEndListener = new AnimatorListenerAdapter() { windowAnimEndListener = new AnimatorListenerAdapter() {
@ -108,10 +91,11 @@ public final class LauncherAppTransitionManagerImpl extends QuickstepAppTransiti
}; };
} else { } else {
AnimatorPlaybackController controller = AnimatorPlaybackController controller =
mLauncher.getStateManager().createAnimationToNewWorkspace(NORMAL, duration); mLauncher.getStateManager().createAnimationToNewWorkspace(NORMAL,
RECENTS_LAUNCH_DURATION);
controller.dispatchOnStart(); controller.dispatchOnStart();
childStateAnimation = controller.getTarget(); childStateAnimation = controller.getTarget();
launcherAnim = controller.getAnimationPlayer().setDuration(duration); launcherAnim = controller.getAnimationPlayer().setDuration(RECENTS_LAUNCH_DURATION);
windowAnimEndListener = new AnimatorListenerAdapter() { windowAnimEndListener = new AnimatorListenerAdapter() {
@Override @Override
public void onAnimationEnd(Animator animation) { public void onAnimationEnd(Animator animation) {

View File

@ -15,10 +15,11 @@
*/ */
package com.android.launcher3.uioverrides; package com.android.launcher3.uioverrides;
import static com.android.launcher3.LauncherAnimUtils.OVERVIEW_TRANSITION_MS;
import android.os.RemoteException; import android.os.RemoteException;
import com.android.launcher3.Launcher; import com.android.launcher3.Launcher;
import com.android.launcher3.allapps.AllAppsTransitionController; import com.android.launcher3.allapps.AllAppsTransitionController;
import com.android.quickstep.QuickScrubController;
import com.android.quickstep.RecentsModel; import com.android.quickstep.RecentsModel;
import com.android.quickstep.util.LayoutUtils; import com.android.quickstep.util.LayoutUtils;
import com.android.quickstep.views.RecentsView; import com.android.quickstep.views.RecentsView;
@ -33,7 +34,7 @@ public class BackgroundAppState extends OverviewState {
FLAG_DISABLE_RESTORE | FLAG_OVERVIEW_UI | FLAG_DISABLE_ACCESSIBILITY; FLAG_DISABLE_RESTORE | FLAG_OVERVIEW_UI | FLAG_DISABLE_ACCESSIBILITY;
public BackgroundAppState(int id) { public BackgroundAppState(int id) {
super(id, QuickScrubController.QUICK_SCRUB_FROM_HOME_START_DURATION, STATE_FLAGS); super(id, OVERVIEW_TRANSITION_MS, STATE_FLAGS);
} }
@Override @Override
@ -51,7 +52,7 @@ public class BackgroundAppState extends OverviewState {
@Override @Override
public float[] getOverviewScaleAndTranslationYFactor(Launcher launcher) { public float[] getOverviewScaleAndTranslationYFactor(Launcher launcher) {
// Initialize the recents view scale to what it would be when starting swipe up/quickscrub // Initialize the recents view scale to what it would be when starting swipe up
RecentsView recentsView = launcher.getOverviewPanel(); RecentsView recentsView = launcher.getOverviewPanel();
recentsView.getTaskSize(sTempRect); recentsView.getTaskSize(sTempRect);
int appWidth = launcher.getDragLayer().getWidth(); int appWidth = launcher.getDragLayer().getWidth();

View File

@ -1,95 +0,0 @@
/*
* Copyright (C) 2018 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;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Rect;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher;
import com.android.launcher3.R;
import com.android.quickstep.QuickScrubController;
import com.android.quickstep.views.RecentsView;
/**
* Extension of overview state used for QuickScrub
*/
public class FastOverviewState extends OverviewState {
private static final float MAX_PREVIEW_SCALE_UP = 1.3f;
/**
* Vertical transition of the task previews relative to the full container.
*/
public static final float OVERVIEW_TRANSLATION_FACTOR = 0.4f;
public static final float OVERVIEW_CENTERED_TRANSLATION_FACTOR = 0.5f;
private static final int STATE_FLAGS = FLAG_DISABLE_RESTORE | FLAG_DISABLE_INTERACTION
| FLAG_OVERVIEW_UI | FLAG_HIDE_BACK_BUTTON | FLAG_DISABLE_ACCESSIBILITY;
public FastOverviewState(int id) {
super(id, QuickScrubController.QUICK_SCRUB_FROM_HOME_START_DURATION, STATE_FLAGS);
}
@Override
public void onStateTransitionEnd(Launcher launcher) {
super.onStateTransitionEnd(launcher);
RecentsView recentsView = launcher.getOverviewPanel();
recentsView.getQuickScrubController().onFinishedTransitionToQuickScrub();
}
@Override
public int getVisibleElements(Launcher launcher) {
return NONE;
}
@Override
public float[] getOverviewScaleAndTranslationYFactor(Launcher launcher) {
RecentsView recentsView = launcher.getOverviewPanel();
recentsView.getTaskSize(sTempRect);
boolean isQuickSwitch = recentsView.getQuickScrubController().isQuickSwitch();
float translationYFactor = isQuickSwitch
? OVERVIEW_CENTERED_TRANSLATION_FACTOR
: OVERVIEW_TRANSLATION_FACTOR;
return new float[] {getOverviewScale(launcher.getDeviceProfile(), sTempRect, launcher,
isQuickSwitch), translationYFactor};
}
public static float getOverviewScale(DeviceProfile dp, Rect taskRect, Context context,
boolean isQuickSwitch) {
if (dp.isVerticalBarLayout() && !isQuickSwitch) {
return 1f;
}
Resources res = context.getResources();
float usedHeight = taskRect.height() + res.getDimension(R.dimen.task_thumbnail_top_margin);
float usedWidth = taskRect.width() + 2 * (res.getDimension(R.dimen.recents_page_spacing)
+ res.getDimension(R.dimen.quickscrub_adjacent_visible_width));
if (isQuickSwitch) {
usedWidth = taskRect.width();
return Math.max(dp.availableHeightPx / usedHeight, dp.availableWidthPx / usedWidth);
}
return Math.min(Math.min(dp.availableHeightPx / usedHeight,
dp.availableWidthPx / usedWidth), MAX_PREVIEW_SCALE_UP);
}
@Override
public void onStateDisabled(Launcher launcher) {
super.onStateDisabled(launcher);
launcher.<RecentsView>getOverviewPanel().getQuickScrubController().cancelActiveQuickscrub();
}
}

View File

@ -15,10 +15,6 @@
*/ */
package com.android.launcher3.uioverrides; package com.android.launcher3.uioverrides;
import static com.android.launcher3.LauncherState.FAST_OVERVIEW;
import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.quickstep.QuickScrubController.QUICK_SCRUB_START_INTERPOLATOR;
import static com.android.quickstep.QuickScrubController.QUICK_SCRUB_TRANSLATION_Y_FACTOR;
import static com.android.quickstep.views.LauncherRecentsView.TRANSLATION_Y_FACTOR; import static com.android.quickstep.views.LauncherRecentsView.TRANSLATION_Y_FACTOR;
import static com.android.quickstep.views.RecentsView.CONTENT_ALPHA; import static com.android.quickstep.views.RecentsView.CONTENT_ALPHA;
@ -26,18 +22,16 @@ import android.animation.ValueAnimator;
import android.annotation.TargetApi; import android.annotation.TargetApi;
import android.os.Build; import android.os.Build;
import android.util.FloatProperty; import android.util.FloatProperty;
import android.view.animation.Interpolator;
import androidx.annotation.NonNull;
import com.android.launcher3.Launcher; import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState; import com.android.launcher3.LauncherState;
import com.android.launcher3.LauncherStateManager.AnimationConfig; import com.android.launcher3.LauncherStateManager.AnimationConfig;
import com.android.launcher3.anim.AnimatorSetBuilder; import com.android.launcher3.anim.AnimatorSetBuilder;
import com.android.launcher3.anim.Interpolators;
import com.android.quickstep.views.LauncherRecentsView; import com.android.quickstep.views.LauncherRecentsView;
import com.android.quickstep.views.RecentsView; import com.android.quickstep.views.RecentsView;
import androidx.annotation.NonNull;
/** /**
* State handler for handling UI changes for {@link LauncherRecentsView}. In addition to managing * State handler for handling UI changes for {@link LauncherRecentsView}. In addition to managing
* the basic view properties, this class also manages changes in the task visuals. * the basic view properties, this class also manages changes in the task visuals.
@ -80,16 +74,6 @@ public final class RecentsViewStateController extends
} }
} }
@Override
Interpolator getScaleAndTransYInterpolator(@NonNull LauncherState toState,
@NonNull AnimatorSetBuilder builder) {
if (mLauncher.getStateManager().getState() == OVERVIEW && toState == FAST_OVERVIEW) {
return Interpolators.clampToProgress(QUICK_SCRUB_START_INTERPOLATOR, 0,
QUICK_SCRUB_TRANSLATION_Y_FACTOR);
}
return super.getScaleAndTransYInterpolator(toState, builder);
}
@Override @Override
FloatProperty<LauncherRecentsView> getTranslationYFactorProperty() { FloatProperty<LauncherRecentsView> getTranslationYFactorProperty() {
return TRANSLATION_Y_FACTOR; return TRANSLATION_Y_FACTOR;

View File

@ -19,23 +19,16 @@ import static android.view.View.TRANSLATION_Y;
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY; import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
import static com.android.launcher3.LauncherState.BACKGROUND_APP; import static com.android.launcher3.LauncherState.BACKGROUND_APP;
import static com.android.launcher3.LauncherState.FAST_OVERVIEW;
import static com.android.launcher3.LauncherState.NORMAL; import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW; import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.allapps.AllAppsTransitionController.SPRING_DAMPING_RATIO; import static com.android.launcher3.allapps.AllAppsTransitionController.SPRING_DAMPING_RATIO;
import static com.android.launcher3.allapps.AllAppsTransitionController.SPRING_STIFFNESS; import static com.android.launcher3.allapps.AllAppsTransitionController.SPRING_STIFFNESS;
import static com.android.launcher3.anim.Interpolators.LINEAR; import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.states.RotationHelper.REQUEST_LOCK;
import static com.android.quickstep.TouchConsumer.INTERACTION_NORMAL;
import static com.android.quickstep.TouchConsumer.INTERACTION_QUICK_SCRUB;
import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_BACK;
import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_ROTATION;
import android.animation.Animator; import android.animation.Animator;
import android.animation.AnimatorListenerAdapter; import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet; import android.animation.AnimatorSet;
import android.animation.ObjectAnimator; import android.animation.ObjectAnimator;
import android.app.ActivityManager.RunningTaskInfo;
import android.content.Context; import android.content.Context;
import android.graphics.Rect; import android.graphics.Rect;
import android.graphics.RectF; import android.graphics.RectF;
@ -44,16 +37,11 @@ import android.view.MotionEvent;
import android.view.View; import android.view.View;
import android.view.animation.Interpolator; import android.view.animation.Interpolator;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
import com.android.launcher3.DeviceProfile; import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Launcher; import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAppState; import com.android.launcher3.LauncherAppState;
import com.android.launcher3.LauncherInitListener; import com.android.launcher3.LauncherInitListener;
import com.android.launcher3.LauncherState; import com.android.launcher3.LauncherState;
import com.android.launcher3.R;
import com.android.launcher3.TestProtocol; import com.android.launcher3.TestProtocol;
import com.android.launcher3.allapps.DiscoveryBounce; import com.android.launcher3.allapps.DiscoveryBounce;
import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.anim.AnimatorPlaybackController;
@ -61,13 +49,10 @@ import com.android.launcher3.anim.SpringObjectAnimator;
import com.android.launcher3.compat.AccessibilityManagerCompat; import com.android.launcher3.compat.AccessibilityManagerCompat;
import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.dragndrop.DragLayer; import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.uioverrides.FastOverviewState;
import com.android.launcher3.userevent.nano.LauncherLogProto; import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.util.MultiValueAlpha.AlphaProperty; import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
import com.android.quickstep.TouchConsumer.InteractionType;
import com.android.quickstep.util.ClipAnimationHelper; import com.android.quickstep.util.ClipAnimationHelper;
import com.android.quickstep.util.LayoutUtils; import com.android.quickstep.util.LayoutUtils;
import com.android.quickstep.util.TransformedRect;
import com.android.quickstep.views.LauncherLayoutListener; import com.android.quickstep.views.LauncherLayoutListener;
import com.android.quickstep.views.RecentsView; import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView; import com.android.quickstep.views.TaskView;
@ -76,6 +61,10 @@ import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import java.util.function.BiPredicate; import java.util.function.BiPredicate;
import java.util.function.Consumer; import java.util.function.Consumer;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
/** /**
* {@link ActivityControlHelper} for the in-launcher recents. * {@link ActivityControlHelper} for the in-launcher recents.
*/ */
@ -86,60 +75,14 @@ public final class LauncherActivityControllerHelper implements ActivityControlHe
return LauncherLayoutListener.resetAndGet(activity); return LauncherLayoutListener.resetAndGet(activity);
} }
@Override
public void onQuickInteractionStart(Launcher activity, RunningTaskInfo taskInfo,
boolean activityVisible, TouchInteractionLog touchInteractionLog) {
LauncherState fromState = activity.getStateManager().getState();
QuickScrubController controller = activity.<RecentsView>getOverviewPanel()
.getQuickScrubController();
boolean isQuickSwitch = controller.isQuickSwitch();
boolean animate = activityVisible;
if (isQuickSwitch && fromState == FAST_OVERVIEW && !animate) {
// We can already be in FAST_OVERVIEW if createActivityController() was called
// before us. This could happen, for instance, when launcher is slow to load when
// starting quick switch, causing us to call onQuickScrubStart() on the background
// thread. In this case, we also hadn't set isQuickSwitch = true before setting
// FAST_OVERVIEW, so we need to reapply FAST_OVERVIEW to take that into account.
activity.getStateManager().reapplyState();
} else {
activity.getStateManager().goToState(FAST_OVERVIEW, animate);
}
controller.onQuickScrubStart(activityVisible && !fromState.overviewUi, this,
touchInteractionLog);
if (!activityVisible) {
// For the duration of the gesture, lock the screen orientation to ensure that we
// do not rotate mid-quickscrub
activity.getRotationHelper().setStateHandlerRequest(REQUEST_LOCK);
}
}
@Override
public float getTranslationYForQuickScrub(TransformedRect targetRect, DeviceProfile dp,
Context context) {
// The padding calculations are exactly same as that of RecentsView.setInsets
int topMargin = context.getResources()
.getDimensionPixelSize(R.dimen.task_thumbnail_top_margin);
int paddingTop = targetRect.rect.top - topMargin - dp.getInsets().top;
int paddingBottom = dp.heightPx - dp.getInsets().bottom - targetRect.rect.bottom;
return FastOverviewState.OVERVIEW_TRANSLATION_FACTOR * (paddingBottom - paddingTop);
}
@Override @Override
public void executeOnWindowAvailable(Launcher activity, Runnable action) { public void executeOnWindowAvailable(Launcher activity, Runnable action) {
activity.getWorkspace().runOnOverlayHidden(action); activity.getWorkspace().runOnOverlayHidden(action);
} }
@Override @Override
public int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context, public int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context, Rect outRect) {
@InteractionType int interactionType, TransformedRect outRect) { LayoutUtils.calculateLauncherTaskSize(context, dp, outRect);
LayoutUtils.calculateLauncherTaskSize(context, dp, outRect.rect);
if (interactionType == INTERACTION_QUICK_SCRUB) {
outRect.scale = FastOverviewState.getOverviewScale(dp, outRect.rect, context,
FeatureFlags.QUICK_SWITCH.get());
}
if (dp.isVerticalBarLayout()) { if (dp.isVerticalBarLayout()) {
Rect targetInsets = dp.getInsets(); Rect targetInsets = dp.getInsets();
int hotseatInset = dp.isSeascape() ? targetInsets.left : targetInsets.right; int hotseatInset = dp.isSeascape() ? targetInsets.left : targetInsets.right;
@ -221,10 +164,9 @@ public final class LauncherActivityControllerHelper implements ActivityControlHe
private ShelfAnimState mShelfState; private ShelfAnimState mShelfState;
@Override @Override
public void createActivityController(long transitionLength, public void createActivityController(long transitionLength) {
@InteractionType int interactionType) {
createActivityControllerInternal(activity, activityVisible, fromState, createActivityControllerInternal(activity, activityVisible, fromState,
transitionLength, interactionType, callback); transitionLength, callback);
} }
@Override @Override
@ -270,10 +212,8 @@ public final class LauncherActivityControllerHelper implements ActivityControlHe
private void createActivityControllerInternal(Launcher activity, boolean wasVisible, private void createActivityControllerInternal(Launcher activity, boolean wasVisible,
LauncherState fromState, long transitionLength, LauncherState fromState, long transitionLength,
@InteractionType int interactionType,
Consumer<AnimatorPlaybackController> callback) { Consumer<AnimatorPlaybackController> callback) {
LauncherState endState = interactionType == INTERACTION_QUICK_SCRUB LauncherState endState = OVERVIEW;
? FAST_OVERVIEW : OVERVIEW;
if (wasVisible && fromState != BACKGROUND_APP) { if (wasVisible && fromState != BACKGROUND_APP) {
// If a translucent app was launched fom launcher, animate launcher states. // If a translucent app was launched fom launcher, animate launcher states.
DeviceProfile dp = activity.getDeviceProfile(); DeviceProfile dp = activity.getDeviceProfile();
@ -295,10 +235,7 @@ public final class LauncherActivityControllerHelper implements ActivityControlHe
endState.getVerticalProgress(activity)); endState.getVerticalProgress(activity));
anim.play(shiftAnim); anim.play(shiftAnim);
} }
playScaleDownAnim(anim, activity, endState);
if (interactionType == INTERACTION_NORMAL) {
playScaleDownAnim(anim, activity, endState);
}
anim.setDuration(transitionLength * 2); anim.setDuration(transitionLength * 2);
activity.getStateManager().setCurrentAnimation(anim); activity.getStateManager().setCurrentAnimation(anim);
@ -407,11 +344,6 @@ public final class LauncherActivityControllerHelper implements ActivityControlHe
return true; return true;
} }
@Override
public boolean deferStartingActivity(int downHitTarget) {
return downHitTarget == HIT_TARGET_BACK || downHitTarget == HIT_TARGET_ROTATION;
}
@Override @Override
public boolean deferStartingActivity(Region activeNavBarRegion, MotionEvent ev) { public boolean deferStartingActivity(Region activeNavBarRegion, MotionEvent ev) {
return activeNavBarRegion.contains((int) ev.getX(), (int) ev.getY()); return activeNavBarRegion.contains((int) ev.getX(), (int) ev.getY());

View File

@ -112,7 +112,6 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans
private static final int APP_LAUNCH_ALPHA_DURATION = 50; private static final int APP_LAUNCH_ALPHA_DURATION = 50;
public static final int RECENTS_LAUNCH_DURATION = 336; public static final int RECENTS_LAUNCH_DURATION = 336;
public static final int RECENTS_QUICKSCRUB_LAUNCH_DURATION = 300;
private static final int LAUNCHER_RESUME_START_DELAY = 100; private static final int LAUNCHER_RESUME_START_DELAY = 100;
private static final int CLOSING_TRANSITION_DURATION_MS = 250; private static final int CLOSING_TRANSITION_DURATION_MS = 250;
@ -181,10 +180,6 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans
public ActivityOptions getActivityLaunchOptions(Launcher launcher, View v) { public ActivityOptions getActivityLaunchOptions(Launcher launcher, View v) {
if (hasControlRemoteAppTransitionPermission()) { if (hasControlRemoteAppTransitionPermission()) {
boolean fromRecents = isLaunchingFromRecents(v, null /* targets */); boolean fromRecents = isLaunchingFromRecents(v, null /* targets */);
if (fromRecents && isQuickSwitchInProgress()) {
return getQuickSwitchActivityOptions();
}
RemoteAnimationRunnerCompat runner = new LauncherAnimationRunner(mHandler, RemoteAnimationRunnerCompat runner = new LauncherAnimationRunner(mHandler,
true /* startAtFrontOfQueue */) { true /* startAtFrontOfQueue */) {
@ -237,20 +232,6 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans
protected abstract boolean isLaunchingFromRecents(@NonNull View v, protected abstract boolean isLaunchingFromRecents(@NonNull View v,
@Nullable RemoteAnimationTargetCompat[] targets); @Nullable RemoteAnimationTargetCompat[] targets);
/**
* Whether a quick scrub is in progress.
*
* @return true if in progress
*/
protected abstract boolean isQuickSwitchInProgress();
/**
* Get activity options for a quick switch launch that include the launch animation.
*
* @return the activity options for a quick switch recents launch
*/
protected abstract ActivityOptions getQuickSwitchActivityOptions();
/** /**
* Composes the animations for a launch from the recents list. * Composes the animations for a launch from the recents list.
* *

View File

@ -125,8 +125,8 @@ public class UiFactory extends RecentsUiFactory {
public static void onEnterAnimationComplete(Context context) { public static void onEnterAnimationComplete(Context context) {
// After the transition to home, enable the high-res thumbnail loader if it wasn't enabled // After the transition to home, enable the high-res thumbnail loader if it wasn't enabled
// as a part of quickstep/scrub, so that high-res thumbnails can load the next time we // as a part of quickstep, so that high-res thumbnails can load the next time we enter
// enter overview // overview
RecentsModel.INSTANCE.get(context).getThumbnailCache() RecentsModel.INSTANCE.get(context).getThumbnailCache()
.getHighResLoadingState().setVisible(true); .getHighResLoadingState().setVisible(true);
} }

View File

@ -17,7 +17,6 @@ package com.android.quickstep;
import android.animation.Animator; import android.animation.Animator;
import android.annotation.TargetApi; import android.annotation.TargetApi;
import android.app.ActivityManager.RunningTaskInfo;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.graphics.Rect; import android.graphics.Rect;
@ -29,24 +28,21 @@ import android.view.MotionEvent;
import android.view.View; import android.view.View;
import android.view.animation.Interpolator; import android.view.animation.Interpolator;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.DeviceProfile; import com.android.launcher3.DeviceProfile;
import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.util.MultiValueAlpha.AlphaProperty; import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
import com.android.quickstep.TouchConsumer.InteractionType;
import com.android.quickstep.util.RemoteAnimationProvider; import com.android.quickstep.util.RemoteAnimationProvider;
import com.android.quickstep.util.RemoteAnimationTargetSet; import com.android.quickstep.util.RemoteAnimationTargetSet;
import com.android.quickstep.util.TransformedRect;
import com.android.quickstep.views.RecentsView;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat; import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import java.util.function.BiPredicate; import java.util.function.BiPredicate;
import java.util.function.Consumer; import java.util.function.Consumer;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
/** /**
* Utility class which abstracts out the logical differences between Launcher and RecentsActivity. * Utility class which abstracts out the logical differences between Launcher and RecentsActivity.
*/ */
@ -55,21 +51,11 @@ public interface ActivityControlHelper<T extends BaseDraggingActivity> {
LayoutListener createLayoutListener(T activity); LayoutListener createLayoutListener(T activity);
/**
* Updates the UI to indicate quick interaction.
*/
void onQuickInteractionStart(T activity, @Nullable RunningTaskInfo taskInfo,
boolean activityVisible, TouchInteractionLog touchInteractionLog);
float getTranslationYForQuickScrub(TransformedRect targetRect, DeviceProfile dp,
Context context);
void executeOnWindowAvailable(T activity, Runnable action); void executeOnWindowAvailable(T activity, Runnable action);
void onTransitionCancelled(T activity, boolean activityVisible); void onTransitionCancelled(T activity, boolean activityVisible);
int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context, int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context, Rect outRect);
@InteractionType int interactionType, TransformedRect outRect);
void onSwipeUpComplete(T activity); void onSwipeUpComplete(T activity);
@ -99,12 +85,6 @@ public interface ActivityControlHelper<T extends BaseDraggingActivity> {
boolean shouldMinimizeSplitScreen(); boolean shouldMinimizeSplitScreen();
/**
* @return {@code true} if recents activity should be started immediately on touchDown,
* {@code false} if it should deferred until some threshold is crossed.
*/
boolean deferStartingActivity(int downHitTarget);
default boolean deferStartingActivity(Region activeNavBarRegion, MotionEvent ev) { default boolean deferStartingActivity(Region activeNavBarRegion, MotionEvent ev) {
return true; return true;
} }
@ -161,7 +141,7 @@ public interface ActivityControlHelper<T extends BaseDraggingActivity> {
default void onRemoteAnimationReceived(RemoteAnimationTargetSet targets) { } default void onRemoteAnimationReceived(RemoteAnimationTargetSet targets) { }
void createActivityController(long transitionLength, @InteractionType int interactionType); void createActivityController(long transitionLength);
default void onTransitionCancelled() { } default void onTransitionCancelled() { }

View File

@ -17,7 +17,6 @@ package com.android.quickstep;
import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN; import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
import static com.android.launcher3.anim.Interpolators.TOUCH_RESPONSE_INTERPOLATOR; import static com.android.launcher3.anim.Interpolators.TOUCH_RESPONSE_INTERPOLATOR;
import static com.android.quickstep.TouchConsumer.INTERACTION_NORMAL;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING; import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING; import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING;
@ -34,7 +33,6 @@ import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.quickstep.util.ClipAnimationHelper; import com.android.quickstep.util.ClipAnimationHelper;
import com.android.quickstep.util.RemoteAnimationProvider; import com.android.quickstep.util.RemoteAnimationProvider;
import com.android.quickstep.util.RemoteAnimationTargetSet; import com.android.quickstep.util.RemoteAnimationTargetSet;
import com.android.quickstep.util.TransformedRect;
import com.android.quickstep.views.RecentsView; import com.android.quickstep.views.RecentsView;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat; import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat; import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat;
@ -82,7 +80,7 @@ final class AppToOverviewAnimationProvider<T extends BaseDraggingActivity> imple
anim.start(); anim.start();
}); });
factory.onRemoteAnimationReceived(null); factory.onRemoteAnimationReceived(null);
factory.createActivityController(RECENTS_LAUNCH_DURATION, INTERACTION_NORMAL); factory.createActivityController(RECENTS_LAUNCH_DURATION);
mActivity = activity; mActivity = activity;
mRecentsView = mActivity.getOverviewPanel(); mRecentsView = mActivity.getOverviewPanel();
return false; return false;
@ -136,9 +134,8 @@ final class AppToOverviewAnimationProvider<T extends BaseDraggingActivity> imple
loc[0] + rootView.getWidth(), loc[1] + rootView.getHeight()); loc[0] + rootView.getWidth(), loc[1] + rootView.getHeight());
clipHelper.updateSource(homeBounds, runningTaskTarget); clipHelper.updateSource(homeBounds, runningTaskTarget);
TransformedRect targetRect = new TransformedRect(); Rect targetRect = new Rect();
mHelper.getSwipeUpDestinationAndLength(mActivity.getDeviceProfile(), mActivity, mHelper.getSwipeUpDestinationAndLength(mActivity.getDeviceProfile(), mActivity, targetRect);
INTERACTION_NORMAL, targetRect);
clipHelper.updateTargetRect(targetRect); clipHelper.updateTargetRect(targetRect);
clipHelper.prepareAnimation(false /* isOpening */); clipHelper.prepareAnimation(false /* isOpening */);

View File

@ -15,41 +15,33 @@
*/ */
package com.android.quickstep; package com.android.quickstep;
import static com.android.launcher3.LauncherAnimUtils.OVERVIEW_TRANSITION_MS;
import static com.android.launcher3.anim.Interpolators.LINEAR; import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.quickstep.TouchConsumer.INTERACTION_NORMAL;
import static com.android.quickstep.views.RecentsView.CONTENT_ALPHA; import static com.android.quickstep.views.RecentsView.CONTENT_ALPHA;
import android.animation.Animator; import android.animation.Animator;
import android.animation.AnimatorSet; import android.animation.AnimatorSet;
import android.animation.ObjectAnimator; import android.animation.ObjectAnimator;
import android.app.ActivityManager.RunningTaskInfo;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Context; import android.content.Context;
import android.graphics.Rect; import android.graphics.Rect;
import android.graphics.RectF; import android.graphics.RectF;
import android.os.Handler;
import android.os.Looper;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.launcher3.DeviceProfile; import com.android.launcher3.DeviceProfile;
import com.android.launcher3.anim.AnimationSuccessListener; import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.AnimatorPlaybackController; import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.userevent.nano.LauncherLogProto; import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.util.MultiValueAlpha.AlphaProperty; import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
import com.android.quickstep.TouchConsumer.InteractionType;
import com.android.quickstep.util.LayoutUtils; import com.android.quickstep.util.LayoutUtils;
import com.android.quickstep.util.RemoteAnimationTargetSet; import com.android.quickstep.util.RemoteAnimationTargetSet;
import com.android.quickstep.util.TransformedRect;
import com.android.quickstep.views.RecentsView; import com.android.quickstep.views.RecentsView;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat; import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import java.util.Objects;
import java.util.function.BiPredicate; import java.util.function.BiPredicate;
import java.util.function.Consumer; import java.util.function.Consumer;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
/** /**
* {@link ActivityControlHelper} for recents when the default launcher is different than the * {@link ActivityControlHelper} for recents when the default launcher is different than the
* currently running one and apps should interact with the {@link RecentsActivity} as opposed * currently running one and apps should interact with the {@link RecentsActivity} as opposed
@ -59,34 +51,11 @@ public final class FallbackActivityControllerHelper implements
ActivityControlHelper<RecentsActivity> { ActivityControlHelper<RecentsActivity> {
private final ComponentName mHomeComponent; private final ComponentName mHomeComponent;
private final Handler mUiHandler = new Handler(Looper.getMainLooper());
public FallbackActivityControllerHelper(ComponentName homeComponent) { public FallbackActivityControllerHelper(ComponentName homeComponent) {
mHomeComponent = homeComponent; mHomeComponent = homeComponent;
} }
@Override
public void onQuickInteractionStart(RecentsActivity activity, RunningTaskInfo taskInfo,
boolean activityVisible, TouchInteractionLog touchInteractionLog) {
QuickScrubController controller = activity.<RecentsView>getOverviewPanel()
.getQuickScrubController();
// TODO: match user is as well
boolean startingFromHome = !activityVisible &&
(taskInfo == null || Objects.equals(taskInfo.topActivity, mHomeComponent));
controller.onQuickScrubStart(startingFromHome, this, touchInteractionLog);
if (activityVisible) {
mUiHandler.postDelayed(controller::onFinishedTransitionToQuickScrub,
OVERVIEW_TRANSITION_MS);
}
}
@Override
public float getTranslationYForQuickScrub(TransformedRect targetRect, DeviceProfile dp,
Context context) {
return 0;
}
@Override @Override
public void executeOnWindowAvailable(RecentsActivity activity, Runnable action) { public void executeOnWindowAvailable(RecentsActivity activity, Runnable action) {
action.run(); action.run();
@ -98,15 +67,14 @@ public final class FallbackActivityControllerHelper implements
} }
@Override @Override
public int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context, public int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context, Rect outRect) {
@InteractionType int interactionType, TransformedRect outRect) { LayoutUtils.calculateFallbackTaskSize(context, dp, outRect);
LayoutUtils.calculateFallbackTaskSize(context, dp, outRect.rect);
if (dp.isVerticalBarLayout()) { if (dp.isVerticalBarLayout()) {
Rect targetInsets = dp.getInsets(); Rect targetInsets = dp.getInsets();
int hotseatInset = dp.isSeascape() ? targetInsets.left : targetInsets.right; int hotseatInset = dp.isSeascape() ? targetInsets.left : targetInsets.right;
return dp.hotseatBarSizePx + hotseatInset; return dp.hotseatBarSizePx + hotseatInset;
} else { } else {
return dp.heightPx - outRect.rect.bottom; return dp.heightPx - outRect.bottom;
} }
} }
@ -148,7 +116,7 @@ public final class FallbackActivityControllerHelper implements
public AnimationFactory prepareRecentsUI(RecentsActivity activity, boolean activityVisible, public AnimationFactory prepareRecentsUI(RecentsActivity activity, boolean activityVisible,
boolean animateActivity, Consumer<AnimatorPlaybackController> callback) { boolean animateActivity, Consumer<AnimatorPlaybackController> callback) {
if (activityVisible) { if (activityVisible) {
return (transitionLength, interactionType) -> { }; return (transitionLength) -> { };
} }
RecentsView rv = activity.getOverviewPanel(); RecentsView rv = activity.getOverviewPanel();
@ -165,12 +133,11 @@ public final class FallbackActivityControllerHelper implements
rv.setContentAlpha(1); rv.setContentAlpha(1);
} }
createActivityController(getSwipeUpDestinationAndLength( createActivityController(getSwipeUpDestinationAndLength(
activity.getDeviceProfile(), activity, INTERACTION_NORMAL, activity.getDeviceProfile(), activity, new Rect()));
new TransformedRect()), INTERACTION_NORMAL);
} }
@Override @Override
public void createActivityController(long transitionLength, int interactionType) { public void createActivityController(long transitionLength) {
if (!isAnimatingToRecents) { if (!isAnimatingToRecents) {
return; return;
} }
@ -231,12 +198,6 @@ public final class FallbackActivityControllerHelper implements
return false; return false;
} }
@Override
public boolean deferStartingActivity(int downHitTarget) {
// Always defer starting the activity when using fallback
return true;
}
@Override @Override
public Rect getOverviewWindowBounds(Rect homeBounds, RemoteAnimationTargetCompat target) { public Rect getOverviewWindowBounds(Rect homeBounds, RemoteAnimationTargetCompat target) {
// TODO: Remove this once b/77875376 is fixed // TODO: Remove this once b/77875376 is fixed

View File

@ -1,159 +0,0 @@
/*
* Copyright (C) 2017 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 static android.view.MotionEvent.ACTION_MASK;
import static android.view.MotionEvent.ACTION_POINTER_INDEX_SHIFT;
import android.annotation.TargetApi;
import android.os.Build;
import android.os.Looper;
import android.util.Log;
import android.util.Pair;
import android.view.Choreographer;
import android.view.InputEvent;
import android.view.MotionEvent;
import com.android.systemui.shared.system.InputChannelCompat;
import com.android.systemui.shared.system.InputChannelCompat.InputEventDispatcher;
import com.android.systemui.shared.system.InputChannelCompat.InputEventReceiver;
import com.android.systemui.shared.system.NavigationBarCompat.HitTarget;
/**
* Helper class for batching input events
*/
@TargetApi(Build.VERSION_CODES.O)
public class MotionEventQueue {
private static final String TAG = "MotionEventQueue";
private static final int ACTION_VIRTUAL = ACTION_MASK - 1;
private static final int ACTION_QUICK_SCRUB_START =
ACTION_VIRTUAL | (1 << ACTION_POINTER_INDEX_SHIFT);
private static final int ACTION_QUICK_SCRUB_PROGRESS =
ACTION_VIRTUAL | (2 << ACTION_POINTER_INDEX_SHIFT);
private static final int ACTION_QUICK_SCRUB_END =
ACTION_VIRTUAL | (3 << ACTION_POINTER_INDEX_SHIFT);
private static final int ACTION_NEW_GESTURE =
ACTION_VIRTUAL | (4 << ACTION_POINTER_INDEX_SHIFT);
private static final int ACTION_SHOW_OVERVIEW_FROM_ALT_TAB =
ACTION_VIRTUAL | (5 << ACTION_POINTER_INDEX_SHIFT);
private final InputEventDispatcher mDispatcher;
private final InputEventReceiver mReceiver;
private final ConsumerFactory mConsumerFactory;
private TouchConsumer mConsumer;
public MotionEventQueue(Looper looper, Choreographer choreographer,
ConsumerFactory consumerFactory) {
Pair<InputEventDispatcher, InputEventReceiver> pair = InputChannelCompat.createPair(
"sysui-callbacks", looper, choreographer, this::onInputEvent);
mConsumerFactory = consumerFactory;
mConsumer = TouchConsumer.NO_OP;
mDispatcher = pair.first;
mReceiver = pair.second;
}
private void onInputEvent(InputEvent ev) {
if (!(ev instanceof MotionEvent)) {
throw new IllegalStateException("Unknown event " + ev);
}
MotionEvent event = (MotionEvent) ev;
if (event.getActionMasked() == ACTION_VIRTUAL) {
switch (event.getAction()) {
case ACTION_QUICK_SCRUB_START:
mConsumer.onQuickScrubStart();
break;
case ACTION_QUICK_SCRUB_PROGRESS:
mConsumer.onQuickScrubProgress(event.getX());
break;
case ACTION_QUICK_SCRUB_END:
mConsumer.onQuickScrubEnd();
break;
case ACTION_NEW_GESTURE: {
boolean useSharedState = mConsumer.isActive();
mConsumer.onConsumerAboutToBeSwitched();
mConsumer = mConsumerFactory.newConsumer(event.getSource(), useSharedState);
break;
}
case ACTION_SHOW_OVERVIEW_FROM_ALT_TAB:
mConsumer.onShowOverviewFromAltTab();
mConsumer.onQuickScrubStart();
break;
default:
Log.e(TAG, "Invalid virtual event: " + event.getAction());
}
} else {
mConsumer.accept(event);
}
}
public void queue(MotionEvent event) {
mDispatcher.dispatch(event);
}
private void queueVirtualAction(int action, float param) {
queue(MotionEvent.obtain(0, 0, action, param, 0, 0));
}
private void queueVirtualAction(int action, int param) {
MotionEvent ev = MotionEvent.obtain(0, 0, action, 0, 0, 0);
ev.setSource(param);
queue(ev);
}
public void onQuickScrubStart() {
queueVirtualAction(ACTION_QUICK_SCRUB_START, 0);
}
public void onOverviewShownFromAltTab() {
queueVirtualAction(ACTION_SHOW_OVERVIEW_FROM_ALT_TAB, 0);
}
public void onQuickScrubProgress(float progress) {
queueVirtualAction(ACTION_QUICK_SCRUB_PROGRESS, progress);
}
public void onQuickScrubEnd() {
queueVirtualAction(ACTION_QUICK_SCRUB_END, 0);
}
public void onNewGesture(@HitTarget int downHitTarget) {
queueVirtualAction(ACTION_NEW_GESTURE, downHitTarget);
}
/**
* To be called by the consumer when it's no longer active.
*/
public void onConsumerInactive(TouchConsumer caller) {
if (mConsumer == caller) {
mConsumer = TouchConsumer.NO_OP;
}
}
public void dispose() {
mDispatcher.dispose();
mReceiver.dispose();
}
public interface ConsumerFactory {
TouchConsumer newConsumer(@HitTarget int downHitTarget, boolean useSharedState);
}
}

View File

@ -15,8 +15,6 @@
*/ */
package com.android.quickstep; package com.android.quickstep;
import static com.android.quickstep.WindowTransformSwipeHandler.STATES;
import android.util.Log; import android.util.Log;
import android.util.SparseArray; import android.util.SparseArray;
@ -29,11 +27,17 @@ import java.util.function.Consumer;
public class MultiStateCallback { public class MultiStateCallback {
private static final String TAG = "MultiStateCallback"; private static final String TAG = "MultiStateCallback";
private static final boolean DEBUG_STATES = false; public static final boolean DEBUG_STATES = false;
private final SparseArray<Runnable> mCallbacks = new SparseArray<>(); private final SparseArray<Runnable> mCallbacks = new SparseArray<>();
private final SparseArray<Consumer<Boolean>> mStateChangeHandlers = new SparseArray<>(); private final SparseArray<Consumer<Boolean>> mStateChangeHandlers = new SparseArray<>();
private final String[] mStateNames;
public MultiStateCallback(String[] stateNames) {
mStateNames = DEBUG_STATES ? stateNames : null;
}
private int mState = 0; private int mState = 0;
/** /**
@ -113,12 +117,12 @@ public class MultiStateCallback {
int state = getState(); int state = getState();
StringJoiner currentStateStr = new StringJoiner(", ", "[", "]"); StringJoiner currentStateStr = new StringJoiner(", ", "[", "]");
String stateFlagStr = "Unknown-" + stateFlag; String stateFlagStr = "Unknown-" + stateFlag;
for (int i = 0; i < STATES.length; i++) { for (int i = 0; i < mStateNames.length; i++) {
if ((state & (i << i)) != 0) { if ((state & (i << i)) != 0) {
currentStateStr.add(STATES[i]); currentStateStr.add(mStateNames[i]);
} }
if (stateFlag == (1 << i)) { if (stateFlag == (1 << i)) {
stateFlagStr = STATES[i] + " (" + stateFlag + ")"; stateFlagStr = mStateNames[i] + " (" + stateFlag + ")";
} }
} }
Log.d(TAG, "[" + System.identityHashCode(this) + "] Adding " + stateFlagStr + " to " Log.d(TAG, "[" + System.identityHashCode(this) + "] Adding " + stateFlagStr + " to "

View File

@ -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.ENTER;
import static com.android.launcher3.util.RaceConditionTracker.EXIT; import static com.android.launcher3.util.RaceConditionTracker.EXIT;
import static com.android.quickstep.TouchInteractionService.TOUCH_INTERACTION_LOG;
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS; import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
import android.annotation.TargetApi; import android.annotation.TargetApi;
@ -35,7 +36,6 @@ import android.graphics.PointF;
import android.graphics.Rect; import android.graphics.Rect;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.os.SystemClock;
import android.view.Display; import android.view.Display;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.Surface; import android.view.Surface;
@ -77,7 +77,6 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC
private final ActivityControlHelper mActivityControlHelper; private final ActivityControlHelper mActivityControlHelper;
private final OverviewCallbacks mOverviewCallbacks; private final OverviewCallbacks mOverviewCallbacks;
private final TaskOverlayFactory mTaskOverlayFactory; private final TaskOverlayFactory mTaskOverlayFactory;
private final TouchInteractionLog mTouchInteractionLog;
private final InputConsumerController mInputConsumer; private final InputConsumerController mInputConsumer;
private final SwipeSharedState mSwipeSharedState; private final SwipeSharedState mSwipeSharedState;
@ -110,7 +109,6 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC
RecentsModel recentsModel, Intent homeIntent, ActivityControlHelper activityControl, RecentsModel recentsModel, Intent homeIntent, ActivityControlHelper activityControl,
boolean isDeferredDownTarget, OverviewCallbacks overviewCallbacks, boolean isDeferredDownTarget, OverviewCallbacks overviewCallbacks,
TaskOverlayFactory taskOverlayFactory, InputConsumerController inputConsumer, TaskOverlayFactory taskOverlayFactory, InputConsumerController inputConsumer,
TouchInteractionLog touchInteractionLog,
Consumer<OtherActivityTouchConsumer> onCompleteCallback, Consumer<OtherActivityTouchConsumer> onCompleteCallback,
SwipeSharedState swipeSharedState) { SwipeSharedState swipeSharedState) {
super(base); super(base);
@ -127,8 +125,6 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC
mIsDeferredDownTarget = isDeferredDownTarget; mIsDeferredDownTarget = isDeferredDownTarget;
mOverviewCallbacks = overviewCallbacks; mOverviewCallbacks = overviewCallbacks;
mTaskOverlayFactory = taskOverlayFactory; mTaskOverlayFactory = taskOverlayFactory;
mTouchInteractionLog = touchInteractionLog;
mTouchInteractionLog.setTouchConsumer(this);
mInputConsumer = inputConsumer; mInputConsumer = inputConsumer;
mSwipeSharedState = swipeSharedState; mSwipeSharedState = swipeSharedState;
@ -142,11 +138,6 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC
mPassedTouchSlop = mPassedDragSlop = mSwipeSharedState.getActiveListener() != null; mPassedTouchSlop = mPassedDragSlop = mSwipeSharedState.getActiveListener() != null;
} }
@Override
public void onShowOverviewFromAltTab() {
startTouchTrackingForWindowAnimation(SystemClock.uptimeMillis());
}
@Override @Override
public void accept(MotionEvent ev) { public void accept(MotionEvent ev) {
if (mVelocityTracker == null) { if (mVelocityTracker == null) {
@ -158,7 +149,6 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC
mMotionPauseDetector.clear(); mMotionPauseDetector.clear();
} }
mTouchInteractionLog.addMotionEvent(ev);
switch (ev.getActionMasked()) { switch (ev.getActionMasked()) {
case ACTION_DOWN: { case ACTION_DOWN: {
RaceConditionTracker.onEvent(DOWN_EVT, ENTER); RaceConditionTracker.onEvent(DOWN_EVT, ENTER);
@ -213,7 +203,7 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC
mTouchSlop) { mTouchSlop) {
mPassedTouchSlop = true; mPassedTouchSlop = true;
mTouchInteractionLog.startQuickStep(); TOUCH_INTERACTION_LOG.startQuickStep();
if (mIsDeferredDownTarget) { if (mIsDeferredDownTarget) {
// Deferred gesture, start the animation and gesture tracking once // Deferred gesture, start the animation and gesture tracking once
// we pass the actual touch slop // we pass the actual touch slop
@ -284,12 +274,12 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC
} }
private void startTouchTrackingForWindowAnimation(long touchTimeMs) { private void startTouchTrackingForWindowAnimation(long touchTimeMs) {
mTouchInteractionLog.startRecentsAnimation(); TOUCH_INTERACTION_LOG.startRecentsAnimation();
RecentsAnimationListenerSet listenerSet = mSwipeSharedState.getActiveListener(); RecentsAnimationListenerSet listenerSet = mSwipeSharedState.getActiveListener();
final WindowTransformSwipeHandler handler = new WindowTransformSwipeHandler( final WindowTransformSwipeHandler handler = new WindowTransformSwipeHandler(
mRunningTask, this, touchTimeMs, mActivityControlHelper, mRunningTask, this, touchTimeMs, mActivityControlHelper,
listenerSet != null, mInputConsumer, mTouchInteractionLog); listenerSet != null, mInputConsumer);
// Preload the plan // Preload the plan
mRecentsModel.getTasks(null); mRecentsModel.getTasks(null);
@ -393,38 +383,6 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC
} }
} }
@Override
public void onQuickScrubStart() {
if (!mPassedDragSlop && mIsDeferredDownTarget && mInteractionHandler == null) {
// If we deferred starting the window animation on touch down, then
// start tracking now
startTouchTrackingForWindowAnimation(SystemClock.uptimeMillis());
mPassedDragSlop = true;
}
mTouchInteractionLog.startQuickScrub();
if (mInteractionHandler != null) {
mInteractionHandler.onQuickScrubStart();
}
notifyGestureStarted();
}
@Override
public void onQuickScrubEnd() {
mTouchInteractionLog.endQuickScrub("onQuickScrubEnd");
if (mInteractionHandler != null) {
mInteractionHandler.onQuickScrubEnd();
}
}
@Override
public void onQuickScrubProgress(float progress) {
mTouchInteractionLog.setQuickScrubProgress(progress);
if (mInteractionHandler != null) {
mInteractionHandler.onQuickScrubProgress(progress);
}
}
private float getDisplacement(MotionEvent ev) { private float getDisplacement(MotionEvent ev) {
float eventX = ev.getX(); float eventX = ev.getX();
float eventY = ev.getY(); float eventY = ev.getY();

View File

@ -31,6 +31,7 @@ import com.android.launcher3.logging.UserEventDispatcher;
import com.android.launcher3.userevent.nano.LauncherLogProto; import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.quickstep.ActivityControlHelper.ActivityInitListener; import com.android.quickstep.ActivityControlHelper.ActivityInitListener;
import com.android.quickstep.views.RecentsView; import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.LatencyTrackerCompat; import com.android.systemui.shared.system.LatencyTrackerCompat;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat; import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
@ -71,6 +72,10 @@ public class OverviewCommandHelper {
mMainThreadExecutor.execute(new ShowRecentsCommand()); mMainThreadExecutor.execute(new ShowRecentsCommand());
} }
public void onOverviewHidden() {
mMainThreadExecutor.execute(new HideRecentsCommand());
}
public void onTip(int actionType, int viewType) { public void onTip(int actionType, int viewType) {
mMainThreadExecutor.execute(() -> mMainThreadExecutor.execute(() ->
UserEventDispatcher.newInstance(mContext).logActionTip(actionType, viewType)); UserEventDispatcher.newInstance(mContext).logActionTip(actionType, viewType));
@ -80,10 +85,29 @@ public class OverviewCommandHelper {
@Override @Override
protected boolean handleCommand(long elapsedTime) { protected boolean handleCommand(long elapsedTime) {
// TODO: Go to the next page if started from alt-tab.
return mHelper.getVisibleRecentsView() != null; return mHelper.getVisibleRecentsView() != null;
} }
} }
private class HideRecentsCommand extends RecentsActivityCommand {
@Override
protected boolean handleCommand(long elapsedTime) {
RecentsView recents = (RecentsView) mHelper.getVisibleRecentsView();
if (recents == null) {
return false;
}
int currentPage = recents.getNextPage();
if (currentPage >= 0 && currentPage < recents.getTaskViewCount()) {
((TaskView) recents.getPageAt(currentPage)).launchTask(true);
} else {
recents.startHome();
}
return true;
}
}
private class RecentsActivityCommand<T extends BaseDraggingActivity> implements Runnable { private class RecentsActivityCommand<T extends BaseDraggingActivity> implements Runnable {
protected final ActivityControlHelper<T> mHelper; protected final ActivityControlHelper<T> mHelper;

View File

@ -22,6 +22,7 @@ import static android.view.MotionEvent.ACTION_POINTER_DOWN;
import static android.view.MotionEvent.ACTION_POINTER_INDEX_SHIFT; import static android.view.MotionEvent.ACTION_POINTER_INDEX_SHIFT;
import static android.view.MotionEvent.ACTION_UP; import static android.view.MotionEvent.ACTION_UP;
import static com.android.quickstep.TouchInteractionService.TOUCH_INTERACTION_LOG;
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS; import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
import android.graphics.PointF; import android.graphics.PointF;
@ -30,7 +31,6 @@ import android.view.ViewConfiguration;
import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.views.BaseDragLayer; import com.android.launcher3.views.BaseDragLayer;
import com.android.quickstep.views.RecentsView;
import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.ActivityManagerWrapper;
/** /**
@ -39,42 +39,22 @@ import com.android.systemui.shared.system.ActivityManagerWrapper;
public class OverviewTouchConsumer<T extends BaseDraggingActivity> public class OverviewTouchConsumer<T extends BaseDraggingActivity>
implements TouchConsumer { implements TouchConsumer {
private static final String TAG = "OverviewTouchConsumer";
private final ActivityControlHelper<T> mActivityHelper;
private final T mActivity; private final T mActivity;
private final BaseDragLayer mTarget; private final BaseDragLayer mTarget;
private final int[] mLocationOnScreen = new int[2]; private final int[] mLocationOnScreen = new int[2];
private final PointF mDownPos = new PointF(); private final PointF mDownPos = new PointF();
private final int mTouchSlop; private final int mTouchSlop;
private final QuickScrubController mQuickScrubController;
private final TouchInteractionLog mTouchInteractionLog;
private final boolean mStartingInActivityBounds; private final boolean mStartingInActivityBounds;
private boolean mTrackingStarted = false; private boolean mTrackingStarted = false;
private boolean mInvalidated = false; private boolean mInvalidated = false;
private float mLastProgress = 0; OverviewTouchConsumer(T activity, boolean startingInActivityBounds) {
private boolean mStartPending = false;
private boolean mEndPending = false;
private boolean mWaitForWindowAvailable;
OverviewTouchConsumer(ActivityControlHelper<T> activityHelper, T activity,
boolean startingInActivityBounds, TouchInteractionLog touchInteractionLog,
boolean waitForWindowAvailable) {
mActivityHelper = activityHelper;
mActivity = activity; mActivity = activity;
mTarget = activity.getDragLayer(); mTarget = activity.getDragLayer();
mTouchSlop = ViewConfiguration.get(mActivity).getScaledTouchSlop(); mTouchSlop = ViewConfiguration.get(mActivity).getScaledTouchSlop();
mStartingInActivityBounds = startingInActivityBounds; mStartingInActivityBounds = startingInActivityBounds;
mQuickScrubController = mActivity.<RecentsView>getOverviewPanel()
.getQuickScrubController();
mTouchInteractionLog = touchInteractionLog;
mTouchInteractionLog.setTouchConsumer(this);
mWaitForWindowAvailable = waitForWindowAvailable;
} }
@Override @Override
@ -82,7 +62,6 @@ public class OverviewTouchConsumer<T extends BaseDraggingActivity>
if (mInvalidated) { if (mInvalidated) {
return; return;
} }
mTouchInteractionLog.addMotionEvent(ev);
int action = ev.getActionMasked(); int action = ev.getActionMasked();
if (action == ACTION_DOWN) { if (action == ACTION_DOWN) {
if (mStartingInActivityBounds) { if (mStartingInActivityBounds) {
@ -145,7 +124,7 @@ public class OverviewTouchConsumer<T extends BaseDraggingActivity>
OverviewCallbacks.get(mActivity).closeAllWindows(); OverviewCallbacks.get(mActivity).closeAllWindows();
ActivityManagerWrapper.getInstance() ActivityManagerWrapper.getInstance()
.closeSystemWindows(CLOSE_SYSTEM_WINDOWS_REASON_RECENTS); .closeSystemWindows(CLOSE_SYSTEM_WINDOWS_REASON_RECENTS);
mTouchInteractionLog.startQuickStep(); TOUCH_INTERACTION_LOG.startQuickStep();
} }
} }
@ -165,83 +144,12 @@ public class OverviewTouchConsumer<T extends BaseDraggingActivity>
ev.setEdgeFlags(flags); ev.setEdgeFlags(flags);
} }
@Override
public void onQuickScrubStart() {
if (mInvalidated) {
return;
}
mTouchInteractionLog.startQuickScrub();
if (!mQuickScrubController.prepareQuickScrub(TAG)) {
mInvalidated = true;
mTouchInteractionLog.endQuickScrub("onQuickScrubStart");
return;
}
OverviewCallbacks.get(mActivity).closeAllWindows();
ActivityManagerWrapper.getInstance()
.closeSystemWindows(CLOSE_SYSTEM_WINDOWS_REASON_RECENTS);
mStartPending = true;
Runnable action = () -> {
if (!mQuickScrubController.prepareQuickScrub(TAG)) {
mInvalidated = true;
mTouchInteractionLog.endQuickScrub("onQuickScrubStart");
return;
}
mActivityHelper.onQuickInteractionStart(mActivity, null, true,
mTouchInteractionLog);
mQuickScrubController.onQuickScrubProgress(mLastProgress);
mStartPending = false;
if (mEndPending) {
mQuickScrubController.onQuickScrubEnd();
mEndPending = false;
}
};
if (mWaitForWindowAvailable) {
mActivityHelper.executeOnWindowAvailable(mActivity, action);
} else {
action.run();
}
}
@Override
public void onQuickScrubEnd() {
mTouchInteractionLog.endQuickScrub("onQuickScrubEnd");
if (mInvalidated) {
return;
}
if (mStartPending) {
mEndPending = true;
} else {
mQuickScrubController.onQuickScrubEnd();
}
}
@Override
public void onQuickScrubProgress(float progress) {
mTouchInteractionLog.setQuickScrubProgress(progress);
mLastProgress = progress;
if (mInvalidated || mStartPending) {
return;
}
mQuickScrubController.onQuickScrubProgress(progress);
}
public static TouchConsumer newInstance(ActivityControlHelper activityHelper, public static TouchConsumer newInstance(ActivityControlHelper activityHelper,
boolean startingInActivityBounds, TouchInteractionLog touchInteractionLog) { boolean startingInActivityBounds) {
return newInstance(activityHelper, startingInActivityBounds, touchInteractionLog,
true /* waitForWindowAvailable */);
}
public static TouchConsumer newInstance(ActivityControlHelper activityHelper,
boolean startingInActivityBounds, TouchInteractionLog touchInteractionLog,
boolean waitForWindowAvailable) {
BaseDraggingActivity activity = activityHelper.getCreatedActivity(); BaseDraggingActivity activity = activityHelper.getCreatedActivity();
if (activity == null) { if (activity == null) {
return TouchConsumer.NO_OP; return TouchConsumer.NO_OP;
} }
return new OverviewTouchConsumer(activityHelper, activity, startingInActivityBounds, return new OverviewTouchConsumer(activity, startingInActivityBounds);
touchInteractionLog, waitForWindowAvailable);
} }
} }

View File

@ -1,432 +0,0 @@
/*
* Copyright (C) 2018 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 static com.android.launcher3.Utilities.SINGLE_FRAME_MS;
import static com.android.launcher3.anim.Interpolators.ACCEL;
import static com.android.launcher3.anim.Interpolators.DEACCEL_3;
import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.config.FeatureFlags.ENABLE_TASK_STABILIZER;
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.annotation.TargetApi;
import android.os.Build;
import android.util.FloatProperty;
import android.util.Log;
import android.view.HapticFeedbackConstants;
import android.view.animation.Interpolator;
import com.android.launcher3.Alarm;
import com.android.launcher3.BaseActivity;
import com.android.launcher3.OnAlarmListener;
import com.android.launcher3.Utilities;
import com.android.launcher3.userevent.nano.LauncherLogProto;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
/**
* Responds to quick scrub callbacks to page through and launch recent tasks.
*
* The behavior is to evenly divide the progress into sections, each of which scrolls one page.
* The first and last section set an alarm to auto-advance backwards or forwards, respectively.
*/
@TargetApi(Build.VERSION_CODES.P)
public class QuickScrubController implements OnAlarmListener {
public static final int QUICK_SWITCH_FROM_APP_START_DURATION = 0;
public static final int QUICK_SCRUB_FROM_APP_START_DURATION = 240;
public static final int QUICK_SCRUB_FROM_HOME_START_DURATION = 200;
// We want the translation y to finish faster than the rest of the animation.
public static final float QUICK_SCRUB_TRANSLATION_Y_FACTOR = 5f / 6;
public static final Interpolator QUICK_SCRUB_START_INTERPOLATOR = FAST_OUT_SLOW_IN;
/**
* Snap to a new page when crossing these thresholds. The first and last auto-advance.
*/
private static final float[] QUICK_SCRUB_THRESHOLDS = new float[] {
0.05f, 0.20f, 0.35f, 0.50f, 0.65f, 0.80f, 0.95f
};
private static final FloatProperty<QuickScrubController> PROGRESS
= new FloatProperty<QuickScrubController>("progress") {
@Override
public void setValue(QuickScrubController quickScrubController, float progress) {
quickScrubController.onQuickScrubProgress(progress);
}
@Override
public Float get(QuickScrubController quickScrubController) {
return quickScrubController.mEndProgress;
}
};
private static final String TAG = "QuickScrubController";
private static final boolean ENABLE_AUTO_ADVANCE = true;
private static final long AUTO_ADVANCE_DELAY = 500;
private static final int QUICKSCRUB_SNAP_DURATION_PER_PAGE = 325;
private static final int QUICKSCRUB_END_SNAP_DURATION_PER_PAGE = 60;
private final Alarm mAutoAdvanceAlarm;
private final RecentsView mRecentsView;
private final BaseActivity mActivity;
private boolean mInQuickScrub;
private boolean mWaitingForTaskLaunch;
private int mQuickScrubSection;
private boolean mStartedFromHome;
private boolean mFinishedTransitionToQuickScrub;
private int mLaunchingTaskId;
private Runnable mOnFinishedTransitionToQuickScrubRunnable;
private ActivityControlHelper mActivityControlHelper;
private TouchInteractionLog mTouchInteractionLog;
private boolean mIsQuickSwitch;
private float mStartProgress;
private float mEndProgress;
private float mPrevProgressDelta;
private float mPrevPrevProgressDelta;
private boolean mShouldSwitchToNext;
public QuickScrubController(BaseActivity activity, RecentsView recentsView) {
mActivity = activity;
mRecentsView = recentsView;
if (ENABLE_AUTO_ADVANCE) {
mAutoAdvanceAlarm = new Alarm();
mAutoAdvanceAlarm.setOnAlarmListener(this);
}
}
public void onQuickScrubStart(boolean startingFromHome, ActivityControlHelper controlHelper,
TouchInteractionLog touchInteractionLog) {
prepareQuickScrub(TAG);
mInQuickScrub = true;
mStartedFromHome = startingFromHome;
mQuickScrubSection = 0;
mFinishedTransitionToQuickScrub = false;
mActivityControlHelper = controlHelper;
mTouchInteractionLog = touchInteractionLog;
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
if (mRecentsView.getRunningTaskView() != null) {
mRecentsView.getRunningTaskView().setShowScreenshot(false);
}
}
if (mIsQuickSwitch) {
mShouldSwitchToNext = true;
mPrevProgressDelta = 0;
TaskView runningTaskView = mRecentsView.getRunningTaskView();
TaskView nextTaskView = mRecentsView.getNextTaskView();
if (runningTaskView != null) {
runningTaskView.setFullscreenProgress(1);
}
if (nextTaskView != null) {
nextTaskView.setFullscreenProgress(1);
}
}
snapToNextTaskIfAvailable();
mActivity.getUserEventDispatcher().resetActionDurationMillis();
}
public void onQuickScrubEnd() {
mInQuickScrub = false;
Runnable launchTaskRunnable = () -> {
int page = mRecentsView.getPageNearestToCenterOfScreen();
TaskView taskView = mRecentsView.getTaskViewAt(page);
if (taskView != null) {
mWaitingForTaskLaunch = true;
mTouchInteractionLog.launchTaskStart();
mLaunchingTaskId = taskView.getTask().key.id;
taskView.launchTask(true, (result) -> {
mTouchInteractionLog.launchTaskEnd(result);
if (!result) {
taskView.notifyTaskLaunchFailed(TAG);
breakOutOfQuickScrub();
} else {
mActivity.getUserEventDispatcher().logTaskLaunchOrDismiss(Touch.DRAGDROP,
LauncherLogProto.Action.Direction.NONE, page,
TaskUtils.getLaunchComponentKeyForTask(taskView.getTask().key));
}
mWaitingForTaskLaunch = false;
if (mIsQuickSwitch) {
mIsQuickSwitch = false;
TaskView runningTaskView = mRecentsView.getRunningTaskView();
TaskView nextTaskView = mRecentsView.getNextTaskView();
if (runningTaskView != null) {
runningTaskView.setFullscreenProgress(0);
}
if (nextTaskView != null) {
nextTaskView.setFullscreenProgress(0);
}
}
}, taskView.getHandler());
} else {
breakOutOfQuickScrub();
}
mActivityControlHelper = null;
};
if (mIsQuickSwitch) {
float progressVelocity = mPrevPrevProgressDelta / SINGLE_FRAME_MS;
// Move to the next frame immediately, then start the animation from the
// following frame since it starts a frame later.
float singleFrameProgress = progressVelocity * SINGLE_FRAME_MS;
float fromProgress = mEndProgress + singleFrameProgress;
onQuickScrubProgress(fromProgress);
fromProgress += singleFrameProgress;
float toProgress = mShouldSwitchToNext ? 1 : 0;
int duration = (int) Math.abs((toProgress - fromProgress) / progressVelocity);
duration = Utilities.boundToRange(duration, 80, 300);
Animator anim = ObjectAnimator.ofFloat(this, PROGRESS, fromProgress, toProgress);
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
launchTaskRunnable.run();
}
});
anim.setDuration(duration).start();
return;
}
if (ENABLE_AUTO_ADVANCE) {
mAutoAdvanceAlarm.cancelAlarm();
}
int page = mRecentsView.getNextPage();
int snapDuration = Math.abs(page - mRecentsView.getPageNearestToCenterOfScreen())
* QUICKSCRUB_END_SNAP_DURATION_PER_PAGE;
if (mRecentsView.getChildCount() > 0 && mRecentsView.snapToPage(page, snapDuration)) {
// Settle on the page then launch it
mRecentsView.setNextPageSwitchRunnable(launchTaskRunnable);
} else {
// No page move needed, just launch it
if (mFinishedTransitionToQuickScrub) {
launchTaskRunnable.run();
} else {
mOnFinishedTransitionToQuickScrubRunnable = launchTaskRunnable;
}
}
}
public void cancelActiveQuickscrub() {
if (!mInQuickScrub) {
return;
}
Log.d(TAG, "Quickscrub was active, cancelling");
mInQuickScrub = false;
mActivityControlHelper = null;
mOnFinishedTransitionToQuickScrubRunnable = null;
mRecentsView.setNextPageSwitchRunnable(null);
mLaunchingTaskId = 0;
}
public boolean prepareQuickScrub(String tag) {
return prepareQuickScrub(tag, mIsQuickSwitch);
}
/**
* Initializes the UI for quick scrub, returns true if success.
*/
public boolean prepareQuickScrub(String tag, boolean isQuickSwitch) {
if (mWaitingForTaskLaunch || mInQuickScrub) {
Log.d(tag, "Waiting for last scrub to finish, will skip this interaction");
return false;
}
mOnFinishedTransitionToQuickScrubRunnable = null;
mRecentsView.setNextPageSwitchRunnable(null);
mIsQuickSwitch = isQuickSwitch;
return true;
}
public boolean isQuickSwitch() {
return mIsQuickSwitch;
}
public boolean isWaitingForTaskLaunch() {
return mWaitingForTaskLaunch;
}
public boolean hasFinishedTransitionToQuickScrub() {
return mFinishedTransitionToQuickScrub;
}
/**
* Attempts to go to normal overview or back to home, so UI doesn't prevent user interaction.
*/
private void breakOutOfQuickScrub() {
if (mRecentsView.getChildCount() == 0 || mActivityControlHelper == null
|| !mActivityControlHelper.switchToRecentsIfVisible(false)) {
mActivity.onBackPressed();
}
}
public void onQuickScrubProgress(float progress) {
if (mIsQuickSwitch) {
TaskView currentPage = mRecentsView.getRunningTaskView();
TaskView nextPage = mRecentsView.getNextTaskView();
if (currentPage == null || nextPage == null) {
return;
}
if (!mFinishedTransitionToQuickScrub || mStartProgress <= 0) {
mStartProgress = mEndProgress = progress;
} else {
float progressDelta = progress - mEndProgress;
mEndProgress = progress;
progress = Utilities.boundToRange(progress, mStartProgress, 1);
progress = Utilities.mapToRange(progress, mStartProgress, 1, 0, 1, LINEAR);
if (mInQuickScrub) {
mShouldSwitchToNext = mPrevProgressDelta > 0.007f || progressDelta > 0.007f
|| progress >= 0.5f;
}
mPrevPrevProgressDelta = mPrevProgressDelta;
mPrevProgressDelta = progressDelta;
int startScroll = mRecentsView.getScrollForPage(
mRecentsView.indexOfChild(currentPage));
int scrollDiff = mRecentsView.getScrollForPage(mRecentsView.indexOfChild(nextPage))
- startScroll;
int linearScrollDiff = (int) (progress * scrollDiff);
currentPage.setZoomScale(1 - DEACCEL_3.getInterpolation(progress)
* TaskView.EDGE_SCALE_DOWN_FACTOR);
if (!ENABLE_TASK_STABILIZER.get()) {
float accelScrollDiff = ACCEL.getInterpolation(progress) * scrollDiff;
currentPage.setTranslationX(linearScrollDiff + accelScrollDiff);
}
nextPage.setTranslationZ(1);
nextPage.setTranslationY(currentPage.getTranslationY());
mRecentsView.setScrollX(startScroll + linearScrollDiff);
}
return;
}
int quickScrubSection = 0;
for (float threshold : QUICK_SCRUB_THRESHOLDS) {
if (progress < threshold) {
break;
}
quickScrubSection++;
}
if (quickScrubSection != mQuickScrubSection) {
boolean cameFromAutoAdvance = mQuickScrubSection == QUICK_SCRUB_THRESHOLDS.length
|| mQuickScrubSection == 0;
int pageToGoTo = mRecentsView.getNextPage() + quickScrubSection - mQuickScrubSection;
if (mFinishedTransitionToQuickScrub && !cameFromAutoAdvance) {
goToPageWithHaptic(pageToGoTo);
}
if (ENABLE_AUTO_ADVANCE) {
if (quickScrubSection == QUICK_SCRUB_THRESHOLDS.length || quickScrubSection == 0) {
mAutoAdvanceAlarm.setAlarm(AUTO_ADVANCE_DELAY);
} else {
mAutoAdvanceAlarm.cancelAlarm();
}
}
mQuickScrubSection = quickScrubSection;
}
}
public void onFinishedTransitionToQuickScrub() {
mFinishedTransitionToQuickScrub = true;
Runnable action = mOnFinishedTransitionToQuickScrubRunnable;
// Clear the runnable before executing it, to prevent potential recursion.
mOnFinishedTransitionToQuickScrubRunnable = null;
if (action != null) {
action.run();
}
mRecentsView.setEnableDrawingLiveTile(true);
}
public void onTaskRemoved(int taskId) {
if (mLaunchingTaskId == taskId) {
// The task has been removed mid-launch, break out of quickscrub and return the user
// to where they were before (and notify the launch failed)
TaskView taskView = mRecentsView.getTaskView(taskId);
if (taskView != null) {
taskView.notifyTaskLaunchFailed(TAG);
}
breakOutOfQuickScrub();
}
}
public void snapToNextTaskIfAvailable() {
if (mInQuickScrub && mRecentsView.getChildCount() > 0) {
int duration = mIsQuickSwitch
? QUICK_SWITCH_FROM_APP_START_DURATION
: mStartedFromHome
? QUICK_SCRUB_FROM_HOME_START_DURATION
: QUICK_SCRUB_FROM_APP_START_DURATION;
final int pageToGoTo;
if (mStartedFromHome) {
pageToGoTo = 0;
} else if (mIsQuickSwitch) {
TaskView tv = mRecentsView.getRunningTaskView();
pageToGoTo = tv != null ? mRecentsView.indexOfChild(tv)
: mRecentsView.getNextPage();
} else {
pageToGoTo = mRecentsView.getNextPage() + 1;
}
goToPageWithHaptic(pageToGoTo, duration, true /* forceHaptic */,
QUICK_SCRUB_START_INTERPOLATOR);
}
}
private void goToPageWithHaptic(int pageToGoTo) {
goToPageWithHaptic(pageToGoTo, -1 /* overrideDuration */, false /* forceHaptic */, null);
}
private void goToPageWithHaptic(int pageToGoTo, int overrideDuration, boolean forceHaptic,
Interpolator interpolator) {
pageToGoTo = Utilities.boundToRange(pageToGoTo, 0, mRecentsView.getTaskViewCount() - 1);
boolean snappingToPage = pageToGoTo != mRecentsView.getNextPage();
if (snappingToPage) {
int duration = overrideDuration > -1 ? overrideDuration
: Math.abs(pageToGoTo - mRecentsView.getNextPage())
* QUICKSCRUB_SNAP_DURATION_PER_PAGE;
mRecentsView.snapToPage(pageToGoTo, duration, interpolator);
}
if (snappingToPage || forceHaptic) {
mRecentsView.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY,
HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
}
}
@Override
public void onAlarm(Alarm alarm) {
int currPage = mRecentsView.getNextPage();
boolean recentsVisible = mActivityControlHelper != null
&& mActivityControlHelper.getVisibleRecentsView() != null;
if (!recentsVisible) {
Log.w(TAG, "Failed to auto advance; recents not visible");
return;
}
if (mQuickScrubSection == QUICK_SCRUB_THRESHOLDS.length
&& currPage < mRecentsView.getTaskViewCount() - 1) {
goToPageWithHaptic(currPage + 1);
} else if (mQuickScrubSection == 0 && currPage > 0) {
goToPageWithHaptic(currPage - 1);
}
if (ENABLE_AUTO_ADVANCE) {
mAutoAdvanceAlarm.setAlarm(AUTO_ADVANCE_DELAY);
}
}
}

View File

@ -19,10 +19,6 @@ import android.annotation.TargetApi;
import android.os.Build; import android.os.Build;
import android.view.MotionEvent; import android.view.MotionEvent;
import androidx.annotation.IntDef;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.function.Consumer; import java.util.function.Consumer;
@TargetApi(Build.VERSION_CODES.O) @TargetApi(Build.VERSION_CODES.O)
@ -31,23 +27,6 @@ public interface TouchConsumer extends Consumer<MotionEvent> {
TouchConsumer NO_OP = (ev) -> {}; TouchConsumer NO_OP = (ev) -> {};
@IntDef(flag = true, value = {
INTERACTION_NORMAL,
INTERACTION_QUICK_SCRUB
})
@Retention(RetentionPolicy.SOURCE)
@interface InteractionType {}
int INTERACTION_NORMAL = 0;
int INTERACTION_QUICK_SCRUB = 1;
default void onQuickScrubStart() { }
default void onQuickScrubEnd() { }
default void onQuickScrubProgress(float progress) { }
default void onShowOverviewFromAltTab() {}
default boolean isActive() { default boolean isActive() {
return false; return false;
} }

View File

@ -23,7 +23,7 @@ import java.util.Calendar;
import java.util.LinkedList; import java.util.LinkedList;
/** /**
* Keeps track of debugging logs for a particular quickstep/scrub gesture. * Keeps track of debugging logs for a particular quickstep gesture.
*/ */
public class TouchInteractionLog { public class TouchInteractionLog {
@ -54,18 +54,6 @@ public class TouchInteractionLog {
getCurrentLog().add("qstStart"); getCurrentLog().add("qstStart");
} }
public void startQuickScrub() {
getCurrentLog().add("qsStart");
}
public void setQuickScrubProgress(float progress) {
getCurrentLog().add("qsP=" + progress);
}
public void endQuickScrub(String reason) {
getCurrentLog().add("qsEnd=" + reason);
}
public void startRecentsAnimation() { public void startRecentsAnimation() {
getCurrentLog().add("raStart"); getCurrentLog().add("raStart");
} }
@ -82,14 +70,6 @@ public class TouchInteractionLog {
getCurrentLog().add("raFinish=" + toHome); getCurrentLog().add("raFinish=" + toHome);
} }
public void launchTaskStart() {
getCurrentLog().add("launchStart");
}
public void launchTaskEnd(boolean result) {
getCurrentLog().add("launchEnd=" + result);
}
public void dump(PrintWriter pw) { public void dump(PrintWriter pw) {
pw.println("TouchInteractionLog {"); pw.println("TouchInteractionLog {");
for (ArrayList<String> gesture : mGestureLogs) { for (ArrayList<String> gesture : mGestureLogs) {

View File

@ -15,12 +15,9 @@
*/ */
package com.android.quickstep; package com.android.quickstep;
import static android.view.MotionEvent.ACTION_CANCEL;
import static android.view.MotionEvent.ACTION_DOWN; import static android.view.MotionEvent.ACTION_DOWN;
import static android.view.MotionEvent.ACTION_UP;
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE; import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.systemui.shared.system.NavigationBarCompat.HIT_TARGET_NONE;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_INPUT_CHANNEL; import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_INPUT_CHANNEL;
import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SYSUI_PROXY; import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SYSUI_PROXY;
@ -34,20 +31,19 @@ import android.os.Bundle;
import android.os.IBinder; import android.os.IBinder;
import android.os.Looper; import android.os.Looper;
import android.util.Log; import android.util.Log;
import android.util.SparseArray; import android.util.Pair;
import android.view.Choreographer; import android.view.Choreographer;
import android.view.InputEvent; import android.view.InputEvent;
import android.view.MotionEvent; import android.view.MotionEvent;
import com.android.launcher3.MainThreadExecutor; import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.util.TraceHelper;
import com.android.systemui.shared.recents.IOverviewProxy; import com.android.systemui.shared.recents.IOverviewProxy;
import com.android.systemui.shared.recents.ISystemUiProxy; import com.android.systemui.shared.recents.ISystemUiProxy;
import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.InputChannelCompat; import com.android.systemui.shared.system.InputChannelCompat;
import com.android.systemui.shared.system.InputChannelCompat.InputEventDispatcher;
import com.android.systemui.shared.system.InputChannelCompat.InputEventReceiver; import com.android.systemui.shared.system.InputChannelCompat.InputEventReceiver;
import com.android.systemui.shared.system.InputConsumerController; import com.android.systemui.shared.system.InputConsumerController;
import com.android.systemui.shared.system.NavigationBarCompat.HitTarget;
import java.io.FileDescriptor; import java.io.FileDescriptor;
import java.io.PrintWriter; import java.io.PrintWriter;
@ -59,15 +55,7 @@ import java.io.PrintWriter;
public class TouchInteractionService extends Service { public class TouchInteractionService extends Service {
public static final MainThreadExecutor MAIN_THREAD_EXECUTOR = new MainThreadExecutor(); public static final MainThreadExecutor MAIN_THREAD_EXECUTOR = new MainThreadExecutor();
public static final TouchInteractionLog TOUCH_INTERACTION_LOG = new TouchInteractionLog();
private static final SparseArray<String> sMotionEventNames;
static {
sMotionEventNames = new SparseArray<>(3);
sMotionEventNames.put(ACTION_DOWN, "ACTION_DOWN");
sMotionEventNames.put(ACTION_UP, "ACTION_UP");
sMotionEventNames.put(ACTION_CANCEL, "ACTION_CANCEL");
}
public static final int EDGE_NAV_BAR = 1 << 8; public static final int EDGE_NAV_BAR = 1 << 8;
@ -85,73 +73,12 @@ public class TouchInteractionService extends Service {
mRecentsModel.setSystemUiProxy(mISystemUiProxy); mRecentsModel.setSystemUiProxy(mISystemUiProxy);
mOverviewInteractionState.setSystemUiProxy(mISystemUiProxy); mOverviewInteractionState.setSystemUiProxy(mISystemUiProxy);
if (mInputEventReceiver != null) { disposeEventHandlers();
mInputEventReceiver.dispose();
}
mInputEventReceiver = InputChannelCompat.fromBundle(bundle, KEY_EXTRA_INPUT_CHANNEL, mInputEventReceiver = InputChannelCompat.fromBundle(bundle, KEY_EXTRA_INPUT_CHANNEL,
Looper.getMainLooper(), mMainChoreographer, Looper.getMainLooper(), mMainChoreographer,
TouchInteractionService.this::onInputEvent); TouchInteractionService.this::onInputEvent);
} }
public void onPreMotionEvent(@HitTarget int downHitTarget) {
// If ev are using the new dispatching system, skip the old logic
if (mInputEventReceiver != null) {
return;
}
mTouchInteractionLog.prepareForNewGesture();
TraceHelper.beginSection("SysUiBinder");
mEventQueue.onNewGesture(downHitTarget);
TraceHelper.partitionSection("SysUiBinder", "Down target " + downHitTarget);
}
public void onMotionEvent(MotionEvent ev) {
// If ev are using the new dispatching system, skip the old logic
if (mInputEventReceiver != null) {
ev.recycle();
return;
}
mEventQueue.queue(ev);
int action = ev.getActionMasked();
String name = sMotionEventNames.get(action);
if (name != null){
TraceHelper.partitionSection("SysUiBinder", name);
}
}
public void onBind(ISystemUiProxy iSystemUiProxy) {
mISystemUiProxy = iSystemUiProxy;
mRecentsModel.setSystemUiProxy(mISystemUiProxy);
mOverviewInteractionState.setSystemUiProxy(mISystemUiProxy);
}
public void onQuickScrubStart() {
// If ev are using the new dispatching system, skip the old logic
if (mInputEventReceiver != null) {
return;
}
mEventQueue.onQuickScrubStart();
TraceHelper.partitionSection("SysUiBinder", "onQuickScrubStart");
}
public void onQuickScrubProgress(float progress) {
// If ev are using the new dispatching system, skip the old logic
if (mInputEventReceiver != null) {
return;
}
mEventQueue.onQuickScrubProgress(progress);
}
public void onQuickScrubEnd() {
// If ev are using the new dispatching system, skip the old logic
if (mInputEventReceiver != null) {
return;
}
mEventQueue.onQuickScrubEnd();
TraceHelper.endSection("SysUiBinder", "onQuickScrubEnd");
}
@Override @Override
public void onOverviewToggle() { public void onOverviewToggle() {
mOverviewCommandHelper.onOverviewToggle(); mOverviewCommandHelper.onOverviewToggle();
@ -159,37 +86,55 @@ public class TouchInteractionService extends Service {
@Override @Override
public void onOverviewShown(boolean triggeredFromAltTab) { public void onOverviewShown(boolean triggeredFromAltTab) {
// If ev are using the new dispatching system, skip the old logic mOverviewCommandHelper.onOverviewShown();
if (mInputEventReceiver != null) {
mOverviewCommandHelper.onOverviewShown();
return;
}
if (triggeredFromAltTab) {
mEventQueue.onNewGesture(HIT_TARGET_NONE);
mEventQueue.onOverviewShownFromAltTab();
} else {
mOverviewCommandHelper.onOverviewShown();
}
} }
@Override @Override
public void onOverviewHidden(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) { public void onOverviewHidden(boolean triggeredFromAltTab, boolean triggeredFromHomeKey) {
// If ev are using the new dispatching system, skip the old logic
if (mInputEventReceiver != null) {
return;
}
if (triggeredFromAltTab && !triggeredFromHomeKey) { if (triggeredFromAltTab && !triggeredFromHomeKey) {
// onOverviewShownFromAltTab initiates quick scrub. Ending it here. // onOverviewShownFromAltTab hides the overview and ends at the target app
mEventQueue.onQuickScrubEnd(); mOverviewCommandHelper.onOverviewHidden();
} }
} }
public void onQuickStep(MotionEvent motionEvent) { }
@Override @Override
public void onTip(int actionType, int viewType) { public void onTip(int actionType, int viewType) {
mOverviewCommandHelper.onTip(actionType, viewType); mOverviewCommandHelper.onTip(actionType, viewType);
} }
/** Deprecated methods **/
public void onQuickStep(MotionEvent motionEvent) { }
public void onQuickScrubEnd() { }
public void onQuickScrubProgress(float progress) { }
public void onQuickScrubStart() { }
public void onPreMotionEvent(int downHitTarget) { }
public void onMotionEvent(MotionEvent ev) {
if (mDeprecatedDispatcher == null) {
ev.recycle();
} else {
mDeprecatedDispatcher.dispatch(ev);
}
}
public void onBind(ISystemUiProxy iSystemUiProxy) {
mISystemUiProxy = iSystemUiProxy;
mRecentsModel.setSystemUiProxy(mISystemUiProxy);
mOverviewInteractionState.setSystemUiProxy(mISystemUiProxy);
// On Bind is received before onInitialize which will dispose these handlers
disposeEventHandlers();
Pair<InputEventDispatcher, InputEventReceiver> pair = InputChannelCompat.createPair(
"sysui-callbacks", Looper.getMainLooper(), mMainChoreographer,
TouchInteractionService.this::onInputEvent);
mDeprecatedDispatcher = pair.first;
mInputEventReceiver = pair.second;
}
}; };
private static boolean sConnected = false; private static boolean sConnected = false;
@ -200,22 +145,23 @@ public class TouchInteractionService extends Service {
private ActivityManagerWrapper mAM; private ActivityManagerWrapper mAM;
private RecentsModel mRecentsModel; private RecentsModel mRecentsModel;
private MotionEventQueue mEventQueue;
private ISystemUiProxy mISystemUiProxy; private ISystemUiProxy mISystemUiProxy;
private OverviewCommandHelper mOverviewCommandHelper; private OverviewCommandHelper mOverviewCommandHelper;
private OverviewComponentObserver mOverviewComponentObserver; private OverviewComponentObserver mOverviewComponentObserver;
private OverviewInteractionState mOverviewInteractionState; private OverviewInteractionState mOverviewInteractionState;
private OverviewCallbacks mOverviewCallbacks; private OverviewCallbacks mOverviewCallbacks;
private TaskOverlayFactory mTaskOverlayFactory; private TaskOverlayFactory mTaskOverlayFactory;
private TouchInteractionLog mTouchInteractionLog;
private InputConsumerController mInputConsumer; private InputConsumerController mInputConsumer;
private SwipeSharedState mSwipeSharedState; private SwipeSharedState mSwipeSharedState;
private TouchConsumer mConsumer = TouchConsumer.NO_OP; private TouchConsumer mConsumer = TouchConsumer.NO_OP;
private Choreographer mMainChoreographer; private Choreographer mMainChoreographer;
private InputEventReceiver mInputEventReceiver; private InputEventReceiver mInputEventReceiver;
private Region mActiveNavBarRegion = new Region(); private Region mActiveNavBarRegion = new Region();
private InputEventDispatcher mDeprecatedDispatcher;
@Override @Override
public void onCreate() { public void onCreate() {
super.onCreate(); super.onCreate();
@ -225,12 +171,9 @@ public class TouchInteractionService extends Service {
mMainChoreographer = Choreographer.getInstance(); mMainChoreographer = Choreographer.getInstance();
mOverviewCommandHelper = new OverviewCommandHelper(this, mOverviewComponentObserver); mOverviewCommandHelper = new OverviewCommandHelper(this, mOverviewComponentObserver);
mEventQueue = new MotionEventQueue(Looper.myLooper(), Choreographer.getInstance(),
this::newConsumer);
mOverviewInteractionState = OverviewInteractionState.INSTANCE.get(this); mOverviewInteractionState = OverviewInteractionState.INSTANCE.get(this);
mOverviewCallbacks = OverviewCallbacks.get(this); mOverviewCallbacks = OverviewCallbacks.get(this);
mTaskOverlayFactory = TaskOverlayFactory.INSTANCE.get(this); mTaskOverlayFactory = TaskOverlayFactory.INSTANCE.get(this);
mTouchInteractionLog = new TouchInteractionLog();
mSwipeSharedState = new SwipeSharedState(); mSwipeSharedState = new SwipeSharedState();
mInputConsumer = InputConsumerController.getRecentsAnimationInputConsumer(); mInputConsumer = InputConsumerController.getRecentsAnimationInputConsumer();
mInputConsumer.registerInputConsumer(); mInputConsumer.registerInputConsumer();
@ -245,14 +188,22 @@ public class TouchInteractionService extends Service {
public void onDestroy() { public void onDestroy() {
mInputConsumer.unregisterInputConsumer(); mInputConsumer.unregisterInputConsumer();
mOverviewComponentObserver.onDestroy(); mOverviewComponentObserver.onDestroy();
mEventQueue.dispose(); disposeEventHandlers();
if (mInputEventReceiver != null) {
mInputEventReceiver.dispose();
}
sConnected = false; sConnected = false;
super.onDestroy(); super.onDestroy();
} }
private void disposeEventHandlers() {
if (mInputEventReceiver != null) {
mInputEventReceiver.dispose();
mInputEventReceiver = null;
}
if (mDeprecatedDispatcher != null) {
mDeprecatedDispatcher.dispose();
mDeprecatedDispatcher = null;
}
}
@Override @Override
public IBinder onBind(Intent intent) { public IBinder onBind(Intent intent) {
Log.d(TAG, "Touch service connected"); Log.d(TAG, "Touch service connected");
@ -266,45 +217,17 @@ public class TouchInteractionService extends Service {
} }
MotionEvent event = (MotionEvent) ev; MotionEvent event = (MotionEvent) ev;
if (event.getAction() == ACTION_DOWN) { if (event.getAction() == ACTION_DOWN) {
mTouchInteractionLog.prepareForNewGesture(); TOUCH_INTERACTION_LOG.prepareForNewGesture();
boolean useSharedState = mConsumer.isActive(); boolean useSharedState = mConsumer.isActive();
mConsumer.onConsumerAboutToBeSwitched(); mConsumer.onConsumerAboutToBeSwitched();
mConsumer = newConsumer(useSharedState, event); mConsumer = newConsumer(useSharedState, event);
TOUCH_INTERACTION_LOG.setTouchConsumer(mConsumer);
} }
TOUCH_INTERACTION_LOG.addMotionEvent(event);
mConsumer.accept(event); mConsumer.accept(event);
} }
private TouchConsumer newConsumer(@HitTarget int downHitTarget, boolean useSharedState) {
RunningTaskInfo runningTaskInfo = mAM.getRunningTask(0);
if (!useSharedState) {
mSwipeSharedState.clearAllState();
}
if (runningTaskInfo == null && !mSwipeSharedState.goingToLauncher) {
return TouchConsumer.NO_OP;
} else if (mSwipeSharedState.goingToLauncher ||
mOverviewComponentObserver.getActivityControlHelper().isResumed()) {
return OverviewTouchConsumer.newInstance(
mOverviewComponentObserver.getActivityControlHelper(), false,
mTouchInteractionLog);
} else if (ENABLE_QUICKSTEP_LIVE_TILE.get() &&
mOverviewComponentObserver.getActivityControlHelper().isInLiveTileMode()) {
return OverviewTouchConsumer.newInstance(
mOverviewComponentObserver.getActivityControlHelper(), false,
mTouchInteractionLog, false /* waitForWindowAvailable */);
} else {
ActivityControlHelper activityControl =
mOverviewComponentObserver.getActivityControlHelper();
return new OtherActivityTouchConsumer(this, runningTaskInfo, mRecentsModel,
mOverviewComponentObserver.getOverviewIntent(),
mOverviewComponentObserver.getActivityControlHelper(),
activityControl.deferStartingActivity(downHitTarget), mOverviewCallbacks,
mTaskOverlayFactory, mInputConsumer, mTouchInteractionLog,
mEventQueue::onConsumerInactive, mSwipeSharedState);
}
}
private TouchConsumer newConsumer(boolean useSharedState, MotionEvent event) { private TouchConsumer newConsumer(boolean useSharedState, MotionEvent event) {
RunningTaskInfo runningTaskInfo = mAM.getRunningTask(0); RunningTaskInfo runningTaskInfo = mAM.getRunningTask(0);
if (!useSharedState) { if (!useSharedState) {
@ -316,13 +239,11 @@ public class TouchInteractionService extends Service {
} else if (mSwipeSharedState.goingToLauncher || } else if (mSwipeSharedState.goingToLauncher ||
mOverviewComponentObserver.getActivityControlHelper().isResumed()) { mOverviewComponentObserver.getActivityControlHelper().isResumed()) {
return OverviewTouchConsumer.newInstance( return OverviewTouchConsumer.newInstance(
mOverviewComponentObserver.getActivityControlHelper(), false, mOverviewComponentObserver.getActivityControlHelper(), false);
mTouchInteractionLog);
} else if (ENABLE_QUICKSTEP_LIVE_TILE.get() && } else if (ENABLE_QUICKSTEP_LIVE_TILE.get() &&
mOverviewComponentObserver.getActivityControlHelper().isInLiveTileMode()) { mOverviewComponentObserver.getActivityControlHelper().isInLiveTileMode()) {
return OverviewTouchConsumer.newInstance( return OverviewTouchConsumer.newInstance(
mOverviewComponentObserver.getActivityControlHelper(), false, mOverviewComponentObserver.getActivityControlHelper(), false);
mTouchInteractionLog, false /* waitForWindowAvailable */);
} else { } else {
ActivityControlHelper activityControl = ActivityControlHelper activityControl =
mOverviewComponentObserver.getActivityControlHelper(); mOverviewComponentObserver.getActivityControlHelper();
@ -331,7 +252,7 @@ public class TouchInteractionService extends Service {
mOverviewComponentObserver.getOverviewIntent(), mOverviewComponentObserver.getOverviewIntent(),
mOverviewComponentObserver.getActivityControlHelper(), mOverviewComponentObserver.getActivityControlHelper(),
shouldDefer, mOverviewCallbacks, shouldDefer, mOverviewCallbacks,
mTaskOverlayFactory, mInputConsumer, mTouchInteractionLog, mTaskOverlayFactory, mInputConsumer,
this::onConsumerInactive, mSwipeSharedState); this::onConsumerInactive, mSwipeSharedState);
} }
} }
@ -347,6 +268,6 @@ public class TouchInteractionService extends Service {
@Override @Override
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
mTouchInteractionLog.dump(pw); TOUCH_INTERACTION_LOG.dump(pw);
} }
} }

View File

@ -25,16 +25,14 @@ import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2; import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2;
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE; import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.launcher3.config.FeatureFlags.QUICKSTEP_SPRINGS; import static com.android.launcher3.config.FeatureFlags.QUICKSTEP_SPRINGS;
import static com.android.launcher3.config.FeatureFlags.SWIPE_HOME;
import static com.android.launcher3.util.RaceConditionTracker.ENTER; import static com.android.launcher3.util.RaceConditionTracker.ENTER;
import static com.android.launcher3.util.RaceConditionTracker.EXIT; import static com.android.launcher3.util.RaceConditionTracker.EXIT;
import static com.android.launcher3.config.FeatureFlags.SWIPE_HOME;
import static com.android.quickstep.ActivityControlHelper.AnimationFactory.ShelfAnimState.HIDE; import static com.android.quickstep.ActivityControlHelper.AnimationFactory.ShelfAnimState.HIDE;
import static com.android.quickstep.ActivityControlHelper.AnimationFactory.ShelfAnimState.PEEK; import static com.android.quickstep.ActivityControlHelper.AnimationFactory.ShelfAnimState.PEEK;
import static com.android.quickstep.QuickScrubController.QUICK_SCRUB_FROM_APP_START_DURATION; import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
import static com.android.quickstep.QuickScrubController.QUICK_SWITCH_FROM_APP_START_DURATION;
import static com.android.quickstep.TouchConsumer.INTERACTION_NORMAL;
import static com.android.quickstep.TouchConsumer.INTERACTION_QUICK_SCRUB;
import static com.android.quickstep.TouchInteractionService.MAIN_THREAD_EXECUTOR; import static com.android.quickstep.TouchInteractionService.MAIN_THREAD_EXECUTOR;
import static com.android.quickstep.TouchInteractionService.TOUCH_INTERACTION_LOG;
import static com.android.quickstep.WindowTransformSwipeHandler.GestureEndTarget.HOME; import static com.android.quickstep.WindowTransformSwipeHandler.GestureEndTarget.HOME;
import static com.android.quickstep.WindowTransformSwipeHandler.GestureEndTarget.LAST_TASK; import static com.android.quickstep.WindowTransformSwipeHandler.GestureEndTarget.LAST_TASK;
import static com.android.quickstep.WindowTransformSwipeHandler.GestureEndTarget.NEW_TASK; import static com.android.quickstep.WindowTransformSwipeHandler.GestureEndTarget.NEW_TASK;
@ -50,7 +48,6 @@ import android.animation.ValueAnimator;
import android.annotation.TargetApi; import android.annotation.TargetApi;
import android.app.ActivityManager.RunningTaskInfo; import android.app.ActivityManager.RunningTaskInfo;
import android.content.Context; import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Point; import android.graphics.Point;
import android.graphics.Rect; import android.graphics.Rect;
@ -60,7 +57,6 @@ import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.os.SystemClock; import android.os.SystemClock;
import android.os.UserHandle;
import android.view.HapticFeedbackConstants; import android.view.HapticFeedbackConstants;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.View; import android.view.View;
@ -68,10 +64,6 @@ import android.view.ViewTreeObserver.OnDrawListener;
import android.view.WindowManager; import android.view.WindowManager;
import android.view.animation.Interpolator; import android.view.animation.Interpolator;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.DeviceProfile; import com.android.launcher3.DeviceProfile;
@ -94,17 +86,14 @@ import com.android.quickstep.ActivityControlHelper.ActivityInitListener;
import com.android.quickstep.ActivityControlHelper.AnimationFactory; import com.android.quickstep.ActivityControlHelper.AnimationFactory;
import com.android.quickstep.ActivityControlHelper.AnimationFactory.ShelfAnimState; import com.android.quickstep.ActivityControlHelper.AnimationFactory.ShelfAnimState;
import com.android.quickstep.ActivityControlHelper.LayoutListener; import com.android.quickstep.ActivityControlHelper.LayoutListener;
import com.android.quickstep.TouchConsumer.InteractionType;
import com.android.quickstep.util.ClipAnimationHelper; import com.android.quickstep.util.ClipAnimationHelper;
import com.android.quickstep.util.RemoteAnimationTargetSet; import com.android.quickstep.util.RemoteAnimationTargetSet;
import com.android.quickstep.util.SwipeAnimationTargetSet; import com.android.quickstep.util.SwipeAnimationTargetSet;
import com.android.quickstep.util.SwipeAnimationTargetSet.SwipeAnimationListener; import com.android.quickstep.util.SwipeAnimationTargetSet.SwipeAnimationListener;
import com.android.quickstep.util.TransformedRect;
import com.android.quickstep.views.RecentsView; import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView; import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.recents.model.ThumbnailData; import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.recents.utilities.RectFEvaluator; import com.android.systemui.shared.recents.utilities.RectFEvaluator;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.InputConsumerController; import com.android.systemui.shared.system.InputConsumerController;
import com.android.systemui.shared.system.LatencyTrackerCompat; import com.android.systemui.shared.system.LatencyTrackerCompat;
import com.android.systemui.shared.system.RecentsAnimationControllerCompat; import com.android.systemui.shared.system.RecentsAnimationControllerCompat;
@ -114,44 +103,67 @@ import com.android.systemui.shared.system.WindowCallbacksCompat;
import java.util.function.BiFunction; import java.util.function.BiFunction;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
@TargetApi(Build.VERSION_CODES.O) @TargetApi(Build.VERSION_CODES.O)
public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
implements SwipeAnimationListener { implements SwipeAnimationListener {
private static final String TAG = WindowTransformSwipeHandler.class.getSimpleName(); private static final String TAG = WindowTransformSwipeHandler.class.getSimpleName();
private static final String[] STATE_NAMES = DEBUG_STATES ? new String[19] : null;
private static int getFlagForIndex(int index, String name) {
if (DEBUG_STATES) {
STATE_NAMES[index] = name;
}
return 1 << index;
}
// Launcher UI related states // Launcher UI related states
private static final int STATE_LAUNCHER_PRESENT = 1 << 0; private static final int STATE_LAUNCHER_PRESENT = getFlagForIndex(0, "STATE_LAUNCHER_PRESENT");
private static final int STATE_LAUNCHER_STARTED = 1 << 1; private static final int STATE_LAUNCHER_STARTED = getFlagForIndex(1, "STATE_LAUNCHER_STARTED");
private static final int STATE_LAUNCHER_DRAWN = 1 << 2; private static final int STATE_LAUNCHER_DRAWN = getFlagForIndex(2, "STATE_LAUNCHER_DRAWN");
private static final int STATE_ACTIVITY_MULTIPLIER_COMPLETE = 1 << 3; private static final int STATE_ACTIVITY_MULTIPLIER_COMPLETE =
getFlagForIndex(3, "STATE_ACTIVITY_MULTIPLIER_COMPLETE");
// Internal initialization states // Internal initialization states
private static final int STATE_APP_CONTROLLER_RECEIVED = 1 << 4; private static final int STATE_APP_CONTROLLER_RECEIVED =
getFlagForIndex(4, "STATE_APP_CONTROLLER_RECEIVED");
// Interaction finish states // Interaction finish states
private static final int STATE_SCALED_CONTROLLER_HOME = 1 << 5; private static final int STATE_SCALED_CONTROLLER_HOME =
private static final int STATE_SCALED_CONTROLLER_RECENTS = 1 << 6; getFlagForIndex(5, "STATE_SCALED_CONTROLLER_HOME");
private static final int STATE_SCALED_CONTROLLER_LAST_TASK = 1 << 7; private static final int STATE_SCALED_CONTROLLER_RECENTS =
getFlagForIndex(6, "STATE_SCALED_CONTROLLER_RECENTS");
private static final int STATE_SCALED_CONTROLLER_LAST_TASK =
getFlagForIndex(7, "STATE_SCALED_CONTROLLER_LAST_TASK");
private static final int STATE_HANDLER_INVALIDATED = 1 << 8; private static final int STATE_HANDLER_INVALIDATED =
private static final int STATE_GESTURE_STARTED_QUICKSTEP = 1 << 9; getFlagForIndex(8, "STATE_HANDLER_INVALIDATED");
private static final int STATE_GESTURE_STARTED_QUICKSCRUB = 1 << 10; private static final int STATE_GESTURE_STARTED =
private static final int STATE_GESTURE_CANCELLED = 1 << 11; getFlagForIndex(9, "STATE_GESTURE_STARTED");
private static final int STATE_GESTURE_COMPLETED = 1 << 12; private static final int STATE_GESTURE_CANCELLED =
getFlagForIndex(10, "STATE_GESTURE_CANCELLED");
private static final int STATE_GESTURE_COMPLETED =
getFlagForIndex(11, "STATE_GESTURE_COMPLETED");
// States for quick switch/scrub private static final int STATE_CAPTURE_SCREENSHOT =
private static final int STATE_CURRENT_TASK_FINISHED = 1 << 13; getFlagForIndex(12, "STATE_CAPTURE_SCREENSHOT");
private static final int STATE_QUICK_SCRUB_START = 1 << 14; private static final int STATE_SCREENSHOT_CAPTURED =
private static final int STATE_QUICK_SCRUB_END = 1 << 15; getFlagForIndex(13, "STATE_SCREENSHOT_CAPTURED");
private static final int STATE_SCREENSHOT_VIEW_SHOWN =
private static final int STATE_CAPTURE_SCREENSHOT = 1 << 16; getFlagForIndex(14, "STATE_SCREENSHOT_VIEW_SHOWN");
private static final int STATE_SCREENSHOT_CAPTURED = 1 << 17;
private static final int STATE_SCREENSHOT_VIEW_SHOWN = 1 << 18;
private static final int STATE_RESUME_LAST_TASK = 1 << 19;
private static final int STATE_START_NEW_TASK = 1 << 20;
private static final int STATE_ASSIST_DATA_RECEIVED = 1 << 21;
private static final int STATE_RESUME_LAST_TASK =
getFlagForIndex(15, "STATE_RESUME_LAST_TASK");
private static final int STATE_START_NEW_TASK =
getFlagForIndex(16, "STATE_START_NEW_TASK");
private static final int STATE_CURRENT_TASK_FINISHED =
getFlagForIndex(17, "STATE_CURRENT_TASK_FINISHED");
private static final int STATE_ASSIST_DATA_RECEIVED =
getFlagForIndex(18, "STATE_ASSIST_DATA_RECEIVED");
private static final int LAUNCHER_UI_STATES = private static final int LAUNCHER_UI_STATES =
STATE_LAUNCHER_PRESENT | STATE_LAUNCHER_DRAWN | STATE_ACTIVITY_MULTIPLIER_COMPLETE STATE_LAUNCHER_PRESENT | STATE_LAUNCHER_DRAWN | STATE_ACTIVITY_MULTIPLIER_COMPLETE
@ -165,34 +177,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
STATE_ACTIVITY_MULTIPLIER_COMPLETE | STATE_LAUNCHER_STARTED STATE_ACTIVITY_MULTIPLIER_COMPLETE | STATE_LAUNCHER_STARTED
| STATE_APP_CONTROLLER_RECEIVED | STATE_SCREENSHOT_CAPTURED; | STATE_APP_CONTROLLER_RECEIVED | STATE_SCREENSHOT_CAPTURED;
private static final int QUICK_SCRUB_START_UI_STATE = STATE_LAUNCHER_STARTED
| STATE_QUICK_SCRUB_START | STATE_APP_CONTROLLER_RECEIVED;
// For debugging, keep in sync with above states // For debugging, keep in sync with above states
public static final String[] STATES = new String[] {
"STATE_LAUNCHER_PRESENT",
"STATE_LAUNCHER_STARTED",
"STATE_LAUNCHER_DRAWN",
"STATE_ACTIVITY_MULTIPLIER_COMPLETE",
"STATE_APP_CONTROLLER_RECEIVED",
"STATE_SCALED_CONTROLLER_HOME",
"STATE_SCALED_CONTROLLER_RECENTS",
"STATE_SCALED_CONTROLLER_LAST_TASK",
"STATE_HANDLER_INVALIDATED",
"STATE_GESTURE_STARTED_QUICKSTEP",
"STATE_GESTURE_STARTED_QUICKSCRUB",
"STATE_GESTURE_CANCELLED",
"STATE_GESTURE_COMPLETED",
"STATE_CURRENT_TASK_FINISHED",
"STATE_QUICK_SCRUB_START",
"STATE_QUICK_SCRUB_END",
"STATE_CAPTURE_SCREENSHOT",
"STATE_SCREENSHOT_CAPTURED",
"STATE_SCREENSHOT_VIEW_SHOWN",
"STATE_RESUME_LAST_TASK",
"STATE_START_NEW_TASK",
"STATE_ASSIST_DATA_RECEIVED",
};
enum GestureEndTarget { enum GestureEndTarget {
HOME(1, STATE_SCALED_CONTROLLER_HOME, true, false, ContainerType.WORKSPACE), HOME(1, STATE_SCALED_CONTROLLER_HOME, true, false, ContainerType.WORKSPACE),
@ -256,7 +241,6 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
private final Context mContext; private final Context mContext;
private final ActivityControlHelper<T> mActivityControlHelper; private final ActivityControlHelper<T> mActivityControlHelper;
private final ActivityInitListener mActivityInitListener; private final ActivityInitListener mActivityInitListener;
private final TouchInteractionLog mTouchInteractionLog;
private final int mRunningTaskId; private final int mRunningTaskId;
private final RunningTaskInfo mRunningTaskInfo; private final RunningTaskInfo mRunningTaskInfo;
@ -269,18 +253,13 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
private LayoutListener mLayoutListener; private LayoutListener mLayoutListener;
private RecentsView mRecentsView; private RecentsView mRecentsView;
private SyncRtSurfaceTransactionApplierCompat mSyncTransactionApplier; private SyncRtSurfaceTransactionApplierCompat mSyncTransactionApplier;
private QuickScrubController mQuickScrubController; private AnimationFactory mAnimationFactory = (t) -> { };
private AnimationFactory mAnimationFactory = (t, i) -> { };
private boolean mWasLauncherAlreadyVisible; private boolean mWasLauncherAlreadyVisible;
private boolean mPassedOverviewThreshold; private boolean mPassedOverviewThreshold;
private boolean mGestureStarted; private boolean mGestureStarted;
private int mLogAction = Touch.SWIPE; private int mLogAction = Touch.SWIPE;
private float mCurrentQuickScrubProgress;
private boolean mQuickScrubBlocked;
private @InteractionType int mInteractionType = INTERACTION_NORMAL;
private final RecentsAnimationWrapper mRecentsAnimationWrapper; private final RecentsAnimationWrapper mRecentsAnimationWrapper;
@ -295,7 +274,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
WindowTransformSwipeHandler(RunningTaskInfo runningTaskInfo, Context context, WindowTransformSwipeHandler(RunningTaskInfo runningTaskInfo, Context context,
long touchTimeMs, ActivityControlHelper<T> controller, boolean continuingLastGesture, long touchTimeMs, ActivityControlHelper<T> controller, boolean continuingLastGesture,
InputConsumerController inputConsumer, TouchInteractionLog touchInteractionLog) { InputConsumerController inputConsumer) {
mContext = context; mContext = context;
mRunningTaskInfo = runningTaskInfo; mRunningTaskInfo = runningTaskInfo;
mRunningTaskId = runningTaskInfo.id; mRunningTaskId = runningTaskInfo.id;
@ -304,7 +283,6 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
mActivityInitListener = mActivityControlHelper mActivityInitListener = mActivityControlHelper
.createActivityInitListener(this::onActivityInit); .createActivityInitListener(this::onActivityInit);
mContinuingLastGesture = continuingLastGesture; mContinuingLastGesture = continuingLastGesture;
mTouchInteractionLog = touchInteractionLog;
mRecentsAnimationWrapper = new RecentsAnimationWrapper(inputConsumer, mRecentsAnimationWrapper = new RecentsAnimationWrapper(inputConsumer,
this::createNewTouchProxyHandler); this::createNewTouchProxyHandler);
mClipAnimationHelper = new ClipAnimationHelper(context); mClipAnimationHelper = new ClipAnimationHelper(context);
@ -314,24 +292,20 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
} }
private void initStateCallbacks() { private void initStateCallbacks() {
mStateCallback = new MultiStateCallback(); mStateCallback = new MultiStateCallback(STATE_NAMES);
// Re-setup the recents UI when gesture starts, as the state could have been changed during // Re-setup the recents UI when gesture starts, as the state could have been changed during
// that time by a previous window transition. // that time by a previous window transition.
mStateCallback.addCallback(STATE_LAUNCHER_STARTED | STATE_GESTURE_STARTED_QUICKSTEP, mStateCallback.addCallback(STATE_LAUNCHER_STARTED | STATE_GESTURE_STARTED,
this::setupRecentsViewUi); this::setupRecentsViewUi);
mStateCallback.addCallback(STATE_LAUNCHER_DRAWN | STATE_GESTURE_STARTED_QUICKSCRUB, mStateCallback.addCallback(STATE_LAUNCHER_DRAWN | STATE_GESTURE_STARTED,
this::initializeLauncherAnimationController);
mStateCallback.addCallback(STATE_LAUNCHER_DRAWN | STATE_GESTURE_STARTED_QUICKSTEP,
this::initializeLauncherAnimationController); this::initializeLauncherAnimationController);
mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_LAUNCHER_DRAWN, mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_LAUNCHER_DRAWN,
this::launcherFrameDrawn); this::launcherFrameDrawn);
mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_GESTURE_STARTED_QUICKSTEP, mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_GESTURE_STARTED,
this::notifyGestureStartedAsync);
mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_GESTURE_STARTED_QUICKSCRUB,
this::notifyGestureStartedAsync); this::notifyGestureStartedAsync);
mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_LAUNCHER_STARTED mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_LAUNCHER_STARTED
@ -367,12 +341,12 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_APP_CONTROLLER_RECEIVED mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_APP_CONTROLLER_RECEIVED
| STATE_ACTIVITY_MULTIPLIER_COMPLETE | STATE_SCALED_CONTROLLER_RECENTS | STATE_ACTIVITY_MULTIPLIER_COMPLETE | STATE_SCALED_CONTROLLER_RECENTS
| STATE_CURRENT_TASK_FINISHED | STATE_GESTURE_COMPLETED | STATE_CURRENT_TASK_FINISHED | STATE_GESTURE_COMPLETED
| STATE_GESTURE_STARTED_QUICKSTEP, | STATE_GESTURE_STARTED,
this::setupLauncherUiAfterSwipeUpAnimation); this::setupLauncherUiAfterSwipeUpAnimation);
mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_APP_CONTROLLER_RECEIVED mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_APP_CONTROLLER_RECEIVED
| STATE_ACTIVITY_MULTIPLIER_COMPLETE | STATE_SCALED_CONTROLLER_RECENTS | STATE_ACTIVITY_MULTIPLIER_COMPLETE | STATE_SCALED_CONTROLLER_RECENTS
| STATE_CURRENT_TASK_FINISHED | STATE_GESTURE_COMPLETED | STATE_CURRENT_TASK_FINISHED | STATE_GESTURE_COMPLETED
| STATE_GESTURE_STARTED_QUICKSTEP | STATE_ASSIST_DATA_RECEIVED, | STATE_GESTURE_STARTED | STATE_ASSIST_DATA_RECEIVED,
this::preloadAssistData); this::preloadAssistData);
mStateCallback.addCallback(STATE_HANDLER_INVALIDATED, this::invalidateHandler); mStateCallback.addCallback(STATE_HANDLER_INVALIDATED, this::invalidateHandler);
@ -382,12 +356,6 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
| STATE_SCALED_CONTROLLER_LAST_TASK, | STATE_SCALED_CONTROLLER_LAST_TASK,
this::notifyTransitionCancelled); this::notifyTransitionCancelled);
mStateCallback.addCallback(QUICK_SCRUB_START_UI_STATE, this::onQuickScrubStartUi);
mStateCallback.addCallback(STATE_LAUNCHER_STARTED | STATE_QUICK_SCRUB_START
| STATE_SCALED_CONTROLLER_RECENTS, this::onFinishedTransitionToQuickScrub);
mStateCallback.addCallback(STATE_LAUNCHER_STARTED | STATE_CURRENT_TASK_FINISHED
| STATE_QUICK_SCRUB_END, this::switchToFinalAppAfterQuickScrub);
mStateCallback.addCallback(LONG_SWIPE_ENTER_STATE, this::checkLongSwipeCanEnter); mStateCallback.addCallback(LONG_SWIPE_ENTER_STATE, this::checkLongSwipeCanEnter);
mStateCallback.addCallback(LONG_SWIPE_START_STATE, this::checkLongSwipeCanStart); mStateCallback.addCallback(LONG_SWIPE_START_STATE, this::checkLongSwipeCanStart);
@ -409,9 +377,9 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
private void initTransitionEndpoints(DeviceProfile dp) { private void initTransitionEndpoints(DeviceProfile dp) {
mDp = dp; mDp = dp;
TransformedRect tempRect = new TransformedRect(); Rect tempRect = new Rect();
mTransitionDragLength = mActivityControlHelper.getSwipeUpDestinationAndLength( mTransitionDragLength = mActivityControlHelper.getSwipeUpDestinationAndLength(
dp, mContext, mInteractionType, tempRect); dp, mContext, tempRect);
mClipAnimationHelper.updateTargetRect(tempRect); mClipAnimationHelper.updateTargetRect(tempRect);
} }
@ -464,7 +432,6 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
}); });
mRecentsView.setRecentsAnimationWrapper(mRecentsAnimationWrapper); mRecentsView.setRecentsAnimationWrapper(mRecentsAnimationWrapper);
mRecentsView.setClipAnimationHelper(mClipAnimationHelper); mRecentsView.setClipAnimationHelper(mClipAnimationHelper);
mQuickScrubController = mRecentsView.getQuickScrubController();
mLayoutListener = mActivityControlHelper.createLayoutListener(mActivity); mLayoutListener = mActivityControlHelper.createLayoutListener(mActivity);
mStateCallback.setState(STATE_LAUNCHER_PRESENT); mStateCallback.setState(STATE_LAUNCHER_PRESENT);
@ -560,38 +527,12 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
LatencyTrackerCompat.logToggleRecents((int) (mLauncherFrameDrawnTime - mTouchTimeMs)); LatencyTrackerCompat.logToggleRecents((int) (mLauncherFrameDrawnTime - mTouchTimeMs));
} }
// This method is only called when STATE_GESTURE_STARTED_QUICKSTEP/ // This method is only called when STATE_GESTURE_STARTED is set, so we can enable the
// STATE_GESTURE_STARTED_QUICKSCRUB is set, so we can enable the high-res thumbnail loader // high-res thumbnail loader here once we are sure that we will end up in an overview state
// here once we are sure that we will end up in an overview state
RecentsModel.INSTANCE.get(mContext).getThumbnailCache() RecentsModel.INSTANCE.get(mContext).getThumbnailCache()
.getHighResLoadingState().setVisible(true); .getHighResLoadingState().setVisible(true);
} }
private void shiftAnimationDestinationForQuickscrub() {
TransformedRect tempRect = new TransformedRect();
mActivityControlHelper
.getSwipeUpDestinationAndLength(mDp, mContext, mInteractionType, tempRect);
mClipAnimationHelper.updateTargetRect(tempRect);
float offsetY =
mActivityControlHelper.getTranslationYForQuickScrub(tempRect, mDp, mContext);
float scale, offsetX;
Resources res = mContext.getResources();
if (ActivityManagerWrapper.getInstance().getRecentTasks(2, UserHandle.myUserId()).size()
< 2) {
// There are not enough tasks, we don't need to shift
offsetX = 0;
scale = 1;
} else {
offsetX = res.getDimensionPixelSize(R.dimen.recents_page_spacing)
+ tempRect.rect.width();
scale = getTaskCurveScaleForOffsetX(offsetX, tempRect.rect.width());
}
mClipAnimationHelper.offsetTarget(scale, Utilities.isRtl(res) ? -offsetX : offsetX, offsetY,
QuickScrubController.QUICK_SCRUB_START_INTERPOLATOR);
}
private float getTaskCurveScaleForOffsetX(float offsetX, float taskWidth) { private float getTaskCurveScaleForOffsetX(float offsetX, float taskWidth) {
float distanceToReachEdge = mDp.widthPx / 2 + taskWidth / 2 + float distanceToReachEdge = mDp.widthPx / 2 + taskWidth / 2 +
mContext.getResources().getDimensionPixelSize(R.dimen.recents_page_spacing); mContext.getResources().getDimensionPixelSize(R.dimen.recents_page_spacing);
@ -647,13 +588,11 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
@UiThread @UiThread
public void setShelfState(ShelfAnimState shelfState, Interpolator interpolator, long duration) { public void setShelfState(ShelfAnimState shelfState, Interpolator interpolator, long duration) {
if (mInteractionType == INTERACTION_NORMAL) { mAnimationFactory.setShelfState(shelfState, interpolator, duration);
mAnimationFactory.setShelfState(shelfState, interpolator, duration); mIsShelfPeeking = shelfState == PEEK;
mIsShelfPeeking = shelfState == PEEK; if (mRecentsView != null && shelfState.shouldPreformHaptic) {
if (mRecentsView != null && shelfState.shouldPreformHaptic) { mRecentsView.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY,
mRecentsView.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY, HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
}
} }
} }
@ -662,7 +601,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
*/ */
public void buildAnimationController() { public void buildAnimationController() {
initTransitionEndpoints(mActivity.getDeviceProfile()); initTransitionEndpoints(mActivity.getDeviceProfile());
mAnimationFactory.createActivityController(mTransitionDragLength, mInteractionType); mAnimationFactory.createActivityController(mTransitionDragLength);
} }
private void onAnimatorPlaybackControllerCreated(AnimatorPlaybackController anim) { private void onAnimatorPlaybackControllerCreated(AnimatorPlaybackController anim) {
@ -678,7 +617,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
RecentsAnimationControllerCompat controller = mRecentsAnimationWrapper.getController(); RecentsAnimationControllerCompat controller = mRecentsAnimationWrapper.getController();
if (controller != null) { if (controller != null) {
float offsetX = 0; float offsetX = 0;
if (mRecentsView != null && mInteractionType == INTERACTION_NORMAL) { if (mRecentsView != null) {
int startScroll = mRecentsView.getScrollForPage(mRecentsView.indexOfChild( int startScroll = mRecentsView.getScrollForPage(mRecentsView.indexOfChild(
mRecentsView.getRunningTaskView())); mRecentsView.getRunningTaskView()));
offsetX = startScroll - mRecentsView.getScrollX(); offsetX = startScroll - mRecentsView.getScrollX();
@ -699,9 +638,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
} }
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) { if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
if (mRecentsAnimationWrapper.getController() != null && mLayoutListener != null && if (mRecentsAnimationWrapper.getController() != null && mLayoutListener != null) {
(mInteractionType == INTERACTION_NORMAL
|| !mQuickScrubController.hasFinishedTransitionToQuickScrub())) {
mLayoutListener.open(); mLayoutListener.open();
mLayoutListener.update(mCurrentShift.value > 1, mLongSwipeMode, mLayoutListener.update(mCurrentShift.value > 1, mLongSwipeMode,
mClipAnimationHelper.getCurrentRectWithInsets(), mClipAnimationHelper.getCurrentRectWithInsets(),
@ -712,15 +649,14 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
final boolean passed = mCurrentShift.value >= MIN_PROGRESS_FOR_OVERVIEW; final boolean passed = mCurrentShift.value >= MIN_PROGRESS_FOR_OVERVIEW;
if (passed != mPassedOverviewThreshold) { if (passed != mPassedOverviewThreshold) {
mPassedOverviewThreshold = passed; mPassedOverviewThreshold = passed;
if (mInteractionType == INTERACTION_NORMAL && mRecentsView != null if (mRecentsView != null && !SWIPE_HOME.get()) {
&& !SWIPE_HOME.get()) {
mRecentsView.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY, mRecentsView.performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY,
HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING); HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING);
} }
} }
// Update insets of the non-running tasks, as we might switch to them. // Update insets of the non-running tasks, as we might switch to them.
int runningTaskIndex = mRecentsView == null ? -1 : mRecentsView.getRunningTaskIndex(); int runningTaskIndex = mRecentsView == null ? -1 : mRecentsView.getRunningTaskIndex();
if (mInteractionType == INTERACTION_NORMAL && runningTaskIndex >= 0) { if (runningTaskIndex >= 0) {
for (int i = 0; i < mRecentsView.getTaskViewCount(); i++) { for (int i = 0; i < mRecentsView.getTaskViewCount(); i++) {
if (i != runningTaskIndex) { if (i != runningTaskIndex) {
mRecentsView.getTaskViewAt(i).setFullscreenProgress(1 - mCurrentShift.value); mRecentsView.getTaskViewAt(i).setFullscreenProgress(1 - mCurrentShift.value);
@ -780,7 +716,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
initTransitionEndpoints(dp); initTransitionEndpoints(dp);
mRecentsAnimationWrapper.setController(targetSet.controller, targetSet); mRecentsAnimationWrapper.setController(targetSet.controller, targetSet);
mTouchInteractionLog.startRecentsAnimationCallback(targetSet.apps.length); TOUCH_INTERACTION_LOG.startRecentsAnimationCallback(targetSet.apps.length);
setStateOnUiThread(STATE_APP_CONTROLLER_RECEIVED); setStateOnUiThread(STATE_APP_CONTROLLER_RECEIVED);
mPassedOverviewThreshold = false; mPassedOverviewThreshold = false;
@ -791,15 +727,14 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
mRecentsAnimationWrapper.setController(null, null); mRecentsAnimationWrapper.setController(null, null);
mActivityInitListener.unregister(); mActivityInitListener.unregister();
setStateOnUiThread(STATE_GESTURE_CANCELLED | STATE_HANDLER_INVALIDATED); setStateOnUiThread(STATE_GESTURE_CANCELLED | STATE_HANDLER_INVALIDATED);
mTouchInteractionLog.cancelRecentsAnimation(); TOUCH_INTERACTION_LOG.cancelRecentsAnimation();
} }
@UiThread @UiThread
public void onGestureStarted() { public void onGestureStarted() {
notifyGestureStartedAsync(); notifyGestureStartedAsync();
mShiftAtGestureStart = mCurrentShift.value; mShiftAtGestureStart = mCurrentShift.value;
setStateOnUiThread(mInteractionType == INTERACTION_NORMAL setStateOnUiThread(STATE_GESTURE_STARTED);
? STATE_GESTURE_STARTED_QUICKSTEP : STATE_GESTURE_STARTED_QUICKSCRUB);
mGestureStarted = true; mGestureStarted = true;
mRecentsAnimationWrapper.hideCurrentInputMethod(); mRecentsAnimationWrapper.hideCurrentInputMethod();
mRecentsAnimationWrapper.enableInputConsumer(); mRecentsAnimationWrapper.enableInputConsumer();
@ -845,8 +780,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
setTargetAlphaProvider(WindowTransformSwipeHandler::getHiddenTargetAlpha); setTargetAlphaProvider(WindowTransformSwipeHandler::getHiddenTargetAlpha);
} }
return OverviewTouchConsumer.newInstance(mActivityControlHelper, true, return OverviewTouchConsumer.newInstance(mActivityControlHelper, true);
mTouchInteractionLog);
} }
@UiThread @UiThread
@ -1114,7 +1048,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
@UiThread @UiThread
private void resumeLastTask() { private void resumeLastTask() {
mRecentsAnimationWrapper.finish(false /* toRecents */, null); mRecentsAnimationWrapper.finish(false /* toRecents */, null);
mTouchInteractionLog.finishRecentsAnimation(false); TOUCH_INTERACTION_LOG.finishRecentsAnimation(false);
} }
@UiThread @UiThread
@ -1132,16 +1066,12 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
mMainThreadHandler); mMainThreadHandler);
}); });
} }
mTouchInteractionLog.finishRecentsAnimation(false); TOUCH_INTERACTION_LOG.finishRecentsAnimation(false);
doLogGesture(NEW_TASK); doLogGesture(NEW_TASK);
} }
public void reset() { public void reset() {
if (mInteractionType != INTERACTION_QUICK_SCRUB) { setStateOnUiThread(STATE_HANDLER_INVALIDATED);
// Only invalidate the handler if we are not quick scrubbing, otherwise, it will be
// invalidated after the quick scrub ends
setStateOnUiThread(STATE_HANDLER_INVALIDATED);
}
} }
public void cancel() { public void cancel() {
@ -1171,7 +1101,6 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
mRecentsView.setEnableFreeScroll(true); mRecentsView.setEnableFreeScroll(true);
mRecentsView.setRunningTaskIconScaledDown(false); mRecentsView.setRunningTaskIconScaledDown(false);
mRecentsView.setOnScrollChangeListener(null); mRecentsView.setOnScrollChangeListener(null);
mQuickScrubController.cancelActiveQuickscrub();
} }
private void notifyTransitionCancelled() { private void notifyTransitionCancelled() {
@ -1250,7 +1179,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
() -> setStateOnUiThread(STATE_CURRENT_TASK_FINISHED)); () -> setStateOnUiThread(STATE_CURRENT_TASK_FINISHED));
} }
} }
mTouchInteractionLog.finishRecentsAnimation(true); TOUCH_INTERACTION_LOG.finishRecentsAnimation(true);
} }
private void finishCurrentTransitionToHome() { private void finishCurrentTransitionToHome() {
@ -1258,7 +1187,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
mRecentsAnimationWrapper.finish(true /* toRecents */, mRecentsAnimationWrapper.finish(true /* toRecents */,
() -> setStateOnUiThread(STATE_CURRENT_TASK_FINISHED)); () -> setStateOnUiThread(STATE_CURRENT_TASK_FINISHED));
} }
mTouchInteractionLog.finishRecentsAnimation(true); TOUCH_INTERACTION_LOG.finishRecentsAnimation(true);
doLogGesture(HOME); doLogGesture(HOME);
} }
@ -1279,91 +1208,6 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
reset(); reset();
} }
public void onQuickScrubStart() {
if (mInteractionType != INTERACTION_NORMAL) {
throw new IllegalArgumentException(
"Can't change interaction type from " + mInteractionType);
}
mInteractionType = INTERACTION_QUICK_SCRUB;
mRecentsAnimationWrapper.runOnInit(this::shiftAnimationDestinationForQuickscrub);
setStateOnUiThread(STATE_QUICK_SCRUB_START | STATE_GESTURE_COMPLETED);
// Start the window animation without waiting for launcher.
long duration = FeatureFlags.QUICK_SWITCH.get()
? QUICK_SWITCH_FROM_APP_START_DURATION
: QUICK_SCRUB_FROM_APP_START_DURATION;
animateToProgress(mCurrentShift.value, 1f, duration, LINEAR, RECENTS, 1f);
}
private void onQuickScrubStartUi() {
if (!mQuickScrubController.prepareQuickScrub(TAG, FeatureFlags.QUICK_SWITCH.get())) {
mQuickScrubBlocked = true;
setStateOnUiThread(STATE_RESUME_LAST_TASK | STATE_HANDLER_INVALIDATED);
return;
}
if (mLauncherTransitionController != null) {
mLauncherTransitionController.getAnimationPlayer().end();
mLauncherTransitionController = null;
}
mActivityControlHelper.onQuickInteractionStart(mActivity, mRunningTaskInfo, false,
mTouchInteractionLog);
// Inform the last progress in case we skipped before.
mQuickScrubController.onQuickScrubProgress(mCurrentQuickScrubProgress);
}
private void onFinishedTransitionToQuickScrub() {
if (mQuickScrubBlocked) {
return;
}
mLayoutListener.finish();
mQuickScrubController.onFinishedTransitionToQuickScrub();
mRecentsView.animateUpRunningTaskIconScale();
if (mQuickScrubController.isQuickSwitch()) {
// Adjust the running task so that it is centered and fills the screen.
TaskView runningTask = mRecentsView.getRunningTaskView();
if (runningTask != null) {
float insetHeight = mDp.heightPx - mDp.getInsets().top - mDp.getInsets().bottom;
// Usually insetDiff will be 0, unless we allow apps to draw under the insets. In
// that case (insetDiff != 0), we need to center in the system-specified available
// height rather than launcher's inset height by adding half the insetDiff.
float insetDiff = mDp.availableHeightPx - insetHeight;
float topMargin = mActivity.getResources().getDimension(
R.dimen.task_thumbnail_half_top_margin);
runningTask.setTranslationY((insetDiff / 2 - topMargin) / mRecentsView.getScaleX());
}
}
RecentsModel.INSTANCE.get(mContext).onOverviewShown(false, TAG);
}
public void onQuickScrubProgress(float progress) {
mCurrentQuickScrubProgress = progress;
if (mQuickScrubController == null || mQuickScrubBlocked ||
!mStateCallback.hasStates(QUICK_SCRUB_START_UI_STATE)) {
return;
}
mQuickScrubController.onQuickScrubProgress(progress);
}
public void onQuickScrubEnd() {
setStateOnUiThread(STATE_QUICK_SCRUB_END);
}
private void switchToFinalAppAfterQuickScrub() {
if (mQuickScrubBlocked) {
return;
}
mQuickScrubController.onQuickScrubEnd();
// Normally this is handled in reset(), but since we are still scrubbing after the
// transition into recents, we need to defer the handler invalidation for quick scrub until
// after the gesture ends
setStateOnUiThread(STATE_HANDLER_INVALIDATED);
}
public void setGestureEndCallback(Runnable gestureEndCallback) { public void setGestureEndCallback(Runnable gestureEndCallback) {
mGestureEndCallback = gestureEndCallback; mGestureEndCallback = gestureEndCallback;
} }

View File

@ -35,7 +35,6 @@ public class FallbackRecentsView extends RecentsView<RecentsActivity> {
public FallbackRecentsView(Context context, AttributeSet attrs, int defStyleAttr) { public FallbackRecentsView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr); super(context, attrs, defStyleAttr);
setOverviewStateEnabled(true); setOverviewStateEnabled(true);
getQuickScrubController().onFinishedTransitionToQuickScrub();
} }
@Override @Override

View File

@ -15,9 +15,7 @@
*/ */
package com.android.quickstep.util; package com.android.quickstep.util;
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE; import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.quickstep.QuickScrubController.QUICK_SCRUB_TRANSLATION_Y_FACTOR;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING; import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING; import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_OPENING;
@ -26,19 +24,15 @@ import android.content.Context;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Matrix; import android.graphics.Matrix;
import android.graphics.Matrix.ScaleToFit; import android.graphics.Matrix.ScaleToFit;
import android.graphics.PointF;
import android.graphics.Rect; import android.graphics.Rect;
import android.graphics.RectF; import android.graphics.RectF;
import android.os.Build; import android.os.Build;
import android.os.RemoteException; import android.os.RemoteException;
import android.view.animation.Interpolator;
import androidx.annotation.Nullable;
import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.DeviceProfile; import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R; import com.android.launcher3.R;
import com.android.launcher3.Utilities; import com.android.launcher3.Utilities;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.views.BaseDragLayer; import com.android.launcher3.views.BaseDragLayer;
import com.android.quickstep.RecentsModel; import com.android.quickstep.RecentsModel;
import com.android.quickstep.views.RecentsView; import com.android.quickstep.views.RecentsView;
@ -53,6 +47,8 @@ import com.android.systemui.shared.system.WindowManagerWrapper;
import java.util.function.BiFunction; import java.util.function.BiFunction;
import androidx.annotation.Nullable;
/** /**
* Utility class to handle window clip animation * Utility class to handle window clip animation
*/ */
@ -67,8 +63,6 @@ public class ClipAnimationHelper {
private final RectF mSourceRect = new RectF(); private final RectF mSourceRect = new RectF();
// The bounds of the task view in launcher window coordinates // The bounds of the task view in launcher window coordinates
private final RectF mTargetRect = new RectF(); private final RectF mTargetRect = new RectF();
// Set when the final window destination is changed, such as offsetting for quick scrub
private final PointF mTargetOffset = new PointF();
// The insets to be used for clipping the app window, which can be larger than mSourceInsets // The insets to be used for clipping the app window, which can be larger than mSourceInsets
// if the aspect ratio of the target is smaller than the aspect ratio of the source rect. In // if the aspect ratio of the target is smaller than the aspect ratio of the source rect. In
// app window coordinates. // app window coordinates.
@ -95,11 +89,6 @@ public class ClipAnimationHelper {
// Corner radius currently applied to transformed window. // Corner radius currently applied to transformed window.
private float mCurrentCornerRadius; private float mCurrentCornerRadius;
private float mTargetScale = 1f;
private float mOffsetScale = 1f;
private Interpolator mInterpolator = LINEAR;
// We translate y slightly faster than the rest of the animation for quick scrub.
private Interpolator mOffsetYInterpolator = LINEAR;
// Whether to boost the opening animation target layers, or the closing // Whether to boost the opening animation target layers, or the closing
private int mBoostModeTargetLayers = -1; private int mBoostModeTargetLayers = -1;
@ -130,13 +119,11 @@ public class ClipAnimationHelper {
updateSourceStack(target); updateSourceStack(target);
} }
public void updateTargetRect(TransformedRect targetRect) { public void updateTargetRect(Rect targetRect) {
mOffsetScale = targetRect.scale;
mSourceRect.set(mSourceInsets.left, mSourceInsets.top, mSourceRect.set(mSourceInsets.left, mSourceInsets.top,
mSourceStackBounds.width() - mSourceInsets.right, mSourceStackBounds.width() - mSourceInsets.right,
mSourceStackBounds.height() - mSourceInsets.bottom); mSourceStackBounds.height() - mSourceInsets.bottom);
mTargetRect.set(targetRect.rect); mTargetRect.set(targetRect);
Utilities.scaleRectFAboutCenter(mTargetRect, targetRect.scale);
mTargetRect.offset(mHomeStackBounds.left - mSourceStackBounds.left, mTargetRect.offset(mHomeStackBounds.left - mSourceStackBounds.left,
mHomeStackBounds.top - mSourceStackBounds.top); mHomeStackBounds.top - mSourceStackBounds.top);
@ -165,18 +152,11 @@ public class ClipAnimationHelper {
if (params.currentRect == null) { if (params.currentRect == null) {
RectF currentRect; RectF currentRect;
mTmpRectF.set(mTargetRect); mTmpRectF.set(mTargetRect);
Utilities.scaleRectFAboutCenter(mTmpRectF, mTargetScale * params.offsetScale); Utilities.scaleRectFAboutCenter(mTmpRectF, params.offsetScale);
float offsetYProgress = mOffsetYInterpolator.getInterpolation(params.progress); float progress = params.progress;
float progress = mInterpolator.getInterpolation(params.progress);
currentRect = mRectFEvaluator.evaluate(progress, mSourceRect, mTmpRectF); currentRect = mRectFEvaluator.evaluate(progress, mSourceRect, mTmpRectF);
currentRect.offset(params.offsetX, 0); currentRect.offset(params.offsetX, 0);
synchronized (mTargetOffset) {
// Stay lined up with the center of the target, since it moves for quick scrub.
currentRect.offset(mTargetOffset.x * mOffsetScale * progress,
mTargetOffset.y * offsetYProgress);
}
final RectF sourceWindowClipInsets = params.forLiveTile final RectF sourceWindowClipInsets = params.forLiveTile
? mSourceWindowClipInsetsForLiveTile : mSourceWindowClipInsets; ? mSourceWindowClipInsetsForLiveTile : mSourceWindowClipInsets;
mClipRectF.left = sourceWindowClipInsets.left * progress; mClipRectF.left = sourceWindowClipInsets.left * progress;
@ -246,16 +226,6 @@ public class ClipAnimationHelper {
mTaskAlphaCallback = callback; mTaskAlphaCallback = callback;
} }
public void offsetTarget(float scale, float offsetX, float offsetY, Interpolator interpolator) {
synchronized (mTargetOffset) {
mTargetOffset.set(offsetX, offsetY);
}
mTargetScale = scale;
mInterpolator = interpolator;
mOffsetYInterpolator = Interpolators.clampToProgress(mInterpolator, 0,
QUICK_SCRUB_TRANSLATION_Y_FACTOR);
}
public void fromTaskThumbnailView(TaskThumbnailView ttv, RecentsView rv) { public void fromTaskThumbnailView(TaskThumbnailView ttv, RecentsView rv) {
fromTaskThumbnailView(ttv, rv, null); fromTaskThumbnailView(ttv, rv, null);
} }
@ -280,8 +250,8 @@ public class ClipAnimationHelper {
mSourceInsets.set(ttv.getInsets(fallback)); mSourceInsets.set(ttv.getInsets(fallback));
} }
TransformedRect targetRect = new TransformedRect(); Rect targetRect = new Rect();
dl.getDescendantRectRelativeToSelf(ttv, targetRect.rect); dl.getDescendantRectRelativeToSelf(ttv, targetRect);
updateTargetRect(targetRect); updateTargetRect(targetRect);
if (target == null) { if (target == null) {

View File

@ -1,32 +0,0 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.quickstep.util;
import android.graphics.Rect;
/**
* A wrapper around {@link Rect} with additional transformation properties
*/
public class TransformedRect {
public final Rect rect = new Rect();
public float scale = 1;
public void set(TransformedRect transformedRect) {
rect.set(transformedRect.rect);
scale = transformedRect.scale;
}
}

View File

@ -88,7 +88,6 @@ import com.android.launcher3.util.PendingAnimation;
import com.android.launcher3.util.Themes; import com.android.launcher3.util.Themes;
import com.android.launcher3.util.ViewPool; import com.android.launcher3.util.ViewPool;
import com.android.quickstep.OverviewCallbacks; import com.android.quickstep.OverviewCallbacks;
import com.android.quickstep.QuickScrubController;
import com.android.quickstep.RecentsAnimationWrapper; import com.android.quickstep.RecentsAnimationWrapper;
import com.android.quickstep.RecentsModel; import com.android.quickstep.RecentsModel;
import com.android.quickstep.TaskThumbnailCache; import com.android.quickstep.TaskThumbnailCache;
@ -152,7 +151,6 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
private static final float[] sTempFloatArray = new float[3]; private static final float[] sTempFloatArray = new float[3];
protected final T mActivity; protected final T mActivity;
private final QuickScrubController mQuickScrubController;
private final float mFastFlingVelocity; private final float mFastFlingVelocity;
private final RecentsModel mModel; private final RecentsModel mModel;
private final int mTaskTopMargin; private final int mTaskTopMargin;
@ -215,9 +213,6 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
return; return;
} }
// Notify the quick scrub controller that a particular task has been removed
mQuickScrubController.onTaskRemoved(taskId);
BackgroundExecutor.get().submit(() -> { BackgroundExecutor.get().submit(() -> {
TaskView taskView = getTaskView(taskId); TaskView taskView = getTaskView(taskId);
if (taskView == null) { if (taskView == null) {
@ -310,7 +305,6 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
mFastFlingVelocity = getResources() mFastFlingVelocity = getResources()
.getDimensionPixelSize(R.dimen.recents_fast_fling_velocity); .getDimensionPixelSize(R.dimen.recents_fast_fling_velocity);
mActivity = (T) BaseActivity.fromContext(context); mActivity = (T) BaseActivity.fromContext(context);
mQuickScrubController = new QuickScrubController(mActivity, this);
mModel = RecentsModel.INSTANCE.get(context); mModel = RecentsModel.INSTANCE.get(context);
mIdp = InvariantDeviceProfile.INSTANCE.get(context); mIdp = InvariantDeviceProfile.INSTANCE.get(context);
@ -550,10 +544,6 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
mIgnoreResetTaskId = -1; mIgnoreResetTaskId = -1;
} }
resetTaskVisuals(); resetTaskVisuals();
if (oldChildCount != getChildCount()) {
mQuickScrubController.snapToNextTaskIfAvailable();
}
onTaskStackUpdated(); onTaskStackUpdated();
} }
@ -605,7 +595,6 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
mTaskWidth = mTempRect.width(); mTaskWidth = mTempRect.width();
mTaskHeight = mTempRect.height(); mTaskHeight = mTempRect.height();
// Keep this logic in sync with ActivityControlHelper.getTranslationYForQuickScrub.
mTempRect.top -= mTaskTopMargin; mTempRect.top -= mTaskTopMargin;
setPadding(mTempRect.left - mInsets.left, mTempRect.top - mInsets.top, setPadding(mTempRect.left - mInsets.left, mTempRect.top - mInsets.top,
dp.widthPx - mInsets.right - mTempRect.right, dp.widthPx - mInsets.right - mTempRect.right,
@ -854,10 +843,6 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
} }
} }
public QuickScrubController getQuickScrubController() {
return mQuickScrubController;
}
public void setRunningTaskIconScaledDown(boolean isScaledDown) { public void setRunningTaskIconScaledDown(boolean isScaledDown) {
if (mRunningTaskIconScaledDown != isScaledDown) { if (mRunningTaskIconScaledDown != isScaledDown) {
mRunningTaskIconScaledDown = isScaledDown; mRunningTaskIconScaledDown = isScaledDown;

View File

@ -412,10 +412,7 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
public void resetVisualProperties() { public void resetVisualProperties() {
resetViewTransforms(); resetViewTransforms();
if (!getRecentsView().getQuickScrubController().isQuickSwitch()) { setFullscreenProgress(0);
// Reset full screen progress unless we are doing back to back quick switch.
setFullscreenProgress(0);
}
} }
@Override @Override

View File

@ -27,7 +27,6 @@ import android.view.animation.Interpolator;
import com.android.launcher3.states.SpringLoadedState; import com.android.launcher3.states.SpringLoadedState;
import com.android.launcher3.uioverrides.AllAppsState; import com.android.launcher3.uioverrides.AllAppsState;
import com.android.launcher3.uioverrides.BackgroundAppState; import com.android.launcher3.uioverrides.BackgroundAppState;
import com.android.launcher3.uioverrides.FastOverviewState;
import com.android.launcher3.uioverrides.OverviewState; import com.android.launcher3.uioverrides.OverviewState;
import com.android.launcher3.uioverrides.UiFactory; import com.android.launcher3.uioverrides.UiFactory;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action; import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
@ -87,9 +86,8 @@ public class LauncherState {
*/ */
public static final LauncherState SPRING_LOADED = new SpringLoadedState(1); public static final LauncherState SPRING_LOADED = new SpringLoadedState(1);
public static final LauncherState OVERVIEW = new OverviewState(2); public static final LauncherState OVERVIEW = new OverviewState(2);
public static final LauncherState FAST_OVERVIEW = new FastOverviewState(3); public static final LauncherState ALL_APPS = new AllAppsState(3);
public static final LauncherState ALL_APPS = new AllAppsState(4); public static final LauncherState BACKGROUND_APP = new BackgroundAppState(4);
public static final LauncherState BACKGROUND_APP = new BackgroundAppState(5);
public final int ordinal; public final int ordinal;
@ -187,6 +185,7 @@ public class LauncherState {
* translationY factor where 0 is top aligned and 0.5 is centered vertically * translationY factor where 0 is top aligned and 0.5 is centered vertically
*/ */
public float[] getOverviewScaleAndTranslationYFactor(Launcher launcher) { public float[] getOverviewScaleAndTranslationYFactor(Launcher launcher) {
// TODO: Simplify to use a constant value instead of a factor.
return new float[] {1.1f, 0f}; return new float[] {1.1f, 0f};
} }

View File

@ -1,26 +0,0 @@
/*
* Copyright (C) 2018 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;
/**
* A dummy overview state
*/
public class FastOverviewState extends OverviewState {
public FastOverviewState(int id) {
super(id);
}
}