• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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 android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
19 
20 import static com.android.quickstep.TaskAnimationManager.ENABLE_SHELL_TRANSITIONS;
21 
22 import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
23 
24 import java.util.ArrayList;
25 import java.util.concurrent.CopyOnWriteArrayList;
26 
27 /**
28  * Holds a collection of RemoteAnimationTargets, filtered by different properties.
29  */
30 public class RemoteAnimationTargets {
31 
32     private final CopyOnWriteArrayList<ReleaseCheck> mReleaseChecks = new CopyOnWriteArrayList<>();
33 
34     public final RemoteAnimationTargetCompat[] unfilteredApps;
35     public final RemoteAnimationTargetCompat[] apps;
36     public final RemoteAnimationTargetCompat[] wallpapers;
37     public final RemoteAnimationTargetCompat[] nonApps;
38     public final int targetMode;
39     public final boolean hasRecents;
40 
41     private boolean mReleased = false;
42 
RemoteAnimationTargets(RemoteAnimationTargetCompat[] apps, RemoteAnimationTargetCompat[] wallpapers, RemoteAnimationTargetCompat[] nonApps, int targetMode)43     public RemoteAnimationTargets(RemoteAnimationTargetCompat[] apps,
44             RemoteAnimationTargetCompat[] wallpapers, RemoteAnimationTargetCompat[] nonApps,
45             int targetMode) {
46         ArrayList<RemoteAnimationTargetCompat> filteredApps = new ArrayList<>();
47         boolean hasRecents = false;
48         if (apps != null) {
49             for (RemoteAnimationTargetCompat target : apps) {
50                 if (target.mode == targetMode) {
51                     filteredApps.add(target);
52                 }
53 
54                 hasRecents |= target.activityType ==
55                         RemoteAnimationTargetCompat.ACTIVITY_TYPE_RECENTS;
56             }
57         }
58 
59         this.unfilteredApps = apps;
60         this.apps = filteredApps.toArray(new RemoteAnimationTargetCompat[filteredApps.size()]);
61         this.wallpapers = wallpapers;
62         this.targetMode = targetMode;
63         this.hasRecents = hasRecents;
64         this.nonApps = nonApps;
65     }
66 
findTask(int taskId)67     public RemoteAnimationTargetCompat findTask(int taskId) {
68         for (RemoteAnimationTargetCompat target : apps) {
69             if (target.taskId == taskId) {
70                 return target;
71             }
72         }
73         return null;
74     }
75 
76     /**
77      * Gets the navigation bar remote animation target if exists.
78      */
getNavBarRemoteAnimationTarget()79     public RemoteAnimationTargetCompat getNavBarRemoteAnimationTarget() {
80         for (RemoteAnimationTargetCompat target : nonApps) {
81             if (target.windowType == TYPE_NAVIGATION_BAR) {
82                 return target;
83             }
84         }
85         return null;
86     }
87 
88     /** Returns the first opening app target. */
getFirstAppTarget()89     public RemoteAnimationTargetCompat getFirstAppTarget() {
90         return apps.length > 0 ? apps[0] : null;
91     }
92 
93     /** Returns the task id of the first opening app target, or -1 if none is found. */
getFirstAppTargetTaskId()94     public int getFirstAppTargetTaskId() {
95         RemoteAnimationTargetCompat target = getFirstAppTarget();
96         return target == null ? -1 : target.taskId;
97     }
98 
isAnimatingHome()99     public boolean isAnimatingHome() {
100         for (RemoteAnimationTargetCompat target : unfilteredApps) {
101             if (target.activityType == RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME) {
102                 return true;
103             }
104         }
105         return false;
106     }
107 
addReleaseCheck(ReleaseCheck check)108     public void addReleaseCheck(ReleaseCheck check) {
109         mReleaseChecks.add(check);
110     }
111 
release()112     public void release() {
113         if (ENABLE_SHELL_TRANSITIONS) {
114             mReleaseChecks.clear();
115             return;
116         }
117         if (mReleased) {
118             return;
119         }
120         for (ReleaseCheck check : mReleaseChecks) {
121             if (!check.mCanRelease) {
122                 check.addOnSafeToReleaseCallback(this::release);
123                 return;
124             }
125         }
126         mReleaseChecks.clear();
127         mReleased = true;
128 
129         for (RemoteAnimationTargetCompat target : unfilteredApps) {
130             target.release();
131         }
132         for (RemoteAnimationTargetCompat target : wallpapers) {
133             target.release();
134         }
135         for (RemoteAnimationTargetCompat target : nonApps) {
136             target.release();
137         }
138     }
139 
140     /**
141      * Interface for intercepting surface release method
142      */
143     public static class ReleaseCheck {
144 
145         boolean mCanRelease = false;
146         private Runnable mAfterApplyCallback;
147 
setCanRelease(boolean canRelease)148         protected void setCanRelease(boolean canRelease) {
149             mCanRelease = canRelease;
150             if (mCanRelease && mAfterApplyCallback != null) {
151                 Runnable r = mAfterApplyCallback;
152                 mAfterApplyCallback = null;
153                 r.run();
154             }
155         }
156 
157         /**
158          * Adds a callback to notify when the surface can safely be released
159          */
addOnSafeToReleaseCallback(Runnable callback)160         void addOnSafeToReleaseCallback(Runnable callback) {
161             if (mCanRelease) {
162                 callback.run();
163             } else {
164                 if (mAfterApplyCallback == null) {
165                     mAfterApplyCallback = callback;
166                 } else {
167                     final Runnable oldCallback = mAfterApplyCallback;
168                     mAfterApplyCallback = () -> {
169                         callback.run();
170                         oldCallback.run();
171                     };
172                 }
173             }
174         }
175     }
176 }
177