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