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