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