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