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.window.TaskFragmentOrganizer.putExceptionInBundle; 20 21 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_ORGANIZER; 22 import static com.android.server.wm.WindowOrganizerController.configurationsAreEqualForOrganizer; 23 24 import android.annotation.IntDef; 25 import android.annotation.NonNull; 26 import android.annotation.Nullable; 27 import android.content.res.Configuration; 28 import android.graphics.Rect; 29 import android.os.Binder; 30 import android.os.Bundle; 31 import android.os.IBinder; 32 import android.os.RemoteException; 33 import android.util.ArrayMap; 34 import android.util.Slog; 35 import android.view.RemoteAnimationDefinition; 36 import android.window.ITaskFragmentOrganizer; 37 import android.window.ITaskFragmentOrganizerController; 38 import android.window.TaskFragmentInfo; 39 40 import com.android.internal.protolog.common.ProtoLog; 41 42 import java.lang.annotation.Retention; 43 import java.lang.annotation.RetentionPolicy; 44 import java.util.ArrayList; 45 import java.util.Map; 46 import java.util.WeakHashMap; 47 48 /** 49 * Stores and manages the client {@link android.window.TaskFragmentOrganizer}. 50 */ 51 public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerController.Stub { 52 private static final String TAG = "TaskFragmentOrganizerController"; 53 54 private final ActivityTaskManagerService mAtmService; 55 private final WindowManagerGlobalLock mGlobalLock; 56 /** 57 * A Map which manages the relationship between 58 * {@link ITaskFragmentOrganizer} and {@link TaskFragmentOrganizerState} 59 */ 60 private final ArrayMap<IBinder, TaskFragmentOrganizerState> mTaskFragmentOrganizerState = 61 new ArrayMap<>(); 62 /** 63 * A List which manages the TaskFragment pending event {@link PendingTaskFragmentEvent} 64 */ 65 private final ArrayList<PendingTaskFragmentEvent> mPendingTaskFragmentEvents = 66 new ArrayList<>(); 67 TaskFragmentOrganizerController(ActivityTaskManagerService atm)68 TaskFragmentOrganizerController(ActivityTaskManagerService atm) { 69 mAtmService = atm; 70 mGlobalLock = atm.mGlobalLock; 71 } 72 73 /** 74 * A class to manage {@link ITaskFragmentOrganizer} and its organized 75 * {@link TaskFragment TaskFragments}. 76 */ 77 private class TaskFragmentOrganizerState implements IBinder.DeathRecipient { 78 private final ArrayList<TaskFragment> mOrganizedTaskFragments = new ArrayList<>(); 79 private final ITaskFragmentOrganizer mOrganizer; 80 private final Map<TaskFragment, TaskFragmentInfo> mLastSentTaskFragmentInfos = 81 new WeakHashMap<>(); 82 private final Map<TaskFragment, Configuration> mLastSentTaskFragmentParentConfigs = 83 new WeakHashMap<>(); 84 85 /** 86 * @see android.window.TaskFragmentOrganizer#registerRemoteAnimations( 87 * RemoteAnimationDefinition) 88 */ 89 @Nullable 90 private RemoteAnimationDefinition mRemoteAnimationDefinition; 91 TaskFragmentOrganizerState(ITaskFragmentOrganizer organizer)92 TaskFragmentOrganizerState(ITaskFragmentOrganizer organizer) { 93 mOrganizer = organizer; 94 try { 95 mOrganizer.asBinder().linkToDeath(this, 0 /*flags*/); 96 } catch (RemoteException e) { 97 Slog.e(TAG, "TaskFragmentOrganizer failed to register death recipient"); 98 } 99 } 100 101 @Override binderDied()102 public void binderDied() { 103 synchronized (mGlobalLock) { 104 removeOrganizer(mOrganizer); 105 } 106 } 107 108 /** 109 * @return {@code true} if taskFragment is organized and not sent the appeared event before. 110 */ addTaskFragment(TaskFragment taskFragment)111 boolean addTaskFragment(TaskFragment taskFragment) { 112 if (taskFragment.mTaskFragmentAppearedSent) { 113 return false; 114 } 115 if (mOrganizedTaskFragments.contains(taskFragment)) { 116 return false; 117 } 118 mOrganizedTaskFragments.add(taskFragment); 119 return true; 120 } 121 removeTaskFragment(TaskFragment taskFragment)122 void removeTaskFragment(TaskFragment taskFragment) { 123 mOrganizedTaskFragments.remove(taskFragment); 124 } 125 dispose()126 void dispose() { 127 while (!mOrganizedTaskFragments.isEmpty()) { 128 final TaskFragment taskFragment = mOrganizedTaskFragments.get(0); 129 taskFragment.removeImmediately(); 130 mOrganizedTaskFragments.remove(taskFragment); 131 } 132 mOrganizer.asBinder().unlinkToDeath(this, 0 /*flags*/); 133 } 134 onTaskFragmentAppeared(ITaskFragmentOrganizer organizer, TaskFragment tf)135 void onTaskFragmentAppeared(ITaskFragmentOrganizer organizer, TaskFragment tf) { 136 ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "TaskFragment appeared name=%s", tf.getName()); 137 final TaskFragmentInfo info = tf.getTaskFragmentInfo(); 138 try { 139 organizer.onTaskFragmentAppeared(info); 140 mLastSentTaskFragmentInfos.put(tf, info); 141 tf.mTaskFragmentAppearedSent = true; 142 } catch (RemoteException e) { 143 Slog.e(TAG, "Exception sending onTaskFragmentAppeared callback", e); 144 } 145 onTaskFragmentParentInfoChanged(organizer, tf); 146 } 147 onTaskFragmentVanished(ITaskFragmentOrganizer organizer, TaskFragment tf)148 void onTaskFragmentVanished(ITaskFragmentOrganizer organizer, TaskFragment tf) { 149 ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "TaskFragment vanished name=%s", tf.getName()); 150 try { 151 organizer.onTaskFragmentVanished(tf.getTaskFragmentInfo()); 152 } catch (RemoteException e) { 153 Slog.e(TAG, "Exception sending onTaskFragmentVanished callback", e); 154 } 155 tf.mTaskFragmentAppearedSent = false; 156 mLastSentTaskFragmentInfos.remove(tf); 157 mLastSentTaskFragmentParentConfigs.remove(tf); 158 } 159 onTaskFragmentInfoChanged(ITaskFragmentOrganizer organizer, TaskFragment tf)160 void onTaskFragmentInfoChanged(ITaskFragmentOrganizer organizer, TaskFragment tf) { 161 // Parent config may have changed. The controller will check if there is any important 162 // config change for the organizer. 163 onTaskFragmentParentInfoChanged(organizer, tf); 164 165 // Check if the info is different from the last reported info. 166 final TaskFragmentInfo info = tf.getTaskFragmentInfo(); 167 final TaskFragmentInfo lastInfo = mLastSentTaskFragmentInfos.get(tf); 168 if (info.equalsForTaskFragmentOrganizer(lastInfo) && configurationsAreEqualForOrganizer( 169 info.getConfiguration(), lastInfo.getConfiguration())) { 170 return; 171 } 172 ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "TaskFragment info changed name=%s", 173 tf.getName()); 174 try { 175 organizer.onTaskFragmentInfoChanged(tf.getTaskFragmentInfo()); 176 mLastSentTaskFragmentInfos.put(tf, info); 177 } catch (RemoteException e) { 178 Slog.e(TAG, "Exception sending onTaskFragmentInfoChanged callback", e); 179 } 180 } 181 onTaskFragmentParentInfoChanged(ITaskFragmentOrganizer organizer, TaskFragment tf)182 void onTaskFragmentParentInfoChanged(ITaskFragmentOrganizer organizer, TaskFragment tf) { 183 // Check if the parent info is different from the last reported parent info. 184 if (tf.getParent() == null || tf.getParent().asTask() == null) { 185 mLastSentTaskFragmentParentConfigs.remove(tf); 186 return; 187 } 188 final Task parent = tf.getParent().asTask(); 189 final Configuration parentConfig = parent.getConfiguration(); 190 final Configuration lastParentConfig = mLastSentTaskFragmentParentConfigs.get(tf); 191 if (configurationsAreEqualForOrganizer(parentConfig, lastParentConfig)) { 192 return; 193 } 194 ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, 195 "TaskFragment parent info changed name=%s parentTaskId=%d", 196 tf.getName(), parent.mTaskId); 197 try { 198 organizer.onTaskFragmentParentInfoChanged(tf.getFragmentToken(), parentConfig); 199 mLastSentTaskFragmentParentConfigs.put(tf, new Configuration(parentConfig)); 200 } catch (RemoteException e) { 201 Slog.e(TAG, "Exception sending onTaskFragmentParentInfoChanged callback", e); 202 } 203 } 204 onTaskFragmentError(ITaskFragmentOrganizer organizer, IBinder errorCallbackToken, Throwable exception)205 void onTaskFragmentError(ITaskFragmentOrganizer organizer, IBinder errorCallbackToken, 206 Throwable exception) { 207 ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, 208 "Sending TaskFragment error exception=%s", exception.toString()); 209 final Bundle exceptionBundle = putExceptionInBundle(exception); 210 try { 211 organizer.onTaskFragmentError(errorCallbackToken, exceptionBundle); 212 } catch (RemoteException e) { 213 Slog.e(TAG, "Exception sending onTaskFragmentError callback", e); 214 } 215 } 216 } 217 218 @Override registerOrganizer(ITaskFragmentOrganizer organizer)219 public void registerOrganizer(ITaskFragmentOrganizer organizer) { 220 final int pid = Binder.getCallingPid(); 221 final long uid = Binder.getCallingUid(); 222 synchronized (mGlobalLock) { 223 ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, 224 "Register task fragment organizer=%s uid=%d pid=%d", 225 organizer.asBinder(), uid, pid); 226 if (mTaskFragmentOrganizerState.containsKey(organizer.asBinder())) { 227 throw new IllegalStateException( 228 "Replacing existing organizer currently unsupported"); 229 } 230 mTaskFragmentOrganizerState.put(organizer.asBinder(), 231 new TaskFragmentOrganizerState(organizer)); 232 } 233 } 234 235 @Override unregisterOrganizer(ITaskFragmentOrganizer organizer)236 public void unregisterOrganizer(ITaskFragmentOrganizer organizer) { 237 validateAndGetState(organizer); 238 final int pid = Binder.getCallingPid(); 239 final long uid = Binder.getCallingUid(); 240 final long origId = Binder.clearCallingIdentity(); 241 try { 242 synchronized (mGlobalLock) { 243 ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, 244 "Unregister task fragment organizer=%s uid=%d pid=%d", 245 organizer.asBinder(), uid, pid); 246 removeOrganizer(organizer); 247 } 248 } finally { 249 Binder.restoreCallingIdentity(origId); 250 } 251 } 252 253 @Override registerRemoteAnimations(ITaskFragmentOrganizer organizer, RemoteAnimationDefinition definition)254 public void registerRemoteAnimations(ITaskFragmentOrganizer organizer, 255 RemoteAnimationDefinition definition) { 256 final int pid = Binder.getCallingPid(); 257 final int uid = Binder.getCallingUid(); 258 synchronized (mGlobalLock) { 259 ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, 260 "Register remote animations for organizer=%s uid=%d pid=%d", 261 organizer.asBinder(), uid, pid); 262 final TaskFragmentOrganizerState organizerState = 263 mTaskFragmentOrganizerState.get(organizer.asBinder()); 264 if (organizerState == null) { 265 throw new IllegalStateException("The organizer hasn't been registered."); 266 } 267 if (organizerState.mRemoteAnimationDefinition != null) { 268 throw new IllegalStateException( 269 "The organizer has already registered remote animations=" 270 + organizerState.mRemoteAnimationDefinition); 271 } 272 273 definition.setCallingPidUid(pid, uid); 274 organizerState.mRemoteAnimationDefinition = definition; 275 } 276 } 277 278 @Override unregisterRemoteAnimations(ITaskFragmentOrganizer organizer)279 public void unregisterRemoteAnimations(ITaskFragmentOrganizer organizer) { 280 final int pid = Binder.getCallingPid(); 281 final long uid = Binder.getCallingUid(); 282 synchronized (mGlobalLock) { 283 ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, 284 "Unregister remote animations for organizer=%s uid=%d pid=%d", 285 organizer.asBinder(), uid, pid); 286 final TaskFragmentOrganizerState organizerState = 287 mTaskFragmentOrganizerState.get(organizer.asBinder()); 288 if (organizerState == null) { 289 Slog.e(TAG, "The organizer hasn't been registered."); 290 return; 291 } 292 293 organizerState.mRemoteAnimationDefinition = null; 294 } 295 } 296 297 /** Gets the {@link RemoteAnimationDefinition} set on the given organizer if exists. */ 298 @Nullable getRemoteAnimationDefinition( ITaskFragmentOrganizer organizer)299 public RemoteAnimationDefinition getRemoteAnimationDefinition( 300 ITaskFragmentOrganizer organizer) { 301 synchronized (mGlobalLock) { 302 final TaskFragmentOrganizerState organizerState = 303 mTaskFragmentOrganizerState.get(organizer.asBinder()); 304 return organizerState != null ? organizerState.mRemoteAnimationDefinition : null; 305 } 306 } 307 onTaskFragmentAppeared(ITaskFragmentOrganizer organizer, TaskFragment taskFragment)308 void onTaskFragmentAppeared(ITaskFragmentOrganizer organizer, TaskFragment taskFragment) { 309 final TaskFragmentOrganizerState state = validateAndGetState(organizer); 310 if (!state.addTaskFragment(taskFragment)) { 311 return; 312 } 313 PendingTaskFragmentEvent pendingEvent = getPendingTaskFragmentEvent(taskFragment, 314 PendingTaskFragmentEvent.EVENT_APPEARED); 315 if (pendingEvent == null) { 316 pendingEvent = new PendingTaskFragmentEvent(taskFragment, organizer, 317 PendingTaskFragmentEvent.EVENT_APPEARED); 318 mPendingTaskFragmentEvents.add(pendingEvent); 319 } 320 } 321 onTaskFragmentInfoChanged(ITaskFragmentOrganizer organizer, TaskFragment taskFragment)322 void onTaskFragmentInfoChanged(ITaskFragmentOrganizer organizer, TaskFragment taskFragment) { 323 handleTaskFragmentInfoChanged(organizer, taskFragment, 324 PendingTaskFragmentEvent.EVENT_INFO_CHANGED); 325 } 326 onTaskFragmentParentInfoChanged(ITaskFragmentOrganizer organizer, TaskFragment taskFragment)327 void onTaskFragmentParentInfoChanged(ITaskFragmentOrganizer organizer, 328 TaskFragment taskFragment) { 329 handleTaskFragmentInfoChanged(organizer, taskFragment, 330 PendingTaskFragmentEvent.EVENT_PARENT_INFO_CHANGED); 331 } 332 handleTaskFragmentInfoChanged(ITaskFragmentOrganizer organizer, TaskFragment taskFragment, int eventType)333 private void handleTaskFragmentInfoChanged(ITaskFragmentOrganizer organizer, 334 TaskFragment taskFragment, int eventType) { 335 validateAndGetState(organizer); 336 if (!taskFragment.mTaskFragmentAppearedSent) { 337 // Skip if TaskFragment still not appeared. 338 return; 339 } 340 PendingTaskFragmentEvent pendingEvent = getLastPendingLifecycleEvent(taskFragment); 341 if (pendingEvent == null) { 342 pendingEvent = new PendingTaskFragmentEvent(taskFragment, organizer, eventType); 343 } else { 344 if (pendingEvent.mEventType == PendingTaskFragmentEvent.EVENT_VANISHED) { 345 // Skipped the info changed event if vanished event is pending. 346 return; 347 } 348 // Remove and add for re-ordering. 349 mPendingTaskFragmentEvents.remove(pendingEvent); 350 } 351 mPendingTaskFragmentEvents.add(pendingEvent); 352 } 353 onTaskFragmentVanished(ITaskFragmentOrganizer organizer, TaskFragment taskFragment)354 void onTaskFragmentVanished(ITaskFragmentOrganizer organizer, TaskFragment taskFragment) { 355 final TaskFragmentOrganizerState state = validateAndGetState(organizer); 356 for (int i = mPendingTaskFragmentEvents.size() - 1; i >= 0; i--) { 357 PendingTaskFragmentEvent entry = mPendingTaskFragmentEvents.get(i); 358 if (taskFragment == entry.mTaskFragment) { 359 mPendingTaskFragmentEvents.remove(i); 360 if (entry.mEventType == PendingTaskFragmentEvent.EVENT_APPEARED) { 361 // If taskFragment appeared callback is pending, ignore the vanished request. 362 return; 363 } 364 } 365 } 366 if (!taskFragment.mTaskFragmentAppearedSent) { 367 return; 368 } 369 PendingTaskFragmentEvent pendingEvent = new PendingTaskFragmentEvent(taskFragment, 370 organizer, PendingTaskFragmentEvent.EVENT_VANISHED); 371 mPendingTaskFragmentEvents.add(pendingEvent); 372 state.removeTaskFragment(taskFragment); 373 } 374 onTaskFragmentError(ITaskFragmentOrganizer organizer, IBinder errorCallbackToken, Throwable exception)375 void onTaskFragmentError(ITaskFragmentOrganizer organizer, IBinder errorCallbackToken, 376 Throwable exception) { 377 validateAndGetState(organizer); 378 Slog.w(TAG, "onTaskFragmentError ", exception); 379 PendingTaskFragmentEvent pendingEvent = new PendingTaskFragmentEvent(organizer, 380 errorCallbackToken, exception, PendingTaskFragmentEvent.EVENT_ERROR); 381 mPendingTaskFragmentEvents.add(pendingEvent); 382 } 383 removeOrganizer(ITaskFragmentOrganizer organizer)384 private void removeOrganizer(ITaskFragmentOrganizer organizer) { 385 final TaskFragmentOrganizerState state = validateAndGetState(organizer); 386 // remove all of the children of the organized TaskFragment 387 state.dispose(); 388 mTaskFragmentOrganizerState.remove(organizer.asBinder()); 389 } 390 391 /** 392 * Makes sure that the organizer has been correctly registered to prevent any Sidecar 393 * implementation from organizing {@link TaskFragment} without registering first. In such case, 394 * we wouldn't register {@link DeathRecipient} for the organizer, and might not remove the 395 * {@link TaskFragment} after the organizer process died. 396 */ validateAndGetState(ITaskFragmentOrganizer organizer)397 private TaskFragmentOrganizerState validateAndGetState(ITaskFragmentOrganizer organizer) { 398 final TaskFragmentOrganizerState state = 399 mTaskFragmentOrganizerState.get(organizer.asBinder()); 400 if (state == null) { 401 throw new IllegalArgumentException( 402 "TaskFragmentOrganizer has not been registered. Organizer=" + organizer); 403 } 404 return state; 405 } 406 407 /** 408 * A class to store {@link ITaskFragmentOrganizer} and its organized 409 * {@link TaskFragment TaskFragments} with different pending event request. 410 */ 411 private static class PendingTaskFragmentEvent { 412 static final int EVENT_APPEARED = 0; 413 static final int EVENT_VANISHED = 1; 414 static final int EVENT_INFO_CHANGED = 2; 415 static final int EVENT_PARENT_INFO_CHANGED = 3; 416 static final int EVENT_ERROR = 4; 417 418 @IntDef(prefix = "EVENT_", value = { 419 EVENT_APPEARED, 420 EVENT_VANISHED, 421 EVENT_INFO_CHANGED, 422 EVENT_PARENT_INFO_CHANGED, 423 EVENT_ERROR 424 }) 425 @Retention(RetentionPolicy.SOURCE) 426 public @interface EventType {} 427 428 @EventType 429 private final int mEventType; 430 private final ITaskFragmentOrganizer mTaskFragmentOrg; 431 private final TaskFragment mTaskFragment; 432 private final IBinder mErrorCallback; 433 private final Throwable mException; 434 // Set when the event is deferred due to the host task is invisible. The defer time will 435 // be the last active time of the host task. 436 private long mDeferTime; 437 PendingTaskFragmentEvent(TaskFragment taskFragment, ITaskFragmentOrganizer taskFragmentOrg, @EventType int eventType)438 private PendingTaskFragmentEvent(TaskFragment taskFragment, 439 ITaskFragmentOrganizer taskFragmentOrg, @EventType int eventType) { 440 this(taskFragment, taskFragmentOrg, null /* errorCallback */, 441 null /* exception */, eventType); 442 443 } 444 PendingTaskFragmentEvent(ITaskFragmentOrganizer taskFragmentOrg, IBinder errorCallback, Throwable exception, @EventType int eventType)445 private PendingTaskFragmentEvent(ITaskFragmentOrganizer taskFragmentOrg, 446 IBinder errorCallback, Throwable exception, @EventType int eventType) { 447 this(null /* taskFragment */, taskFragmentOrg, errorCallback, exception, 448 eventType); 449 } 450 PendingTaskFragmentEvent(TaskFragment taskFragment, ITaskFragmentOrganizer taskFragmentOrg, IBinder errorCallback, Throwable exception, @EventType int eventType)451 private PendingTaskFragmentEvent(TaskFragment taskFragment, 452 ITaskFragmentOrganizer taskFragmentOrg, IBinder errorCallback, Throwable exception, 453 @EventType int eventType) { 454 mTaskFragment = taskFragment; 455 mTaskFragmentOrg = taskFragmentOrg; 456 mErrorCallback = errorCallback; 457 mException = exception; 458 mEventType = eventType; 459 } 460 461 /** 462 * @return {@code true} if the pending event is related with taskFragment created, vanished 463 * and information changed. 464 */ isLifecycleEvent()465 boolean isLifecycleEvent() { 466 switch (mEventType) { 467 case EVENT_APPEARED: 468 case EVENT_VANISHED: 469 case EVENT_INFO_CHANGED: 470 case EVENT_PARENT_INFO_CHANGED: 471 return true; 472 default: 473 return false; 474 } 475 } 476 } 477 478 @Nullable getLastPendingLifecycleEvent(TaskFragment tf)479 private PendingTaskFragmentEvent getLastPendingLifecycleEvent(TaskFragment tf) { 480 for (int i = mPendingTaskFragmentEvents.size() - 1; i >= 0; i--) { 481 PendingTaskFragmentEvent entry = mPendingTaskFragmentEvents.get(i); 482 if (tf == entry.mTaskFragment && entry.isLifecycleEvent()) { 483 return entry; 484 } 485 } 486 return null; 487 } 488 489 @Nullable getPendingTaskFragmentEvent(TaskFragment taskFragment, int type)490 private PendingTaskFragmentEvent getPendingTaskFragmentEvent(TaskFragment taskFragment, 491 int type) { 492 for (int i = mPendingTaskFragmentEvents.size() - 1; i >= 0; i--) { 493 PendingTaskFragmentEvent entry = mPendingTaskFragmentEvents.get(i); 494 if (taskFragment == entry.mTaskFragment && type == entry.mEventType) { 495 return entry; 496 } 497 } 498 return null; 499 } 500 shouldSendEventWhenTaskInvisible(@onNull Task task, @NonNull PendingTaskFragmentEvent event)501 private boolean shouldSendEventWhenTaskInvisible(@NonNull Task task, 502 @NonNull PendingTaskFragmentEvent event) { 503 final TaskFragmentOrganizerState state = 504 mTaskFragmentOrganizerState.get(event.mTaskFragmentOrg.asBinder()); 505 final TaskFragmentInfo lastInfo = state.mLastSentTaskFragmentInfos.get(event.mTaskFragment); 506 final TaskFragmentInfo info = event.mTaskFragment.getTaskFragmentInfo(); 507 // Send an info changed callback if this event is for the last activities to finish in a 508 // Task so that the {@link TaskFragmentOrganizer} can delete this TaskFragment. Otherwise, 509 // the Task may be removed before it becomes visible again to send this event because it no 510 // longer has activities. As a result, the organizer will never get this info changed event 511 // and will not delete the TaskFragment because the organizer thinks the TaskFragment still 512 // has running activities. 513 return event.mEventType == PendingTaskFragmentEvent.EVENT_INFO_CHANGED 514 && task.topRunningActivity() == null && lastInfo != null 515 && lastInfo.getRunningActivityCount() > 0 && info.getRunningActivityCount() == 0; 516 } 517 dispatchPendingEvents()518 void dispatchPendingEvents() { 519 if (mAtmService.mWindowManager.mWindowPlacerLocked.isLayoutDeferred() 520 || mPendingTaskFragmentEvents.isEmpty()) { 521 return; 522 } 523 524 final ArrayList<Task> visibleTasks = new ArrayList<>(); 525 final ArrayList<Task> invisibleTasks = new ArrayList<>(); 526 final ArrayList<PendingTaskFragmentEvent> candidateEvents = new ArrayList<>(); 527 for (int i = 0, n = mPendingTaskFragmentEvents.size(); i < n; i++) { 528 final PendingTaskFragmentEvent event = mPendingTaskFragmentEvents.get(i); 529 final Task task = event.mTaskFragment != null ? event.mTaskFragment.getTask() : null; 530 if (task != null && (task.lastActiveTime <= event.mDeferTime 531 || !(isTaskVisible(task, visibleTasks, invisibleTasks) 532 || shouldSendEventWhenTaskInvisible(task, event)))) { 533 // Defer sending events to the TaskFragment until the host task is active again. 534 event.mDeferTime = task.lastActiveTime; 535 continue; 536 } 537 candidateEvents.add(event); 538 } 539 final int numEvents = candidateEvents.size(); 540 for (int i = 0; i < numEvents; i++) { 541 dispatchEvent(candidateEvents.get(i)); 542 } 543 if (numEvents > 0) { 544 mPendingTaskFragmentEvents.removeAll(candidateEvents); 545 } 546 } 547 isTaskVisible(Task task, ArrayList<Task> knownVisibleTasks, ArrayList<Task> knownInvisibleTasks)548 private static boolean isTaskVisible(Task task, ArrayList<Task> knownVisibleTasks, 549 ArrayList<Task> knownInvisibleTasks) { 550 if (knownVisibleTasks.contains(task)) { 551 return true; 552 } 553 if (knownInvisibleTasks.contains(task)) { 554 return false; 555 } 556 if (task.shouldBeVisible(null /* starting */)) { 557 knownVisibleTasks.add(task); 558 return true; 559 } else { 560 knownInvisibleTasks.add(task); 561 return false; 562 } 563 } 564 dispatchPendingInfoChangedEvent(TaskFragment taskFragment)565 void dispatchPendingInfoChangedEvent(TaskFragment taskFragment) { 566 PendingTaskFragmentEvent event = getPendingTaskFragmentEvent(taskFragment, 567 PendingTaskFragmentEvent.EVENT_INFO_CHANGED); 568 if (event == null) { 569 return; 570 } 571 572 dispatchEvent(event); 573 mPendingTaskFragmentEvents.remove(event); 574 } 575 dispatchEvent(PendingTaskFragmentEvent event)576 private void dispatchEvent(PendingTaskFragmentEvent event) { 577 final ITaskFragmentOrganizer taskFragmentOrg = event.mTaskFragmentOrg; 578 final TaskFragment taskFragment = event.mTaskFragment; 579 final TaskFragmentOrganizerState state = 580 mTaskFragmentOrganizerState.get(taskFragmentOrg.asBinder()); 581 if (state == null) { 582 return; 583 } 584 switch (event.mEventType) { 585 case PendingTaskFragmentEvent.EVENT_APPEARED: 586 state.onTaskFragmentAppeared(taskFragmentOrg, taskFragment); 587 break; 588 case PendingTaskFragmentEvent.EVENT_VANISHED: 589 state.onTaskFragmentVanished(taskFragmentOrg, taskFragment); 590 break; 591 case PendingTaskFragmentEvent.EVENT_INFO_CHANGED: 592 state.onTaskFragmentInfoChanged(taskFragmentOrg, taskFragment); 593 break; 594 case PendingTaskFragmentEvent.EVENT_PARENT_INFO_CHANGED: 595 state.onTaskFragmentParentInfoChanged(taskFragmentOrg, taskFragment); 596 break; 597 case PendingTaskFragmentEvent.EVENT_ERROR: 598 state.onTaskFragmentError(taskFragmentOrg, event.mErrorCallback, 599 event.mException); 600 } 601 } 602 603 // TODO(b/204399167): change to push the embedded state to the client side 604 @Override isActivityEmbedded(IBinder activityToken)605 public boolean isActivityEmbedded(IBinder activityToken) { 606 synchronized (mGlobalLock) { 607 final ActivityRecord activity = ActivityRecord.forTokenLocked(activityToken); 608 if (activity == null) { 609 return false; 610 } 611 final TaskFragment taskFragment = activity.getOrganizedTaskFragment(); 612 if (taskFragment == null) { 613 return false; 614 } 615 final Task parentTask = taskFragment.getTask(); 616 if (parentTask != null) { 617 final Rect taskBounds = parentTask.getBounds(); 618 final Rect taskFragBounds = taskFragment.getBounds(); 619 return !taskBounds.equals(taskFragBounds) && taskBounds.contains(taskFragBounds); 620 } 621 return false; 622 } 623 } 624 } 625