mirror of
https://github.com/LawnchairLauncher/lawnchair.git
synced 2026-02-20 11:18:21 +00:00
Merge "Cancel gestures on launcher destroy" into tm-qpr-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
c4d6dee069
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
* Copyright (C) 2022 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.
|
||||
@@ -16,19 +16,23 @@
|
||||
package com.android.launcher3;
|
||||
|
||||
import android.animation.AnimatorSet;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.TargetApi;
|
||||
import android.os.Build;
|
||||
import android.os.CancellationSignal;
|
||||
import android.view.RemoteAnimationTarget;
|
||||
|
||||
import com.android.launcher3.uioverrides.QuickstepLauncher;
|
||||
import com.android.quickstep.util.ActivityInitListener;
|
||||
import com.android.quickstep.util.ActivityLifecycleListener;
|
||||
import com.android.quickstep.util.RemoteAnimationProvider;
|
||||
|
||||
import java.util.function.BiPredicate;
|
||||
|
||||
/**
|
||||
* {@link ActivityLifecycleListener} for the in-launcher recents.
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.P)
|
||||
public class LauncherInitListener extends ActivityInitListener<Launcher> {
|
||||
public class LauncherLifecycleListener extends ActivityLifecycleListener<Launcher> {
|
||||
|
||||
private RemoteAnimationProvider mRemoteAnimationProvider;
|
||||
|
||||
@@ -36,13 +40,16 @@ public class LauncherInitListener extends ActivityInitListener<Launcher> {
|
||||
* @param onInitListener a callback made when the activity is initialized. The callback should
|
||||
* return true to continue receiving callbacks (ie. for if the activity is
|
||||
* recreated).
|
||||
* @param onDestroyListener a callback made when the activity is destroyed.
|
||||
*/
|
||||
public LauncherInitListener(BiPredicate<Launcher, Boolean> onInitListener) {
|
||||
super(onInitListener, Launcher.ACTIVITY_TRACKER);
|
||||
public LauncherLifecycleListener(
|
||||
@Nullable BiPredicate<Launcher, Boolean> onInitListener,
|
||||
@Nullable Runnable onDestroyListener) {
|
||||
super(onInitListener, onDestroyListener, Launcher.ACTIVITY_TRACKER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleInit(Launcher launcher, boolean alreadyOnHome) {
|
||||
public boolean handleActivityReady(Launcher launcher, boolean alreadyOnHome) {
|
||||
if (mRemoteAnimationProvider != null) {
|
||||
QuickstepTransitionManager appTransitionManager =
|
||||
((QuickstepLauncher) launcher).getAppTransitionManager();
|
||||
@@ -68,7 +75,7 @@ public class LauncherInitListener extends ActivityInitListener<Launcher> {
|
||||
}, cancellationSignal);
|
||||
}
|
||||
launcher.deferOverlayCallbacksUntilNextResumeOrStop();
|
||||
return super.handleInit(launcher, alreadyOnHome);
|
||||
return super.handleActivityReady(launcher, alreadyOnHome);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -50,6 +50,7 @@ import static com.android.quickstep.GestureState.STATE_RECENTS_SCROLLING_FINISHE
|
||||
import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
|
||||
import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.CANCEL_RECENTS_ANIMATION;
|
||||
import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.EXPECTING_TASK_APPEARED;
|
||||
import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.LAUNCHER_DESTROYED;
|
||||
import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.ON_SETTLED_ON_END_TARGET;
|
||||
import static com.android.quickstep.util.VibratorWrapper.OVERVIEW_HAPTIC;
|
||||
import static com.android.quickstep.views.RecentsView.UPDATE_SYSUI_FLAGS_THRESHOLD;
|
||||
@@ -113,7 +114,7 @@ import com.android.quickstep.GestureState.GestureEndTarget;
|
||||
import com.android.quickstep.RemoteTargetGluer.RemoteTargetHandle;
|
||||
import com.android.quickstep.util.ActiveGestureErrorDetector;
|
||||
import com.android.quickstep.util.ActiveGestureLog;
|
||||
import com.android.quickstep.util.ActivityInitListener;
|
||||
import com.android.quickstep.util.ActivityLifecycleListener;
|
||||
import com.android.quickstep.util.AnimatorControllerWithResistance;
|
||||
import com.android.quickstep.util.InputConsumerProxy;
|
||||
import com.android.quickstep.util.InputProxyHandlerFactory;
|
||||
@@ -159,7 +160,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
|
||||
|
||||
protected final BaseActivityInterface<S, T> mActivityInterface;
|
||||
protected final InputConsumerProxy mInputConsumerProxy;
|
||||
protected final ActivityInitListener mActivityInitListener;
|
||||
protected final ActivityLifecycleListener mActivityInitListener;
|
||||
// Callbacks to be made once the recents animation starts
|
||||
private final ArrayList<Runnable> mRecentsAnimationStartCallbacks = new ArrayList<>();
|
||||
private final OnScrollChangedListener mOnRecentsScrollListener = this::onRecentsViewScroll;
|
||||
@@ -329,7 +330,8 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
|
||||
InputConsumerController inputConsumer) {
|
||||
super(context, deviceState, gestureState);
|
||||
mActivityInterface = gestureState.getActivityInterface();
|
||||
mActivityInitListener = mActivityInterface.createActivityInitListener(this::onActivityInit);
|
||||
mActivityInitListener = mActivityInterface.createActivityLifecycleListener(
|
||||
this::onActivityInit, this::onActivityDestroy);
|
||||
mInputConsumerProxy =
|
||||
new InputConsumerProxy(context, /* rotationSupplier = */ () -> {
|
||||
if (mRecentsView == null) {
|
||||
@@ -520,6 +522,11 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
|
||||
return true;
|
||||
}
|
||||
|
||||
private void onActivityDestroy() {
|
||||
ActiveGestureLog.INSTANCE.addLog("Launcher activity destroyed", LAUNCHER_DESTROYED);
|
||||
onGestureCancelled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the window should be translated horizontally if the recents view scrolls
|
||||
*/
|
||||
|
||||
@@ -60,7 +60,7 @@ import com.android.launcher3.touch.PagedOrientationHandler;
|
||||
import com.android.launcher3.util.DisplayController;
|
||||
import com.android.launcher3.util.NavigationMode;
|
||||
import com.android.launcher3.views.ScrimView;
|
||||
import com.android.quickstep.util.ActivityInitListener;
|
||||
import com.android.quickstep.util.ActivityLifecycleListener;
|
||||
import com.android.quickstep.util.AnimatorControllerWithResistance;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
import com.android.systemui.shared.recents.model.ThumbnailData;
|
||||
@@ -123,8 +123,17 @@ public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_T
|
||||
public abstract AnimationFactory prepareRecentsUI(RecentsAnimationDeviceState deviceState,
|
||||
boolean activityVisible, Consumer<AnimatorControllerWithResistance> callback);
|
||||
|
||||
public abstract ActivityInitListener createActivityInitListener(
|
||||
Predicate<Boolean> onInitListener);
|
||||
/**
|
||||
* Creates a activity listener for activity initialized and/or destroyed. One or both of these
|
||||
* listeners must be provided.
|
||||
*
|
||||
* @param onInitListener a callback made when the activity is initialized. The callback should
|
||||
* return true to continue receiving callbacks (ie. for if the activity is
|
||||
* recreated).
|
||||
* @param onDestroyListener a callback made when the activity is destroyed.
|
||||
*/
|
||||
public abstract ActivityLifecycleListener createActivityLifecycleListener(
|
||||
@Nullable Predicate<Boolean> onInitListener, @Nullable Runnable onDestroyListener);
|
||||
|
||||
/**
|
||||
* Sets a callback to be run when an activity launch happens while launcher is not yet resumed.
|
||||
|
||||
@@ -36,7 +36,7 @@ import com.android.launcher3.touch.PagedOrientationHandler;
|
||||
import com.android.launcher3.util.DisplayController;
|
||||
import com.android.quickstep.GestureState.GestureEndTarget;
|
||||
import com.android.quickstep.fallback.RecentsState;
|
||||
import com.android.quickstep.util.ActivityInitListener;
|
||||
import com.android.quickstep.util.ActivityLifecycleListener;
|
||||
import com.android.quickstep.util.AnimatorControllerWithResistance;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
|
||||
@@ -88,10 +88,12 @@ public final class FallbackActivityInterface extends
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActivityInitListener createActivityInitListener(
|
||||
Predicate<Boolean> onInitListener) {
|
||||
return new ActivityInitListener<>((activity, alreadyOnHome) ->
|
||||
onInitListener.test(alreadyOnHome), RecentsActivity.ACTIVITY_TRACKER);
|
||||
public ActivityLifecycleListener createActivityLifecycleListener(
|
||||
@Nullable Predicate<Boolean> onInitListener, @Nullable Runnable onDestroyListener) {
|
||||
return new ActivityLifecycleListener<>(
|
||||
(activity, alreadyOnHome) -> onInitListener.test(alreadyOnHome),
|
||||
onDestroyListener,
|
||||
RecentsActivity.ACTIVITY_TRACKER);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -37,7 +37,7 @@ import androidx.annotation.UiThread;
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherAnimUtils;
|
||||
import com.android.launcher3.LauncherInitListener;
|
||||
import com.android.launcher3.LauncherLifecycleListener;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.anim.PendingAnimation;
|
||||
import com.android.launcher3.statehandlers.DepthController;
|
||||
@@ -49,7 +49,7 @@ import com.android.launcher3.uioverrides.QuickstepLauncher;
|
||||
import com.android.launcher3.util.DisplayController;
|
||||
import com.android.launcher3.util.NavigationMode;
|
||||
import com.android.quickstep.GestureState.GestureEndTarget;
|
||||
import com.android.quickstep.util.ActivityInitListener;
|
||||
import com.android.quickstep.util.ActivityLifecycleListener;
|
||||
import com.android.quickstep.util.AnimatorControllerWithResistance;
|
||||
import com.android.quickstep.util.LayoutUtils;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
@@ -136,9 +136,10 @@ public final class LauncherActivityInterface extends
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActivityInitListener createActivityInitListener(Predicate<Boolean> onInitListener) {
|
||||
return new LauncherInitListener((activity, alreadyOnHome) ->
|
||||
onInitListener.test(alreadyOnHome));
|
||||
public ActivityLifecycleListener createActivityLifecycleListener(
|
||||
@Nullable Predicate<Boolean> onInitListener, @Nullable Runnable onDestroyListener) {
|
||||
return new LauncherLifecycleListener((activity, alreadyOnHome) ->
|
||||
onInitListener.test(alreadyOnHome), onDestroyListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -37,7 +37,7 @@ public class ActiveGestureErrorDetector {
|
||||
ON_SETTLED_ON_END_TARGET, START_RECENTS_ANIMATION, FINISH_RECENTS_ANIMATION,
|
||||
CANCEL_RECENTS_ANIMATION, SET_ON_PAGE_TRANSITION_END_CALLBACK, CANCEL_CURRENT_ANIMATION,
|
||||
CLEANUP_SCREENSHOT, SCROLLER_ANIMATION_ABORTED, TASK_APPEARED, EXPECTING_TASK_APPEARED,
|
||||
FLAG_USING_OTHER_ACTIVITY_INPUT_CONSUMER,
|
||||
FLAG_USING_OTHER_ACTIVITY_INPUT_CONSUMER, LAUNCHER_DESTROYED,
|
||||
|
||||
/**
|
||||
* These GestureEvents are specifically associated to state flags that get set in
|
||||
@@ -162,6 +162,13 @@ public class ActiveGestureErrorDetector {
|
||||
+ "before/without setting end target to new task",
|
||||
writer);
|
||||
break;
|
||||
case LAUNCHER_DESTROYED:
|
||||
errorDetected |= printErrorIfTrue(
|
||||
true,
|
||||
prefix,
|
||||
/* errorMessage= */ "Launcher destroyed mid-gesture",
|
||||
writer);
|
||||
break;
|
||||
case STATE_GESTURE_COMPLETED:
|
||||
errorDetected |= printErrorIfTrue(
|
||||
!encounteredEvents.contains(GestureEvent.MOTION_UP),
|
||||
|
||||
@@ -1,73 +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.quickstep.util;
|
||||
|
||||
import com.android.launcher3.BaseActivity;
|
||||
import com.android.launcher3.util.ActivityTracker;
|
||||
import com.android.launcher3.util.ActivityTracker.SchedulerCallback;
|
||||
|
||||
import java.util.function.BiPredicate;
|
||||
|
||||
public class ActivityInitListener<T extends BaseActivity> implements
|
||||
SchedulerCallback<T> {
|
||||
|
||||
private BiPredicate<T, Boolean> mOnInitListener;
|
||||
private final ActivityTracker<T> mActivityTracker;
|
||||
|
||||
private boolean mIsRegistered = false;
|
||||
|
||||
/**
|
||||
* @param onInitListener a callback made when the activity is initialized. The callback should
|
||||
* return true to continue receiving callbacks (ie. for if the activity is
|
||||
* recreated).
|
||||
*/
|
||||
public ActivityInitListener(BiPredicate<T, Boolean> onInitListener,
|
||||
ActivityTracker<T> tracker) {
|
||||
mOnInitListener = onInitListener;
|
||||
mActivityTracker = tracker;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean init(T activity, boolean alreadyOnHome) {
|
||||
if (!mIsRegistered) {
|
||||
// Don't receive any more updates
|
||||
return false;
|
||||
}
|
||||
return handleInit(activity, alreadyOnHome);
|
||||
}
|
||||
|
||||
protected boolean handleInit(T activity, boolean alreadyOnHome) {
|
||||
return mOnInitListener.test(activity, alreadyOnHome);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the activity-created listener. If the activity is already created, then the
|
||||
* callback provided in the constructor will be called synchronously.
|
||||
*/
|
||||
public void register() {
|
||||
mIsRegistered = true;
|
||||
mActivityTracker.registerCallback(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* After calling this, we won't {@link #init} even when the activity is ready.
|
||||
*/
|
||||
public void unregister() {
|
||||
mActivityTracker.unregisterCallback(this);
|
||||
mIsRegistered = false;
|
||||
mOnInitListener = null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.util.Log;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.BaseActivity;
|
||||
import com.android.launcher3.util.ActivityTracker;
|
||||
import com.android.launcher3.util.ActivityTracker.SchedulerCallback;
|
||||
|
||||
import java.util.function.BiPredicate;
|
||||
|
||||
/**
|
||||
* Listener for activity initialized and/or destroyed.
|
||||
*/
|
||||
public class ActivityLifecycleListener<T extends BaseActivity> implements
|
||||
SchedulerCallback<T> {
|
||||
|
||||
private static final String TAG = "ActivityLifecycleListener";
|
||||
|
||||
@Nullable private final BiPredicate<T, Boolean> mOnInitListener;
|
||||
@Nullable private final Runnable mOnDestroyListener;
|
||||
private final ActivityTracker<T> mActivityTracker;
|
||||
|
||||
private boolean mIsRegistered = false;
|
||||
|
||||
/**
|
||||
* One or both of {@code onInitListener} and {@code onInitListener} must be provided, otherwise
|
||||
* the created instance will effectively be a no-op.
|
||||
*
|
||||
* @param onInitListener a callback made when the activity is initialized. The callback should
|
||||
* return true to continue receiving callbacks (ie. for if the activity is
|
||||
* recreated).
|
||||
* @param onDestroyListener a callback made when the activity is destroyed.
|
||||
*/
|
||||
public ActivityLifecycleListener(
|
||||
@Nullable BiPredicate<T, Boolean> onInitListener,
|
||||
@Nullable Runnable onDestroyListener,
|
||||
ActivityTracker<T> tracker) {
|
||||
if (onInitListener == null && onDestroyListener == null) {
|
||||
throw new IllegalArgumentException("Both listeners cannot be null");
|
||||
}
|
||||
mOnInitListener = onInitListener;
|
||||
mOnDestroyListener = onDestroyListener;
|
||||
mActivityTracker = tracker;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean onActivityReady(T activity, boolean alreadyOnHome) {
|
||||
if (!mIsRegistered) {
|
||||
// Don't receive any more updates
|
||||
return false;
|
||||
}
|
||||
return handleActivityReady(activity, alreadyOnHome);
|
||||
}
|
||||
|
||||
protected boolean handleActivityReady(T activity, boolean alreadyOnHome) {
|
||||
if (mOnInitListener == null) {
|
||||
Log.e(TAG, "Cannot handle init: init listener is null", new Exception());
|
||||
return false;
|
||||
}
|
||||
return mOnInitListener.test(activity, alreadyOnHome);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityDestroyed() {
|
||||
if (mOnDestroyListener == null) {
|
||||
Log.e(TAG, "Cannot clean up: destroy listener is null", new Exception());
|
||||
return;
|
||||
}
|
||||
mOnDestroyListener.run();
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the activity-created listener. If the activity is already created, then the
|
||||
* callback provided in the constructor will be called synchronously.
|
||||
*/
|
||||
public void register() {
|
||||
mIsRegistered = true;
|
||||
mActivityTracker.registerCallback(this, getType());
|
||||
}
|
||||
|
||||
/**
|
||||
* After calling this, we won't call {@link #onActivityReady} even when the activity is ready.
|
||||
*/
|
||||
public void unregister() {
|
||||
mActivityTracker.unregisterCallback(this, getType());
|
||||
mIsRegistered = false;
|
||||
}
|
||||
|
||||
private int getType() {
|
||||
return mOnInitListener != null && mOnDestroyListener != null
|
||||
? ActivityTracker.TYPE_BOTH
|
||||
: (mOnInitListener != null
|
||||
? ActivityTracker.TYPE_INIT
|
||||
: ActivityTracker.TYPE_DESTROY);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user