1 /* 2 * Copyright (C) 2019 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.StartingWindowRemovalInfo.DEFER_MODE_NONE; 21 import static android.window.StartingWindowRemovalInfo.DEFER_MODE_NORMAL; 22 import static android.window.StartingWindowRemovalInfo.DEFER_MODE_ROTATION; 23 24 import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_WINDOW_ORGANIZER; 25 import static com.android.server.wm.ActivityTaskManagerService.enforceTaskPermission; 26 import static com.android.server.wm.DisplayContent.IME_TARGET_LAYERING; 27 import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_STARTING_REVEAL; 28 import static com.android.server.wm.WindowOrganizerController.configurationsAreEqualForOrganizer; 29 30 import android.annotation.NonNull; 31 import android.annotation.Nullable; 32 import android.app.ActivityManager; 33 import android.app.ActivityManager.RunningTaskInfo; 34 import android.app.WindowConfiguration; 35 import android.content.Intent; 36 import android.content.pm.ParceledListSlice; 37 import android.content.res.Configuration; 38 import android.graphics.Rect; 39 import android.os.Binder; 40 import android.os.IBinder; 41 import android.os.Parcel; 42 import android.os.RemoteException; 43 import android.util.ArrayMap; 44 import android.util.Slog; 45 import android.util.proto.ProtoOutputStream; 46 import android.view.Display; 47 import android.view.SurfaceControl; 48 import android.window.ITaskOrganizer; 49 import android.window.ITaskOrganizerController; 50 import android.window.IWindowlessStartingSurfaceCallback; 51 import android.window.SplashScreenView; 52 import android.window.StartingWindowInfo; 53 import android.window.StartingWindowRemovalInfo; 54 import android.window.TaskAppearedInfo; 55 import android.window.TaskSnapshot; 56 import android.window.WindowContainerToken; 57 58 import com.android.internal.annotations.VisibleForTesting; 59 import com.android.internal.protolog.ProtoLog; 60 import com.android.internal.util.ArrayUtils; 61 62 import java.io.PrintWriter; 63 import java.util.ArrayDeque; 64 import java.util.ArrayList; 65 import java.util.HashSet; 66 import java.util.List; 67 import java.util.WeakHashMap; 68 69 /** 70 * Stores the TaskOrganizers associated with a given windowing mode and 71 * their associated state. 72 */ 73 class TaskOrganizerController extends ITaskOrganizerController.Stub { 74 private static final String TAG = "TaskOrganizerController"; 75 76 @VisibleForTesting 77 class DeathRecipient implements IBinder.DeathRecipient { 78 ITaskOrganizer mTaskOrganizer; 79 DeathRecipient(ITaskOrganizer organizer)80 DeathRecipient(ITaskOrganizer organizer) { 81 mTaskOrganizer = organizer; 82 } 83 84 @Override binderDied()85 public void binderDied() { 86 synchronized (mGlobalLock) { 87 final TaskOrganizerState state = mTaskOrganizerStates.get( 88 mTaskOrganizer.asBinder()); 89 if (state != null) { 90 state.dispose(); 91 } 92 } 93 } 94 } 95 96 /** 97 * A wrapper class around ITaskOrganizer to ensure that the calls are made in the right 98 * lifecycle order since we may be updating the visibility of task surface controls in a pending 99 * transaction before they are presented to the task org. 100 */ 101 private static class TaskOrganizerCallbacks { 102 final ITaskOrganizer mTaskOrganizer; 103 TaskOrganizerCallbacks(ITaskOrganizer taskOrg)104 TaskOrganizerCallbacks(ITaskOrganizer taskOrg) { 105 mTaskOrganizer = taskOrg; 106 } 107 getBinder()108 IBinder getBinder() { 109 return mTaskOrganizer.asBinder(); 110 } 111 prepareLeash(Task task, String reason)112 SurfaceControl prepareLeash(Task task, String reason) { 113 return new SurfaceControl(task.getSurfaceControl(), reason); 114 } 115 onTaskAppeared(Task task)116 void onTaskAppeared(Task task) { 117 ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Task appeared taskId=%d", task.mTaskId); 118 final RunningTaskInfo taskInfo = task.getTaskInfo(); 119 try { 120 mTaskOrganizer.onTaskAppeared(taskInfo, prepareLeash(task, 121 "TaskOrganizerController.onTaskAppeared")); 122 } catch (RemoteException e) { 123 Slog.e(TAG, "Exception sending onTaskAppeared callback", e); 124 } 125 } 126 onTaskVanished(Task task)127 void onTaskVanished(Task task) { 128 ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Task vanished taskId=%d", task.mTaskId); 129 final RunningTaskInfo taskInfo = task.getTaskInfo(); 130 try { 131 mTaskOrganizer.onTaskVanished(taskInfo); 132 } catch (RemoteException e) { 133 Slog.e(TAG, "Exception sending onTaskVanished callback", e); 134 } 135 } 136 onTaskInfoChanged(Task task, ActivityManager.RunningTaskInfo taskInfo)137 void onTaskInfoChanged(Task task, ActivityManager.RunningTaskInfo taskInfo) { 138 if (!task.mTaskAppearedSent) { 139 // Skip if the task has not yet received taskAppeared(). 140 return; 141 } 142 ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Task info changed taskId=%d", task.mTaskId); 143 if (!task.isOrganized()) { 144 // This is safe to ignore if the task is no longer organized 145 return; 146 } 147 try { 148 // Purposely notify of task info change immediately instead of deferring (like 149 // appear and vanish) to allow info changes (such as new PIP params) to flow 150 // without waiting. 151 mTaskOrganizer.onTaskInfoChanged(taskInfo); 152 } catch (RemoteException e) { 153 Slog.e(TAG, "Exception sending onTaskInfoChanged callback", e); 154 } 155 } 156 onBackPressedOnTaskRoot(Task task)157 void onBackPressedOnTaskRoot(Task task) { 158 ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Task back pressed on root taskId=%d", 159 task.mTaskId); 160 if (!task.mTaskAppearedSent) { 161 // Skip if the task has not yet received taskAppeared(). 162 return; 163 } 164 if (!task.isOrganized()) { 165 // This is safe to ignore if the task is no longer organized 166 return; 167 } 168 try { 169 mTaskOrganizer.onBackPressedOnTaskRoot(task.getTaskInfo()); 170 } catch (Exception e) { 171 Slog.e(TAG, "Exception sending onBackPressedOnTaskRoot callback", e); 172 } 173 } 174 } 175 176 /** 177 * Maintains a list of all the pending events for a given {@link android.window.TaskOrganizer} 178 */ 179 static final class TaskOrganizerPendingEventsQueue { 180 private final WeakHashMap<Task, RunningTaskInfo> mLastSentTaskInfos = new WeakHashMap<>(); 181 private final TaskOrganizerState mOrganizerState; 182 private RunningTaskInfo mTmpTaskInfo; 183 // Pending task events due to layout deferred. 184 private final ArrayList<PendingTaskEvent> mPendingTaskEvents = new ArrayList<>(); 185 TaskOrganizerPendingEventsQueue(TaskOrganizerState taskOrganizerState)186 TaskOrganizerPendingEventsQueue(TaskOrganizerState taskOrganizerState) { 187 mOrganizerState = taskOrganizerState; 188 } 189 190 @VisibleForTesting getPendingEventList()191 public ArrayList<PendingTaskEvent> getPendingEventList() { 192 return mPendingTaskEvents; 193 } 194 numPendingTaskEvents()195 int numPendingTaskEvents() { 196 return mPendingTaskEvents.size(); 197 } 198 clearPendingTaskEvents()199 void clearPendingTaskEvents() { 200 mPendingTaskEvents.clear(); 201 } 202 addPendingTaskEvent(PendingTaskEvent event)203 void addPendingTaskEvent(PendingTaskEvent event) { 204 mPendingTaskEvents.add(event); 205 } 206 removePendingTaskEvent(PendingTaskEvent event)207 void removePendingTaskEvent(PendingTaskEvent event) { 208 mPendingTaskEvents.remove(event); 209 } 210 211 /** 212 * Removes all the pending task events for the given {@code task}. 213 * 214 * @param task 215 * @return true if a {@link PendingTaskEvent#EVENT_APPEARED} is still pending for the given 216 * {code task}. 217 */ removePendingTaskEvents(Task task)218 boolean removePendingTaskEvents(Task task) { 219 boolean foundPendingAppearedEvents = false; 220 for (int i = mPendingTaskEvents.size() - 1; i >= 0; i--) { 221 PendingTaskEvent entry = mPendingTaskEvents.get(i); 222 if (task.mTaskId == entry.mTask.mTaskId) { 223 // This task is vanished so remove all pending event of it. 224 mPendingTaskEvents.remove(i); 225 226 if (entry.mEventType == PendingTaskEvent.EVENT_APPEARED) { 227 foundPendingAppearedEvents = true; 228 } 229 } 230 } 231 return foundPendingAppearedEvents; 232 } 233 234 @Nullable getPendingTaskEvent(Task task, int type)235 private PendingTaskEvent getPendingTaskEvent(Task task, int type) { 236 for (int i = mPendingTaskEvents.size() - 1; i >= 0; i--) { 237 PendingTaskEvent entry = mPendingTaskEvents.get(i); 238 if (task.mTaskId == entry.mTask.mTaskId && type == entry.mEventType) { 239 return entry; 240 } 241 } 242 return null; 243 } 244 245 @VisibleForTesting 246 @Nullable getPendingLifecycleTaskEvent(Task task)247 PendingTaskEvent getPendingLifecycleTaskEvent(Task task) { 248 for (int i = mPendingTaskEvents.size() - 1; i >= 0; i--) { 249 PendingTaskEvent entry = mPendingTaskEvents.get(i); 250 if (task.mTaskId == entry.mTask.mTaskId && entry.isLifecycleEvent()) { 251 return entry; 252 } 253 } 254 return null; 255 } 256 dispatchPendingEvents()257 void dispatchPendingEvents() { 258 if (mPendingTaskEvents.isEmpty()) { 259 return; 260 } 261 for (int i = 0, n = mPendingTaskEvents.size(); i < n; i++) { 262 dispatchPendingEvent(mPendingTaskEvents.get(i)); 263 } 264 mPendingTaskEvents.clear(); 265 } 266 dispatchPendingEvent(PendingTaskEvent event)267 private void dispatchPendingEvent(PendingTaskEvent event) { 268 final Task task = event.mTask; 269 switch (event.mEventType) { 270 case PendingTaskEvent.EVENT_APPEARED: 271 if (task.taskAppearedReady()) { 272 mOrganizerState.mOrganizer.onTaskAppeared(task); 273 } 274 break; 275 case PendingTaskEvent.EVENT_VANISHED: 276 mOrganizerState.mOrganizer.onTaskVanished(task); 277 mLastSentTaskInfos.remove(task); 278 break; 279 case PendingTaskEvent.EVENT_INFO_CHANGED: 280 dispatchTaskInfoChanged(event.mTask, event.mForce); 281 break; 282 case PendingTaskEvent.EVENT_ROOT_BACK_PRESSED: 283 mOrganizerState.mOrganizer.onBackPressedOnTaskRoot(task); 284 break; 285 } 286 } 287 dispatchTaskInfoChanged(Task task, boolean force)288 private void dispatchTaskInfoChanged(Task task, boolean force) { 289 RunningTaskInfo lastInfo = mLastSentTaskInfos.get(task); 290 if (mTmpTaskInfo == null) { 291 mTmpTaskInfo = new RunningTaskInfo(); 292 } 293 mTmpTaskInfo.configuration.unset(); 294 task.fillTaskInfo(mTmpTaskInfo); 295 296 boolean changed = !mTmpTaskInfo 297 .equalsForTaskOrganizer(lastInfo) 298 || !configurationsAreEqualForOrganizer( 299 mTmpTaskInfo.configuration, 300 lastInfo.configuration); 301 if (!(changed || force)) { 302 // mTmpTaskInfo will be reused next time. 303 return; 304 } 305 final RunningTaskInfo newInfo = mTmpTaskInfo; 306 mLastSentTaskInfos.put(task, 307 mTmpTaskInfo); 308 // Since we've stored this, clean up the reference so a new one will be created next 309 // time. 310 // Transferring it this way means we only have to construct new RunningTaskInfos when 311 // they change. 312 mTmpTaskInfo = null; 313 314 if (task.isOrganized()) { 315 // Because we defer sending taskAppeared() until the app has drawn, we may receive a 316 // configuration change before the state actually has the task registered. As such 317 // we should ignore these change events to the organizer until taskAppeared(). If 318 // the task was created by the organizer, then we always send the info change. 319 mOrganizerState.mOrganizer.onTaskInfoChanged(task, newInfo); 320 } 321 } 322 } 323 324 @VisibleForTesting 325 class TaskOrganizerState { 326 private final TaskOrganizerCallbacks mOrganizer; 327 private final DeathRecipient mDeathRecipient; 328 private final ArrayList<Task> mOrganizedTasks = new ArrayList<>(); 329 private final TaskOrganizerPendingEventsQueue mPendingEventsQueue; 330 private final int mUid; 331 TaskOrganizerState(ITaskOrganizer organizer, int uid)332 TaskOrganizerState(ITaskOrganizer organizer, int uid) { 333 mOrganizer = new TaskOrganizerCallbacks(organizer); 334 mDeathRecipient = new DeathRecipient(organizer); 335 mPendingEventsQueue = new TaskOrganizerPendingEventsQueue(this); 336 try { 337 organizer.asBinder().linkToDeath(mDeathRecipient, 0); 338 } catch (RemoteException e) { 339 Slog.e(TAG, "TaskOrganizer failed to register death recipient"); 340 } 341 mUid = uid; 342 } 343 344 @VisibleForTesting getDeathRecipient()345 DeathRecipient getDeathRecipient() { 346 return mDeathRecipient; 347 } 348 349 @VisibleForTesting getPendingEventsQueue()350 TaskOrganizerPendingEventsQueue getPendingEventsQueue() { 351 return mPendingEventsQueue; 352 } 353 354 /** 355 * Register this task with this state, but doesn't trigger the task appeared callback to 356 * the organizer. 357 */ addTaskWithoutCallback(Task t, String reason)358 SurfaceControl addTaskWithoutCallback(Task t, String reason) { 359 t.mTaskAppearedSent = true; 360 if (!mOrganizedTasks.contains(t)) { 361 mOrganizedTasks.add(t); 362 } 363 return mOrganizer.prepareLeash(t, reason); 364 } 365 addTask(Task t)366 private boolean addTask(Task t) { 367 if (t.mTaskAppearedSent) { 368 return false; 369 } 370 371 if (!mOrganizedTasks.contains(t)) { 372 mOrganizedTasks.add(t); 373 } 374 375 if (t.taskAppearedReady()) { 376 t.mTaskAppearedSent = true; 377 return true; 378 } 379 return false; 380 } 381 removeTask(Task t, boolean removeFromSystem)382 private boolean removeTask(Task t, boolean removeFromSystem) { 383 mOrganizedTasks.remove(t); 384 mInterceptBackPressedOnRootTasks.remove(t.mTaskId); 385 boolean taskAppearedSent = t.mTaskAppearedSent; 386 if (taskAppearedSent) { 387 if (t.getSurfaceControl() != null) { 388 t.migrateToNewSurfaceControl(t.getSyncTransaction()); 389 } 390 t.mTaskAppearedSent = false; 391 } 392 if (removeFromSystem) { 393 mService.removeTask(t); 394 } 395 return taskAppearedSent; 396 } 397 dispose()398 void dispose() { 399 // Move organizer from managing specific windowing modes 400 mTaskOrganizers.remove(mOrganizer.mTaskOrganizer); 401 402 // Update tasks currently managed by this organizer to the next one available if 403 // possible. 404 while (!mOrganizedTasks.isEmpty()) { 405 final Task t = mOrganizedTasks.get(0); 406 if (t.mCreatedByOrganizer) { 407 // The tasks created by this organizer should ideally be deleted when this 408 // organizer is disposed off to avoid inconsistent behavior. 409 t.removeImmediately(); 410 } else { 411 t.updateTaskOrganizerState(); 412 } 413 if (mOrganizedTasks.contains(t)) { 414 // updateTaskOrganizerState should remove the task from the list, but still 415 // check it again to avoid while-loop isn't terminate. 416 if (removeTask(t, t.mRemoveWithTaskOrganizer)) { 417 TaskOrganizerController.this.onTaskVanishedInternal(this, t); 418 } 419 } 420 if (mService.getTransitionController().isShellTransitionsEnabled()) { 421 // dispose is only called outside of transitions (eg during unregister). Since 422 // we "migrate" surfaces when replacing organizers, visibility gets delegated 423 // to transitions; however, since there is no transition at this point, we have 424 // to manually show the surface here. 425 if (t.mTaskOrganizer != null && t.getSurfaceControl() != null) { 426 t.getSyncTransaction().show(t.getSurfaceControl()); 427 } 428 } 429 } 430 431 // Pending events queue for this organizer need to be cleared because this organizer 432 // has either died or unregistered itself. 433 mPendingEventsQueue.clearPendingTaskEvents(); 434 mTaskOrganizerStates.remove(mOrganizer.getBinder()); 435 } 436 unlinkDeath()437 void unlinkDeath() { 438 mOrganizer.getBinder().unlinkToDeath(mDeathRecipient, 0); 439 } 440 } 441 442 static class PendingTaskEvent { 443 static final int EVENT_APPEARED = 0; 444 static final int EVENT_VANISHED = 1; 445 static final int EVENT_INFO_CHANGED = 2; 446 static final int EVENT_ROOT_BACK_PRESSED = 3; 447 448 final int mEventType; 449 final Task mTask; 450 final ITaskOrganizer mTaskOrg; 451 boolean mForce; 452 PendingTaskEvent(Task task, int event)453 PendingTaskEvent(Task task, int event) { 454 this(task, task.mTaskOrganizer, event); 455 } 456 PendingTaskEvent(Task task, ITaskOrganizer taskOrg, int eventType)457 PendingTaskEvent(Task task, ITaskOrganizer taskOrg, int eventType) { 458 mTask = task; 459 mTaskOrg = taskOrg; 460 mEventType = eventType; 461 } 462 isLifecycleEvent()463 boolean isLifecycleEvent() { 464 return mEventType == EVENT_APPEARED || mEventType == EVENT_VANISHED 465 || mEventType == EVENT_INFO_CHANGED; 466 } 467 } 468 469 private final ActivityTaskManagerService mService; 470 private final WindowManagerGlobalLock mGlobalLock; 471 472 // List of task organizers by priority 473 private final ArrayDeque<ITaskOrganizer> mTaskOrganizers = new ArrayDeque<>(); 474 private final ArrayMap<IBinder, TaskOrganizerState> mTaskOrganizerStates = new ArrayMap<>(); 475 // Set of organized tasks (by taskId) that dispatch back pressed to their organizers 476 private final HashSet<Integer> mInterceptBackPressedOnRootTasks = new HashSet<>(); 477 TaskOrganizerController(ActivityTaskManagerService atm)478 TaskOrganizerController(ActivityTaskManagerService atm) { 479 mService = atm; 480 mGlobalLock = atm.mGlobalLock; 481 } 482 483 @Override onTransact(int code, Parcel data, Parcel reply, int flags)484 public boolean onTransact(int code, Parcel data, Parcel reply, int flags) 485 throws RemoteException { 486 try { 487 return super.onTransact(code, data, reply, flags); 488 } catch (RuntimeException e) { 489 throw ActivityTaskManagerService.logAndRethrowRuntimeExceptionOnTransact(TAG, e); 490 } 491 } 492 493 /** 494 * Register a TaskOrganizer to manage tasks as they enter the a supported windowing mode. 495 */ 496 @Override registerTaskOrganizer(ITaskOrganizer organizer)497 public ParceledListSlice<TaskAppearedInfo> registerTaskOrganizer(ITaskOrganizer organizer) { 498 enforceTaskPermission("registerTaskOrganizer()"); 499 final int uid = Binder.getCallingUid(); 500 final long origId = Binder.clearCallingIdentity(); 501 try { 502 final ArrayList<TaskAppearedInfo> taskInfos = new ArrayList<>(); 503 final Runnable withGlobalLock = () -> { 504 ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Register task organizer=%s uid=%d", 505 organizer.asBinder(), uid); 506 if (!mTaskOrganizerStates.containsKey(organizer.asBinder())) { 507 mTaskOrganizers.add(organizer); 508 mTaskOrganizerStates.put(organizer.asBinder(), 509 new TaskOrganizerState(organizer, uid)); 510 } 511 512 final TaskOrganizerState state = mTaskOrganizerStates.get(organizer.asBinder()); 513 mService.mRootWindowContainer.forAllTasks((task) -> { 514 boolean returnTask = !task.mCreatedByOrganizer; 515 task.updateTaskOrganizerState(returnTask /* skipTaskAppeared */); 516 // It is possible for the task to not yet have a surface control, so ensure that 517 // the update succeeded in setting the organizer for the task before returning 518 if (task.isOrganized() && returnTask) { 519 SurfaceControl taskLeash = state.addTaskWithoutCallback(task, 520 "TaskOrganizerController.registerTaskOrganizer"); 521 taskInfos.add(new TaskAppearedInfo(task.getTaskInfo(), taskLeash)); 522 } 523 }); 524 }; 525 if (mService.getTransitionController().isShellTransitionsEnabled()) { 526 mService.getTransitionController().mRunningLock.runWhenIdle(1000, withGlobalLock); 527 } else { 528 synchronized (mGlobalLock) { 529 withGlobalLock.run(); 530 } 531 } 532 return new ParceledListSlice<>(taskInfos); 533 } finally { 534 Binder.restoreCallingIdentity(origId); 535 } 536 } 537 538 @Override unregisterTaskOrganizer(ITaskOrganizer organizer)539 public void unregisterTaskOrganizer(ITaskOrganizer organizer) { 540 enforceTaskPermission("unregisterTaskOrganizer()"); 541 final int uid = Binder.getCallingUid(); 542 final long origId = Binder.clearCallingIdentity(); 543 try { 544 final Runnable withGlobalLock = () -> { 545 final TaskOrganizerState state = mTaskOrganizerStates.get(organizer.asBinder()); 546 if (state == null) { 547 return; 548 } 549 ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Unregister task organizer=%s uid=%d", 550 organizer.asBinder(), uid); 551 state.unlinkDeath(); 552 state.dispose(); 553 }; 554 if (mService.getTransitionController().isShellTransitionsEnabled()) { 555 mService.getTransitionController().mRunningLock.runWhenIdle(1000, withGlobalLock); 556 } else { 557 synchronized (mGlobalLock) { 558 withGlobalLock.run(); 559 } 560 } 561 } finally { 562 Binder.restoreCallingIdentity(origId); 563 } 564 } 565 566 /** 567 * @return the task organizer key for a given windowing mode. 568 */ getTaskOrganizer()569 ITaskOrganizer getTaskOrganizer() { 570 return mTaskOrganizers.peekLast(); 571 } 572 573 // Capture the animation surface control for activity's main window 574 static class StartingWindowAnimationAdaptor implements AnimationAdapter { 575 576 @Override getShowWallpaper()577 public boolean getShowWallpaper() { 578 return false; 579 } 580 581 @Override startAnimation(SurfaceControl animationLeash, SurfaceControl.Transaction t, int type, @NonNull SurfaceAnimator.OnAnimationFinishedCallback finishCallback)582 public void startAnimation(SurfaceControl animationLeash, SurfaceControl.Transaction t, 583 int type, @NonNull SurfaceAnimator.OnAnimationFinishedCallback finishCallback) { 584 } 585 586 @Override onAnimationCancelled(SurfaceControl animationLeash)587 public void onAnimationCancelled(SurfaceControl animationLeash) { 588 } 589 590 @Override getDurationHint()591 public long getDurationHint() { 592 return 0; 593 } 594 595 @Override getStatusBarTransitionsStartTime()596 public long getStatusBarTransitionsStartTime() { 597 return 0; 598 } 599 600 @Override dump(PrintWriter pw, String prefix)601 public void dump(PrintWriter pw, String prefix) { 602 } 603 604 @Override dumpDebug(ProtoOutputStream proto)605 public void dumpDebug(ProtoOutputStream proto) { 606 } 607 } 608 applyStartingWindowAnimation(WindowState window)609 static SurfaceControl applyStartingWindowAnimation(WindowState window) { 610 final SurfaceControl.Transaction t = window.getPendingTransaction(); 611 final StartingWindowAnimationAdaptor adaptor = new StartingWindowAnimationAdaptor(); 612 window.startAnimation(t, adaptor, false, ANIMATION_TYPE_STARTING_REVEAL); 613 final SurfaceControl leash = window.getAnimationLeash(); 614 if (leash == null) { 615 Slog.e(TAG, "Cannot start starting window animation, the window " + window 616 + " was removed"); 617 return null; 618 } 619 t.setPosition(leash, window.mSurfacePosition.x, window.mSurfacePosition.y); 620 return leash; 621 } 622 addStartingWindow(Task task, ActivityRecord activity, int launchTheme, TaskSnapshot taskSnapshot)623 boolean addStartingWindow(Task task, ActivityRecord activity, int launchTheme, 624 TaskSnapshot taskSnapshot) { 625 final Task rootTask = task.getRootTask(); 626 if (rootTask == null || activity.mStartingData == null) { 627 return false; 628 } 629 final ITaskOrganizer lastOrganizer = getTaskOrganizer(); 630 if (lastOrganizer == null) { 631 return false; 632 } 633 final StartingWindowInfo info = task.getStartingWindowInfo(activity); 634 if (launchTheme != 0) { 635 info.splashScreenThemeResId = launchTheme; 636 } 637 info.taskSnapshot = taskSnapshot; 638 info.appToken = activity.token; 639 // make this happen prior than prepare surface 640 try { 641 lastOrganizer.addStartingWindow(info); 642 } catch (RemoteException e) { 643 Slog.e(TAG, "Exception sending onTaskStart callback", e); 644 return false; 645 } 646 return true; 647 } 648 removeStartingWindow(Task task, ITaskOrganizer taskOrganizer, boolean prepareAnimation, boolean hasImeSurface)649 void removeStartingWindow(Task task, ITaskOrganizer taskOrganizer, boolean prepareAnimation, 650 boolean hasImeSurface) { 651 final Task rootTask = task.getRootTask(); 652 if (rootTask == null) { 653 return; 654 } 655 final ITaskOrganizer lastOrganizer = taskOrganizer != null ? taskOrganizer 656 : getTaskOrganizer(); 657 if (lastOrganizer == null) { 658 return; 659 } 660 final StartingWindowRemovalInfo removalInfo = new StartingWindowRemovalInfo(); 661 removalInfo.taskId = task.mTaskId; 662 removalInfo.playRevealAnimation = prepareAnimation 663 && task.getDisplayContent() != null 664 && task.getDisplayInfo().state == Display.STATE_ON; 665 final boolean playShiftUpAnimation = !task.inMultiWindowMode(); 666 final ActivityRecord topActivity = task.topActivityContainsStartingWindow(); 667 if (topActivity != null) { 668 // Set defer remove mode for IME 669 final DisplayContent dc = topActivity.getDisplayContent(); 670 if (hasImeSurface) { 671 if (topActivity.isVisibleRequested() && dc.mInputMethodWindow != null 672 && dc.isFixedRotationLaunchingApp(topActivity)) { 673 removalInfo.deferRemoveMode = DEFER_MODE_ROTATION; 674 } else { 675 removalInfo.deferRemoveMode = DEFER_MODE_NORMAL; 676 } 677 } 678 679 final WindowState mainWindow = 680 topActivity.findMainWindow(false/* includeStartingApp */); 681 // No app window for this activity, app might be crashed. 682 // Remove starting window immediately without playing reveal animation. 683 if (mainWindow == null || mainWindow.mRemoved) { 684 removalInfo.playRevealAnimation = false; 685 } else if (removalInfo.playRevealAnimation && playShiftUpAnimation) { 686 removalInfo.roundedCornerRadius = 687 topActivity.mAppCompatController.getLetterboxPolicy() 688 .getRoundedCornersRadius(mainWindow); 689 removalInfo.windowAnimationLeash = applyStartingWindowAnimation(mainWindow); 690 removalInfo.mainFrame = new Rect(mainWindow.getFrame()); 691 removalInfo.mainFrame.offsetTo(mainWindow.mSurfacePosition.x, 692 mainWindow.mSurfacePosition.y); 693 } 694 } 695 try { 696 lastOrganizer.removeStartingWindow(removalInfo); 697 } catch (RemoteException e) { 698 Slog.e(TAG, "Exception sending onStartTaskFinished callback", e); 699 } 700 } 701 702 /** 703 * Create a starting surface which attach on a given surface. 704 * @param activity Target activity, this isn't necessary to be the top activity. 705 * @param root The root surface which the created surface will attach on. 706 * @param taskSnapshot Whether to draw snapshot. 707 * @param callback Called when surface is drawn and attached to the root surface. 708 * @return The taskId, this is a token and should be used to remove the surface, even if 709 * the task was removed from hierarchy. 710 */ addWindowlessStartingSurface(Task task, ActivityRecord activity, SurfaceControl root, TaskSnapshot taskSnapshot, Configuration configuration, IWindowlessStartingSurfaceCallback callback)711 int addWindowlessStartingSurface(Task task, ActivityRecord activity, SurfaceControl root, 712 TaskSnapshot taskSnapshot, Configuration configuration, 713 IWindowlessStartingSurfaceCallback callback) { 714 final Task rootTask = task.getRootTask(); 715 if (rootTask == null) { 716 return INVALID_TASK_ID; 717 } 718 final ITaskOrganizer lastOrganizer = mTaskOrganizers.peekLast(); 719 if (lastOrganizer == null) { 720 return INVALID_TASK_ID; 721 } 722 final StartingWindowInfo info = task.getStartingWindowInfo(activity); 723 info.taskInfo.configuration.setTo(configuration); 724 info.taskInfo.taskDescription = activity.taskDescription; 725 info.taskSnapshot = taskSnapshot; 726 info.windowlessStartingSurfaceCallback = callback; 727 info.rootSurface = root; 728 try { 729 lastOrganizer.addStartingWindow(info); 730 } catch (RemoteException e) { 731 Slog.e(TAG, "Exception sending addWindowlessStartingSurface ", e); 732 return INVALID_TASK_ID; 733 } 734 return task.mTaskId; 735 } 736 removeWindowlessStartingSurface(int taskId, boolean immediately)737 void removeWindowlessStartingSurface(int taskId, boolean immediately) { 738 final ITaskOrganizer lastOrganizer = mTaskOrganizers.peekLast(); 739 if (lastOrganizer == null || taskId == 0) { 740 return; 741 } 742 final StartingWindowRemovalInfo removalInfo = new StartingWindowRemovalInfo(); 743 removalInfo.taskId = taskId; 744 removalInfo.windowlessSurface = true; 745 removalInfo.removeImmediately = immediately; 746 removalInfo.deferRemoveMode = DEFER_MODE_NONE; 747 try { 748 lastOrganizer.removeStartingWindow(removalInfo); 749 } catch (RemoteException e) { 750 Slog.e(TAG, "Exception sending removeWindowlessStartingSurface ", e); 751 } 752 } 753 copySplashScreenView(Task task, ITaskOrganizer taskOrganizer)754 boolean copySplashScreenView(Task task, ITaskOrganizer taskOrganizer) { 755 final Task rootTask = task.getRootTask(); 756 if (rootTask == null) { 757 return false; 758 } 759 final ITaskOrganizer lastOrganizer = taskOrganizer != null ? taskOrganizer 760 : getTaskOrganizer(); 761 if (lastOrganizer == null) { 762 return false; 763 } 764 try { 765 lastOrganizer.copySplashScreenView(task.mTaskId); 766 } catch (RemoteException e) { 767 Slog.e(TAG, "Exception sending copyStartingWindowView callback", e); 768 return false; 769 } 770 return true; 771 } 772 isSupportWindowlessStartingSurface()773 boolean isSupportWindowlessStartingSurface() { 774 final ITaskOrganizer lastOrganizer = mTaskOrganizers.peekLast(); 775 return lastOrganizer != null; 776 } 777 /** 778 * Notify the shell ({@link com.android.wm.shell.ShellTaskOrganizer} that the client has 779 * removed the splash screen view. 780 * @see com.android.wm.shell.ShellTaskOrganizer#onAppSplashScreenViewRemoved(int) 781 * @see SplashScreenView#remove() 782 */ onAppSplashScreenViewRemoved(Task task, ITaskOrganizer organizer)783 public void onAppSplashScreenViewRemoved(Task task, ITaskOrganizer organizer) { 784 final Task rootTask = task.getRootTask(); 785 if (rootTask == null) { 786 return; 787 } 788 final ITaskOrganizer lastOrganizer = organizer != null ? organizer : getTaskOrganizer(); 789 if (lastOrganizer == null) { 790 return; 791 } 792 try { 793 lastOrganizer.onAppSplashScreenViewRemoved(task.mTaskId); 794 } catch (RemoteException e) { 795 Slog.e(TAG, "Exception sending onAppSplashScreenViewRemoved callback", e); 796 } 797 } 798 onTaskAppeared(ITaskOrganizer organizer, Task task)799 void onTaskAppeared(ITaskOrganizer organizer, Task task) { 800 final TaskOrganizerState state = mTaskOrganizerStates.get(organizer.asBinder()); 801 if (state != null && state.addTask(task)) { 802 final TaskOrganizerPendingEventsQueue pendingEvents = 803 state.mPendingEventsQueue; 804 PendingTaskEvent pending = pendingEvents.getPendingTaskEvent(task, 805 PendingTaskEvent.EVENT_APPEARED); 806 if (pending == null) { 807 pendingEvents.addPendingTaskEvent(new PendingTaskEvent(task, 808 PendingTaskEvent.EVENT_APPEARED)); 809 } 810 } 811 } 812 onTaskVanished(ITaskOrganizer organizer, Task task)813 void onTaskVanished(ITaskOrganizer organizer, Task task) { 814 final TaskOrganizerState state = mTaskOrganizerStates.get(organizer.asBinder()); 815 if (state != null && state.removeTask(task, task.mRemoveWithTaskOrganizer)) { 816 onTaskVanishedInternal(state, task); 817 } 818 } 819 onTaskVanishedInternal(TaskOrganizerState organizerState, Task task)820 private void onTaskVanishedInternal(TaskOrganizerState organizerState, Task task) { 821 if (organizerState == null) { 822 Slog.i(TAG, "cannot send onTaskVanished because organizer state is not " 823 + "present for this organizer"); 824 return; 825 } 826 TaskOrganizerPendingEventsQueue pendingEventsQueue = 827 organizerState.mPendingEventsQueue; 828 boolean hadPendingAppearedEvents = 829 pendingEventsQueue.removePendingTaskEvents(task); 830 if (hadPendingAppearedEvents) { 831 return; 832 } 833 pendingEventsQueue.addPendingTaskEvent(new PendingTaskEvent(task, 834 organizerState.mOrganizer.mTaskOrganizer, PendingTaskEvent.EVENT_VANISHED)); 835 } 836 837 @Override createRootTask(int displayId, int windowingMode, @Nullable IBinder launchCookie, boolean removeWithTaskOrganizer)838 public void createRootTask(int displayId, int windowingMode, @Nullable IBinder launchCookie, 839 boolean removeWithTaskOrganizer) { 840 enforceTaskPermission("createRootTask()"); 841 final long origId = Binder.clearCallingIdentity(); 842 try { 843 synchronized (mGlobalLock) { 844 DisplayContent display = mService.mRootWindowContainer.getDisplayContent(displayId); 845 if (display == null) { 846 ProtoLog.e(WM_DEBUG_WINDOW_ORGANIZER, 847 "createRootTask unknown displayId=%d", displayId); 848 return; 849 } 850 851 createRootTask(display, windowingMode, launchCookie, removeWithTaskOrganizer); 852 } 853 } finally { 854 Binder.restoreCallingIdentity(origId); 855 } 856 } 857 858 @VisibleForTesting createRootTask(DisplayContent display, int windowingMode, @Nullable IBinder launchCookie)859 Task createRootTask(DisplayContent display, int windowingMode, @Nullable IBinder launchCookie) { 860 return createRootTask(display, windowingMode, launchCookie, 861 false /* removeWithTaskOrganizer */); 862 } 863 createRootTask(DisplayContent display, int windowingMode, @Nullable IBinder launchCookie, boolean removeWithTaskOrganizer)864 Task createRootTask(DisplayContent display, int windowingMode, @Nullable IBinder launchCookie, 865 boolean removeWithTaskOrganizer) { 866 ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Create root task displayId=%d winMode=%d", 867 display.mDisplayId, windowingMode); 868 // We want to defer the task appear signal until the task is fully created and attached to 869 // to the hierarchy so that the complete starting configuration is in the task info we send 870 // over to the organizer. 871 final Task task = new Task.Builder(mService) 872 .setWindowingMode(windowingMode) 873 .setIntent(new Intent()) 874 .setCreatedByOrganizer(true) 875 .setDeferTaskAppear(true) 876 .setLaunchCookie(launchCookie) 877 .setParent(display.getDefaultTaskDisplayArea()) 878 .setRemoveWithTaskOrganizer(removeWithTaskOrganizer) 879 .build(); 880 task.setDeferTaskAppear(false /* deferTaskAppear */); 881 return task; 882 } 883 884 @Override deleteRootTask(WindowContainerToken token)885 public boolean deleteRootTask(WindowContainerToken token) { 886 enforceTaskPermission("deleteRootTask()"); 887 final long origId = Binder.clearCallingIdentity(); 888 try { 889 synchronized (mGlobalLock) { 890 final WindowContainer wc = WindowContainer.fromBinder(token.asBinder()); 891 if (wc == null) return false; 892 final Task task = wc.asTask(); 893 if (task == null) return false; 894 if (!task.mCreatedByOrganizer) { 895 throw new IllegalArgumentException( 896 "Attempt to delete task not created by organizer task=" + task); 897 } 898 899 ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Delete root task display=%d winMode=%d", 900 task.getDisplayId(), task.getWindowingMode()); 901 task.remove(true /* withTransition */, "deleteRootTask"); 902 return true; 903 } 904 } finally { 905 Binder.restoreCallingIdentity(origId); 906 } 907 } 908 dispatchPendingEvents()909 void dispatchPendingEvents() { 910 if (mService.mWindowManager.mWindowPlacerLocked.isLayoutDeferred()) { 911 return; 912 } 913 for (int taskOrgIdx = 0; taskOrgIdx < mTaskOrganizerStates.size(); taskOrgIdx++) { 914 TaskOrganizerState taskOrganizerState = mTaskOrganizerStates.valueAt(taskOrgIdx); 915 taskOrganizerState.mPendingEventsQueue.dispatchPendingEvents(); 916 } 917 } 918 reportImeDrawnOnTask(Task task)919 void reportImeDrawnOnTask(Task task) { 920 final TaskOrganizerState state = mTaskOrganizerStates.get(task.mTaskOrganizer.asBinder()); 921 if (state != null) { 922 try { 923 state.mOrganizer.mTaskOrganizer.onImeDrawnOnTask(task.mTaskId); 924 } catch (RemoteException e) { 925 Slog.e(TAG, "Exception sending onImeDrawnOnTask callback", e); 926 } 927 } 928 } 929 onTaskInfoChanged(Task task, boolean force)930 void onTaskInfoChanged(Task task, boolean force) { 931 if (!task.mTaskAppearedSent) { 932 // Skip if task still not appeared. 933 return; 934 } 935 final TaskOrganizerState taskOrganizerState = 936 mTaskOrganizerStates.get(task.mTaskOrganizer.asBinder()); 937 final TaskOrganizerPendingEventsQueue pendingEventsQueue = 938 taskOrganizerState.mPendingEventsQueue; 939 if (pendingEventsQueue == null) { 940 Slog.i(TAG, "cannot send onTaskInfoChanged because pending events queue is not " 941 + "present for this organizer"); 942 return; 943 } 944 if (force && pendingEventsQueue.numPendingTaskEvents() == 0) { 945 // There are task-info changed events do not result in 946 // - RootWindowContainer#performSurfacePlacementNoTrace OR 947 // - WindowAnimator#animate 948 // For instance, when an app requesting aspect ratio change when in PiP mode. 949 // To solve this, we directly dispatch the pending event if there are no events queued ( 950 // otherwise, all pending events should be dispatched on next drawn). 951 pendingEventsQueue.dispatchTaskInfoChanged(task, true /* force */); 952 return; 953 } 954 955 // Defer task info reporting while layout is deferred. This is because layout defer 956 // blocks tend to do lots of re-ordering which can mess up animations in receivers. 957 PendingTaskEvent pending = pendingEventsQueue 958 .getPendingLifecycleTaskEvent(task); 959 if (pending == null) { 960 pending = new PendingTaskEvent(task, PendingTaskEvent.EVENT_INFO_CHANGED); 961 } else { 962 if (pending.mEventType != PendingTaskEvent.EVENT_INFO_CHANGED) { 963 // If queued event is appeared, it means task still not appeared so ignore 964 // this info changed. If queued event is vanished, it means task should 965 // will vanished early so do not need this info changed. 966 return; 967 } 968 // Remove and add for re-ordering. 969 pendingEventsQueue.removePendingTaskEvent(pending); 970 } 971 pending.mForce |= force; 972 pendingEventsQueue.addPendingTaskEvent(pending); 973 } 974 975 @Override getImeTarget(int displayId)976 public WindowContainerToken getImeTarget(int displayId) { 977 enforceTaskPermission("getImeTarget()"); 978 final long origId = Binder.clearCallingIdentity(); 979 try { 980 synchronized (mGlobalLock) { 981 final DisplayContent dc = mService.mWindowManager.mRoot 982 .getDisplayContent(displayId); 983 if (dc == null) { 984 return null; 985 } 986 987 final InsetsControlTarget imeLayeringTarget = dc.getImeTarget(IME_TARGET_LAYERING); 988 if (imeLayeringTarget == null || imeLayeringTarget.getWindow() == null) { 989 return null; 990 } 991 992 // Avoid WindowState#getRootTask() so we don't attribute system windows to a task. 993 final Task task = imeLayeringTarget.getWindow().getTask(); 994 if (task == null) { 995 return null; 996 } 997 998 return task.mRemoteToken.toWindowContainerToken(); 999 } 1000 } finally { 1001 Binder.restoreCallingIdentity(origId); 1002 } 1003 } 1004 1005 @Override getChildTasks(WindowContainerToken parent, @Nullable int[] activityTypes)1006 public List<RunningTaskInfo> getChildTasks(WindowContainerToken parent, 1007 @Nullable int[] activityTypes) { 1008 enforceTaskPermission("getChildTasks()"); 1009 final long ident = Binder.clearCallingIdentity(); 1010 try { 1011 synchronized (mGlobalLock) { 1012 if (parent == null) { 1013 throw new IllegalArgumentException("Can't get children of null parent"); 1014 } 1015 final WindowContainer container = WindowContainer.fromBinder(parent.asBinder()); 1016 if (container == null) { 1017 Slog.e(TAG, "Can't get children of " + parent + " because it is not valid."); 1018 return null; 1019 } 1020 final Task task = container.asTask(); 1021 if (task == null) { 1022 Slog.e(TAG, container + " is not a task..."); 1023 return null; 1024 } 1025 // For now, only support returning children of tasks created by the organizer. 1026 if (!task.mCreatedByOrganizer) { 1027 Slog.w(TAG, "Can only get children of root tasks created via createRootTask"); 1028 return null; 1029 } 1030 ArrayList<RunningTaskInfo> out = new ArrayList<>(); 1031 for (int i = task.getChildCount() - 1; i >= 0; --i) { 1032 final Task child = task.getChildAt(i).asTask(); 1033 if (child == null) continue; 1034 if (activityTypes != null 1035 && !ArrayUtils.contains(activityTypes, child.getActivityType())) { 1036 continue; 1037 } 1038 out.add(child.getTaskInfo()); 1039 } 1040 return out; 1041 } 1042 } finally { 1043 Binder.restoreCallingIdentity(ident); 1044 } 1045 } 1046 1047 @Override getRootTasks(int displayId, @Nullable int[] activityTypes)1048 public List<RunningTaskInfo> getRootTasks(int displayId, @Nullable int[] activityTypes) { 1049 enforceTaskPermission("getRootTasks()"); 1050 final long ident = Binder.clearCallingIdentity(); 1051 try { 1052 synchronized (mGlobalLock) { 1053 final DisplayContent dc = 1054 mService.mRootWindowContainer.getDisplayContent(displayId); 1055 if (dc == null) { 1056 throw new IllegalArgumentException("Display " + displayId + " doesn't exist"); 1057 } 1058 final ArrayList<RunningTaskInfo> out = new ArrayList<>(); 1059 dc.forAllRootTasks(task -> { 1060 if (activityTypes != null 1061 && !ArrayUtils.contains(activityTypes, task.getActivityType())) { 1062 return; 1063 } 1064 out.add(task.getTaskInfo()); 1065 }); 1066 return out; 1067 } 1068 } finally { 1069 Binder.restoreCallingIdentity(ident); 1070 } 1071 } 1072 1073 @Override setInterceptBackPressedOnTaskRoot(WindowContainerToken token, boolean interceptBackPressed)1074 public void setInterceptBackPressedOnTaskRoot(WindowContainerToken token, 1075 boolean interceptBackPressed) { 1076 enforceTaskPermission("setInterceptBackPressedOnTaskRoot()"); 1077 final long origId = Binder.clearCallingIdentity(); 1078 try { 1079 synchronized (mGlobalLock) { 1080 ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Set intercept back pressed on root=%b", 1081 interceptBackPressed); 1082 final WindowContainer wc = WindowContainer.fromBinder(token.asBinder()); 1083 if (wc == null) { 1084 Slog.w(TAG, "Could not resolve window from token"); 1085 return; 1086 } 1087 final Task task = wc.asTask(); 1088 if (task == null) { 1089 Slog.w(TAG, "Could not resolve task from token"); 1090 return; 1091 } 1092 if (interceptBackPressed) { 1093 mInterceptBackPressedOnRootTasks.add(task.mTaskId); 1094 } else { 1095 mInterceptBackPressedOnRootTasks.remove(task.mTaskId); 1096 } 1097 } 1098 } finally { 1099 Binder.restoreCallingIdentity(origId); 1100 } 1101 } 1102 1103 @Override restartTaskTopActivityProcessIfVisible(WindowContainerToken token)1104 public void restartTaskTopActivityProcessIfVisible(WindowContainerToken token) { 1105 enforceTaskPermission("restartTopActivityProcessIfVisible()"); 1106 final long origId = Binder.clearCallingIdentity(); 1107 try { 1108 synchronized (mGlobalLock) { 1109 final WindowContainer wc = WindowContainer.fromBinder(token.asBinder()); 1110 if (wc == null) { 1111 Slog.w(TAG, "Could not resolve window from token"); 1112 return; 1113 } 1114 final Task task = wc.asTask(); 1115 if (task == null) { 1116 Slog.w(TAG, "Could not resolve task from token"); 1117 return; 1118 } 1119 ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, 1120 "Restart top activity process of Task taskId=%d", task.mTaskId); 1121 final ActivityRecord activity = task.getTopNonFinishingActivity(); 1122 if (activity != null) { 1123 activity.restartProcessIfVisible(); 1124 } 1125 } 1126 } finally { 1127 Binder.restoreCallingIdentity(origId); 1128 } 1129 } 1130 handleInterceptBackPressedOnTaskRoot(Task task)1131 public boolean handleInterceptBackPressedOnTaskRoot(Task task) { 1132 if (!shouldInterceptBackPressedOnRootTask(task)) { 1133 return false; 1134 } 1135 final TaskOrganizerPendingEventsQueue pendingEventsQueue = 1136 mTaskOrganizerStates.get(task.mTaskOrganizer.asBinder()) 1137 .mPendingEventsQueue; 1138 if (pendingEventsQueue == null) { 1139 Slog.w(TAG, "cannot get handle BackPressedOnTaskRoot because organizerState is " 1140 + "not present"); 1141 return false; 1142 } 1143 1144 PendingTaskEvent pendingVanished = 1145 pendingEventsQueue.getPendingTaskEvent(task, 1146 PendingTaskEvent.EVENT_VANISHED); 1147 if (pendingVanished != null) { 1148 // This task will vanish before this callback so just ignore. 1149 return false; 1150 } 1151 1152 PendingTaskEvent pending = pendingEventsQueue.getPendingTaskEvent( 1153 task, PendingTaskEvent.EVENT_ROOT_BACK_PRESSED); 1154 if (pending == null) { 1155 pending = new PendingTaskEvent(task, PendingTaskEvent.EVENT_ROOT_BACK_PRESSED); 1156 } else { 1157 // Pending already exist, remove and add for re-ordering. 1158 pendingEventsQueue.removePendingTaskEvent(pending); 1159 } 1160 pendingEventsQueue.addPendingTaskEvent(pending); 1161 mService.mWindowManager.mWindowPlacerLocked.requestTraversal(); 1162 return true; 1163 } 1164 shouldInterceptBackPressedOnRootTask(Task task)1165 boolean shouldInterceptBackPressedOnRootTask(Task task) { 1166 return task != null && task.isOrganized() 1167 && mInterceptBackPressedOnRootTasks.contains(task.mTaskId); 1168 } 1169 dump(PrintWriter pw, String prefix)1170 public void dump(PrintWriter pw, String prefix) { 1171 final String innerPrefix = prefix + " "; 1172 pw.print(prefix); pw.println("TaskOrganizerController:"); 1173 final ITaskOrganizer lastOrganizer = mTaskOrganizers.peekLast(); 1174 for (ITaskOrganizer organizer : mTaskOrganizers) { 1175 final TaskOrganizerState state = mTaskOrganizerStates.get(organizer.asBinder()); 1176 final ArrayList<Task> tasks = state.mOrganizedTasks; 1177 pw.print(innerPrefix + " "); 1178 pw.print(state.mOrganizer.mTaskOrganizer + " uid=" + state.mUid); 1179 if (lastOrganizer == organizer) { 1180 pw.print(" (active)"); 1181 } 1182 pw.println(':'); 1183 for (int k = 0; k < tasks.size(); k++) { 1184 final Task task = tasks.get(k); 1185 final int mode = task.getWindowingMode(); 1186 pw.println(innerPrefix + " (" 1187 + WindowConfiguration.windowingModeToString(mode) + ") " + task); 1188 } 1189 1190 } 1191 pw.println(); 1192 } 1193 1194 @VisibleForTesting getTaskOrganizerState(IBinder taskOrganizer)1195 TaskOrganizerState getTaskOrganizerState(IBinder taskOrganizer) { 1196 return mTaskOrganizerStates.get(taskOrganizer); 1197 } 1198 1199 @VisibleForTesting getTaskOrganizerPendingEvents(IBinder taskOrganizer)1200 TaskOrganizerPendingEventsQueue getTaskOrganizerPendingEvents(IBinder taskOrganizer) { 1201 return mTaskOrganizerStates.get(taskOrganizer).mPendingEventsQueue; 1202 } 1203 } 1204