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