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.app.ActivityTaskManager.INVALID_TASK_ID;
20 import static android.window.TaskFragmentOrganizer.putErrorInfoInBundle;
21 import static android.window.TaskFragmentTransaction.TYPE_ACTIVITY_REPARENTED_TO_TASK;
22 import static android.window.TaskFragmentTransaction.TYPE_TASK_FRAGMENT_APPEARED;
23 import static android.window.TaskFragmentTransaction.TYPE_TASK_FRAGMENT_ERROR;
24 import static android.window.TaskFragmentTransaction.TYPE_TASK_FRAGMENT_INFO_CHANGED;
25 import static android.window.TaskFragmentTransaction.TYPE_TASK_FRAGMENT_PARENT_INFO_CHANGED;
26 import static android.window.TaskFragmentTransaction.TYPE_TASK_FRAGMENT_VANISHED;
27 
28 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_ORGANIZER;
29 import static com.android.server.wm.TaskFragment.EMBEDDING_ALLOWED;
30 import static com.android.server.wm.WindowOrganizerController.configurationsAreEqualForOrganizer;
31 
32 import static java.util.Objects.requireNonNull;
33 
34 import android.annotation.IntDef;
35 import android.annotation.NonNull;
36 import android.annotation.Nullable;
37 import android.content.Intent;
38 import android.content.res.Configuration;
39 import android.os.Binder;
40 import android.os.Bundle;
41 import android.os.IBinder;
42 import android.os.RemoteException;
43 import android.util.ArrayMap;
44 import android.util.ArraySet;
45 import android.util.Slog;
46 import android.util.SparseArray;
47 import android.view.RemoteAnimationDefinition;
48 import android.view.WindowManager;
49 import android.window.ITaskFragmentOrganizer;
50 import android.window.ITaskFragmentOrganizerController;
51 import android.window.TaskFragmentInfo;
52 import android.window.TaskFragmentOperation;
53 import android.window.TaskFragmentParentInfo;
54 import android.window.TaskFragmentTransaction;
55 import android.window.WindowContainerTransaction;
56 
57 import com.android.internal.protolog.ProtoLogGroup;
58 import com.android.internal.protolog.common.ProtoLog;
59 
60 import java.lang.annotation.Retention;
61 import java.lang.annotation.RetentionPolicy;
62 import java.util.ArrayList;
63 import java.util.List;
64 import java.util.Map;
65 import java.util.WeakHashMap;
66 
67 /**
68  * Stores and manages the client {@link android.window.TaskFragmentOrganizer}.
69  */
70 public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerController.Stub {
71     private static final String TAG = "TaskFragmentOrganizerController";
72     private static final long TEMPORARY_ACTIVITY_TOKEN_TIMEOUT_MS = 5000;
73 
74     private final ActivityTaskManagerService mAtmService;
75     private final WindowManagerGlobalLock mGlobalLock;
76     private final WindowOrganizerController mWindowOrganizerController;
77 
78     /**
79      * A Map which manages the relationship between
80      * {@link ITaskFragmentOrganizer} and {@link TaskFragmentOrganizerState}
81      */
82     private final ArrayMap<IBinder, TaskFragmentOrganizerState> mTaskFragmentOrganizerState =
83             new ArrayMap<>();
84     /**
85      * Map from {@link ITaskFragmentOrganizer} to a list of related {@link PendingTaskFragmentEvent}
86      */
87     private final ArrayMap<IBinder, List<PendingTaskFragmentEvent>> mPendingTaskFragmentEvents =
88             new ArrayMap<>();
89 
90     private final ArraySet<Task> mTmpTaskSet = new ArraySet<>();
91 
TaskFragmentOrganizerController(@onNull ActivityTaskManagerService atm, @NonNull WindowOrganizerController windowOrganizerController)92     TaskFragmentOrganizerController(@NonNull ActivityTaskManagerService atm,
93             @NonNull WindowOrganizerController windowOrganizerController) {
94         mAtmService = requireNonNull(atm);
95         mGlobalLock = atm.mGlobalLock;
96         mWindowOrganizerController = requireNonNull(windowOrganizerController);
97     }
98 
99     /**
100      * A class to manage {@link ITaskFragmentOrganizer} and its organized
101      * {@link TaskFragment TaskFragments}.
102      */
103     private class TaskFragmentOrganizerState implements IBinder.DeathRecipient {
104         private final ArrayList<TaskFragment> mOrganizedTaskFragments = new ArrayList<>();
105         private final ITaskFragmentOrganizer mOrganizer;
106         private final int mOrganizerPid;
107         private final int mOrganizerUid;
108 
109         /**
110          * Map from {@link TaskFragment} to the last {@link TaskFragmentInfo} sent to the
111          * organizer.
112          */
113         private final Map<TaskFragment, TaskFragmentInfo> mLastSentTaskFragmentInfos =
114                 new WeakHashMap<>();
115 
116         /**
117          * Map from {@link TaskFragment} to its leaf {@link Task#mTaskId}. Embedded
118          * {@link TaskFragment} will not be reparented until it is removed.
119          */
120         private final Map<TaskFragment, Integer> mTaskFragmentTaskIds = new WeakHashMap<>();
121 
122         /**
123          * Map from {@link Task#mTaskId} to the last {@link TaskFragmentParentInfo} sent to the
124          * organizer.
125          */
126         private final SparseArray<TaskFragmentParentInfo> mLastSentTaskFragmentParentInfos =
127                 new SparseArray<>();
128 
129         /**
130          * Map from temporary activity token to the corresponding {@link ActivityRecord}.
131          */
132         private final Map<IBinder, ActivityRecord> mTemporaryActivityTokens =
133                 new WeakHashMap<>();
134 
135         /**
136          * {@link RemoteAnimationDefinition} for embedded activities transition animation that is
137          * organized by this organizer.
138          */
139         @Nullable
140         private RemoteAnimationDefinition mRemoteAnimationDefinition;
141 
142         /**
143          * Map from {@link TaskFragmentTransaction#getTransactionToken()} to the
144          * {@link Transition#getSyncId()} that has been deferred. {@link TransitionController} will
145          * wait until the organizer finished handling the {@link TaskFragmentTransaction}.
146          * @see #onTransactionFinished(IBinder)
147          */
148         private final ArrayMap<IBinder, Integer> mDeferredTransitions = new ArrayMap<>();
149 
TaskFragmentOrganizerState(ITaskFragmentOrganizer organizer, int pid, int uid)150         TaskFragmentOrganizerState(ITaskFragmentOrganizer organizer, int pid, int uid) {
151             mOrganizer = organizer;
152             mOrganizerPid = pid;
153             mOrganizerUid = uid;
154             try {
155                 mOrganizer.asBinder().linkToDeath(this, 0 /*flags*/);
156             } catch (RemoteException e) {
157                 Slog.e(TAG, "TaskFragmentOrganizer failed to register death recipient");
158             }
159         }
160 
161         @Override
binderDied()162         public void binderDied() {
163             synchronized (mGlobalLock) {
164                 removeOrganizer(mOrganizer);
165             }
166         }
167 
168         /**
169          * @return {@code true} if taskFragment is organized and not sent the appeared event before.
170          */
addTaskFragment(TaskFragment taskFragment)171         boolean addTaskFragment(TaskFragment taskFragment) {
172             if (taskFragment.mTaskFragmentAppearedSent) {
173                 return false;
174             }
175             if (mOrganizedTaskFragments.contains(taskFragment)) {
176                 return false;
177             }
178             mOrganizedTaskFragments.add(taskFragment);
179             return true;
180         }
181 
removeTaskFragment(TaskFragment taskFragment)182         void removeTaskFragment(TaskFragment taskFragment) {
183             mOrganizedTaskFragments.remove(taskFragment);
184         }
185 
dispose()186         void dispose() {
187             boolean wasVisible = false;
188             for (int i = mOrganizedTaskFragments.size() - 1; i >= 0; i--) {
189                 final TaskFragment taskFragment = mOrganizedTaskFragments.get(i);
190                 if (taskFragment.isVisibleRequested()) {
191                     wasVisible = true;
192                 }
193                 // Cleanup the TaskFragmentOrganizer from all TaskFragments it organized before
194                 // removing the windows to prevent it from adding any additional TaskFragment
195                 // pending event.
196                 taskFragment.onTaskFragmentOrganizerRemoved();
197             }
198 
199             final TransitionController transitionController = mAtmService.getTransitionController();
200             if (wasVisible && transitionController.isShellTransitionsEnabled()
201                     && !transitionController.isCollecting()) {
202                 final Task task = mOrganizedTaskFragments.get(0).getTask();
203                 final boolean containsNonEmbeddedActivity =
204                         task != null && task.getActivity(a -> !a.isEmbedded()) != null;
205                 transitionController.requestStartTransition(
206                         transitionController.createTransition(WindowManager.TRANSIT_CLOSE),
207                         // The task will be removed if all its activities are embedded, then the
208                         // task is the trigger.
209                         containsNonEmbeddedActivity ? null : task,
210                         null /* remoteTransition */, null /* displayChange */);
211             }
212             // Defer to avoid unnecessary layout when there are multiple TaskFragments removal.
213             mAtmService.deferWindowLayout();
214             try {
215                 while (!mOrganizedTaskFragments.isEmpty()) {
216                     final TaskFragment taskFragment = mOrganizedTaskFragments.remove(0);
217                     taskFragment.removeImmediately();
218                 }
219             } finally {
220                 mAtmService.continueWindowLayout();
221             }
222 
223             for (int i = mDeferredTransitions.size() - 1; i >= 0; i--) {
224                 // Cleanup any running transaction to unblock the current transition.
225                 onTransactionFinished(mDeferredTransitions.keyAt(i));
226             }
227             mOrganizer.asBinder().unlinkToDeath(this, 0 /* flags */);
228         }
229 
230         @NonNull
prepareTaskFragmentAppeared(@onNull TaskFragment tf)231         TaskFragmentTransaction.Change prepareTaskFragmentAppeared(@NonNull TaskFragment tf) {
232             ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "TaskFragment appeared name=%s", tf.getName());
233             final TaskFragmentInfo info = tf.getTaskFragmentInfo();
234             final int taskId = tf.getTask().mTaskId;
235             tf.mTaskFragmentAppearedSent = true;
236             mLastSentTaskFragmentInfos.put(tf, info);
237             mTaskFragmentTaskIds.put(tf, taskId);
238             return new TaskFragmentTransaction.Change(
239                     TYPE_TASK_FRAGMENT_APPEARED)
240                     .setTaskFragmentToken(tf.getFragmentToken())
241                     .setTaskFragmentInfo(info)
242                     .setTaskId(taskId);
243         }
244 
245         @NonNull
prepareTaskFragmentVanished(@onNull TaskFragment tf)246         TaskFragmentTransaction.Change prepareTaskFragmentVanished(@NonNull TaskFragment tf) {
247             ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "TaskFragment vanished name=%s", tf.getName());
248             tf.mTaskFragmentAppearedSent = false;
249             mLastSentTaskFragmentInfos.remove(tf);
250 
251             // Cleanup TaskFragmentParentConfig if this is the last TaskFragment in the Task.
252             final int taskId;
253             if (mTaskFragmentTaskIds.containsKey(tf)) {
254                 taskId = mTaskFragmentTaskIds.remove(tf);
255                 if (!mTaskFragmentTaskIds.containsValue(taskId)) {
256                     // No more TaskFragment in the Task.
257                     mLastSentTaskFragmentParentInfos.remove(taskId);
258                 }
259             } else {
260                 // This can happen if the appeared wasn't sent before remove.
261                 taskId = INVALID_TASK_ID;
262             }
263 
264             return new TaskFragmentTransaction.Change(TYPE_TASK_FRAGMENT_VANISHED)
265                     .setTaskFragmentToken(tf.getFragmentToken())
266                     .setTaskFragmentInfo(tf.getTaskFragmentInfo())
267                     .setTaskId(taskId);
268         }
269 
270         @Nullable
prepareTaskFragmentInfoChanged( @onNull TaskFragment tf)271         TaskFragmentTransaction.Change prepareTaskFragmentInfoChanged(
272                 @NonNull TaskFragment tf) {
273             // Check if the info is different from the last reported info.
274             final TaskFragmentInfo info = tf.getTaskFragmentInfo();
275             final TaskFragmentInfo lastInfo = mLastSentTaskFragmentInfos.get(tf);
276             if (info.equalsForTaskFragmentOrganizer(lastInfo) && configurationsAreEqualForOrganizer(
277                     info.getConfiguration(), lastInfo.getConfiguration())) {
278                 return null;
279             }
280 
281             ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "TaskFragment info changed name=%s",
282                     tf.getName());
283             mLastSentTaskFragmentInfos.put(tf, info);
284             return new TaskFragmentTransaction.Change(
285                     TYPE_TASK_FRAGMENT_INFO_CHANGED)
286                     .setTaskFragmentToken(tf.getFragmentToken())
287                     .setTaskFragmentInfo(info)
288                     .setTaskId(tf.getTask().mTaskId);
289         }
290 
291         @Nullable
prepareTaskFragmentParentInfoChanged(@onNull Task task)292         TaskFragmentTransaction.Change prepareTaskFragmentParentInfoChanged(@NonNull Task task) {
293             final int taskId = task.mTaskId;
294             // Check if the parent info is different from the last reported parent info.
295             final TaskFragmentParentInfo parentInfo = task.getTaskFragmentParentInfo();
296             final TaskFragmentParentInfo lastParentInfo = mLastSentTaskFragmentParentInfos
297                     .get(taskId);
298             final Configuration lastParentConfig = lastParentInfo != null
299                     ? lastParentInfo.getConfiguration() : null;
300             if (parentInfo.equalsForTaskFragmentOrganizer(lastParentInfo)
301                     && configurationsAreEqualForOrganizer(parentInfo.getConfiguration(),
302                             lastParentConfig)) {
303                 return null;
304             }
305 
306             ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER,
307                     "TaskFragment parent info changed name=%s parentTaskId=%d",
308                     task.getName(), taskId);
309             mLastSentTaskFragmentParentInfos.put(taskId, new TaskFragmentParentInfo(parentInfo));
310             return new TaskFragmentTransaction.Change(TYPE_TASK_FRAGMENT_PARENT_INFO_CHANGED)
311                     .setTaskId(taskId)
312                     .setTaskFragmentParentInfo(parentInfo);
313         }
314 
315         @NonNull
prepareTaskFragmentError( @ullable IBinder errorCallbackToken, @Nullable TaskFragment taskFragment, @TaskFragmentOperation.OperationType int opType, @NonNull Throwable exception)316         TaskFragmentTransaction.Change prepareTaskFragmentError(
317                 @Nullable IBinder errorCallbackToken, @Nullable TaskFragment taskFragment,
318                 @TaskFragmentOperation.OperationType int opType, @NonNull Throwable exception) {
319             ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER,
320                     "Sending TaskFragment error exception=%s", exception.toString());
321             final TaskFragmentInfo info =
322                     taskFragment != null ? taskFragment.getTaskFragmentInfo() : null;
323             final Bundle errorBundle = putErrorInfoInBundle(exception, info, opType);
324             return new TaskFragmentTransaction.Change(TYPE_TASK_FRAGMENT_ERROR)
325                     .setErrorCallbackToken(errorCallbackToken)
326                     .setErrorBundle(errorBundle);
327         }
328 
329         @Nullable
prepareActivityReparentedToTask( @onNull ActivityRecord activity)330         TaskFragmentTransaction.Change prepareActivityReparentedToTask(
331                 @NonNull ActivityRecord activity) {
332             if (activity.finishing) {
333                 Slog.d(TAG, "Reparent activity=" + activity.token + " is finishing");
334                 return null;
335             }
336             final Task task = activity.getTask();
337             if (task == null || task.effectiveUid != mOrganizerUid) {
338                 Slog.d(TAG, "Reparent activity=" + activity.token
339                         + " is not in a task belong to the organizer app.");
340                 return null;
341             }
342             if (task.isAllowedToEmbedActivity(activity, mOrganizerUid) != EMBEDDING_ALLOWED
343                     || !task.isAllowedToEmbedActivityInTrustedMode(activity, mOrganizerUid)) {
344                 Slog.d(TAG, "Reparent activity=" + activity.token
345                         + " is not allowed to be embedded in trusted mode.");
346                 return null;
347             }
348 
349             final IBinder activityToken;
350             if (activity.getPid() == mOrganizerPid) {
351                 // We only pass the actual token if the activity belongs to the organizer process.
352                 activityToken = activity.token;
353             } else {
354                 // For security, we can't pass the actual token if the activity belongs to a
355                 // different process. In this case, we will pass a temporary token that organizer
356                 // can use to reparent through WindowContainerTransaction.
357                 activityToken = new Binder("TemporaryActivityToken");
358                 mTemporaryActivityTokens.put(activityToken, activity);
359                 final Runnable timeout = () -> {
360                     synchronized (mGlobalLock) {
361                         mTemporaryActivityTokens.remove(activityToken);
362                     }
363                 };
364                 mAtmService.mWindowManager.mH.postDelayed(timeout,
365                         TEMPORARY_ACTIVITY_TOKEN_TIMEOUT_MS);
366             }
367             ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Activity=%s reparent to taskId=%d",
368                     activity.token, task.mTaskId);
369             return new TaskFragmentTransaction.Change(TYPE_ACTIVITY_REPARENTED_TO_TASK)
370                     .setTaskId(task.mTaskId)
371                     .setActivityIntent(trimIntent(activity.intent))
372                     .setActivityToken(activityToken);
373         }
374 
dispatchTransaction(@onNull TaskFragmentTransaction transaction)375         void dispatchTransaction(@NonNull TaskFragmentTransaction transaction) {
376             if (transaction.isEmpty()) {
377                 return;
378             }
379             try {
380                 mOrganizer.onTransactionReady(transaction);
381             } catch (RemoteException e) {
382                 Slog.d(TAG, "Exception sending TaskFragmentTransaction", e);
383                 return;
384             }
385             onTransactionStarted(transaction.getTransactionToken());
386         }
387 
388         /** Called when the transaction is sent to the organizer. */
onTransactionStarted(@onNull IBinder transactionToken)389         void onTransactionStarted(@NonNull IBinder transactionToken) {
390             if (!mWindowOrganizerController.getTransitionController().isCollecting()) {
391                 return;
392             }
393             final int transitionId = mWindowOrganizerController.getTransitionController()
394                     .getCollectingTransitionId();
395             ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS,
396                     "Defer transition id=%d for TaskFragmentTransaction=%s", transitionId,
397                     transactionToken);
398             mDeferredTransitions.put(transactionToken, transitionId);
399             mWindowOrganizerController.getTransitionController().deferTransitionReady();
400         }
401 
402         /** Called when the transaction is finished. */
onTransactionFinished(@onNull IBinder transactionToken)403         void onTransactionFinished(@NonNull IBinder transactionToken) {
404             if (!mDeferredTransitions.containsKey(transactionToken)) {
405                 return;
406             }
407             final int transitionId = mDeferredTransitions.remove(transactionToken);
408             if (!mWindowOrganizerController.getTransitionController().isCollecting()
409                     || mWindowOrganizerController.getTransitionController()
410                     .getCollectingTransitionId() != transitionId) {
411                 // This can happen when the transition is timeout or abort.
412                 ProtoLog.w(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS,
413                         "Deferred transition id=%d has been continued before the"
414                                 + " TaskFragmentTransaction=%s is finished",
415                         transitionId, transactionToken);
416                 return;
417             }
418             ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS,
419                     "Continue transition id=%d for TaskFragmentTransaction=%s", transitionId,
420                     transactionToken);
421             mWindowOrganizerController.getTransitionController().continueTransitionReady();
422         }
423     }
424 
425     @Nullable
getReparentActivityFromTemporaryToken( @ullable ITaskFragmentOrganizer organizer, @Nullable IBinder activityToken)426     ActivityRecord getReparentActivityFromTemporaryToken(
427             @Nullable ITaskFragmentOrganizer organizer, @Nullable IBinder activityToken) {
428         if (organizer == null || activityToken == null) {
429             return null;
430         }
431         final TaskFragmentOrganizerState state = mTaskFragmentOrganizerState.get(
432                 organizer.asBinder());
433         return state != null
434                 ? state.mTemporaryActivityTokens.remove(activityToken)
435                 : null;
436     }
437 
438     @Override
registerOrganizer(@onNull ITaskFragmentOrganizer organizer)439     public void registerOrganizer(@NonNull ITaskFragmentOrganizer organizer) {
440         final int pid = Binder.getCallingPid();
441         final int uid = Binder.getCallingUid();
442         synchronized (mGlobalLock) {
443             ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER,
444                     "Register task fragment organizer=%s uid=%d pid=%d",
445                     organizer.asBinder(), uid, pid);
446             if (isOrganizerRegistered(organizer)) {
447                 throw new IllegalStateException(
448                         "Replacing existing organizer currently unsupported");
449             }
450             mTaskFragmentOrganizerState.put(organizer.asBinder(),
451                     new TaskFragmentOrganizerState(organizer, pid, uid));
452             mPendingTaskFragmentEvents.put(organizer.asBinder(), new ArrayList<>());
453         }
454     }
455 
456     @Override
unregisterOrganizer(@onNull ITaskFragmentOrganizer organizer)457     public void unregisterOrganizer(@NonNull ITaskFragmentOrganizer organizer) {
458         final int pid = Binder.getCallingPid();
459         final long uid = Binder.getCallingUid();
460         final long origId = Binder.clearCallingIdentity();
461         try {
462             synchronized (mGlobalLock) {
463                 ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER,
464                         "Unregister task fragment organizer=%s uid=%d pid=%d",
465                         organizer.asBinder(), uid, pid);
466                 removeOrganizer(organizer);
467             }
468         } finally {
469             Binder.restoreCallingIdentity(origId);
470         }
471     }
472 
473     @Override
registerRemoteAnimations(@onNull ITaskFragmentOrganizer organizer, @NonNull RemoteAnimationDefinition definition)474     public void registerRemoteAnimations(@NonNull ITaskFragmentOrganizer organizer,
475             @NonNull RemoteAnimationDefinition definition) {
476         final int pid = Binder.getCallingPid();
477         final int uid = Binder.getCallingUid();
478         synchronized (mGlobalLock) {
479             ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER,
480                     "Register remote animations for organizer=%s uid=%d pid=%d",
481                     organizer.asBinder(), uid, pid);
482             final TaskFragmentOrganizerState organizerState =
483                     mTaskFragmentOrganizerState.get(organizer.asBinder());
484             if (organizerState == null) {
485                 throw new IllegalStateException("The organizer hasn't been registered.");
486             }
487             if (organizerState.mRemoteAnimationDefinition != null) {
488                 throw new IllegalStateException(
489                         "The organizer has already registered remote animations="
490                                 + organizerState.mRemoteAnimationDefinition);
491             }
492 
493             definition.setCallingPidUid(pid, uid);
494             organizerState.mRemoteAnimationDefinition = definition;
495         }
496     }
497 
498     @Override
unregisterRemoteAnimations(@onNull ITaskFragmentOrganizer organizer)499     public void unregisterRemoteAnimations(@NonNull ITaskFragmentOrganizer organizer) {
500         final int pid = Binder.getCallingPid();
501         final long uid = Binder.getCallingUid();
502         synchronized (mGlobalLock) {
503             ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER,
504                     "Unregister remote animations for organizer=%s uid=%d pid=%d",
505                     organizer.asBinder(), uid, pid);
506             final TaskFragmentOrganizerState organizerState =
507                     mTaskFragmentOrganizerState.get(organizer.asBinder());
508             if (organizerState == null) {
509                 Slog.e(TAG, "The organizer hasn't been registered.");
510                 return;
511             }
512 
513             organizerState.mRemoteAnimationDefinition = null;
514         }
515     }
516 
517     @Override
onTransactionHandled(@onNull IBinder transactionToken, @NonNull WindowContainerTransaction wct, @WindowManager.TransitionType int transitionType, boolean shouldApplyIndependently)518     public void onTransactionHandled(@NonNull IBinder transactionToken,
519             @NonNull WindowContainerTransaction wct,
520             @WindowManager.TransitionType int transitionType, boolean shouldApplyIndependently) {
521         // Keep the calling identity to avoid unsecure change.
522         synchronized (mGlobalLock) {
523             if (isValidTransaction(wct)) {
524                 applyTransaction(wct, transitionType, shouldApplyIndependently);
525             }
526             // Even if the transaction is empty, we still need to invoke #onTransactionFinished
527             // unless the organizer has been unregistered.
528             final ITaskFragmentOrganizer organizer = wct.getTaskFragmentOrganizer();
529             final TaskFragmentOrganizerState state = organizer != null
530                     ? mTaskFragmentOrganizerState.get(organizer.asBinder())
531                     : null;
532             if (state != null) {
533                 state.onTransactionFinished(transactionToken);
534             }
535         }
536     }
537 
538     @Override
applyTransaction(@onNull WindowContainerTransaction wct, @WindowManager.TransitionType int transitionType, boolean shouldApplyIndependently)539     public void applyTransaction(@NonNull WindowContainerTransaction wct,
540             @WindowManager.TransitionType int transitionType, boolean shouldApplyIndependently) {
541         // Keep the calling identity to avoid unsecure change.
542         synchronized (mGlobalLock) {
543             if (!isValidTransaction(wct)) {
544                 return;
545             }
546             mWindowOrganizerController.applyTaskFragmentTransactionLocked(wct, transitionType,
547                     shouldApplyIndependently);
548         }
549     }
550 
551     /**
552      * Gets the {@link RemoteAnimationDefinition} set on the given organizer if exists. Returns
553      * {@code null} if it doesn't.
554      */
555     @Nullable
getRemoteAnimationDefinition( @onNull ITaskFragmentOrganizer organizer)556     public RemoteAnimationDefinition getRemoteAnimationDefinition(
557             @NonNull ITaskFragmentOrganizer organizer) {
558         synchronized (mGlobalLock) {
559             final TaskFragmentOrganizerState organizerState =
560                     mTaskFragmentOrganizerState.get(organizer.asBinder());
561             if (organizerState == null) {
562                 Slog.e(TAG, "TaskFragmentOrganizer has been unregistered or died when trying"
563                         + " to play animation on its organized windows.");
564                 return null;
565             }
566             return organizerState.mRemoteAnimationDefinition;
567         }
568     }
569 
getTaskFragmentOrganizerUid(@onNull ITaskFragmentOrganizer organizer)570     int getTaskFragmentOrganizerUid(@NonNull ITaskFragmentOrganizer organizer) {
571         final TaskFragmentOrganizerState state = validateAndGetState(organizer);
572         return state.mOrganizerUid;
573     }
574 
onTaskFragmentAppeared(@onNull ITaskFragmentOrganizer organizer, @NonNull TaskFragment taskFragment)575     void onTaskFragmentAppeared(@NonNull ITaskFragmentOrganizer organizer,
576             @NonNull TaskFragment taskFragment) {
577         if (taskFragment.mTaskFragmentVanishedSent) {
578             return;
579         }
580         if (taskFragment.getTask() == null) {
581             Slog.w(TAG, "onTaskFragmentAppeared failed because it is not attached tf="
582                     + taskFragment);
583             return;
584         }
585         final TaskFragmentOrganizerState state = validateAndGetState(organizer);
586         if (!state.addTaskFragment(taskFragment)) {
587             return;
588         }
589         PendingTaskFragmentEvent pendingEvent = getPendingTaskFragmentEvent(taskFragment,
590                 PendingTaskFragmentEvent.EVENT_APPEARED);
591         if (pendingEvent == null) {
592             addPendingEvent(new PendingTaskFragmentEvent.Builder(
593                     PendingTaskFragmentEvent.EVENT_APPEARED, organizer)
594                     .setTaskFragment(taskFragment)
595                     .build());
596         }
597     }
598 
onTaskFragmentInfoChanged(@onNull ITaskFragmentOrganizer organizer, @NonNull TaskFragment taskFragment)599     void onTaskFragmentInfoChanged(@NonNull ITaskFragmentOrganizer organizer,
600             @NonNull TaskFragment taskFragment) {
601         if (taskFragment.mTaskFragmentVanishedSent) {
602             return;
603         }
604         validateAndGetState(organizer);
605         if (!taskFragment.mTaskFragmentAppearedSent) {
606             // Skip if TaskFragment still not appeared.
607             return;
608         }
609         PendingTaskFragmentEvent pendingEvent = getLastPendingLifecycleEvent(taskFragment);
610         if (pendingEvent == null) {
611             pendingEvent = new PendingTaskFragmentEvent.Builder(
612                     PendingTaskFragmentEvent.EVENT_INFO_CHANGED, organizer)
613                     .setTaskFragment(taskFragment)
614                     .build();
615         } else {
616             // Remove and add for re-ordering.
617             removePendingEvent(pendingEvent);
618             // Reset the defer time when TaskFragment is changed, so that it can check again if
619             // the event should be sent to the organizer, for example the TaskFragment may become
620             // empty.
621             pendingEvent.mDeferTime = 0;
622         }
623         addPendingEvent(pendingEvent);
624     }
625 
onTaskFragmentVanished(@onNull ITaskFragmentOrganizer organizer, @NonNull TaskFragment taskFragment)626     void onTaskFragmentVanished(@NonNull ITaskFragmentOrganizer organizer,
627             @NonNull TaskFragment taskFragment) {
628         if (taskFragment.mTaskFragmentVanishedSent) {
629             return;
630         }
631         taskFragment.mTaskFragmentVanishedSent = true;
632         final TaskFragmentOrganizerState state = validateAndGetState(organizer);
633         final List<PendingTaskFragmentEvent> pendingEvents = mPendingTaskFragmentEvents
634                 .get(organizer.asBinder());
635         // Remove any pending events since this TaskFragment is being removed.
636         for (int i = pendingEvents.size() - 1; i >= 0; i--) {
637             final PendingTaskFragmentEvent event = pendingEvents.get(i);
638             if (taskFragment == event.mTaskFragment) {
639                 pendingEvents.remove(i);
640             }
641         }
642         addPendingEvent(new PendingTaskFragmentEvent.Builder(
643                 PendingTaskFragmentEvent.EVENT_VANISHED, organizer)
644                 .setTaskFragment(taskFragment)
645                 .build());
646         state.removeTaskFragment(taskFragment);
647         // Make sure the vanished event will be dispatched if there are no other changes.
648         mAtmService.mWindowManager.mWindowPlacerLocked.requestTraversal();
649     }
650 
onTaskFragmentError(@onNull ITaskFragmentOrganizer organizer, @Nullable IBinder errorCallbackToken, @Nullable TaskFragment taskFragment, @TaskFragmentOperation.OperationType int opType, @NonNull Throwable exception)651     void onTaskFragmentError(@NonNull ITaskFragmentOrganizer organizer,
652             @Nullable IBinder errorCallbackToken, @Nullable TaskFragment taskFragment,
653             @TaskFragmentOperation.OperationType int opType, @NonNull Throwable exception) {
654         if (taskFragment != null && taskFragment.mTaskFragmentVanishedSent) {
655             return;
656         }
657         validateAndGetState(organizer);
658         Slog.w(TAG, "onTaskFragmentError ", exception);
659         addPendingEvent(new PendingTaskFragmentEvent.Builder(
660                 PendingTaskFragmentEvent.EVENT_ERROR, organizer)
661                 .setErrorCallbackToken(errorCallbackToken)
662                 .setTaskFragment(taskFragment)
663                 .setException(exception)
664                 .setOpType(opType)
665                 .build());
666         // Make sure the error event will be dispatched if there are no other changes.
667         mAtmService.mWindowManager.mWindowPlacerLocked.requestTraversal();
668     }
669 
onActivityReparentedToTask(@onNull ActivityRecord activity)670     void onActivityReparentedToTask(@NonNull ActivityRecord activity) {
671         final ITaskFragmentOrganizer organizer;
672         if (activity.mLastTaskFragmentOrganizerBeforePip != null) {
673             // If the activity is previously embedded in an organized TaskFragment.
674             organizer = activity.mLastTaskFragmentOrganizerBeforePip;
675         } else {
676             // Find the topmost TaskFragmentOrganizer.
677             final Task task = activity.getTask();
678             final TaskFragment[] organizedTf = new TaskFragment[1];
679             task.forAllLeafTaskFragments(tf -> {
680                 if (tf.isOrganizedTaskFragment()) {
681                     organizedTf[0] = tf;
682                     return true;
683                 }
684                 return false;
685             });
686             if (organizedTf[0] == null) {
687                 return;
688             }
689             organizer = organizedTf[0].getTaskFragmentOrganizer();
690         }
691         if (!isOrganizerRegistered(organizer)) {
692             Slog.w(TAG, "The last TaskFragmentOrganizer no longer exists");
693             return;
694         }
695         addPendingEvent(new PendingTaskFragmentEvent.Builder(
696                 PendingTaskFragmentEvent.EVENT_ACTIVITY_REPARENTED_TO_TASK, organizer)
697                 .setActivity(activity)
698                 .build());
699     }
700 
onTaskFragmentParentInfoChanged(@onNull ITaskFragmentOrganizer organizer, @NonNull Task task)701     void onTaskFragmentParentInfoChanged(@NonNull ITaskFragmentOrganizer organizer,
702             @NonNull Task task) {
703         validateAndGetState(organizer);
704         final PendingTaskFragmentEvent pendingEvent = getLastPendingParentInfoChangedEvent(
705                 organizer, task);
706         if (pendingEvent == null) {
707             addPendingEvent(new PendingTaskFragmentEvent.Builder(
708                     PendingTaskFragmentEvent.EVENT_PARENT_INFO_CHANGED, organizer)
709                     .setTask(task)
710                     .build());
711         }
712     }
713 
714     @Nullable
getLastPendingParentInfoChangedEvent( @onNull ITaskFragmentOrganizer organizer, @NonNull Task task)715     private PendingTaskFragmentEvent getLastPendingParentInfoChangedEvent(
716             @NonNull ITaskFragmentOrganizer organizer, @NonNull Task task) {
717         final List<PendingTaskFragmentEvent> events = mPendingTaskFragmentEvents
718                 .get(organizer.asBinder());
719         for (int i = events.size() - 1; i >= 0; i--) {
720             final PendingTaskFragmentEvent event = events.get(i);
721             if (task == event.mTask
722                     && event.mEventType == PendingTaskFragmentEvent.EVENT_PARENT_INFO_CHANGED) {
723                 return event;
724             }
725         }
726         return null;
727     }
728 
addPendingEvent(@onNull PendingTaskFragmentEvent event)729     private void addPendingEvent(@NonNull PendingTaskFragmentEvent event) {
730         mPendingTaskFragmentEvents.get(event.mTaskFragmentOrg.asBinder()).add(event);
731     }
732 
removePendingEvent(@onNull PendingTaskFragmentEvent event)733     private void removePendingEvent(@NonNull PendingTaskFragmentEvent event) {
734         mPendingTaskFragmentEvents.get(event.mTaskFragmentOrg.asBinder()).remove(event);
735     }
736 
isOrganizerRegistered(@onNull ITaskFragmentOrganizer organizer)737     private boolean isOrganizerRegistered(@NonNull ITaskFragmentOrganizer organizer) {
738         return mTaskFragmentOrganizerState.containsKey(organizer.asBinder());
739     }
740 
removeOrganizer(@onNull ITaskFragmentOrganizer organizer)741     private void removeOrganizer(@NonNull ITaskFragmentOrganizer organizer) {
742         final TaskFragmentOrganizerState state = mTaskFragmentOrganizerState.get(
743                 organizer.asBinder());
744         if (state == null) {
745             Slog.w(TAG, "The organizer has already been removed.");
746             return;
747         }
748         // Remove any pending event of this organizer first because state.dispose() may trigger
749         // event dispatch as result of surface placement.
750         mPendingTaskFragmentEvents.remove(organizer.asBinder());
751         // remove all of the children of the organized TaskFragment
752         state.dispose();
753         mTaskFragmentOrganizerState.remove(organizer.asBinder());
754     }
755 
756     /**
757      * Makes sure that the organizer has been correctly registered to prevent any Sidecar
758      * implementation from organizing {@link TaskFragment} without registering first. In such case,
759      * we wouldn't register {@link DeathRecipient} for the organizer, and might not remove the
760      * {@link TaskFragment} after the organizer process died.
761      */
762     @NonNull
validateAndGetState( @onNull ITaskFragmentOrganizer organizer)763     private TaskFragmentOrganizerState validateAndGetState(
764             @NonNull ITaskFragmentOrganizer organizer) {
765         final TaskFragmentOrganizerState state =
766                 mTaskFragmentOrganizerState.get(organizer.asBinder());
767         if (state == null) {
768             throw new IllegalArgumentException(
769                     "TaskFragmentOrganizer has not been registered. Organizer=" + organizer);
770         }
771         return state;
772     }
773 
isValidTransaction(@onNull WindowContainerTransaction t)774     boolean isValidTransaction(@NonNull WindowContainerTransaction t) {
775         if (t.isEmpty()) {
776             return false;
777         }
778         final ITaskFragmentOrganizer organizer = t.getTaskFragmentOrganizer();
779         if (t.getTaskFragmentOrganizer() == null || !isOrganizerRegistered(organizer)) {
780             // Transaction from an unregistered organizer should not be applied. This can happen
781             // when the organizer process died before the transaction is applied.
782             Slog.e(TAG, "Caller organizer=" + organizer + " is no longer registered");
783             return false;
784         }
785         return true;
786     }
787 
788     /**
789      * A class to store {@link ITaskFragmentOrganizer} and its organized
790      * {@link TaskFragment TaskFragments} with different pending event request.
791      */
792     private static class PendingTaskFragmentEvent {
793         static final int EVENT_APPEARED = 0;
794         static final int EVENT_VANISHED = 1;
795         static final int EVENT_INFO_CHANGED = 2;
796         static final int EVENT_PARENT_INFO_CHANGED = 3;
797         static final int EVENT_ERROR = 4;
798         static final int EVENT_ACTIVITY_REPARENTED_TO_TASK = 5;
799 
800         @IntDef(prefix = "EVENT_", value = {
801                 EVENT_APPEARED,
802                 EVENT_VANISHED,
803                 EVENT_INFO_CHANGED,
804                 EVENT_PARENT_INFO_CHANGED,
805                 EVENT_ERROR,
806                 EVENT_ACTIVITY_REPARENTED_TO_TASK
807         })
808         @Retention(RetentionPolicy.SOURCE)
809         public @interface EventType {}
810 
811         @EventType
812         private final int mEventType;
813         private final ITaskFragmentOrganizer mTaskFragmentOrg;
814         @Nullable
815         private final TaskFragment mTaskFragment;
816         @Nullable
817         private final IBinder mErrorCallbackToken;
818         @Nullable
819         private final Throwable mException;
820         @Nullable
821         private final ActivityRecord mActivity;
822         @Nullable
823         private final Task mTask;
824         // Set when the event is deferred due to the host task is invisible. The defer time will
825         // be the last active time of the host task.
826         private long mDeferTime;
827         @TaskFragmentOperation.OperationType
828         private int mOpType;
829 
PendingTaskFragmentEvent(@ventType int eventType, ITaskFragmentOrganizer taskFragmentOrg, @Nullable TaskFragment taskFragment, @Nullable IBinder errorCallbackToken, @Nullable Throwable exception, @Nullable ActivityRecord activity, @Nullable Task task, @TaskFragmentOperation.OperationType int opType)830         private PendingTaskFragmentEvent(@EventType int eventType,
831                 ITaskFragmentOrganizer taskFragmentOrg,
832                 @Nullable TaskFragment taskFragment,
833                 @Nullable IBinder errorCallbackToken,
834                 @Nullable Throwable exception,
835                 @Nullable ActivityRecord activity,
836                 @Nullable Task task,
837                 @TaskFragmentOperation.OperationType int opType) {
838             mEventType = eventType;
839             mTaskFragmentOrg = taskFragmentOrg;
840             mTaskFragment = taskFragment;
841             mErrorCallbackToken = errorCallbackToken;
842             mException = exception;
843             mActivity = activity;
844             mTask = task;
845             mOpType = opType;
846         }
847 
848         /**
849          * @return {@code true} if the pending event is related with taskFragment created, vanished
850          * and information changed.
851          */
isLifecycleEvent()852         boolean isLifecycleEvent() {
853             switch (mEventType) {
854                 case EVENT_APPEARED:
855                 case EVENT_VANISHED:
856                 case EVENT_INFO_CHANGED:
857                 case EVENT_PARENT_INFO_CHANGED:
858                     return true;
859                 default:
860                     return false;
861             }
862         }
863 
864         private static class Builder {
865             @EventType
866             private final int mEventType;
867             private final ITaskFragmentOrganizer mTaskFragmentOrg;
868             @Nullable
869             private TaskFragment mTaskFragment;
870             @Nullable
871             private IBinder mErrorCallbackToken;
872             @Nullable
873             private Throwable mException;
874             @Nullable
875             private ActivityRecord mActivity;
876             @Nullable
877             private Task mTask;
878             @TaskFragmentOperation.OperationType
879             private int mOpType;
880 
Builder(@ventType int eventType, @NonNull ITaskFragmentOrganizer taskFragmentOrg)881             Builder(@EventType int eventType, @NonNull ITaskFragmentOrganizer taskFragmentOrg) {
882                 mEventType = eventType;
883                 mTaskFragmentOrg = requireNonNull(taskFragmentOrg);
884             }
885 
setTaskFragment(@ullable TaskFragment taskFragment)886             Builder setTaskFragment(@Nullable TaskFragment taskFragment) {
887                 mTaskFragment = taskFragment;
888                 return this;
889             }
890 
setErrorCallbackToken(@ullable IBinder errorCallbackToken)891             Builder setErrorCallbackToken(@Nullable IBinder errorCallbackToken) {
892                 mErrorCallbackToken = errorCallbackToken;
893                 return this;
894             }
895 
setException(@onNull Throwable exception)896             Builder setException(@NonNull Throwable exception) {
897                 mException = requireNonNull(exception);
898                 return this;
899             }
900 
setActivity(@onNull ActivityRecord activity)901             Builder setActivity(@NonNull ActivityRecord activity) {
902                 mActivity = requireNonNull(activity);
903                 return this;
904             }
905 
setTask(@onNull Task task)906             Builder setTask(@NonNull Task task) {
907                 mTask = requireNonNull(task);
908                 return this;
909             }
910 
setOpType(@askFragmentOperation.OperationType int opType)911             Builder setOpType(@TaskFragmentOperation.OperationType int opType) {
912                 mOpType = opType;
913                 return this;
914             }
915 
build()916             PendingTaskFragmentEvent build() {
917                 return new PendingTaskFragmentEvent(mEventType, mTaskFragmentOrg, mTaskFragment,
918                         mErrorCallbackToken, mException, mActivity, mTask, mOpType);
919             }
920         }
921     }
922 
923     @Nullable
getLastPendingLifecycleEvent(@onNull TaskFragment tf)924     private PendingTaskFragmentEvent getLastPendingLifecycleEvent(@NonNull TaskFragment tf) {
925         final ITaskFragmentOrganizer organizer = tf.getTaskFragmentOrganizer();
926         final List<PendingTaskFragmentEvent> events = mPendingTaskFragmentEvents
927                 .get(organizer.asBinder());
928         for (int i = events.size() - 1; i >= 0; i--) {
929             final PendingTaskFragmentEvent event = events.get(i);
930             if (tf == event.mTaskFragment && event.isLifecycleEvent()) {
931                 return event;
932             }
933         }
934         return null;
935     }
936 
937     @Nullable
getPendingTaskFragmentEvent(@onNull TaskFragment taskFragment, int type)938     private PendingTaskFragmentEvent getPendingTaskFragmentEvent(@NonNull TaskFragment taskFragment,
939             int type) {
940         final ITaskFragmentOrganizer organizer = taskFragment.getTaskFragmentOrganizer();
941         final List<PendingTaskFragmentEvent> events = mPendingTaskFragmentEvents
942                 .get(organizer.asBinder());
943         for (int i = events.size() - 1; i >= 0; i--) {
944             final PendingTaskFragmentEvent event = events.get(i);
945             if (taskFragment == event.mTaskFragment && type == event.mEventType) {
946                 return event;
947             }
948         }
949         return null;
950     }
951 
dispatchPendingEvents()952     void dispatchPendingEvents() {
953         if (mAtmService.mWindowManager.mWindowPlacerLocked.isLayoutDeferred()
954                 || mPendingTaskFragmentEvents.isEmpty()) {
955             return;
956         }
957         final int organizerNum = mPendingTaskFragmentEvents.size();
958         for (int i = 0; i < organizerNum; i++) {
959             final TaskFragmentOrganizerState state =
960                     mTaskFragmentOrganizerState.get(mPendingTaskFragmentEvents.keyAt(i));
961             dispatchPendingEvents(state, mPendingTaskFragmentEvents.valueAt(i));
962         }
963     }
964 
dispatchPendingEvents(@onNull TaskFragmentOrganizerState state, @NonNull List<PendingTaskFragmentEvent> pendingEvents)965     private void dispatchPendingEvents(@NonNull TaskFragmentOrganizerState state,
966             @NonNull List<PendingTaskFragmentEvent> pendingEvents) {
967         if (pendingEvents.isEmpty()) {
968             return;
969         }
970         if (shouldDeferPendingEvents(state, pendingEvents)) {
971             return;
972         }
973         mTmpTaskSet.clear();
974         final int numEvents = pendingEvents.size();
975         final TaskFragmentTransaction transaction = new TaskFragmentTransaction();
976         for (int i = 0; i < numEvents; i++) {
977             final PendingTaskFragmentEvent event = pendingEvents.get(i);
978             if (event.mEventType == PendingTaskFragmentEvent.EVENT_APPEARED
979                     || event.mEventType == PendingTaskFragmentEvent.EVENT_INFO_CHANGED) {
980                 final Task task = event.mTaskFragment.getTask();
981                 if (mTmpTaskSet.add(task)) {
982                     // Make sure the organizer know about the Task config.
983                     transaction.addChange(prepareChange(new PendingTaskFragmentEvent.Builder(
984                             PendingTaskFragmentEvent.EVENT_PARENT_INFO_CHANGED, state.mOrganizer)
985                             .setTask(task)
986                             .build()));
987                 }
988             }
989             transaction.addChange(prepareChange(event));
990         }
991         mTmpTaskSet.clear();
992         state.dispatchTransaction(transaction);
993         pendingEvents.clear();
994     }
995 
996     /**
997      * Whether or not to defer sending the events to the organizer to avoid waking the app process
998      * when it is in background. We want to either send all events or none to avoid inconsistency.
999      */
shouldDeferPendingEvents(@onNull TaskFragmentOrganizerState state, @NonNull List<PendingTaskFragmentEvent> pendingEvents)1000     private boolean shouldDeferPendingEvents(@NonNull TaskFragmentOrganizerState state,
1001             @NonNull List<PendingTaskFragmentEvent> pendingEvents) {
1002         final ArrayList<Task> visibleTasks = new ArrayList<>();
1003         final ArrayList<Task> invisibleTasks = new ArrayList<>();
1004         for (int i = 0, n = pendingEvents.size(); i < n; i++) {
1005             final PendingTaskFragmentEvent event = pendingEvents.get(i);
1006             if (event.mEventType != PendingTaskFragmentEvent.EVENT_PARENT_INFO_CHANGED
1007                     && event.mEventType != PendingTaskFragmentEvent.EVENT_INFO_CHANGED
1008                     && event.mEventType != PendingTaskFragmentEvent.EVENT_APPEARED) {
1009                 // Send events for any other types.
1010                 return false;
1011             }
1012 
1013             // Check if we should send the event given the Task visibility and events.
1014             final Task task;
1015             if (event.mEventType == PendingTaskFragmentEvent.EVENT_PARENT_INFO_CHANGED) {
1016                 task = event.mTask;
1017             } else {
1018                 task = event.mTaskFragment.getTask();
1019             }
1020             if (task.lastActiveTime > event.mDeferTime
1021                     && isTaskVisible(task, visibleTasks, invisibleTasks)) {
1022                 // Send events when the app has at least one visible Task.
1023                 return false;
1024             } else if (shouldSendEventWhenTaskInvisible(task, state, event)) {
1025                 // Sent events even if the Task is invisible.
1026                 return false;
1027             }
1028 
1029             // Defer sending events to the organizer until the host task is active (visible) again.
1030             event.mDeferTime = task.lastActiveTime;
1031         }
1032         // Defer for invisible Task.
1033         return true;
1034     }
1035 
isTaskVisible(@onNull Task task, @NonNull ArrayList<Task> knownVisibleTasks, @NonNull ArrayList<Task> knownInvisibleTasks)1036     private static boolean isTaskVisible(@NonNull Task task,
1037             @NonNull ArrayList<Task> knownVisibleTasks,
1038             @NonNull ArrayList<Task> knownInvisibleTasks) {
1039         if (knownVisibleTasks.contains(task)) {
1040             return true;
1041         }
1042         if (knownInvisibleTasks.contains(task)) {
1043             return false;
1044         }
1045         if (task.shouldBeVisible(null /* starting */)) {
1046             knownVisibleTasks.add(task);
1047             return true;
1048         } else {
1049             knownInvisibleTasks.add(task);
1050             return false;
1051         }
1052     }
1053 
shouldSendEventWhenTaskInvisible(@onNull Task task, @NonNull TaskFragmentOrganizerState state, @NonNull PendingTaskFragmentEvent event)1054     private boolean shouldSendEventWhenTaskInvisible(@NonNull Task task,
1055             @NonNull TaskFragmentOrganizerState state,
1056             @NonNull PendingTaskFragmentEvent event) {
1057         final TaskFragmentParentInfo lastParentInfo = state.mLastSentTaskFragmentParentInfos
1058                 .get(task.mTaskId);
1059         if (lastParentInfo == null || lastParentInfo.isVisible()) {
1060             // When the Task was visible, or when there was no Task info changed sent (in which case
1061             // the organizer will consider it as visible by default), always send the event to
1062             // update the Task visibility.
1063             return true;
1064         }
1065         if (event.mEventType == PendingTaskFragmentEvent.EVENT_INFO_CHANGED) {
1066             // Send info changed if the TaskFragment is becoming empty/non-empty so the
1067             // organizer can choose whether or not to remove the TaskFragment.
1068             final TaskFragmentInfo lastInfo = state.mLastSentTaskFragmentInfos
1069                     .get(event.mTaskFragment);
1070             final boolean isEmpty = event.mTaskFragment.getNonFinishingActivityCount() == 0;
1071             return lastInfo == null || lastInfo.isEmpty() != isEmpty;
1072         }
1073         return false;
1074     }
1075 
dispatchPendingInfoChangedEvent(@onNull TaskFragment taskFragment)1076     void dispatchPendingInfoChangedEvent(@NonNull TaskFragment taskFragment) {
1077         final PendingTaskFragmentEvent event = getPendingTaskFragmentEvent(taskFragment,
1078                 PendingTaskFragmentEvent.EVENT_INFO_CHANGED);
1079         if (event == null) {
1080             return;
1081         }
1082 
1083         final ITaskFragmentOrganizer organizer = taskFragment.getTaskFragmentOrganizer();
1084         final TaskFragmentOrganizerState state = validateAndGetState(organizer);
1085         final TaskFragmentTransaction transaction = new TaskFragmentTransaction();
1086         // Make sure the organizer know about the Task config.
1087         transaction.addChange(prepareChange(new PendingTaskFragmentEvent.Builder(
1088                 PendingTaskFragmentEvent.EVENT_PARENT_INFO_CHANGED, organizer)
1089                 .setTask(taskFragment.getTask())
1090                 .build()));
1091         transaction.addChange(prepareChange(event));
1092         state.dispatchTransaction(transaction);
1093         mPendingTaskFragmentEvents.get(organizer.asBinder()).remove(event);
1094     }
1095 
1096     @Nullable
prepareChange( @onNull PendingTaskFragmentEvent event)1097     private TaskFragmentTransaction.Change prepareChange(
1098             @NonNull PendingTaskFragmentEvent event) {
1099         final ITaskFragmentOrganizer taskFragmentOrg = event.mTaskFragmentOrg;
1100         final TaskFragment taskFragment = event.mTaskFragment;
1101         final TaskFragmentOrganizerState state =
1102                 mTaskFragmentOrganizerState.get(taskFragmentOrg.asBinder());
1103         if (state == null) {
1104             return null;
1105         }
1106         switch (event.mEventType) {
1107             case PendingTaskFragmentEvent.EVENT_APPEARED:
1108                 return state.prepareTaskFragmentAppeared(taskFragment);
1109             case PendingTaskFragmentEvent.EVENT_VANISHED:
1110                 return state.prepareTaskFragmentVanished(taskFragment);
1111             case PendingTaskFragmentEvent.EVENT_INFO_CHANGED:
1112                 return state.prepareTaskFragmentInfoChanged(taskFragment);
1113             case PendingTaskFragmentEvent.EVENT_PARENT_INFO_CHANGED:
1114                 return state.prepareTaskFragmentParentInfoChanged(event.mTask);
1115             case PendingTaskFragmentEvent.EVENT_ERROR:
1116                 return state.prepareTaskFragmentError(event.mErrorCallbackToken, taskFragment,
1117                         event.mOpType, event.mException);
1118             case PendingTaskFragmentEvent.EVENT_ACTIVITY_REPARENTED_TO_TASK:
1119                 return state.prepareActivityReparentedToTask(event.mActivity);
1120             default:
1121                 throw new IllegalArgumentException("Unknown TaskFragmentEvent=" + event.mEventType);
1122         }
1123     }
1124 
1125     // TODO(b/204399167): change to push the embedded state to the client side
1126     @Override
isActivityEmbedded(IBinder activityToken)1127     public boolean isActivityEmbedded(IBinder activityToken) {
1128         synchronized (mGlobalLock) {
1129             final ActivityRecord activity = ActivityRecord.forTokenLocked(activityToken);
1130             if (activity == null) {
1131                 return false;
1132             }
1133             final TaskFragment taskFragment = activity.getOrganizedTaskFragment();
1134             return taskFragment != null && taskFragment.isEmbeddedWithBoundsOverride();
1135         }
1136     }
1137 
1138     /**
1139      * Trims the given Intent to only those that are needed to for embedding rules. This helps to
1140      * make it safer for cross-uid embedding even if we only send the Intent for trusted embedding.
1141      */
trimIntent(@onNull Intent intent)1142     private static Intent trimIntent(@NonNull Intent intent) {
1143         return new Intent()
1144                 .setComponent(intent.getComponent())
1145                 .setPackage(intent.getPackage())
1146                 .setAction(intent.getAction());
1147     }
1148 }
1149