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.app.CameraCompatTaskInfo.cameraCompatControlStateToString; 21 import static android.window.StartingWindowRemovalInfo.DEFER_MODE_NONE; 22 import static android.window.StartingWindowRemovalInfo.DEFER_MODE_NORMAL; 23 import static android.window.StartingWindowRemovalInfo.DEFER_MODE_ROTATION; 24 25 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_ORGANIZER; 26 import static com.android.server.wm.ActivityTaskManagerService.enforceTaskPermission; 27 import static com.android.server.wm.DisplayContent.IME_TARGET_LAYERING; 28 import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_STARTING_REVEAL; 29 import static com.android.server.wm.WindowOrganizerController.configurationsAreEqualForOrganizer; 30 31 import android.annotation.NonNull; 32 import android.annotation.Nullable; 33 import android.app.ActivityManager; 34 import android.app.ActivityManager.RunningTaskInfo; 35 import android.app.WindowConfiguration; 36 import android.content.Intent; 37 import android.content.pm.ParceledListSlice; 38 import android.content.res.Configuration; 39 import android.graphics.Rect; 40 import android.os.Binder; 41 import android.os.IBinder; 42 import android.os.Parcel; 43 import android.os.RemoteException; 44 import android.util.ArrayMap; 45 import android.util.Slog; 46 import android.util.proto.ProtoOutputStream; 47 import android.view.Display; 48 import android.view.SurfaceControl; 49 import android.window.ITaskOrganizer; 50 import android.window.ITaskOrganizerController; 51 import android.window.IWindowlessStartingSurfaceCallback; 52 import android.window.SplashScreenView; 53 import android.window.StartingWindowInfo; 54 import android.window.StartingWindowRemovalInfo; 55 import android.window.TaskAppearedInfo; 56 import android.window.TaskSnapshot; 57 import android.window.WindowContainerToken; 58 59 import com.android.internal.annotations.VisibleForTesting; 60 import com.android.internal.protolog.common.ProtoLog; 61 import com.android.internal.util.ArrayUtils; 62 63 import java.io.PrintWriter; 64 import java.util.ArrayDeque; 65 import java.util.ArrayList; 66 import java.util.HashSet; 67 import java.util.List; 68 import java.util.WeakHashMap; 69 70 /** 71 * Stores the TaskOrganizers associated with a given windowing mode and 72 * their associated state. 73 */ 74 class TaskOrganizerController extends ITaskOrganizerController.Stub { 75 private static final String TAG = "TaskOrganizerController"; 76 77 @VisibleForTesting 78 class DeathRecipient implements IBinder.DeathRecipient { 79 ITaskOrganizer mTaskOrganizer; 80 DeathRecipient(ITaskOrganizer organizer)81 DeathRecipient(ITaskOrganizer organizer) { 82 mTaskOrganizer = organizer; 83 } 84 85 @Override binderDied()86 public void binderDied() { 87 synchronized (mGlobalLock) { 88 final TaskOrganizerState state = mTaskOrganizerStates.get( 89 mTaskOrganizer.asBinder()); 90 if (state != null) { 91 state.dispose(); 92 } 93 } 94 } 95 } 96 97 /** 98 * A wrapper class around ITaskOrganizer to ensure that the calls are made in the right 99 * lifecycle order since we may be updating the visibility of task surface controls in a pending 100 * transaction before they are presented to the task org. 101 */ 102 private static class TaskOrganizerCallbacks { 103 final ITaskOrganizer mTaskOrganizer; 104 TaskOrganizerCallbacks(ITaskOrganizer taskOrg)105 TaskOrganizerCallbacks(ITaskOrganizer taskOrg) { 106 mTaskOrganizer = taskOrg; 107 } 108 getBinder()109 IBinder getBinder() { 110 return mTaskOrganizer.asBinder(); 111 } 112 prepareLeash(Task task, String reason)113 SurfaceControl prepareLeash(Task task, String reason) { 114 return new SurfaceControl(task.getSurfaceControl(), reason); 115 } 116 onTaskAppeared(Task task)117 void onTaskAppeared(Task task) { 118 ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Task appeared taskId=%d", task.mTaskId); 119 final RunningTaskInfo taskInfo = task.getTaskInfo(); 120 try { 121 mTaskOrganizer.onTaskAppeared(taskInfo, prepareLeash(task, 122 "TaskOrganizerController.onTaskAppeared")); 123 } catch (RemoteException e) { 124 Slog.e(TAG, "Exception sending onTaskAppeared callback", e); 125 } 126 } 127 onTaskVanished(Task task)128 void onTaskVanished(Task task) { 129 ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Task vanished taskId=%d", task.mTaskId); 130 final RunningTaskInfo taskInfo = task.getTaskInfo(); 131 try { 132 mTaskOrganizer.onTaskVanished(taskInfo); 133 } catch (RemoteException e) { 134 Slog.e(TAG, "Exception sending onTaskVanished callback", e); 135 } 136 } 137 onTaskInfoChanged(Task task, ActivityManager.RunningTaskInfo taskInfo)138 void onTaskInfoChanged(Task task, ActivityManager.RunningTaskInfo taskInfo) { 139 if (!task.mTaskAppearedSent) { 140 // Skip if the task has not yet received taskAppeared(). 141 return; 142 } 143 ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Task info changed taskId=%d", task.mTaskId); 144 if (!task.isOrganized()) { 145 // This is safe to ignore if the task is no longer organized 146 return; 147 } 148 try { 149 // Purposely notify of task info change immediately instead of deferring (like 150 // appear and vanish) to allow info changes (such as new PIP params) to flow 151 // without waiting. 152 mTaskOrganizer.onTaskInfoChanged(taskInfo); 153 } catch (RemoteException e) { 154 Slog.e(TAG, "Exception sending onTaskInfoChanged callback", e); 155 } 156 } 157 onBackPressedOnTaskRoot(Task task)158 void onBackPressedOnTaskRoot(Task task) { 159 ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Task back pressed on root taskId=%d", 160 task.mTaskId); 161 if (!task.mTaskAppearedSent) { 162 // Skip if the task has not yet received taskAppeared(). 163 return; 164 } 165 if (!task.isOrganized()) { 166 // This is safe to ignore if the task is no longer organized 167 return; 168 } 169 try { 170 mTaskOrganizer.onBackPressedOnTaskRoot(task.getTaskInfo()); 171 } catch (Exception e) { 172 Slog.e(TAG, "Exception sending onBackPressedOnTaskRoot callback", e); 173 } 174 } 175 } 176 177 /** 178 * Maintains a list of all the pending events for a given {@link android.window.TaskOrganizer} 179 */ 180 static final class TaskOrganizerPendingEventsQueue { 181 private final WeakHashMap<Task, RunningTaskInfo> mLastSentTaskInfos = new WeakHashMap<>(); 182 private final TaskOrganizerState mOrganizerState; 183 private RunningTaskInfo mTmpTaskInfo; 184 // Pending task events due to layout deferred. 185 private final ArrayList<PendingTaskEvent> mPendingTaskEvents = new ArrayList<>(); 186 TaskOrganizerPendingEventsQueue(TaskOrganizerState taskOrganizerState)187 TaskOrganizerPendingEventsQueue(TaskOrganizerState taskOrganizerState) { 188 mOrganizerState = taskOrganizerState; 189 } 190 191 @VisibleForTesting getPendingEventList()192 public ArrayList<PendingTaskEvent> getPendingEventList() { 193 return mPendingTaskEvents; 194 } 195 numPendingTaskEvents()196 int numPendingTaskEvents() { 197 return mPendingTaskEvents.size(); 198 } 199 clearPendingTaskEvents()200 void clearPendingTaskEvents() { 201 mPendingTaskEvents.clear(); 202 } 203 addPendingTaskEvent(PendingTaskEvent event)204 void addPendingTaskEvent(PendingTaskEvent event) { 205 mPendingTaskEvents.add(event); 206 } 207 removePendingTaskEvent(PendingTaskEvent event)208 void removePendingTaskEvent(PendingTaskEvent event) { 209 mPendingTaskEvents.remove(event); 210 } 211 212 /** 213 * Removes all the pending task events for the given {@code task}. 214 * 215 * @param task 216 * @return true if a {@link PendingTaskEvent#EVENT_APPEARED} is still pending for the given 217 * {code task}. 218 */ removePendingTaskEvents(Task task)219 boolean removePendingTaskEvents(Task task) { 220 boolean foundPendingAppearedEvents = false; 221 for (int i = mPendingTaskEvents.size() - 1; i >= 0; i--) { 222 PendingTaskEvent entry = mPendingTaskEvents.get(i); 223 if (task.mTaskId == entry.mTask.mTaskId) { 224 // This task is vanished so remove all pending event of it. 225 mPendingTaskEvents.remove(i); 226 227 if (entry.mEventType == PendingTaskEvent.EVENT_APPEARED) { 228 foundPendingAppearedEvents = true; 229 } 230 } 231 } 232 return foundPendingAppearedEvents; 233 } 234 235 @Nullable getPendingTaskEvent(Task task, int type)236 private PendingTaskEvent getPendingTaskEvent(Task task, int type) { 237 for (int i = mPendingTaskEvents.size() - 1; i >= 0; i--) { 238 PendingTaskEvent entry = mPendingTaskEvents.get(i); 239 if (task.mTaskId == entry.mTask.mTaskId && type == entry.mEventType) { 240 return entry; 241 } 242 } 243 return null; 244 } 245 246 @VisibleForTesting 247 @Nullable getPendingLifecycleTaskEvent(Task task)248 PendingTaskEvent getPendingLifecycleTaskEvent(Task task) { 249 for (int i = mPendingTaskEvents.size() - 1; i >= 0; i--) { 250 PendingTaskEvent entry = mPendingTaskEvents.get(i); 251 if (task.mTaskId == entry.mTask.mTaskId && entry.isLifecycleEvent()) { 252 return entry; 253 } 254 } 255 return null; 256 } 257 dispatchPendingEvents()258 void dispatchPendingEvents() { 259 if (mPendingTaskEvents.isEmpty()) { 260 return; 261 } 262 for (int i = 0, n = mPendingTaskEvents.size(); i < n; i++) { 263 dispatchPendingEvent(mPendingTaskEvents.get(i)); 264 } 265 mPendingTaskEvents.clear(); 266 } 267 dispatchPendingEvent(PendingTaskEvent event)268 private void dispatchPendingEvent(PendingTaskEvent event) { 269 final Task task = event.mTask; 270 switch (event.mEventType) { 271 case PendingTaskEvent.EVENT_APPEARED: 272 if (task.taskAppearedReady()) { 273 mOrganizerState.mOrganizer.onTaskAppeared(task); 274 } 275 break; 276 case PendingTaskEvent.EVENT_VANISHED: 277 mOrganizerState.mOrganizer.onTaskVanished(task); 278 mLastSentTaskInfos.remove(task); 279 break; 280 case PendingTaskEvent.EVENT_INFO_CHANGED: 281 dispatchTaskInfoChanged(event.mTask, event.mForce); 282 break; 283 case PendingTaskEvent.EVENT_ROOT_BACK_PRESSED: 284 mOrganizerState.mOrganizer.onBackPressedOnTaskRoot(task); 285 break; 286 } 287 } 288 dispatchTaskInfoChanged(Task task, boolean force)289 private void dispatchTaskInfoChanged(Task task, boolean force) { 290 RunningTaskInfo lastInfo = mLastSentTaskInfos.get(task); 291 if (mTmpTaskInfo == null) { 292 mTmpTaskInfo = new RunningTaskInfo(); 293 } 294 mTmpTaskInfo.configuration.unset(); 295 task.fillTaskInfo(mTmpTaskInfo); 296 297 boolean changed = !mTmpTaskInfo 298 .equalsForTaskOrganizer(lastInfo) 299 || !configurationsAreEqualForOrganizer( 300 mTmpTaskInfo.configuration, 301 lastInfo.configuration); 302 if (!(changed || force)) { 303 // mTmpTaskInfo will be reused next time. 304 return; 305 } 306 final RunningTaskInfo newInfo = mTmpTaskInfo; 307 mLastSentTaskInfos.put(task, 308 mTmpTaskInfo); 309 // Since we've stored this, clean up the reference so a new one will be created next 310 // time. 311 // Transferring it this way means we only have to construct new RunningTaskInfos when 312 // they change. 313 mTmpTaskInfo = null; 314 315 if (task.isOrganized()) { 316 // Because we defer sending taskAppeared() until the app has drawn, we may receive a 317 // configuration change before the state actually has the task registered. As such 318 // we should ignore these change events to the organizer until taskAppeared(). If 319 // the task was created by the organizer, then we always send the info change. 320 mOrganizerState.mOrganizer.onTaskInfoChanged(task, newInfo); 321 } 322 } 323 } 324 325 @VisibleForTesting 326 class TaskOrganizerState { 327 private final TaskOrganizerCallbacks mOrganizer; 328 private final DeathRecipient mDeathRecipient; 329 private final ArrayList<Task> mOrganizedTasks = new ArrayList<>(); 330 private final TaskOrganizerPendingEventsQueue mPendingEventsQueue; 331 private final int mUid; 332 TaskOrganizerState(ITaskOrganizer organizer, int uid)333 TaskOrganizerState(ITaskOrganizer organizer, int uid) { 334 mOrganizer = new TaskOrganizerCallbacks(organizer); 335 mDeathRecipient = new DeathRecipient(organizer); 336 mPendingEventsQueue = new TaskOrganizerPendingEventsQueue(this); 337 try { 338 organizer.asBinder().linkToDeath(mDeathRecipient, 0); 339 } catch (RemoteException e) { 340 Slog.e(TAG, "TaskOrganizer failed to register death recipient"); 341 } 342 mUid = uid; 343 } 344 345 @VisibleForTesting getDeathRecipient()346 DeathRecipient getDeathRecipient() { 347 return mDeathRecipient; 348 } 349 350 @VisibleForTesting getPendingEventsQueue()351 TaskOrganizerPendingEventsQueue getPendingEventsQueue() { 352 return mPendingEventsQueue; 353 } 354 355 /** 356 * Register this task with this state, but doesn't trigger the task appeared callback to 357 * the organizer. 358 */ addTaskWithoutCallback(Task t, String reason)359 SurfaceControl addTaskWithoutCallback(Task t, String reason) { 360 t.mTaskAppearedSent = true; 361 if (!mOrganizedTasks.contains(t)) { 362 mOrganizedTasks.add(t); 363 } 364 return mOrganizer.prepareLeash(t, reason); 365 } 366 addTask(Task t)367 private boolean addTask(Task t) { 368 if (t.mTaskAppearedSent) { 369 return false; 370 } 371 372 if (!mOrganizedTasks.contains(t)) { 373 mOrganizedTasks.add(t); 374 } 375 376 if (t.taskAppearedReady()) { 377 t.mTaskAppearedSent = true; 378 return true; 379 } 380 return false; 381 } 382 removeTask(Task t, boolean removeFromSystem)383 private boolean removeTask(Task t, boolean removeFromSystem) { 384 mOrganizedTasks.remove(t); 385 mInterceptBackPressedOnRootTasks.remove(t.mTaskId); 386 boolean taskAppearedSent = t.mTaskAppearedSent; 387 if (taskAppearedSent) { 388 if (t.getSurfaceControl() != null) { 389 t.migrateToNewSurfaceControl(t.getSyncTransaction()); 390 } 391 t.mTaskAppearedSent = false; 392 } 393 if (removeFromSystem) { 394 mService.removeTask(t.mTaskId); 395 } 396 return taskAppearedSent; 397 } 398 dispose()399 void dispose() { 400 // Move organizer from managing specific windowing modes 401 mTaskOrganizers.remove(mOrganizer.mTaskOrganizer); 402 403 // Update tasks currently managed by this organizer to the next one available if 404 // possible. 405 while (!mOrganizedTasks.isEmpty()) { 406 final Task t = mOrganizedTasks.get(0); 407 if (t.mCreatedByOrganizer) { 408 // The tasks created by this organizer should ideally be deleted when this 409 // organizer is disposed off to avoid inconsistent behavior. 410 t.removeImmediately(); 411 } else { 412 t.updateTaskOrganizerState(); 413 } 414 if (mOrganizedTasks.contains(t)) { 415 // updateTaskOrganizerState should remove the task from the list, but still 416 // check it again to avoid while-loop isn't terminate. 417 if (removeTask(t, t.mRemoveWithTaskOrganizer)) { 418 TaskOrganizerController.this.onTaskVanishedInternal(this, t); 419 } 420 } 421 if (mService.getTransitionController().isShellTransitionsEnabled()) { 422 // dispose is only called outside of transitions (eg during unregister). Since 423 // we "migrate" surfaces when replacing organizers, visibility gets delegated 424 // to transitions; however, since there is no transition at this point, we have 425 // to manually show the surface here. 426 if (t.mTaskOrganizer != null && t.getSurfaceControl() != null) { 427 t.getSyncTransaction().show(t.getSurfaceControl()); 428 } 429 } 430 } 431 432 // Pending events queue for this organizer need to be cleared because this organizer 433 // has either died or unregistered itself. 434 mPendingEventsQueue.clearPendingTaskEvents(); 435 mTaskOrganizerStates.remove(mOrganizer.getBinder()); 436 } 437 unlinkDeath()438 void unlinkDeath() { 439 mOrganizer.getBinder().unlinkToDeath(mDeathRecipient, 0); 440 } 441 } 442 443 static class PendingTaskEvent { 444 static final int EVENT_APPEARED = 0; 445 static final int EVENT_VANISHED = 1; 446 static final int EVENT_INFO_CHANGED = 2; 447 static final int EVENT_ROOT_BACK_PRESSED = 3; 448 449 final int mEventType; 450 final Task mTask; 451 final ITaskOrganizer mTaskOrg; 452 boolean mForce; 453 PendingTaskEvent(Task task, int event)454 PendingTaskEvent(Task task, int event) { 455 this(task, task.mTaskOrganizer, event); 456 } 457 PendingTaskEvent(Task task, ITaskOrganizer taskOrg, int eventType)458 PendingTaskEvent(Task task, ITaskOrganizer taskOrg, int eventType) { 459 mTask = task; 460 mTaskOrg = taskOrg; 461 mEventType = eventType; 462 } 463 isLifecycleEvent()464 boolean isLifecycleEvent() { 465 return mEventType == EVENT_APPEARED || mEventType == EVENT_VANISHED 466 || mEventType == EVENT_INFO_CHANGED; 467 } 468 } 469 470 private final ActivityTaskManagerService mService; 471 private final WindowManagerGlobalLock mGlobalLock; 472 473 // List of task organizers by priority 474 private final ArrayDeque<ITaskOrganizer> mTaskOrganizers = new ArrayDeque<>(); 475 private final ArrayMap<IBinder, TaskOrganizerState> mTaskOrganizerStates = new ArrayMap<>(); 476 // Set of organized tasks (by taskId) that dispatch back pressed to their organizers 477 private final HashSet<Integer> mInterceptBackPressedOnRootTasks = new HashSet<>(); 478 TaskOrganizerController(ActivityTaskManagerService atm)479 TaskOrganizerController(ActivityTaskManagerService atm) { 480 mService = atm; 481 mGlobalLock = atm.mGlobalLock; 482 } 483 484 @Override onTransact(int code, Parcel data, Parcel reply, int flags)485 public boolean onTransact(int code, Parcel data, Parcel reply, int flags) 486 throws RemoteException { 487 try { 488 return super.onTransact(code, data, reply, flags); 489 } catch (RuntimeException e) { 490 throw ActivityTaskManagerService.logAndRethrowRuntimeExceptionOnTransact(TAG, e); 491 } 492 } 493 494 /** 495 * Register a TaskOrganizer to manage tasks as they enter the a supported windowing mode. 496 */ 497 @Override registerTaskOrganizer(ITaskOrganizer organizer)498 public ParceledListSlice<TaskAppearedInfo> registerTaskOrganizer(ITaskOrganizer organizer) { 499 enforceTaskPermission("registerTaskOrganizer()"); 500 final int uid = Binder.getCallingUid(); 501 final long origId = Binder.clearCallingIdentity(); 502 try { 503 final ArrayList<TaskAppearedInfo> taskInfos = new ArrayList<>(); 504 final Runnable withGlobalLock = () -> { 505 ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Register task organizer=%s uid=%d", 506 organizer.asBinder(), uid); 507 if (!mTaskOrganizerStates.containsKey(organizer.asBinder())) { 508 mTaskOrganizers.add(organizer); 509 mTaskOrganizerStates.put(organizer.asBinder(), 510 new TaskOrganizerState(organizer, uid)); 511 } 512 513 final TaskOrganizerState state = mTaskOrganizerStates.get(organizer.asBinder()); 514 mService.mRootWindowContainer.forAllTasks((task) -> { 515 boolean returnTask = !task.mCreatedByOrganizer; 516 task.updateTaskOrganizerState(returnTask /* skipTaskAppeared */); 517 // It is possible for the task to not yet have a surface control, so ensure that 518 // the update succeeded in setting the organizer for the task before returning 519 if (task.isOrganized() && returnTask) { 520 SurfaceControl taskLeash = state.addTaskWithoutCallback(task, 521 "TaskOrganizerController.registerTaskOrganizer"); 522 taskInfos.add(new TaskAppearedInfo(task.getTaskInfo(), taskLeash)); 523 } 524 }); 525 }; 526 if (mService.getTransitionController().isShellTransitionsEnabled()) { 527 mService.getTransitionController().mRunningLock.runWhenIdle(1000, withGlobalLock); 528 } else { 529 synchronized (mGlobalLock) { 530 withGlobalLock.run(); 531 } 532 } 533 return new ParceledListSlice<>(taskInfos); 534 } finally { 535 Binder.restoreCallingIdentity(origId); 536 } 537 } 538 539 @Override unregisterTaskOrganizer(ITaskOrganizer organizer)540 public void unregisterTaskOrganizer(ITaskOrganizer organizer) { 541 enforceTaskPermission("unregisterTaskOrganizer()"); 542 final int uid = Binder.getCallingUid(); 543 final long origId = Binder.clearCallingIdentity(); 544 try { 545 final Runnable withGlobalLock = () -> { 546 final TaskOrganizerState state = mTaskOrganizerStates.get(organizer.asBinder()); 547 if (state == null) { 548 return; 549 } 550 ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Unregister task organizer=%s uid=%d", 551 organizer.asBinder(), uid); 552 state.unlinkDeath(); 553 state.dispose(); 554 }; 555 if (mService.getTransitionController().isShellTransitionsEnabled()) { 556 mService.getTransitionController().mRunningLock.runWhenIdle(1000, withGlobalLock); 557 } else { 558 synchronized (mGlobalLock) { 559 withGlobalLock.run(); 560 } 561 } 562 } finally { 563 Binder.restoreCallingIdentity(origId); 564 } 565 } 566 567 /** 568 * @return the task organizer key for a given windowing mode. 569 */ getTaskOrganizer()570 ITaskOrganizer getTaskOrganizer() { 571 return mTaskOrganizers.peekLast(); 572 } 573 574 // Capture the animation surface control for activity's main window 575 static class StartingWindowAnimationAdaptor implements AnimationAdapter { 576 577 @Override getShowWallpaper()578 public boolean getShowWallpaper() { 579 return false; 580 } 581 582 @Override startAnimation(SurfaceControl animationLeash, SurfaceControl.Transaction t, int type, @NonNull SurfaceAnimator.OnAnimationFinishedCallback finishCallback)583 public void startAnimation(SurfaceControl animationLeash, SurfaceControl.Transaction t, 584 int type, @NonNull SurfaceAnimator.OnAnimationFinishedCallback finishCallback) { 585 } 586 587 @Override onAnimationCancelled(SurfaceControl animationLeash)588 public void onAnimationCancelled(SurfaceControl animationLeash) { 589 } 590 591 @Override getDurationHint()592 public long getDurationHint() { 593 return 0; 594 } 595 596 @Override getStatusBarTransitionsStartTime()597 public long getStatusBarTransitionsStartTime() { 598 return 0; 599 } 600 601 @Override dump(PrintWriter pw, String prefix)602 public void dump(PrintWriter pw, String prefix) { 603 } 604 605 @Override dumpDebug(ProtoOutputStream proto)606 public void dumpDebug(ProtoOutputStream proto) { 607 } 608 } 609 applyStartingWindowAnimation(WindowState window)610 static SurfaceControl applyStartingWindowAnimation(WindowState window) { 611 final SurfaceControl.Transaction t = window.getPendingTransaction(); 612 final StartingWindowAnimationAdaptor adaptor = new StartingWindowAnimationAdaptor(); 613 window.startAnimation(t, adaptor, false, ANIMATION_TYPE_STARTING_REVEAL); 614 final SurfaceControl leash = window.getAnimationLeash(); 615 if (leash == null) { 616 Slog.e(TAG, "Cannot start starting window animation, the window " + window 617 + " was removed"); 618 return null; 619 } 620 t.setPosition(leash, window.mSurfacePosition.x, window.mSurfacePosition.y); 621 return leash; 622 } 623 addStartingWindow(Task task, ActivityRecord activity, int launchTheme, TaskSnapshot taskSnapshot)624 boolean addStartingWindow(Task task, ActivityRecord activity, int launchTheme, 625 TaskSnapshot taskSnapshot) { 626 final Task rootTask = task.getRootTask(); 627 if (rootTask == null || activity.mStartingData == null) { 628 return false; 629 } 630 final ITaskOrganizer lastOrganizer = getTaskOrganizer(); 631 if (lastOrganizer == null) { 632 return false; 633 } 634 final StartingWindowInfo info = task.getStartingWindowInfo(activity); 635 if (launchTheme != 0) { 636 info.splashScreenThemeResId = launchTheme; 637 } 638 info.taskSnapshot = taskSnapshot; 639 info.appToken = activity.token; 640 // make this happen prior than prepare surface 641 try { 642 lastOrganizer.addStartingWindow(info); 643 } catch (RemoteException e) { 644 Slog.e(TAG, "Exception sending onTaskStart callback", e); 645 return false; 646 } 647 return true; 648 } 649 removeStartingWindow(Task task, ITaskOrganizer taskOrganizer, boolean prepareAnimation, boolean hasImeSurface)650 void removeStartingWindow(Task task, ITaskOrganizer taskOrganizer, boolean prepareAnimation, 651 boolean hasImeSurface) { 652 final Task rootTask = task.getRootTask(); 653 if (rootTask == null) { 654 return; 655 } 656 final ITaskOrganizer lastOrganizer = taskOrganizer != null ? taskOrganizer 657 : getTaskOrganizer(); 658 if (lastOrganizer == null) { 659 return; 660 } 661 final StartingWindowRemovalInfo removalInfo = new StartingWindowRemovalInfo(); 662 removalInfo.taskId = task.mTaskId; 663 removalInfo.playRevealAnimation = prepareAnimation 664 && task.getDisplayContent() != null 665 && task.getDisplayInfo().state == Display.STATE_ON; 666 final boolean playShiftUpAnimation = !task.inMultiWindowMode(); 667 final ActivityRecord topActivity = task.topActivityContainsStartingWindow(); 668 if (topActivity != null) { 669 // Set defer remove mode for IME 670 final DisplayContent dc = topActivity.getDisplayContent(); 671 if (hasImeSurface) { 672 if (topActivity.isVisibleRequested() && dc.mInputMethodWindow != null 673 && dc.isFixedRotationLaunchingApp(topActivity)) { 674 removalInfo.deferRemoveMode = DEFER_MODE_ROTATION; 675 } else { 676 removalInfo.deferRemoveMode = DEFER_MODE_NORMAL; 677 } 678 } 679 680 final WindowState mainWindow = 681 topActivity.findMainWindow(false/* includeStartingApp */); 682 // No app window for this activity, app might be crashed. 683 // Remove starting window immediately without playing reveal animation. 684 if (mainWindow == null || mainWindow.mRemoved) { 685 removalInfo.playRevealAnimation = false; 686 } else if (removalInfo.playRevealAnimation && playShiftUpAnimation) { 687 removalInfo.roundedCornerRadius = 688 topActivity.mLetterboxUiController.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 1131 @Override updateCameraCompatControlState(WindowContainerToken token, int state)1132 public void updateCameraCompatControlState(WindowContainerToken token, int state) { 1133 enforceTaskPermission("updateCameraCompatControlState()"); 1134 final long origId = Binder.clearCallingIdentity(); 1135 try { 1136 synchronized (mGlobalLock) { 1137 final WindowContainer wc = WindowContainer.fromBinder(token.asBinder()); 1138 if (wc == null) { 1139 Slog.w(TAG, "Could not resolve window from token"); 1140 return; 1141 } 1142 final Task task = wc.asTask(); 1143 if (task == null) { 1144 Slog.w(TAG, "Could not resolve task from token"); 1145 return; 1146 } 1147 ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, 1148 "Update camera compat control state to %s for taskId=%d", 1149 cameraCompatControlStateToString(state), task.mTaskId); 1150 final ActivityRecord activity = task.getTopNonFinishingActivity(); 1151 if (activity != null) { 1152 activity.updateCameraCompatStateFromUser(state); 1153 } 1154 } 1155 } finally { 1156 Binder.restoreCallingIdentity(origId); 1157 } 1158 } 1159 handleInterceptBackPressedOnTaskRoot(Task task)1160 public boolean handleInterceptBackPressedOnTaskRoot(Task task) { 1161 if (!shouldInterceptBackPressedOnRootTask(task)) { 1162 return false; 1163 } 1164 final TaskOrganizerPendingEventsQueue pendingEventsQueue = 1165 mTaskOrganizerStates.get(task.mTaskOrganizer.asBinder()) 1166 .mPendingEventsQueue; 1167 if (pendingEventsQueue == null) { 1168 Slog.w(TAG, "cannot get handle BackPressedOnTaskRoot because organizerState is " 1169 + "not present"); 1170 return false; 1171 } 1172 1173 PendingTaskEvent pendingVanished = 1174 pendingEventsQueue.getPendingTaskEvent(task, 1175 PendingTaskEvent.EVENT_VANISHED); 1176 if (pendingVanished != null) { 1177 // This task will vanish before this callback so just ignore. 1178 return false; 1179 } 1180 1181 PendingTaskEvent pending = pendingEventsQueue.getPendingTaskEvent( 1182 task, PendingTaskEvent.EVENT_ROOT_BACK_PRESSED); 1183 if (pending == null) { 1184 pending = new PendingTaskEvent(task, PendingTaskEvent.EVENT_ROOT_BACK_PRESSED); 1185 } else { 1186 // Pending already exist, remove and add for re-ordering. 1187 pendingEventsQueue.removePendingTaskEvent(pending); 1188 } 1189 pendingEventsQueue.addPendingTaskEvent(pending); 1190 mService.mWindowManager.mWindowPlacerLocked.requestTraversal(); 1191 return true; 1192 } 1193 shouldInterceptBackPressedOnRootTask(Task task)1194 boolean shouldInterceptBackPressedOnRootTask(Task task) { 1195 return task != null && task.isOrganized() 1196 && mInterceptBackPressedOnRootTasks.contains(task.mTaskId); 1197 } 1198 dump(PrintWriter pw, String prefix)1199 public void dump(PrintWriter pw, String prefix) { 1200 final String innerPrefix = prefix + " "; 1201 pw.print(prefix); pw.println("TaskOrganizerController:"); 1202 final ITaskOrganizer lastOrganizer = mTaskOrganizers.peekLast(); 1203 for (ITaskOrganizer organizer : mTaskOrganizers) { 1204 final TaskOrganizerState state = mTaskOrganizerStates.get(organizer.asBinder()); 1205 final ArrayList<Task> tasks = state.mOrganizedTasks; 1206 pw.print(innerPrefix + " "); 1207 pw.print(state.mOrganizer.mTaskOrganizer + " uid=" + state.mUid); 1208 if (lastOrganizer == organizer) { 1209 pw.print(" (active)"); 1210 } 1211 pw.println(':'); 1212 for (int k = 0; k < tasks.size(); k++) { 1213 final Task task = tasks.get(k); 1214 final int mode = task.getWindowingMode(); 1215 pw.println(innerPrefix + " (" 1216 + WindowConfiguration.windowingModeToString(mode) + ") " + task); 1217 } 1218 1219 } 1220 pw.println(); 1221 } 1222 1223 @VisibleForTesting getTaskOrganizerState(IBinder taskOrganizer)1224 TaskOrganizerState getTaskOrganizerState(IBinder taskOrganizer) { 1225 return mTaskOrganizerStates.get(taskOrganizer); 1226 } 1227 1228 @VisibleForTesting getTaskOrganizerPendingEvents(IBinder taskOrganizer)1229 TaskOrganizerPendingEventsQueue getTaskOrganizerPendingEvents(IBinder taskOrganizer) { 1230 return mTaskOrganizerStates.get(taskOrganizer).mPendingEventsQueue; 1231 } 1232 } 1233