1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package com.android.quickstep; 17 18 import static com.android.quickstep.TouchInteractionService.MAIN_THREAD_EXECUTOR; 19 20 import android.util.Log; 21 22 import com.android.launcher3.Utilities; 23 import com.android.launcher3.config.FeatureFlags; 24 import com.android.launcher3.util.Preconditions; 25 import com.android.quickstep.util.RecentsAnimationListenerSet; 26 import com.android.quickstep.util.SwipeAnimationTargetSet; 27 import com.android.quickstep.util.SwipeAnimationTargetSet.SwipeAnimationListener; 28 import java.io.PrintWriter; 29 30 /** 31 * Utility class used to store state information shared across multiple transitions. 32 */ 33 public class SwipeSharedState implements SwipeAnimationListener { 34 35 private OverviewComponentObserver mOverviewComponentObserver; 36 37 private RecentsAnimationListenerSet mRecentsAnimationListener; 38 private SwipeAnimationTargetSet mLastAnimationTarget; 39 40 private boolean mLastAnimationCancelled = false; 41 private boolean mLastAnimationRunning = false; 42 43 public boolean canGestureBeContinued; 44 public boolean goingToLauncher; 45 public boolean recentsAnimationFinishInterrupted; 46 public int nextRunningTaskId = -1; 47 setOverviewComponentObserver(OverviewComponentObserver observer)48 public void setOverviewComponentObserver(OverviewComponentObserver observer) { 49 mOverviewComponentObserver = observer; 50 } 51 52 @Override onRecentsAnimationStart(SwipeAnimationTargetSet targetSet)53 public final void onRecentsAnimationStart(SwipeAnimationTargetSet targetSet) { 54 mLastAnimationTarget = targetSet; 55 56 mLastAnimationCancelled = false; 57 mLastAnimationRunning = true; 58 } 59 clearAnimationTarget()60 private void clearAnimationTarget() { 61 if (mLastAnimationTarget != null) { 62 mLastAnimationTarget.release(); 63 mLastAnimationTarget = null; 64 } 65 } 66 67 @Override onRecentsAnimationCanceled()68 public final void onRecentsAnimationCanceled() { 69 clearAnimationTarget(); 70 71 mLastAnimationCancelled = true; 72 mLastAnimationRunning = false; 73 } 74 clearListenerState(boolean finishAnimation)75 private void clearListenerState(boolean finishAnimation) { 76 if (mRecentsAnimationListener != null) { 77 mRecentsAnimationListener.removeListener(this); 78 mRecentsAnimationListener.cancelListener(); 79 if (mLastAnimationRunning && mLastAnimationTarget != null) { 80 Utilities.postAsyncCallback(MAIN_THREAD_EXECUTOR.getHandler(), 81 finishAnimation 82 ? mLastAnimationTarget::finishAnimation 83 : mLastAnimationTarget::cancelAnimation); 84 mLastAnimationTarget = null; 85 } 86 } 87 mRecentsAnimationListener = null; 88 clearAnimationTarget(); 89 mLastAnimationCancelled = false; 90 mLastAnimationRunning = false; 91 } 92 onSwipeAnimationFinished(SwipeAnimationTargetSet targetSet)93 private void onSwipeAnimationFinished(SwipeAnimationTargetSet targetSet) { 94 if (mLastAnimationTarget == targetSet) { 95 mLastAnimationRunning = false; 96 } 97 } 98 newRecentsAnimationListenerSet()99 public RecentsAnimationListenerSet newRecentsAnimationListenerSet() { 100 Preconditions.assertUIThread(); 101 102 if (mLastAnimationRunning) { 103 String msg = "New animation started before completing old animation"; 104 if (FeatureFlags.IS_DOGFOOD_BUILD) { 105 throw new IllegalArgumentException(msg); 106 } else { 107 Log.e("SwipeSharedState", msg, new Exception()); 108 } 109 } 110 111 clearListenerState(false /* finishAnimation */); 112 boolean shouldMinimiseSplitScreen = mOverviewComponentObserver == null ? false 113 : mOverviewComponentObserver.getActivityControlHelper().shouldMinimizeSplitScreen(); 114 mRecentsAnimationListener = new RecentsAnimationListenerSet( 115 shouldMinimiseSplitScreen, this::onSwipeAnimationFinished); 116 mRecentsAnimationListener.addListener(this); 117 return mRecentsAnimationListener; 118 } 119 getActiveListener()120 public RecentsAnimationListenerSet getActiveListener() { 121 return mRecentsAnimationListener; 122 } 123 applyActiveRecentsAnimationState(SwipeAnimationListener listener)124 public void applyActiveRecentsAnimationState(SwipeAnimationListener listener) { 125 if (mLastAnimationTarget != null) { 126 listener.onRecentsAnimationStart(mLastAnimationTarget); 127 } else if (mLastAnimationCancelled) { 128 listener.onRecentsAnimationCanceled(); 129 } 130 } 131 132 /** 133 * Called when a recents animation has finished, but was interrupted before the next task was 134 * launched. The given {@param runningTaskId} should be used as the running task for the 135 * continuing input consumer. 136 */ setRecentsAnimationFinishInterrupted(int runningTaskId)137 public void setRecentsAnimationFinishInterrupted(int runningTaskId) { 138 recentsAnimationFinishInterrupted = true; 139 nextRunningTaskId = runningTaskId; 140 mLastAnimationTarget = mLastAnimationTarget.cloneWithoutTargets(); 141 } 142 clearAllState(boolean finishAnimation)143 public void clearAllState(boolean finishAnimation) { 144 clearListenerState(finishAnimation); 145 canGestureBeContinued = false; 146 recentsAnimationFinishInterrupted = false; 147 nextRunningTaskId = -1; 148 goingToLauncher = false; 149 } 150 dump(String prefix, PrintWriter pw)151 public void dump(String prefix, PrintWriter pw) { 152 pw.println(prefix + "goingToLauncher=" + goingToLauncher); 153 pw.println(prefix + "canGestureBeContinued=" + canGestureBeContinued); 154 pw.println(prefix + "recentsAnimationFinishInterrupted=" + recentsAnimationFinishInterrupted); 155 pw.println(prefix + "nextRunningTaskId=" + nextRunningTaskId); 156 pw.println(prefix + "lastAnimationCancelled=" + mLastAnimationCancelled); 157 pw.println(prefix + "lastAnimationRunning=" + mLastAnimationRunning); 158 } 159 } 160