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