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 
20 import android.graphics.Rect;
21 import android.util.ArraySet;
22 
23 import androidx.annotation.BinderThread;
24 import androidx.annotation.UiThread;
25 
26 import com.android.launcher3.Utilities;
27 import com.android.launcher3.util.Preconditions;
28 import com.android.systemui.shared.recents.model.ThumbnailData;
29 import com.android.systemui.shared.system.RecentsAnimationControllerCompat;
30 import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
31 
32 import java.util.Set;
33 
34 /**
35  * Wrapper around {@link com.android.systemui.shared.system.RecentsAnimationListener} which
36  * delegates callbacks to multiple listeners on the main thread
37  */
38 public class RecentsAnimationCallbacks implements
39         com.android.systemui.shared.system.RecentsAnimationListener {
40 
41     private final Set<RecentsAnimationListener> mListeners = new ArraySet<>();
42     private final boolean mAllowMinimizeSplitScreen;
43 
44     // TODO(141886704): Remove these references when they are no longer needed
45     private RecentsAnimationController mController;
46 
47     private boolean mCancelled;
48 
RecentsAnimationCallbacks(boolean allowMinimizeSplitScreen)49     public RecentsAnimationCallbacks(boolean allowMinimizeSplitScreen) {
50         mAllowMinimizeSplitScreen = allowMinimizeSplitScreen;
51     }
52 
53     @UiThread
addListener(RecentsAnimationListener listener)54     public void addListener(RecentsAnimationListener listener) {
55         Preconditions.assertUIThread();
56         mListeners.add(listener);
57     }
58 
59     @UiThread
removeListener(RecentsAnimationListener listener)60     public void removeListener(RecentsAnimationListener listener) {
61         Preconditions.assertUIThread();
62         mListeners.remove(listener);
63     }
64 
65     @UiThread
removeAllListeners()66     public void removeAllListeners() {
67         Preconditions.assertUIThread();
68         mListeners.clear();
69     }
70 
notifyAnimationCanceled()71     public void notifyAnimationCanceled() {
72         mCancelled = true;
73         onAnimationCanceled(null);
74     }
75 
76     // Called only in Q platform
77     @BinderThread
78     @Deprecated
onAnimationStart(RecentsAnimationControllerCompat controller, RemoteAnimationTargetCompat[] appTargets, Rect homeContentInsets, Rect minimizedHomeBounds)79     public final void onAnimationStart(RecentsAnimationControllerCompat controller,
80             RemoteAnimationTargetCompat[] appTargets, Rect homeContentInsets,
81             Rect minimizedHomeBounds) {
82         onAnimationStart(controller, appTargets, new RemoteAnimationTargetCompat[0],
83                 homeContentInsets, minimizedHomeBounds);
84     }
85 
86     // Called only in R+ platform
87     @BinderThread
onAnimationStart(RecentsAnimationControllerCompat animationController, RemoteAnimationTargetCompat[] appTargets, RemoteAnimationTargetCompat[] wallpaperTargets, Rect homeContentInsets, Rect minimizedHomeBounds)88     public final void onAnimationStart(RecentsAnimationControllerCompat animationController,
89             RemoteAnimationTargetCompat[] appTargets,
90             RemoteAnimationTargetCompat[] wallpaperTargets,
91             Rect homeContentInsets, Rect minimizedHomeBounds) {
92         RecentsAnimationTargets targets = new RecentsAnimationTargets(appTargets,
93                 wallpaperTargets, homeContentInsets, minimizedHomeBounds);
94         mController = new RecentsAnimationController(animationController,
95                 mAllowMinimizeSplitScreen, this::onAnimationFinished);
96 
97         if (mCancelled) {
98             Utilities.postAsyncCallback(MAIN_EXECUTOR.getHandler(),
99                     mController::finishAnimationToApp);
100         } else {
101             Utilities.postAsyncCallback(MAIN_EXECUTOR.getHandler(), () -> {
102                 for (RecentsAnimationListener listener : getListeners()) {
103                     listener.onRecentsAnimationStart(mController, targets);
104                 }
105             });
106         }
107     }
108 
109     @BinderThread
110     @Override
onAnimationCanceled(ThumbnailData thumbnailData)111     public final void onAnimationCanceled(ThumbnailData thumbnailData) {
112         Utilities.postAsyncCallback(MAIN_EXECUTOR.getHandler(), () -> {
113             for (RecentsAnimationListener listener : getListeners()) {
114                 listener.onRecentsAnimationCanceled(thumbnailData);
115             }
116         });
117     }
118 
119     @BinderThread
120     @Override
onTaskAppeared(RemoteAnimationTargetCompat app)121     public void onTaskAppeared(RemoteAnimationTargetCompat app) {
122         Utilities.postAsyncCallback(MAIN_EXECUTOR.getHandler(), () -> {
123             for (RecentsAnimationListener listener : getListeners()) {
124                 listener.onTaskAppeared(app);
125             }
126         });
127     }
128 
onAnimationFinished(RecentsAnimationController controller)129     private final void onAnimationFinished(RecentsAnimationController controller) {
130         Utilities.postAsyncCallback(MAIN_EXECUTOR.getHandler(), () -> {
131             for (RecentsAnimationListener listener : getListeners()) {
132                 listener.onRecentsAnimationFinished(controller);
133             }
134         });
135     }
136 
getListeners()137     private RecentsAnimationListener[] getListeners() {
138         return mListeners.toArray(new RecentsAnimationListener[mListeners.size()]);
139     }
140 
141     /**
142      * Listener for the recents animation callbacks.
143      */
144     public interface RecentsAnimationListener {
onRecentsAnimationStart(RecentsAnimationController controller, RecentsAnimationTargets targets)145         default void onRecentsAnimationStart(RecentsAnimationController controller,
146                 RecentsAnimationTargets targets) {}
147 
148         /**
149          * Callback from the system when the recents animation is canceled. {@param thumbnailData}
150          * is passed back for rendering screenshot to replace live tile.
151          */
onRecentsAnimationCanceled(ThumbnailData thumbnailData)152         default void onRecentsAnimationCanceled(ThumbnailData thumbnailData) {}
153 
154         /**
155          * Callback made whenever the recents animation is finished.
156          */
onRecentsAnimationFinished(RecentsAnimationController controller)157         default void onRecentsAnimationFinished(RecentsAnimationController controller) {}
158 
159         /**
160          * Callback made when a task started from the recents is ready for an app transition.
161          */
onTaskAppeared(RemoteAnimationTargetCompat appearedTaskTarget)162         default void onTaskAppeared(RemoteAnimationTargetCompat appearedTaskTarget) {}
163     }
164 }
165