1 /*
2  * Copyright (C) 2021 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 
17 package com.android.server.wm;
18 
19 import static android.window.TaskFragmentOrganizer.putExceptionInBundle;
20 
21 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_ORGANIZER;
22 import static com.android.server.wm.WindowOrganizerController.configurationsAreEqualForOrganizer;
23 
24 import android.annotation.IntDef;
25 import android.annotation.NonNull;
26 import android.annotation.Nullable;
27 import android.content.res.Configuration;
28 import android.graphics.Rect;
29 import android.os.Binder;
30 import android.os.Bundle;
31 import android.os.IBinder;
32 import android.os.RemoteException;
33 import android.util.ArrayMap;
34 import android.util.Slog;
35 import android.view.RemoteAnimationDefinition;
36 import android.window.ITaskFragmentOrganizer;
37 import android.window.ITaskFragmentOrganizerController;
38 import android.window.TaskFragmentInfo;
39 
40 import com.android.internal.protolog.common.ProtoLog;
41 
42 import java.lang.annotation.Retention;
43 import java.lang.annotation.RetentionPolicy;
44 import java.util.ArrayList;
45 import java.util.Map;
46 import java.util.WeakHashMap;
47 
48 /**
49  * Stores and manages the client {@link android.window.TaskFragmentOrganizer}.
50  */
51 public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerController.Stub {
52     private static final String TAG = "TaskFragmentOrganizerController";
53 
54     private final ActivityTaskManagerService mAtmService;
55     private final WindowManagerGlobalLock mGlobalLock;
56     /**
57      * A Map which manages the relationship between
58      * {@link ITaskFragmentOrganizer} and {@link TaskFragmentOrganizerState}
59      */
60     private final ArrayMap<IBinder, TaskFragmentOrganizerState> mTaskFragmentOrganizerState =
61             new ArrayMap<>();
62     /**
63      * A List which manages the TaskFragment pending event {@link PendingTaskFragmentEvent}
64      */
65     private final ArrayList<PendingTaskFragmentEvent> mPendingTaskFragmentEvents =
66             new ArrayList<>();
67 
TaskFragmentOrganizerController(ActivityTaskManagerService atm)68     TaskFragmentOrganizerController(ActivityTaskManagerService atm) {
69         mAtmService = atm;
70         mGlobalLock = atm.mGlobalLock;
71     }
72 
73     /**
74      * A class to manage {@link ITaskFragmentOrganizer} and its organized
75      * {@link TaskFragment TaskFragments}.
76      */
77     private class TaskFragmentOrganizerState implements IBinder.DeathRecipient {
78         private final ArrayList<TaskFragment> mOrganizedTaskFragments = new ArrayList<>();
79         private final ITaskFragmentOrganizer mOrganizer;
80         private final Map<TaskFragment, TaskFragmentInfo> mLastSentTaskFragmentInfos =
81                 new WeakHashMap<>();
82         private final Map<TaskFragment, Configuration> mLastSentTaskFragmentParentConfigs =
83                 new WeakHashMap<>();
84 
85         /**
86          * @see android.window.TaskFragmentOrganizer#registerRemoteAnimations(
87          * RemoteAnimationDefinition)
88          */
89         @Nullable
90         private RemoteAnimationDefinition mRemoteAnimationDefinition;
91 
TaskFragmentOrganizerState(ITaskFragmentOrganizer organizer)92         TaskFragmentOrganizerState(ITaskFragmentOrganizer organizer) {
93             mOrganizer = organizer;
94             try {
95                 mOrganizer.asBinder().linkToDeath(this, 0 /*flags*/);
96             } catch (RemoteException e) {
97                 Slog.e(TAG, "TaskFragmentOrganizer failed to register death recipient");
98             }
99         }
100 
101         @Override
binderDied()102         public void binderDied() {
103             synchronized (mGlobalLock) {
104                 removeOrganizer(mOrganizer);
105             }
106         }
107 
108         /**
109          * @return {@code true} if taskFragment is organized and not sent the appeared event before.
110          */
addTaskFragment(TaskFragment taskFragment)111         boolean addTaskFragment(TaskFragment taskFragment) {
112             if (taskFragment.mTaskFragmentAppearedSent) {
113                 return false;
114             }
115             if (mOrganizedTaskFragments.contains(taskFragment)) {
116                 return false;
117             }
118             mOrganizedTaskFragments.add(taskFragment);
119             return true;
120         }
121 
removeTaskFragment(TaskFragment taskFragment)122         void removeTaskFragment(TaskFragment taskFragment) {
123             mOrganizedTaskFragments.remove(taskFragment);
124         }
125 
dispose()126         void dispose() {
127             while (!mOrganizedTaskFragments.isEmpty()) {
128                 final TaskFragment taskFragment = mOrganizedTaskFragments.get(0);
129                 taskFragment.removeImmediately();
130                 mOrganizedTaskFragments.remove(taskFragment);
131             }
132             mOrganizer.asBinder().unlinkToDeath(this, 0 /*flags*/);
133         }
134 
onTaskFragmentAppeared(ITaskFragmentOrganizer organizer, TaskFragment tf)135         void onTaskFragmentAppeared(ITaskFragmentOrganizer organizer, TaskFragment tf) {
136             ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "TaskFragment appeared name=%s", tf.getName());
137             final TaskFragmentInfo info = tf.getTaskFragmentInfo();
138             try {
139                 organizer.onTaskFragmentAppeared(info);
140                 mLastSentTaskFragmentInfos.put(tf, info);
141                 tf.mTaskFragmentAppearedSent = true;
142             } catch (RemoteException e) {
143                 Slog.e(TAG, "Exception sending onTaskFragmentAppeared callback", e);
144             }
145             onTaskFragmentParentInfoChanged(organizer, tf);
146         }
147 
onTaskFragmentVanished(ITaskFragmentOrganizer organizer, TaskFragment tf)148         void onTaskFragmentVanished(ITaskFragmentOrganizer organizer, TaskFragment tf) {
149             ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "TaskFragment vanished name=%s", tf.getName());
150             try {
151                 organizer.onTaskFragmentVanished(tf.getTaskFragmentInfo());
152             } catch (RemoteException e) {
153                 Slog.e(TAG, "Exception sending onTaskFragmentVanished callback", e);
154             }
155             tf.mTaskFragmentAppearedSent = false;
156             mLastSentTaskFragmentInfos.remove(tf);
157             mLastSentTaskFragmentParentConfigs.remove(tf);
158         }
159 
onTaskFragmentInfoChanged(ITaskFragmentOrganizer organizer, TaskFragment tf)160         void onTaskFragmentInfoChanged(ITaskFragmentOrganizer organizer, TaskFragment tf) {
161             // Parent config may have changed. The controller will check if there is any important
162             // config change for the organizer.
163             onTaskFragmentParentInfoChanged(organizer, tf);
164 
165             // Check if the info is different from the last reported info.
166             final TaskFragmentInfo info = tf.getTaskFragmentInfo();
167             final TaskFragmentInfo lastInfo = mLastSentTaskFragmentInfos.get(tf);
168             if (info.equalsForTaskFragmentOrganizer(lastInfo) && configurationsAreEqualForOrganizer(
169                     info.getConfiguration(), lastInfo.getConfiguration())) {
170                 return;
171             }
172             ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "TaskFragment info changed name=%s",
173                     tf.getName());
174             try {
175                 organizer.onTaskFragmentInfoChanged(tf.getTaskFragmentInfo());
176                 mLastSentTaskFragmentInfos.put(tf, info);
177             } catch (RemoteException e) {
178                 Slog.e(TAG, "Exception sending onTaskFragmentInfoChanged callback", e);
179             }
180         }
181 
onTaskFragmentParentInfoChanged(ITaskFragmentOrganizer organizer, TaskFragment tf)182         void onTaskFragmentParentInfoChanged(ITaskFragmentOrganizer organizer, TaskFragment tf) {
183             // Check if the parent info is different from the last reported parent info.
184             if (tf.getParent() == null || tf.getParent().asTask() == null) {
185                 mLastSentTaskFragmentParentConfigs.remove(tf);
186                 return;
187             }
188             final Task parent = tf.getParent().asTask();
189             final Configuration parentConfig = parent.getConfiguration();
190             final Configuration lastParentConfig = mLastSentTaskFragmentParentConfigs.get(tf);
191             if (configurationsAreEqualForOrganizer(parentConfig, lastParentConfig)) {
192                 return;
193             }
194             ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER,
195                     "TaskFragment parent info changed name=%s parentTaskId=%d",
196                     tf.getName(), parent.mTaskId);
197             try {
198                 organizer.onTaskFragmentParentInfoChanged(tf.getFragmentToken(), parentConfig);
199                 mLastSentTaskFragmentParentConfigs.put(tf, new Configuration(parentConfig));
200             } catch (RemoteException e) {
201                 Slog.e(TAG, "Exception sending onTaskFragmentParentInfoChanged callback", e);
202             }
203         }
204 
onTaskFragmentError(ITaskFragmentOrganizer organizer, IBinder errorCallbackToken, Throwable exception)205         void onTaskFragmentError(ITaskFragmentOrganizer organizer, IBinder errorCallbackToken,
206                 Throwable exception) {
207             ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER,
208                     "Sending TaskFragment error exception=%s", exception.toString());
209             final Bundle exceptionBundle = putExceptionInBundle(exception);
210             try {
211                 organizer.onTaskFragmentError(errorCallbackToken, exceptionBundle);
212             } catch (RemoteException e) {
213                 Slog.e(TAG, "Exception sending onTaskFragmentError callback", e);
214             }
215         }
216     }
217 
218     @Override
registerOrganizer(ITaskFragmentOrganizer organizer)219     public void registerOrganizer(ITaskFragmentOrganizer organizer) {
220         final int pid = Binder.getCallingPid();
221         final long uid = Binder.getCallingUid();
222         synchronized (mGlobalLock) {
223             ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER,
224                     "Register task fragment organizer=%s uid=%d pid=%d",
225                     organizer.asBinder(), uid, pid);
226             if (mTaskFragmentOrganizerState.containsKey(organizer.asBinder())) {
227                 throw new IllegalStateException(
228                         "Replacing existing organizer currently unsupported");
229             }
230             mTaskFragmentOrganizerState.put(organizer.asBinder(),
231                     new TaskFragmentOrganizerState(organizer));
232         }
233     }
234 
235     @Override
unregisterOrganizer(ITaskFragmentOrganizer organizer)236     public void unregisterOrganizer(ITaskFragmentOrganizer organizer) {
237         validateAndGetState(organizer);
238         final int pid = Binder.getCallingPid();
239         final long uid = Binder.getCallingUid();
240         final long origId = Binder.clearCallingIdentity();
241         try {
242             synchronized (mGlobalLock) {
243                 ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER,
244                         "Unregister task fragment organizer=%s uid=%d pid=%d",
245                         organizer.asBinder(), uid, pid);
246                 removeOrganizer(organizer);
247             }
248         } finally {
249             Binder.restoreCallingIdentity(origId);
250         }
251     }
252 
253     @Override
registerRemoteAnimations(ITaskFragmentOrganizer organizer, RemoteAnimationDefinition definition)254     public void registerRemoteAnimations(ITaskFragmentOrganizer organizer,
255             RemoteAnimationDefinition definition) {
256         final int pid = Binder.getCallingPid();
257         final int uid = Binder.getCallingUid();
258         synchronized (mGlobalLock) {
259             ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER,
260                     "Register remote animations for organizer=%s uid=%d pid=%d",
261                     organizer.asBinder(), uid, pid);
262             final TaskFragmentOrganizerState organizerState =
263                     mTaskFragmentOrganizerState.get(organizer.asBinder());
264             if (organizerState == null) {
265                 throw new IllegalStateException("The organizer hasn't been registered.");
266             }
267             if (organizerState.mRemoteAnimationDefinition != null) {
268                 throw new IllegalStateException(
269                         "The organizer has already registered remote animations="
270                                 + organizerState.mRemoteAnimationDefinition);
271             }
272 
273             definition.setCallingPidUid(pid, uid);
274             organizerState.mRemoteAnimationDefinition = definition;
275         }
276     }
277 
278     @Override
unregisterRemoteAnimations(ITaskFragmentOrganizer organizer)279     public void unregisterRemoteAnimations(ITaskFragmentOrganizer organizer) {
280         final int pid = Binder.getCallingPid();
281         final long uid = Binder.getCallingUid();
282         synchronized (mGlobalLock) {
283             ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER,
284                     "Unregister remote animations for organizer=%s uid=%d pid=%d",
285                     organizer.asBinder(), uid, pid);
286             final TaskFragmentOrganizerState organizerState =
287                     mTaskFragmentOrganizerState.get(organizer.asBinder());
288             if (organizerState == null) {
289                 Slog.e(TAG, "The organizer hasn't been registered.");
290                 return;
291             }
292 
293             organizerState.mRemoteAnimationDefinition = null;
294         }
295     }
296 
297     /** Gets the {@link RemoteAnimationDefinition} set on the given organizer if exists. */
298     @Nullable
getRemoteAnimationDefinition( ITaskFragmentOrganizer organizer)299     public RemoteAnimationDefinition getRemoteAnimationDefinition(
300             ITaskFragmentOrganizer organizer) {
301         synchronized (mGlobalLock) {
302             final TaskFragmentOrganizerState organizerState =
303                     mTaskFragmentOrganizerState.get(organizer.asBinder());
304             return organizerState != null ? organizerState.mRemoteAnimationDefinition : null;
305         }
306     }
307 
onTaskFragmentAppeared(ITaskFragmentOrganizer organizer, TaskFragment taskFragment)308     void onTaskFragmentAppeared(ITaskFragmentOrganizer organizer, TaskFragment taskFragment) {
309         final TaskFragmentOrganizerState state = validateAndGetState(organizer);
310         if (!state.addTaskFragment(taskFragment)) {
311             return;
312         }
313         PendingTaskFragmentEvent pendingEvent = getPendingTaskFragmentEvent(taskFragment,
314                 PendingTaskFragmentEvent.EVENT_APPEARED);
315         if (pendingEvent == null) {
316             pendingEvent = new PendingTaskFragmentEvent(taskFragment, organizer,
317                     PendingTaskFragmentEvent.EVENT_APPEARED);
318             mPendingTaskFragmentEvents.add(pendingEvent);
319         }
320     }
321 
onTaskFragmentInfoChanged(ITaskFragmentOrganizer organizer, TaskFragment taskFragment)322     void onTaskFragmentInfoChanged(ITaskFragmentOrganizer organizer, TaskFragment taskFragment) {
323         handleTaskFragmentInfoChanged(organizer, taskFragment,
324                 PendingTaskFragmentEvent.EVENT_INFO_CHANGED);
325     }
326 
onTaskFragmentParentInfoChanged(ITaskFragmentOrganizer organizer, TaskFragment taskFragment)327     void onTaskFragmentParentInfoChanged(ITaskFragmentOrganizer organizer,
328             TaskFragment taskFragment) {
329         handleTaskFragmentInfoChanged(organizer, taskFragment,
330                 PendingTaskFragmentEvent.EVENT_PARENT_INFO_CHANGED);
331     }
332 
handleTaskFragmentInfoChanged(ITaskFragmentOrganizer organizer, TaskFragment taskFragment, int eventType)333     private void handleTaskFragmentInfoChanged(ITaskFragmentOrganizer organizer,
334             TaskFragment taskFragment, int eventType) {
335         validateAndGetState(organizer);
336         if (!taskFragment.mTaskFragmentAppearedSent) {
337             // Skip if TaskFragment still not appeared.
338             return;
339         }
340         PendingTaskFragmentEvent pendingEvent = getLastPendingLifecycleEvent(taskFragment);
341         if (pendingEvent == null) {
342             pendingEvent = new PendingTaskFragmentEvent(taskFragment, organizer, eventType);
343         } else {
344             if (pendingEvent.mEventType == PendingTaskFragmentEvent.EVENT_VANISHED) {
345                 // Skipped the info changed event if vanished event is pending.
346                 return;
347             }
348             // Remove and add for re-ordering.
349             mPendingTaskFragmentEvents.remove(pendingEvent);
350         }
351         mPendingTaskFragmentEvents.add(pendingEvent);
352     }
353 
onTaskFragmentVanished(ITaskFragmentOrganizer organizer, TaskFragment taskFragment)354     void onTaskFragmentVanished(ITaskFragmentOrganizer organizer, TaskFragment taskFragment) {
355         final TaskFragmentOrganizerState state = validateAndGetState(organizer);
356         for (int i = mPendingTaskFragmentEvents.size() - 1; i >= 0; i--) {
357             PendingTaskFragmentEvent entry = mPendingTaskFragmentEvents.get(i);
358             if (taskFragment == entry.mTaskFragment) {
359                 mPendingTaskFragmentEvents.remove(i);
360                 if (entry.mEventType == PendingTaskFragmentEvent.EVENT_APPEARED) {
361                     // If taskFragment appeared callback is pending, ignore the vanished request.
362                     return;
363                 }
364             }
365         }
366         if (!taskFragment.mTaskFragmentAppearedSent) {
367             return;
368         }
369         PendingTaskFragmentEvent pendingEvent = new PendingTaskFragmentEvent(taskFragment,
370                 organizer, PendingTaskFragmentEvent.EVENT_VANISHED);
371         mPendingTaskFragmentEvents.add(pendingEvent);
372         state.removeTaskFragment(taskFragment);
373     }
374 
onTaskFragmentError(ITaskFragmentOrganizer organizer, IBinder errorCallbackToken, Throwable exception)375     void onTaskFragmentError(ITaskFragmentOrganizer organizer, IBinder errorCallbackToken,
376             Throwable exception) {
377         validateAndGetState(organizer);
378         Slog.w(TAG, "onTaskFragmentError ", exception);
379         PendingTaskFragmentEvent pendingEvent = new PendingTaskFragmentEvent(organizer,
380                 errorCallbackToken, exception, PendingTaskFragmentEvent.EVENT_ERROR);
381         mPendingTaskFragmentEvents.add(pendingEvent);
382     }
383 
removeOrganizer(ITaskFragmentOrganizer organizer)384     private void removeOrganizer(ITaskFragmentOrganizer organizer) {
385         final TaskFragmentOrganizerState state = validateAndGetState(organizer);
386         // remove all of the children of the organized TaskFragment
387         state.dispose();
388         mTaskFragmentOrganizerState.remove(organizer.asBinder());
389     }
390 
391     /**
392      * Makes sure that the organizer has been correctly registered to prevent any Sidecar
393      * implementation from organizing {@link TaskFragment} without registering first. In such case,
394      * we wouldn't register {@link DeathRecipient} for the organizer, and might not remove the
395      * {@link TaskFragment} after the organizer process died.
396      */
validateAndGetState(ITaskFragmentOrganizer organizer)397     private TaskFragmentOrganizerState validateAndGetState(ITaskFragmentOrganizer organizer) {
398         final TaskFragmentOrganizerState state =
399                 mTaskFragmentOrganizerState.get(organizer.asBinder());
400         if (state == null) {
401             throw new IllegalArgumentException(
402                     "TaskFragmentOrganizer has not been registered. Organizer=" + organizer);
403         }
404         return state;
405     }
406 
407     /**
408      * A class to store {@link ITaskFragmentOrganizer} and its organized
409      * {@link TaskFragment TaskFragments} with different pending event request.
410      */
411     private static class PendingTaskFragmentEvent {
412         static final int EVENT_APPEARED = 0;
413         static final int EVENT_VANISHED = 1;
414         static final int EVENT_INFO_CHANGED = 2;
415         static final int EVENT_PARENT_INFO_CHANGED = 3;
416         static final int EVENT_ERROR = 4;
417 
418         @IntDef(prefix = "EVENT_", value = {
419                 EVENT_APPEARED,
420                 EVENT_VANISHED,
421                 EVENT_INFO_CHANGED,
422                 EVENT_PARENT_INFO_CHANGED,
423                 EVENT_ERROR
424         })
425         @Retention(RetentionPolicy.SOURCE)
426         public @interface EventType {}
427 
428         @EventType
429         private final int mEventType;
430         private final ITaskFragmentOrganizer mTaskFragmentOrg;
431         private final TaskFragment mTaskFragment;
432         private final IBinder mErrorCallback;
433         private final Throwable mException;
434         // Set when the event is deferred due to the host task is invisible. The defer time will
435         // be the last active time of the host task.
436         private long mDeferTime;
437 
PendingTaskFragmentEvent(TaskFragment taskFragment, ITaskFragmentOrganizer taskFragmentOrg, @EventType int eventType)438         private PendingTaskFragmentEvent(TaskFragment taskFragment,
439                 ITaskFragmentOrganizer taskFragmentOrg, @EventType int eventType) {
440             this(taskFragment, taskFragmentOrg, null /* errorCallback */,
441                     null /* exception */, eventType);
442 
443         }
444 
PendingTaskFragmentEvent(ITaskFragmentOrganizer taskFragmentOrg, IBinder errorCallback, Throwable exception, @EventType int eventType)445         private PendingTaskFragmentEvent(ITaskFragmentOrganizer taskFragmentOrg,
446                 IBinder errorCallback, Throwable exception, @EventType int eventType) {
447             this(null /* taskFragment */, taskFragmentOrg, errorCallback, exception,
448                     eventType);
449         }
450 
PendingTaskFragmentEvent(TaskFragment taskFragment, ITaskFragmentOrganizer taskFragmentOrg, IBinder errorCallback, Throwable exception, @EventType int eventType)451         private PendingTaskFragmentEvent(TaskFragment taskFragment,
452                 ITaskFragmentOrganizer taskFragmentOrg, IBinder errorCallback, Throwable exception,
453                 @EventType int eventType) {
454             mTaskFragment = taskFragment;
455             mTaskFragmentOrg = taskFragmentOrg;
456             mErrorCallback = errorCallback;
457             mException = exception;
458             mEventType = eventType;
459         }
460 
461         /**
462          * @return {@code true} if the pending event is related with taskFragment created, vanished
463          * and information changed.
464          */
isLifecycleEvent()465         boolean isLifecycleEvent() {
466             switch (mEventType) {
467                 case EVENT_APPEARED:
468                 case EVENT_VANISHED:
469                 case EVENT_INFO_CHANGED:
470                 case EVENT_PARENT_INFO_CHANGED:
471                     return true;
472                 default:
473                     return false;
474             }
475         }
476     }
477 
478     @Nullable
getLastPendingLifecycleEvent(TaskFragment tf)479     private PendingTaskFragmentEvent getLastPendingLifecycleEvent(TaskFragment tf) {
480         for (int i = mPendingTaskFragmentEvents.size() - 1; i >= 0; i--) {
481             PendingTaskFragmentEvent entry = mPendingTaskFragmentEvents.get(i);
482             if (tf == entry.mTaskFragment && entry.isLifecycleEvent()) {
483                 return entry;
484             }
485         }
486         return null;
487     }
488 
489     @Nullable
getPendingTaskFragmentEvent(TaskFragment taskFragment, int type)490     private PendingTaskFragmentEvent getPendingTaskFragmentEvent(TaskFragment taskFragment,
491             int type) {
492         for (int i = mPendingTaskFragmentEvents.size() - 1; i >= 0; i--) {
493             PendingTaskFragmentEvent entry = mPendingTaskFragmentEvents.get(i);
494             if (taskFragment == entry.mTaskFragment && type == entry.mEventType) {
495                 return entry;
496             }
497         }
498         return null;
499     }
500 
shouldSendEventWhenTaskInvisible(@onNull Task task, @NonNull PendingTaskFragmentEvent event)501     private boolean shouldSendEventWhenTaskInvisible(@NonNull Task task,
502             @NonNull PendingTaskFragmentEvent event) {
503         final TaskFragmentOrganizerState state =
504                 mTaskFragmentOrganizerState.get(event.mTaskFragmentOrg.asBinder());
505         final TaskFragmentInfo lastInfo = state.mLastSentTaskFragmentInfos.get(event.mTaskFragment);
506         final TaskFragmentInfo info = event.mTaskFragment.getTaskFragmentInfo();
507         // Send an info changed callback if this event is for the last activities to finish in a
508         // Task so that the {@link TaskFragmentOrganizer} can delete this TaskFragment. Otherwise,
509         // the Task may be removed before it becomes visible again to send this event because it no
510         // longer has activities. As a result, the organizer will never get this info changed event
511         // and will not delete the TaskFragment because the organizer thinks the TaskFragment still
512         // has running activities.
513         return event.mEventType == PendingTaskFragmentEvent.EVENT_INFO_CHANGED
514                 && task.topRunningActivity() == null && lastInfo != null
515                 && lastInfo.getRunningActivityCount() > 0 && info.getRunningActivityCount() == 0;
516     }
517 
dispatchPendingEvents()518     void dispatchPendingEvents() {
519         if (mAtmService.mWindowManager.mWindowPlacerLocked.isLayoutDeferred()
520                 || mPendingTaskFragmentEvents.isEmpty()) {
521             return;
522         }
523 
524         final ArrayList<Task> visibleTasks = new ArrayList<>();
525         final ArrayList<Task> invisibleTasks = new ArrayList<>();
526         final ArrayList<PendingTaskFragmentEvent> candidateEvents = new ArrayList<>();
527         for (int i = 0, n = mPendingTaskFragmentEvents.size(); i < n; i++) {
528             final PendingTaskFragmentEvent event = mPendingTaskFragmentEvents.get(i);
529             final Task task = event.mTaskFragment != null ? event.mTaskFragment.getTask() : null;
530             if (task != null && (task.lastActiveTime <= event.mDeferTime
531                     || !(isTaskVisible(task, visibleTasks, invisibleTasks)
532                     || shouldSendEventWhenTaskInvisible(task, event)))) {
533                 // Defer sending events to the TaskFragment until the host task is active again.
534                 event.mDeferTime = task.lastActiveTime;
535                 continue;
536             }
537             candidateEvents.add(event);
538         }
539         final int numEvents = candidateEvents.size();
540         for (int i = 0; i < numEvents; i++) {
541             dispatchEvent(candidateEvents.get(i));
542         }
543         if (numEvents > 0) {
544             mPendingTaskFragmentEvents.removeAll(candidateEvents);
545         }
546     }
547 
isTaskVisible(Task task, ArrayList<Task> knownVisibleTasks, ArrayList<Task> knownInvisibleTasks)548     private static boolean isTaskVisible(Task task, ArrayList<Task> knownVisibleTasks,
549             ArrayList<Task> knownInvisibleTasks) {
550         if (knownVisibleTasks.contains(task)) {
551             return true;
552         }
553         if (knownInvisibleTasks.contains(task)) {
554             return false;
555         }
556         if (task.shouldBeVisible(null /* starting */)) {
557             knownVisibleTasks.add(task);
558             return true;
559         } else {
560             knownInvisibleTasks.add(task);
561             return false;
562         }
563     }
564 
dispatchPendingInfoChangedEvent(TaskFragment taskFragment)565     void dispatchPendingInfoChangedEvent(TaskFragment taskFragment) {
566         PendingTaskFragmentEvent event = getPendingTaskFragmentEvent(taskFragment,
567                 PendingTaskFragmentEvent.EVENT_INFO_CHANGED);
568         if (event == null) {
569             return;
570         }
571 
572         dispatchEvent(event);
573         mPendingTaskFragmentEvents.remove(event);
574     }
575 
dispatchEvent(PendingTaskFragmentEvent event)576     private void dispatchEvent(PendingTaskFragmentEvent event) {
577         final ITaskFragmentOrganizer taskFragmentOrg = event.mTaskFragmentOrg;
578         final TaskFragment taskFragment = event.mTaskFragment;
579         final TaskFragmentOrganizerState state =
580                 mTaskFragmentOrganizerState.get(taskFragmentOrg.asBinder());
581         if (state == null) {
582             return;
583         }
584         switch (event.mEventType) {
585             case PendingTaskFragmentEvent.EVENT_APPEARED:
586                 state.onTaskFragmentAppeared(taskFragmentOrg, taskFragment);
587                 break;
588             case PendingTaskFragmentEvent.EVENT_VANISHED:
589                 state.onTaskFragmentVanished(taskFragmentOrg, taskFragment);
590                 break;
591             case PendingTaskFragmentEvent.EVENT_INFO_CHANGED:
592                 state.onTaskFragmentInfoChanged(taskFragmentOrg, taskFragment);
593                 break;
594             case PendingTaskFragmentEvent.EVENT_PARENT_INFO_CHANGED:
595                 state.onTaskFragmentParentInfoChanged(taskFragmentOrg, taskFragment);
596                 break;
597             case PendingTaskFragmentEvent.EVENT_ERROR:
598                 state.onTaskFragmentError(taskFragmentOrg, event.mErrorCallback,
599                         event.mException);
600         }
601     }
602 
603     // TODO(b/204399167): change to push the embedded state to the client side
604     @Override
isActivityEmbedded(IBinder activityToken)605     public boolean isActivityEmbedded(IBinder activityToken) {
606         synchronized (mGlobalLock) {
607             final ActivityRecord activity = ActivityRecord.forTokenLocked(activityToken);
608             if (activity == null) {
609                 return false;
610             }
611             final TaskFragment taskFragment = activity.getOrganizedTaskFragment();
612             if (taskFragment == null) {
613                 return false;
614             }
615             final Task parentTask = taskFragment.getTask();
616             if (parentTask != null) {
617                 final Rect taskBounds = parentTask.getBounds();
618                 final Rect taskFragBounds = taskFragment.getBounds();
619                 return !taskBounds.equals(taskFragBounds) && taskBounds.contains(taskFragBounds);
620             }
621             return false;
622         }
623     }
624 }
625