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