• 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.launcher3.util.Executors.MAIN_EXECUTOR;
19 import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.CANCEL_RECENTS_ANIMATION;
20 import static com.android.quickstep.util.ActiveGestureErrorDetector.GestureEvent.START_RECENTS_ANIMATION;
21 
22 import android.graphics.Rect;
23 import android.util.ArraySet;
24 import android.view.RemoteAnimationTarget;
25 
26 import androidx.annotation.BinderThread;
27 import androidx.annotation.NonNull;
28 import androidx.annotation.UiThread;
29 
30 import com.android.launcher3.Utilities;
31 import com.android.launcher3.util.Preconditions;
32 import com.android.quickstep.util.ActiveGestureErrorDetector;
33 import com.android.quickstep.util.ActiveGestureLog;
34 import com.android.systemui.shared.recents.model.ThumbnailData;
35 import com.android.systemui.shared.system.RecentsAnimationControllerCompat;
36 
37 import java.util.HashMap;
38 import java.util.Set;
39 
40 /**
41  * Wrapper around {@link com.android.systemui.shared.system.RecentsAnimationListener} which
42  * delegates callbacks to multiple listeners on the main thread
43  */
44 public class RecentsAnimationCallbacks implements
45         com.android.systemui.shared.system.RecentsAnimationListener {
46 
47     private final Set<RecentsAnimationListener> mListeners = new ArraySet<>();
48     private final SystemUiProxy mSystemUiProxy;
49     private final boolean mAllowMinimizeSplitScreen;
50 
51     // TODO(141886704): Remove these references when they are no longer needed
52     private RecentsAnimationController mController;
53 
54     private boolean mCancelled;
55 
RecentsAnimationCallbacks(SystemUiProxy systemUiProxy, boolean allowMinimizeSplitScreen)56     public RecentsAnimationCallbacks(SystemUiProxy systemUiProxy,
57             boolean allowMinimizeSplitScreen) {
58         mSystemUiProxy = systemUiProxy;
59         mAllowMinimizeSplitScreen = allowMinimizeSplitScreen;
60     }
61 
62     @UiThread
addListener(RecentsAnimationListener listener)63     public void addListener(RecentsAnimationListener listener) {
64         Preconditions.assertUIThread();
65         mListeners.add(listener);
66     }
67 
68     @UiThread
removeListener(RecentsAnimationListener listener)69     public void removeListener(RecentsAnimationListener listener) {
70         Preconditions.assertUIThread();
71         mListeners.remove(listener);
72     }
73 
74     @UiThread
removeAllListeners()75     public void removeAllListeners() {
76         Preconditions.assertUIThread();
77         mListeners.clear();
78     }
79 
notifyAnimationCanceled()80     public void notifyAnimationCanceled() {
81         mCancelled = true;
82         onAnimationCanceled(new HashMap<>());
83     }
84 
85     // Called only in Q platform
86     @BinderThread
87     @Deprecated
onAnimationStart(RecentsAnimationControllerCompat controller, RemoteAnimationTarget[] appTargets, Rect homeContentInsets, Rect minimizedHomeBounds)88     public final void onAnimationStart(RecentsAnimationControllerCompat controller,
89             RemoteAnimationTarget[] appTargets, Rect homeContentInsets,
90             Rect minimizedHomeBounds) {
91         onAnimationStart(controller, appTargets, new RemoteAnimationTarget[0],
92                 homeContentInsets, minimizedHomeBounds);
93     }
94 
95     // Called only in R+ platform
96     @BinderThread
onAnimationStart(RecentsAnimationControllerCompat animationController, RemoteAnimationTarget[] appTargets, RemoteAnimationTarget[] wallpaperTargets, Rect homeContentInsets, Rect minimizedHomeBounds)97     public final void onAnimationStart(RecentsAnimationControllerCompat animationController,
98             RemoteAnimationTarget[] appTargets,
99             RemoteAnimationTarget[] wallpaperTargets,
100             Rect homeContentInsets, Rect minimizedHomeBounds) {
101         mController = new RecentsAnimationController(animationController,
102                 mAllowMinimizeSplitScreen, this::onAnimationFinished);
103 
104         if (mCancelled) {
105             Utilities.postAsyncCallback(MAIN_EXECUTOR.getHandler(),
106                     mController::finishAnimationToApp);
107         } else {
108             RemoteAnimationTarget[] nonAppTargets =
109                     mSystemUiProxy.onGoingToRecentsLegacy(appTargets);
110             if (nonAppTargets == null) {
111                 nonAppTargets = new RemoteAnimationTarget[0];
112             }
113             final RecentsAnimationTargets targets = new RecentsAnimationTargets(appTargets,
114                     wallpaperTargets, nonAppTargets, homeContentInsets, minimizedHomeBounds);
115 
116             Utilities.postAsyncCallback(MAIN_EXECUTOR.getHandler(), () -> {
117                 ActiveGestureLog.INSTANCE.addLog(
118                         /* event= */ "RecentsAnimationCallbacks.onAnimationStart",
119                         /* extras= */ targets.apps.length,
120                         /* gestureEvent= */ START_RECENTS_ANIMATION);
121                 for (RecentsAnimationListener listener : getListeners()) {
122                     listener.onRecentsAnimationStart(mController, targets);
123                 }
124             });
125         }
126     }
127 
128     @BinderThread
129     @Override
onAnimationCanceled(HashMap<Integer, ThumbnailData> thumbnailDatas)130     public final void onAnimationCanceled(HashMap<Integer, ThumbnailData> thumbnailDatas) {
131         Utilities.postAsyncCallback(MAIN_EXECUTOR.getHandler(), () -> {
132             ActiveGestureLog.INSTANCE.addLog(
133                     /* event= */ "RecentsAnimationCallbacks.onAnimationCanceled",
134                     /* gestureEvent= */ CANCEL_RECENTS_ANIMATION);
135             for (RecentsAnimationListener listener : getListeners()) {
136                 listener.onRecentsAnimationCanceled(thumbnailDatas);
137             }
138         });
139     }
140 
141     @BinderThread
142     @Override
onTasksAppeared(RemoteAnimationTarget[] apps)143     public void onTasksAppeared(RemoteAnimationTarget[] apps) {
144         Utilities.postAsyncCallback(MAIN_EXECUTOR.getHandler(), () -> {
145             ActiveGestureLog.INSTANCE.addLog("RecentsAnimationCallbacks.onTasksAppeared",
146                     ActiveGestureErrorDetector.GestureEvent.TASK_APPEARED);
147             for (RecentsAnimationListener listener : getListeners()) {
148                 listener.onTasksAppeared(apps);
149             }
150         });
151     }
152 
153     @BinderThread
154     @Override
onSwitchToScreenshot(Runnable onFinished)155     public boolean onSwitchToScreenshot(Runnable onFinished) {
156         Utilities.postAsyncCallback(MAIN_EXECUTOR.getHandler(), () -> {
157             for (RecentsAnimationListener listener : getListeners()) {
158                 if (listener.onSwitchToScreenshot(onFinished)) return;
159             }
160             onFinished.run();
161         });
162         return true;
163     }
164 
onAnimationFinished(RecentsAnimationController controller)165     private final void onAnimationFinished(RecentsAnimationController controller) {
166         Utilities.postAsyncCallback(MAIN_EXECUTOR.getHandler(), () -> {
167             ActiveGestureLog.INSTANCE.addLog(
168                     /* event= */ "RecentsAnimationCallbacks.onAnimationFinished");
169             for (RecentsAnimationListener listener : getListeners()) {
170                 listener.onRecentsAnimationFinished(controller);
171             }
172         });
173     }
174 
getListeners()175     private RecentsAnimationListener[] getListeners() {
176         return mListeners.toArray(new RecentsAnimationListener[mListeners.size()]);
177     }
178 
179     /**
180      * Listener for the recents animation callbacks.
181      */
182     public interface RecentsAnimationListener {
onRecentsAnimationStart(RecentsAnimationController controller, RecentsAnimationTargets targets)183         default void onRecentsAnimationStart(RecentsAnimationController controller,
184                 RecentsAnimationTargets targets) {}
185 
186         /**
187          * Callback from the system when the recents animation is canceled. {@param thumbnailData}
188          * is passed back for rendering screenshot to replace live tile.
189          */
onRecentsAnimationCanceled( @onNull HashMap<Integer, ThumbnailData> thumbnailDatas)190         default void onRecentsAnimationCanceled(
191                 @NonNull HashMap<Integer, ThumbnailData> thumbnailDatas) {}
192 
193         /**
194          * Callback made whenever the recents animation is finished.
195          */
onRecentsAnimationFinished(@onNull RecentsAnimationController controller)196         default void onRecentsAnimationFinished(@NonNull RecentsAnimationController controller) {}
197 
198         /**
199          * Callback made when a task started from the recents is ready for an app transition.
200          */
onTasksAppeared(@onNull RemoteAnimationTarget[] appearedTaskTarget)201         default void onTasksAppeared(@NonNull RemoteAnimationTarget[] appearedTaskTarget) {}
202 
203         /**
204          * @return whether this will call onFinished or not (onFinished should only be called once).
205          */
onSwitchToScreenshot(Runnable onFinished)206         default boolean onSwitchToScreenshot(Runnable onFinished) {
207             return false;
208         }
209     }
210 }
211