Merge "Moving some recents controller methods into wrapper class and better tracking the controller states" into ub-launcher3-master

This commit is contained in:
TreeHugger Robot 2019-02-20 00:12:59 +00:00 committed by Android (Google) Code Review
commit 774f825b04
8 changed files with 153 additions and 132 deletions

View File

@ -292,8 +292,6 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC
mMotionPauseDetector.setOnMotionPauseListener(handler::onMotionPauseChanged);
handler.initWhenReady();
TraceHelper.beginSection("RecentsController");
if (listenerSet != null) {
listenerSet.addListener(handler);
mSwipeSharedState.applyActiveRecentsAnimationState(handler);

View File

@ -21,17 +21,11 @@ import static android.view.MotionEvent.ACTION_UP;
import android.view.MotionEvent;
import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.util.LooperExecutor;
import com.android.launcher3.util.Preconditions;
import com.android.launcher3.util.TraceHelper;
import com.android.launcher3.util.UiThreadHelper;
import com.android.quickstep.util.RemoteAnimationTargetSet;
import com.android.quickstep.util.SwipeAnimationTargetSet;
import com.android.systemui.shared.system.InputConsumerController;
import com.android.systemui.shared.system.RecentsAnimationControllerCompat;
import java.util.ArrayList;
import java.util.concurrent.ExecutorService;
import java.util.function.Supplier;
import androidx.annotation.UiThread;
@ -45,17 +39,10 @@ public class RecentsAnimationWrapper {
// than the state callbacks as these run on the current worker thread.
private final ArrayList<Runnable> mCallbacks = new ArrayList<>();
public RemoteAnimationTargetSet targetSet;
public SwipeAnimationTargetSet targetSet;
private RecentsAnimationControllerCompat mController;
private boolean mInputConsumerEnabled = false;
private boolean mBehindSystemBars = true;
private boolean mSplitScreenMinimized = false;
private boolean mWindowThresholdCrossed = false;
private final ExecutorService mExecutorService =
new LooperExecutor(UiThreadHelper.getBackgroundLooper());
private final MainThreadExecutor mMainThreadExecutor = new MainThreadExecutor();
private final InputConsumerController mInputConsumer;
private final Supplier<TouchConsumer> mTouchProxySupplier;
@ -71,19 +58,14 @@ public class RecentsAnimationWrapper {
}
@UiThread
public synchronized void setController(
RecentsAnimationControllerCompat controller, RemoteAnimationTargetSet targetSet) {
public synchronized void setController(SwipeAnimationTargetSet targetSet) {
Preconditions.assertUIThread();
TraceHelper.partitionSection("RecentsController", "Set controller " + controller);
this.mController = controller;
this.targetSet = targetSet;
if (controller == null) {
if (targetSet == null) {
return;
}
if (mInputConsumerEnabled) {
enableInputConsumer();
}
targetSet.setWindowThresholdCrossed(mWindowThresholdCrossed);
if (!mCallbacks.isEmpty()) {
for (Runnable action : new ArrayList<>(mCallbacks)) {
@ -105,13 +87,12 @@ public class RecentsAnimationWrapper {
* @param onFinishComplete A callback that runs on the main thread after the animation
* controller has finished on the background thread.
*/
@UiThread
public void finish(boolean toRecents, Runnable onFinishComplete) {
Preconditions.assertUIThread();
if (!toRecents) {
mExecutorService.submit(() -> finishBg(false, onFinishComplete));
return;
}
mMainThreadExecutor.execute(() -> {
finishAndClear(false, onFinishComplete);
} else {
if (mTouchInProgress) {
mFinishPending = true;
// Execute the callback
@ -119,45 +100,39 @@ public class RecentsAnimationWrapper {
onFinishComplete.run();
}
} else {
mExecutorService.submit(() -> finishBg(true, onFinishComplete));
finishAndClear(true, onFinishComplete);
}
});
}
}
protected void finishBg(boolean toRecents, Runnable onFinishComplete) {
RecentsAnimationControllerCompat controller = mController;
mController = null;
TraceHelper.endSection("RecentsController", "Finish " + controller
+ ", toRecents=" + toRecents);
private void finishAndClear(boolean toRecents, Runnable onFinishComplete) {
SwipeAnimationTargetSet controller = targetSet;
targetSet = null;
if (controller != null) {
controller.setInputConsumerEnabled(false);
controller.finish(toRecents);
if (onFinishComplete != null) {
mMainThreadExecutor.execute(onFinishComplete);
}
controller.finishController(toRecents, onFinishComplete);
}
}
public void enableInputConsumer() {
mInputConsumerEnabled = true;
if (mInputConsumerEnabled) {
mExecutorService.submit(() -> {
RecentsAnimationControllerCompat controller = mController;
TraceHelper.partitionSection("RecentsController",
"Enabling consumer on " + controller);
if (controller != null) {
controller.setInputConsumerEnabled(true);
}
});
if (targetSet != null) {
targetSet.enableInputConsumer();
}
}
/**
* Indicates that the gesture has crossed the window boundary threshold and system UI can be
* update the represent the window behind
*/
public void setWindowThresholdCrossed(boolean windowThresholdCrossed) {
if (mWindowThresholdCrossed != windowThresholdCrossed) {
mWindowThresholdCrossed = windowThresholdCrossed;
if (targetSet != null) {
targetSet.setWindowThresholdCrossed(windowThresholdCrossed);
}
}
}
public void enableTouchProxy() {
mMainThreadExecutor.execute(this::enableTouchProxyUi);
}
private void enableTouchProxyUi() {
mInputConsumer.setTouchListener(this::onInputConsumerTouch);
}
@ -171,7 +146,7 @@ public class RecentsAnimationWrapper {
mTouchInProgress = false;
if (mFinishPending) {
mFinishPending = false;
mExecutorService.submit(() -> finishBg(true, null));
finishAndClear(true /* toRecents */, null);
}
}
if (mTouchConsumer != null) {
@ -181,54 +156,7 @@ public class RecentsAnimationWrapper {
return true;
}
public void setAnimationTargetsBehindSystemBars(boolean behindSystemBars) {
if (mBehindSystemBars == behindSystemBars) {
return;
}
mBehindSystemBars = behindSystemBars;
mExecutorService.submit(() -> {
RecentsAnimationControllerCompat controller = mController;
TraceHelper.partitionSection("RecentsController",
"Setting behind system bars on " + controller);
if (controller != null) {
controller.setAnimationTargetsBehindSystemBars(behindSystemBars);
}
});
}
/**
* NOTE: As a workaround for conflicting animations (Launcher animating the task leash, and
* SystemUI resizing the docked stack, which resizes the task), we currently only set the
* minimized mode, and not the inverse.
* TODO: Synchronize the minimize animation with the launcher animation
*/
public void setSplitScreenMinimizedForTransaction(boolean minimized) {
if (mSplitScreenMinimized || !minimized) {
return;
}
mSplitScreenMinimized = minimized;
mExecutorService.submit(() -> {
RecentsAnimationControllerCompat controller = mController;
TraceHelper.partitionSection("RecentsController",
"Setting minimize dock on " + controller);
if (controller != null) {
controller.setSplitScreenMinimized(minimized);
}
});
}
public void hideCurrentInputMethod() {
mExecutorService.submit(() -> {
RecentsAnimationControllerCompat controller = mController;
TraceHelper.partitionSection("RecentsController",
"Hiding currentinput method on " + controller);
if (controller != null) {
controller.hideCurrentInputMethod();
}
});
}
public RecentsAnimationControllerCompat getController() {
return mController;
public SwipeAnimationTargetSet getController() {
return targetSet;
}
}

View File

@ -15,6 +15,9 @@
*/
package com.android.quickstep;
import android.util.Log;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.util.Preconditions;
import com.android.quickstep.util.RecentsAnimationListenerSet;
import com.android.quickstep.util.SwipeAnimationTargetSet;
@ -25,23 +28,35 @@ import com.android.quickstep.util.SwipeAnimationTargetSet.SwipeAnimationListener
*/
public class SwipeSharedState implements SwipeAnimationListener {
private final OverviewComponentObserver mOverviewComponentObserver;
private RecentsAnimationListenerSet mRecentsAnimationListener;
private SwipeAnimationTargetSet mLastAnimationTarget;
private boolean mLastAnimationCancelled = false;
private boolean mLastAnimationRunning = false;
public boolean canGestureBeContinued;
public boolean goingToLauncher;
public SwipeSharedState(OverviewComponentObserver overviewComponentObserver) {
mOverviewComponentObserver = overviewComponentObserver;
}
@Override
public final void onRecentsAnimationStart(SwipeAnimationTargetSet targetSet) {
mLastAnimationTarget = targetSet;
mLastAnimationCancelled = false;
mLastAnimationRunning = true;
}
@Override
public final void onRecentsAnimationCanceled() {
mLastAnimationTarget = null;
mLastAnimationCancelled = true;
mLastAnimationRunning = false;
}
private void clearListenerState() {
@ -51,12 +66,31 @@ public class SwipeSharedState implements SwipeAnimationListener {
mRecentsAnimationListener = null;
mLastAnimationTarget = null;
mLastAnimationCancelled = false;
mLastAnimationRunning = false;
}
private void onSwipeAnimationFinished(SwipeAnimationTargetSet targetSet) {
if (mLastAnimationTarget == targetSet) {
mLastAnimationRunning = false;
}
}
public RecentsAnimationListenerSet newRecentsAnimationListenerSet() {
Preconditions.assertUIThread();
if (mLastAnimationRunning) {
String msg = "New animation started before completing old animation";
if (FeatureFlags.IS_DOGFOOD_BUILD) {
throw new IllegalArgumentException(msg);
} else {
Log.e("SwipeSharedState", msg, new Exception());
}
}
clearListenerState();
mRecentsAnimationListener = new RecentsAnimationListenerSet();
mRecentsAnimationListener = new RecentsAnimationListenerSet(mOverviewComponentObserver
.getActivityControlHelper().shouldMinimizeSplitScreen(),
this::onSwipeAnimationFinished);
mRecentsAnimationListener.addListener(this);
return mRecentsAnimationListener;
}

View File

@ -37,6 +37,8 @@ import android.view.InputEvent;
import android.view.MotionEvent;
import com.android.launcher3.MainThreadExecutor;
import com.android.launcher3.util.LooperExecutor;
import com.android.launcher3.util.UiThreadHelper;
import com.android.systemui.shared.recents.IOverviewProxy;
import com.android.systemui.shared.recents.ISystemUiProxy;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@ -55,6 +57,9 @@ import java.io.PrintWriter;
public class TouchInteractionService extends Service {
public static final MainThreadExecutor MAIN_THREAD_EXECUTOR = new MainThreadExecutor();
public static final LooperExecutor BACKGROUND_EXECUTOR =
new LooperExecutor(UiThreadHelper.getBackgroundLooper());
public static final TouchInteractionLog TOUCH_INTERACTION_LOG = new TouchInteractionLog();
public static final int EDGE_NAV_BAR = 1 << 8;
@ -174,7 +179,7 @@ public class TouchInteractionService extends Service {
mOverviewInteractionState = OverviewInteractionState.INSTANCE.get(this);
mOverviewCallbacks = OverviewCallbacks.get(this);
mTaskOverlayFactory = TaskOverlayFactory.INSTANCE.get(this);
mSwipeSharedState = new SwipeSharedState();
mSwipeSharedState = new SwipeSharedState(mOverviewComponentObserver);
mInputConsumer = InputConsumerController.getRecentsAnimationInputConsumer();
mInputConsumer.registerInputConsumer();
@ -249,10 +254,8 @@ public class TouchInteractionService extends Service {
mOverviewComponentObserver.getActivityControlHelper();
boolean shouldDefer = activityControl.deferStartingActivity(mActiveNavBarRegion, event);
return new OtherActivityTouchConsumer(this, runningTaskInfo, mRecentsModel,
mOverviewComponentObserver.getOverviewIntent(),
mOverviewComponentObserver.getActivityControlHelper(),
shouldDefer, mOverviewCallbacks,
mTaskOverlayFactory, mInputConsumer,
mOverviewComponentObserver.getOverviewIntent(), activityControl,
shouldDefer, mOverviewCallbacks, mTaskOverlayFactory, mInputConsumer,
this::onConsumerInactive, mSwipeSharedState);
}
}

View File

@ -99,7 +99,6 @@ import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.recents.utilities.RectFEvaluator;
import com.android.systemui.shared.system.InputConsumerController;
import com.android.systemui.shared.system.LatencyTrackerCompat;
import com.android.systemui.shared.system.RecentsAnimationControllerCompat;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat;
import com.android.systemui.shared.system.WindowCallbacksCompat;
@ -115,7 +114,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
implements SwipeAnimationListener, OnApplyWindowInsetsListener {
private static final String TAG = WindowTransformSwipeHandler.class.getSimpleName();
private static final String[] STATE_NAMES = DEBUG_STATES ? new String[20] : null;
private static final String[] STATE_NAMES = DEBUG_STATES ? new String[19] : null;
private static int getFlagForIndex(int index, String name) {
if (DEBUG_STATES) {
@ -351,6 +350,9 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
| STATE_SCALED_CONTROLLER_LAST_TASK,
this::notifyTransitionCancelled);
mStateCallback.addCallback(STATE_APP_CONTROLLER_RECEIVED | STATE_GESTURE_STARTED,
mRecentsAnimationWrapper::enableInputConsumer);
if (!ENABLE_QUICKSTEP_LIVE_TILE.get()) {
mStateCallback.addChangeHandler(STATE_APP_CONTROLLER_RECEIVED | STATE_LAUNCHER_PRESENT
| STATE_SCREENSHOT_VIEW_SHOWN | STATE_CAPTURE_SCREENSHOT,
@ -599,7 +601,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
private void updateFinalShift() {
float shift = mCurrentShift.value;
RecentsAnimationControllerCompat controller = mRecentsAnimationWrapper.getController();
SwipeAnimationTargetSet controller = mRecentsAnimationWrapper.getController();
if (controller != null) {
float offsetX = 0;
if (mRecentsView != null) {
@ -614,12 +616,8 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
.setSyncTransactionApplier(mSyncTransactionApplier);
mClipAnimationHelper.applyTransform(mRecentsAnimationWrapper.targetSet,
mTransformParams);
boolean passedThreshold = shift > 1 - UPDATE_SYSUI_FLAGS_THRESHOLD;
mRecentsAnimationWrapper.setAnimationTargetsBehindSystemBars(!passedThreshold);
if (mActivityControlHelper.shouldMinimizeSplitScreen()) {
mRecentsAnimationWrapper.setSplitScreenMinimizedForTransaction(passedThreshold);
}
mRecentsAnimationWrapper.setWindowThresholdCrossed(
shift > 1 - UPDATE_SYSUI_FLAGS_THRESHOLD);
}
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
@ -698,7 +696,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
mClipAnimationHelper.prepareAnimation(false /* isOpening */);
initTransitionEndpoints(dp);
mRecentsAnimationWrapper.setController(targetSet.controller, targetSet);
mRecentsAnimationWrapper.setController(targetSet);
TOUCH_INTERACTION_LOG.startRecentsAnimationCallback(targetSet.apps.length);
setStateOnUiThread(STATE_APP_CONTROLLER_RECEIVED);
@ -707,7 +705,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
@Override
public void onRecentsAnimationCanceled() {
mRecentsAnimationWrapper.setController(null, null);
mRecentsAnimationWrapper.setController(null);
mActivityInitListener.unregister();
setStateOnUiThread(STATE_GESTURE_CANCELLED | STATE_HANDLER_INVALIDATED);
TOUCH_INTERACTION_LOG.cancelRecentsAnimation();
@ -719,8 +717,6 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
mShiftAtGestureStart = mCurrentShift.value;
setStateOnUiThread(STATE_GESTURE_STARTED);
mGestureStarted = true;
mRecentsAnimationWrapper.hideCurrentInputMethod();
mRecentsAnimationWrapper.enableInputConsumer();
}
/**
@ -1122,7 +1118,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
setStateOnUiThread(STATE_SCREENSHOT_CAPTURED);
} else {
boolean finishTransitionPosted = false;
RecentsAnimationControllerCompat controller = mRecentsAnimationWrapper.getController();
SwipeAnimationTargetSet controller = mRecentsAnimationWrapper.getController();
if (controller != null) {
// Update the screenshot of the task
if (mTaskSnapshot == null) {

View File

@ -28,6 +28,7 @@ import com.android.systemui.shared.system.RecentsAnimationListener;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import java.util.Set;
import java.util.function.Consumer;
import androidx.annotation.UiThread;
@ -38,6 +39,14 @@ import androidx.annotation.UiThread;
public class RecentsAnimationListenerSet implements RecentsAnimationListener {
private final Set<SwipeAnimationListener> mListeners = new ArraySet<>();
private final boolean mShouldMinimizeSplitScreen;
private final Consumer<SwipeAnimationTargetSet> mOnFinishListener;
public RecentsAnimationListenerSet(boolean shouldMinimizeSplitScreen,
Consumer<SwipeAnimationTargetSet> onFinishListener) {
mShouldMinimizeSplitScreen = shouldMinimizeSplitScreen;
mOnFinishListener = onFinishListener;
}
@UiThread
public void addListener(SwipeAnimationListener listener) {
@ -56,7 +65,8 @@ public class RecentsAnimationListenerSet implements RecentsAnimationListener {
RemoteAnimationTargetCompat[] targets, Rect homeContentInsets,
Rect minimizedHomeBounds) {
SwipeAnimationTargetSet targetSet = new SwipeAnimationTargetSet(controller, targets,
homeContentInsets, minimizedHomeBounds);
homeContentInsets, minimizedHomeBounds, mShouldMinimizeSplitScreen,
mOnFinishListener);
Utilities.postAsyncCallback(MAIN_THREAD_EXECUTOR.getHandler(), () -> {
for (SwipeAnimationListener listener : getListeners()) {
listener.onRecentsAnimationStart(targetSet);

View File

@ -15,32 +15,79 @@
*/
package com.android.quickstep.util;
import static com.android.quickstep.TouchInteractionService.BACKGROUND_EXECUTOR;
import static com.android.quickstep.TouchInteractionService.MAIN_THREAD_EXECUTOR;
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MODE_CLOSING;
import android.graphics.Rect;
import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.RecentsAnimationControllerCompat;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import java.util.function.Consumer;
/**
* Extension of {@link RemoteAnimationTargetSet} with additional information about swipe
* up animation
*/
public class SwipeAnimationTargetSet extends RemoteAnimationTargetSet {
private final boolean mShouldMinimizeSplitScreen;
private final Consumer<SwipeAnimationTargetSet> mOnFinishListener;
public final RecentsAnimationControllerCompat controller;
public final Rect homeContentInsets;
public final Rect minimizedHomeBounds;
public SwipeAnimationTargetSet(RecentsAnimationControllerCompat controller,
RemoteAnimationTargetCompat[] targets, Rect homeContentInsets,
Rect minimizedHomeBounds) {
Rect minimizedHomeBounds, boolean shouldMinimizeSplitScreen,
Consumer<SwipeAnimationTargetSet> onFinishListener) {
super(targets, MODE_CLOSING);
this.controller = controller;
this.homeContentInsets = homeContentInsets;
this.minimizedHomeBounds = minimizedHomeBounds;
this.mShouldMinimizeSplitScreen = shouldMinimizeSplitScreen;
this.mOnFinishListener = onFinishListener;
}
public void finishController(boolean toRecents, Runnable callback) {
mOnFinishListener.accept(this);
BACKGROUND_EXECUTOR.execute(() -> {
controller.setInputConsumerEnabled(false);
controller.finish(toRecents);
if (callback != null) {
MAIN_THREAD_EXECUTOR.execute(callback);
}
});
}
public void enableInputConsumer() {
BACKGROUND_EXECUTOR.submit(() -> {
controller.hideCurrentInputMethod();
controller.setInputConsumerEnabled(true);
});
}
public void setWindowThresholdCrossed(boolean thresholdCrossed) {
BACKGROUND_EXECUTOR.execute(() -> {
controller.setAnimationTargetsBehindSystemBars(!thresholdCrossed);
if (mShouldMinimizeSplitScreen && thresholdCrossed) {
// NOTE: As a workaround for conflicting animations (Launcher animating the task
// leash, and SystemUI resizing the docked stack, which resizes the task), we
// currently only set the minimized mode, and not the inverse.
// TODO: Synchronize the minimize animation with the launcher animation
controller.setSplitScreenMinimized(thresholdCrossed);
}
});
}
public ThumbnailData screenshotTask(int taskId) {
return controller != null ? controller.screenshotTask(taskId) : null;
}
public interface SwipeAnimationListener {
@ -48,4 +95,9 @@ public class SwipeAnimationTargetSet extends RemoteAnimationTargetSet {
void onRecentsAnimationCanceled();
}
public interface SwipeAnimationFinishListener {
void onSwipeAnimationFinished(SwipeAnimationTargetSet targetSet);
}
}

View File

@ -93,13 +93,13 @@ import com.android.quickstep.RecentsModel;
import com.android.quickstep.TaskThumbnailCache;
import com.android.quickstep.TaskUtils;
import com.android.quickstep.util.ClipAnimationHelper;
import com.android.quickstep.util.SwipeAnimationTargetSet;
import com.android.quickstep.util.TaskViewDrawable;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.BackgroundExecutor;
import com.android.systemui.shared.system.PackageManagerWrapper;
import com.android.systemui.shared.system.RecentsAnimationControllerCompat;
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat;
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.shared.system.WindowCallbacksCompat;
@ -1590,7 +1590,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
return;
}
RecentsAnimationControllerCompat controller = mRecentsAnimationWrapper.getController();
SwipeAnimationTargetSet controller = mRecentsAnimationWrapper.getController();
if (controller != null) {
// Update the screenshot of the task
ThumbnailData taskSnapshot = controller.screenshotTask(mRunningTaskId);