• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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