1 /* 2 * Copyright (C) 2020 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.Manifest.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS; 20 import static android.app.Activity.FULLSCREEN_MODE_REQUEST_ENTER; 21 import static android.app.Activity.FULLSCREEN_MODE_REQUEST_EXIT; 22 import static android.app.ActivityOptions.ANIM_SCENE_TRANSITION; 23 import static android.app.ActivityTaskManager.INVALID_TASK_ID; 24 import static android.app.ActivityTaskManager.INVALID_WINDOWING_MODE; 25 import static android.app.FullscreenRequestHandler.REMOTE_CALLBACK_RESULT_KEY; 26 import static android.app.FullscreenRequestHandler.RESULT_APPROVED; 27 import static android.app.FullscreenRequestHandler.RESULT_FAILED_ALREADY_FULLY_EXPANDED; 28 import static android.app.FullscreenRequestHandler.RESULT_FAILED_NOT_IN_FULLSCREEN_WITH_HISTORY; 29 import static android.app.FullscreenRequestHandler.RESULT_FAILED_NOT_TOP_FOCUSED; 30 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; 31 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; 32 import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; 33 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; 34 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; 35 import static android.content.pm.PackageManager.PERMISSION_DENIED; 36 import static android.content.pm.PackageManager.PERMISSION_GRANTED; 37 import static android.os.Process.INVALID_UID; 38 import static android.os.Process.SYSTEM_UID; 39 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; 40 import static android.service.voice.VoiceInteractionSession.SHOW_SOURCE_APPLICATION; 41 import static android.view.Display.DEFAULT_DISPLAY; 42 import static android.view.Display.INVALID_DISPLAY; 43 import static android.view.WindowManager.TRANSIT_CHANGE; 44 import static android.view.WindowManager.TRANSIT_TO_BACK; 45 import static android.view.WindowManager.TRANSIT_TO_FRONT; 46 47 import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_CONFIGURATION; 48 import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_IMMERSIVE; 49 import static com.android.server.wm.ActivityRecord.State.DESTROYED; 50 import static com.android.server.wm.ActivityRecord.State.DESTROYING; 51 import static com.android.server.wm.ActivityRecord.State.PAUSING; 52 import static com.android.server.wm.ActivityRecord.State.RESTARTING_PROCESS; 53 import static com.android.server.wm.ActivityRecord.State.RESUMED; 54 import static com.android.server.wm.ActivityRecord.State.STOPPING; 55 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ALL; 56 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH; 57 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM; 58 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME; 59 import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_NONE; 60 import static com.android.server.wm.ActivityTaskManagerService.TAG_SWITCH; 61 import static com.android.server.wm.ActivityTaskManagerService.enforceNotIsolatedCaller; 62 import static com.android.window.flags.Flags.allowDisableActivityRecordInputSink; 63 64 import android.Manifest; 65 import android.annotation.ColorInt; 66 import android.annotation.NonNull; 67 import android.annotation.Nullable; 68 import android.app.Activity; 69 import android.app.ActivityManager; 70 import android.app.ActivityTaskManager; 71 import android.app.FullscreenRequestHandler; 72 import android.app.IActivityClientController; 73 import android.app.IRequestFinishCallback; 74 import android.app.PictureInPictureParams; 75 import android.app.PictureInPictureUiState; 76 import android.app.compat.CompatChanges; 77 import android.app.servertransaction.EnterPipRequestedItem; 78 import android.app.servertransaction.PipStateTransactionItem; 79 import android.compat.annotation.ChangeId; 80 import android.content.ComponentName; 81 import android.content.Context; 82 import android.content.Intent; 83 import android.content.pm.ActivityInfo; 84 import android.content.pm.PackageManagerInternal; 85 import android.content.res.Configuration; 86 import android.net.Uri; 87 import android.os.Binder; 88 import android.os.Bundle; 89 import android.os.IBinder; 90 import android.os.IRemoteCallback; 91 import android.os.Parcel; 92 import android.os.PersistableBundle; 93 import android.os.RemoteException; 94 import android.os.SystemClock; 95 import android.os.Trace; 96 import android.os.UserHandle; 97 import android.service.voice.VoiceInteractionManagerInternal; 98 import android.util.Slog; 99 import android.view.RemoteAnimationDefinition; 100 import android.window.DesktopModeFlags; 101 import android.window.SizeConfigurationBuckets; 102 import android.window.TransitionInfo; 103 104 import com.android.internal.annotations.VisibleForTesting; 105 import com.android.internal.app.AssistUtils; 106 import com.android.internal.policy.IKeyguardDismissCallback; 107 import com.android.internal.protolog.ProtoLog; 108 import com.android.server.LocalServices; 109 import com.android.server.Watchdog; 110 import com.android.server.pm.KnownPackages; 111 import com.android.server.pm.pkg.AndroidPackage; 112 import com.android.server.uri.GrantUri; 113 import com.android.server.uri.NeededUriGrants; 114 import com.android.server.utils.quota.Categorizer; 115 import com.android.server.utils.quota.Category; 116 import com.android.server.utils.quota.CountQuotaTracker; 117 import com.android.server.vr.VrManagerInternal; 118 119 /** 120 * Server side implementation for the client activity to interact with system. 121 * 122 * @see android.app.ActivityClient 123 */ 124 class ActivityClientController extends IActivityClientController.Stub { 125 private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityClientController" : TAG_ATM; 126 127 private final ActivityTaskManagerService mService; 128 private final WindowManagerGlobalLock mGlobalLock; 129 private final ActivityTaskSupervisor mTaskSupervisor; 130 private final Context mContext; 131 132 // Prevent malicious app abusing the Activity#setPictureInPictureParams API 133 @VisibleForTesting CountQuotaTracker mSetPipAspectRatioQuotaTracker; 134 // Limit to 60 times / minute 135 private static final int SET_PIP_ASPECT_RATIO_LIMIT = 60; 136 // The timeWindowMs here can not be smaller than QuotaTracker#MIN_WINDOW_SIZE_MS 137 private static final long SET_PIP_ASPECT_RATIO_TIME_WINDOW_MS = 60_000; 138 139 /** Wrapper around VoiceInteractionServiceManager. */ 140 private AssistUtils mAssistUtils; 141 142 /** 143 * Grants access to the launching app's identity if the app opted-in to sharing its identity 144 * by launching this activity with an instance of {@link android.app.ActivityOptions} on which 145 * {@link android.app.ActivityOptions#setShareIdentityEnabled(boolean)} was invoked with a 146 * value of {@code true}, or if the launched activity's uid is the same as the launching 147 * app's. When this change is enabled and one of these requirements is met, the activity 148 * can access the launching app's uid and package name with {@link 149 * android.app.Activity#getLaunchedFromUid()} and {@link 150 * android.app.Activity#getLaunchedFromPackage()}, respectively. 151 */ 152 @ChangeId 153 public static final long ACCESS_SHARED_IDENTITY = 259743961L; 154 ActivityClientController(ActivityTaskManagerService service)155 ActivityClientController(ActivityTaskManagerService service) { 156 mService = service; 157 mGlobalLock = service.mGlobalLock; 158 mTaskSupervisor = service.mTaskSupervisor; 159 mContext = service.mContext; 160 } 161 onSystemReady()162 void onSystemReady() { 163 mAssistUtils = new AssistUtils(mContext); 164 } 165 166 @Override onTransact(int code, Parcel data, Parcel reply, int flags)167 public boolean onTransact(int code, Parcel data, Parcel reply, int flags) 168 throws RemoteException { 169 try { 170 return super.onTransact(code, data, reply, flags); 171 } catch (RuntimeException e) { 172 throw ActivityTaskManagerService.logAndRethrowRuntimeExceptionOnTransact( 173 "ActivityClientController", e); 174 } 175 } 176 177 @Override activityIdle(IBinder token, Configuration config, boolean stopProfiling)178 public void activityIdle(IBinder token, Configuration config, boolean stopProfiling) { 179 final long origId = Binder.clearCallingIdentity(); 180 try { 181 synchronized (mGlobalLock) { 182 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "activityIdle"); 183 final ActivityRecord r = ActivityRecord.forTokenLocked(token); 184 if (r == null) { 185 return; 186 } 187 mTaskSupervisor.activityIdleInternal(r, false /* fromTimeout */, 188 false /* processPausingActivities */, config); 189 if (stopProfiling && r.hasProcess()) { 190 r.app.clearProfilerIfNeeded(); 191 } 192 } 193 } finally { 194 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 195 Binder.restoreCallingIdentity(origId); 196 } 197 } 198 199 @Override activityResumed(IBinder token, boolean handleSplashScreenExit)200 public void activityResumed(IBinder token, boolean handleSplashScreenExit) { 201 final long origId = Binder.clearCallingIdentity(); 202 synchronized (mGlobalLock) { 203 ActivityRecord.activityResumedLocked(token, handleSplashScreenExit); 204 } 205 Binder.restoreCallingIdentity(origId); 206 } 207 208 @Override activityRefreshed(IBinder token)209 public void activityRefreshed(IBinder token) { 210 final long origId = Binder.clearCallingIdentity(); 211 synchronized (mGlobalLock) { 212 ActivityRecord.activityRefreshedLocked(token); 213 } 214 Binder.restoreCallingIdentity(origId); 215 } 216 217 @Override activityTopResumedStateLost()218 public void activityTopResumedStateLost() { 219 final long origId = Binder.clearCallingIdentity(); 220 synchronized (mGlobalLock) { 221 mTaskSupervisor.handleTopResumedStateReleased(false /* timeout */); 222 } 223 Binder.restoreCallingIdentity(origId); 224 } 225 226 @Override activityPaused(IBinder token)227 public void activityPaused(IBinder token) { 228 final long origId = Binder.clearCallingIdentity(); 229 synchronized (mGlobalLock) { 230 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "activityPaused"); 231 final ActivityRecord r = ActivityRecord.forTokenLocked(token); 232 if (r != null) { 233 r.activityPaused(false); 234 } 235 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 236 } 237 Binder.restoreCallingIdentity(origId); 238 } 239 240 @Override activityStopped(IBinder token, Bundle icicle, PersistableBundle persistentState, CharSequence description)241 public void activityStopped(IBinder token, Bundle icicle, PersistableBundle persistentState, 242 CharSequence description) { 243 if (DEBUG_ALL) Slog.v(TAG, "Activity stopped: token=" + token); 244 245 // Refuse possible leaked file descriptors. 246 if (icicle != null && icicle.hasFileDescriptors()) { 247 throw new IllegalArgumentException("File descriptors passed in Bundle"); 248 } 249 250 final long origId = Binder.clearCallingIdentity(); 251 252 String restartingName = null; 253 int restartingUid = 0; 254 final ActivityRecord r; 255 synchronized (mGlobalLock) { 256 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "activityStopped"); 257 r = ActivityRecord.isInRootTaskLocked(token); 258 if (r != null) { 259 if (!r.isState(STOPPING, RESTARTING_PROCESS) 260 && mTaskSupervisor.hasScheduledRestartTimeouts(r)) { 261 // Recover the restarting state which was replaced by other lifecycle changes. 262 r.setState(RESTARTING_PROCESS, "continue-restart"); 263 } 264 if (r.attachedToProcess() && r.isState(RESTARTING_PROCESS)) { 265 // The activity was requested to restart from 266 // {@link #restartActivityProcessIfVisible}. 267 restartingName = r.app.mName; 268 restartingUid = r.app.mUid; 269 } 270 r.activityStopped(icicle, persistentState, description); 271 } 272 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 273 } 274 275 if (restartingName != null) { 276 // In order to let the foreground activity can be restarted with its saved state from 277 // {@link android.app.Activity#onSaveInstanceState}, the kill operation is postponed 278 // until the activity reports stopped with the state. And the activity record will be 279 // kept because the record state is restarting, then the activity will be restarted 280 // immediately if it is still the top one. 281 mTaskSupervisor.removeRestartTimeouts(r); 282 mService.mAmInternal.killProcess(restartingName, restartingUid, 283 "restartActivityProcess"); 284 } 285 mService.mAmInternal.trimApplications(); 286 287 Binder.restoreCallingIdentity(origId); 288 } 289 290 @Override activityDestroyed(IBinder token)291 public void activityDestroyed(IBinder token) { 292 if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "ACTIVITY DESTROYED: " + token); 293 final long origId = Binder.clearCallingIdentity(); 294 synchronized (mGlobalLock) { 295 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "activityDestroyed"); 296 try { 297 final ActivityRecord r = ActivityRecord.forTokenLocked(token); 298 if (r != null) { 299 r.destroyed("activityDestroyed"); 300 } 301 } finally { 302 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 303 Binder.restoreCallingIdentity(origId); 304 } 305 } 306 } 307 308 @Override activityLocalRelaunch(IBinder token)309 public void activityLocalRelaunch(IBinder token) { 310 final long origId = Binder.clearCallingIdentity(); 311 synchronized (mGlobalLock) { 312 final ActivityRecord r = ActivityRecord.forTokenLocked(token); 313 if (r != null) { 314 r.startRelaunching(); 315 } 316 } 317 Binder.restoreCallingIdentity(origId); 318 } 319 320 @Override activityRelaunched(IBinder token)321 public void activityRelaunched(IBinder token) { 322 final long origId = Binder.clearCallingIdentity(); 323 synchronized (mGlobalLock) { 324 final ActivityRecord r = ActivityRecord.forTokenLocked(token); 325 if (r != null) { 326 r.finishRelaunching(); 327 } 328 } 329 Binder.restoreCallingIdentity(origId); 330 } 331 332 @Override reportSizeConfigurations(IBinder token, SizeConfigurationBuckets sizeConfigurations)333 public void reportSizeConfigurations(IBinder token, 334 SizeConfigurationBuckets sizeConfigurations) { 335 ProtoLog.v(WM_DEBUG_CONFIGURATION, "Report configuration: %s %s", 336 token, sizeConfigurations); 337 synchronized (mGlobalLock) { 338 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token); 339 if (r != null) { 340 r.setSizeConfigurations(sizeConfigurations); 341 } 342 } 343 } 344 345 /** 346 * Attempts to move a task backwards in z-order (the order of activities within the task is 347 * unchanged). 348 * 349 * There are several possible results of this call: 350 * - if the task is locked, then we will show the lock toast. 351 * - if there is a task behind the provided task, then that task is made visible and resumed as 352 * this task is moved to the back. 353 * - otherwise, if there are no other tasks in the root task: 354 * - if this task is in the pinned mode, then we remove the task completely, which will 355 * have the effect of moving the task to the top or bottom of the fullscreen root task 356 * (depending on whether it is visible). 357 * - otherwise, we simply return home and hide this task. 358 * 359 * @param token A reference to the activity we wish to move. 360 * @param nonRoot If false then this only works if the activity is the root 361 * of a task; if true it will work for any activity in a task. 362 * @return Returns true if the move completed, false if not. 363 */ 364 @Override moveActivityTaskToBack(IBinder token, boolean nonRoot)365 public boolean moveActivityTaskToBack(IBinder token, boolean nonRoot) { 366 enforceNotIsolatedCaller("moveActivityTaskToBack"); 367 final long origId = Binder.clearCallingIdentity(); 368 try { 369 synchronized (mGlobalLock) { 370 final int taskId = ActivityRecord.getTaskForActivityLocked(token, !nonRoot); 371 final Task task = mService.mRootWindowContainer.anyTaskForId(taskId); 372 if (task != null) { 373 return ActivityRecord.getRootTask(token).moveTaskToBack(task); 374 } 375 } 376 } finally { 377 Binder.restoreCallingIdentity(origId); 378 } 379 return false; 380 } 381 382 @Override shouldUpRecreateTask(IBinder token, String destAffinity)383 public boolean shouldUpRecreateTask(IBinder token, String destAffinity) { 384 synchronized (mGlobalLock) { 385 final ActivityRecord srec = ActivityRecord.forTokenLocked(token); 386 if (srec != null) { 387 return srec.getRootTask().shouldUpRecreateTaskLocked(srec, destAffinity); 388 } 389 } 390 return false; 391 } 392 393 @Override navigateUpTo(IBinder token, Intent destIntent, String resolvedType, int resultCode, Intent resultData)394 public boolean navigateUpTo(IBinder token, Intent destIntent, String resolvedType, 395 int resultCode, Intent resultData) { 396 final ActivityRecord r; 397 synchronized (mGlobalLock) { 398 r = ActivityRecord.isInRootTaskLocked(token); 399 if (r == null) { 400 return false; 401 } 402 } 403 404 // Carefully collect grants without holding lock. 405 final NeededUriGrants destGrants = mService.collectGrants(destIntent, r); 406 final NeededUriGrants resultGrants = mService.collectGrants(resultData, r.resultTo); 407 408 synchronized (mGlobalLock) { 409 return r.getRootTask().navigateUpTo( 410 r, destIntent, resolvedType, destGrants, resultCode, resultData, resultGrants); 411 } 412 } 413 414 @Override releaseActivityInstance(IBinder token)415 public boolean releaseActivityInstance(IBinder token) { 416 final long origId = Binder.clearCallingIdentity(); 417 try { 418 synchronized (mGlobalLock) { 419 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token); 420 if (r == null || !r.isDestroyable()) { 421 return false; 422 } 423 r.destroyImmediately("app-req"); 424 return r.isState(DESTROYING, DESTROYED); 425 } 426 } finally { 427 Binder.restoreCallingIdentity(origId); 428 } 429 } 430 431 /** 432 * This is the internal entry point for handling Activity.finish(). 433 * 434 * @param token The Binder token referencing the Activity we want to finish. 435 * @param resultCode Result code, if any, from this Activity. 436 * @param resultData Result data (Intent), if any, from this Activity. 437 * @param finishTask Whether to finish the task associated with this Activity. 438 * @return Returns true if the activity successfully finished, or false if it is still running. 439 */ 440 @Override finishActivity(IBinder token, int resultCode, Intent resultData, int finishTask)441 public boolean finishActivity(IBinder token, int resultCode, Intent resultData, 442 int finishTask) { 443 // Refuse possible leaked file descriptors. 444 if (resultData != null && resultData.hasFileDescriptors()) { 445 throw new IllegalArgumentException("File descriptors passed in Intent"); 446 } 447 448 final ActivityRecord r; 449 synchronized (mGlobalLock) { 450 r = ActivityRecord.isInRootTaskLocked(token); 451 if (r == null) { 452 return true; 453 } 454 } 455 456 // Carefully collect grants without holding lock. 457 final NeededUriGrants resultGrants = mService.collectGrants(resultData, r.resultTo); 458 459 synchronized (mGlobalLock) { 460 // Check again in case activity was removed when collecting grants. 461 if (!r.isInHistory()) { 462 return true; 463 } 464 465 // Keep track of the root activity of the task before we finish it. 466 final Task tr = r.getTask(); 467 final ActivityRecord rootR = tr.getRootActivity(); 468 if (rootR == null) { 469 Slog.w(TAG, "Finishing task with all activities already finished"); 470 } 471 // Do not allow task to finish if last task in lockTask mode. Launchable priv-apps can 472 // finish. 473 if (mService.getLockTaskController().activityBlockedFromFinish(r)) { 474 return false; 475 } 476 477 // TODO: There is a dup. of this block of code in ActivityStack.navigateUpToLocked 478 // We should consolidate. 479 if (mService.mController != null) { 480 // Find the first activity that is not finishing. 481 final ActivityRecord next = 482 r.getRootTask().topRunningActivity(token, INVALID_TASK_ID); 483 if (next != null) { 484 // ask watcher if this is allowed 485 boolean resumeOK = true; 486 try { 487 resumeOK = mService.mController.activityResuming(next.packageName); 488 } catch (RemoteException e) { 489 mService.mController = null; 490 Watchdog.getInstance().setActivityController(null); 491 } 492 493 if (!resumeOK) { 494 Slog.i(TAG, "Not finishing activity because controller resumed"); 495 return false; 496 } 497 } 498 } 499 500 // Note down that the process has finished an activity and is in background activity 501 // starts grace period. 502 if (r.app != null) { 503 r.app.setLastActivityFinishTimeIfNeeded(SystemClock.uptimeMillis()); 504 } 505 506 mService.mAmInternal.addCreatorToken(resultData, r.packageName); 507 508 final long origId = Binder.clearCallingIdentity(); 509 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "finishActivity"); 510 try { 511 final boolean res; 512 final boolean finishWithRootActivity = 513 finishTask == Activity.FINISH_TASK_WITH_ROOT_ACTIVITY; 514 mTaskSupervisor.getBackgroundActivityLaunchController() 515 .onActivityRequestedFinishing(r); 516 if (finishTask == Activity.FINISH_TASK_WITH_ACTIVITY 517 || (finishWithRootActivity && r == rootR)) { 518 // If requested, remove the task that is associated to this activity only if it 519 // was the root activity in the task. The result code and data is ignored 520 // because we don't support returning them across task boundaries. Also, to 521 // keep backwards compatibility we remove the task from recents when finishing 522 // task with root activity. 523 mTaskSupervisor.removeTask(tr, false /*killProcess*/, 524 finishWithRootActivity, "finish-activity", r.getUid(), r.getPid(), 525 r.info.name); 526 res = true; 527 // Explicitly dismissing the activity so reset its relaunch flag. 528 r.mRelaunchReason = RELAUNCH_REASON_NONE; 529 } else { 530 r.finishIfPossible(resultCode, resultData, resultGrants, "app-request", 531 true /* oomAdj */); 532 res = r.finishing; 533 if (!res) { 534 Slog.i(TAG, "Failed to finish by app-request"); 535 } 536 } 537 return res; 538 } finally { 539 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 540 Binder.restoreCallingIdentity(origId); 541 } 542 } 543 } 544 545 @Override finishActivityAffinity(IBinder token)546 public boolean finishActivityAffinity(IBinder token) { 547 final long origId = Binder.clearCallingIdentity(); 548 try { 549 synchronized (mGlobalLock) { 550 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token); 551 if (r == null) { 552 return false; 553 } 554 555 // Do not allow task to finish if last task in lockTask mode. Launchable priv-apps 556 // can finish. 557 if (mService.getLockTaskController().activityBlockedFromFinish(r)) { 558 return false; 559 } 560 561 r.getTask().forAllActivities(activity -> r.finishIfSameAffinity(activity), 562 r /* boundary */, true /* includeBoundary */, 563 true /* traverseTopToBottom */); 564 return true; 565 } 566 } finally { 567 Binder.restoreCallingIdentity(origId); 568 } 569 } 570 571 @Override finishSubActivity(IBinder token, String resultWho, int requestCode)572 public void finishSubActivity(IBinder token, String resultWho, int requestCode) { 573 final long origId = Binder.clearCallingIdentity(); 574 try { 575 synchronized (mGlobalLock) { 576 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token); 577 if (r == null) return; 578 579 // TODO: This should probably only loop over the task since you need to be in the 580 // same task to return results. 581 r.getRootTask().forAllActivities(activity -> { 582 activity.finishIfSubActivity(r /* parent */, resultWho, requestCode); 583 }, true /* traverseTopToBottom */); 584 585 mService.updateOomAdj(); 586 } 587 } finally { 588 Binder.restoreCallingIdentity(origId); 589 } 590 } 591 592 @Override setForceSendResultForMediaProjection(IBinder token)593 public void setForceSendResultForMediaProjection(IBinder token) { 594 // Require that this is invoked only during MediaProjection setup. 595 mService.mAmInternal.enforceCallingPermission( 596 Manifest.permission.MANAGE_MEDIA_PROJECTION, 597 "setForceSendResultForMediaProjection"); 598 599 final ActivityRecord r; 600 synchronized (mGlobalLock) { 601 r = ActivityRecord.isInRootTaskLocked(token); 602 if (r == null || !r.isInHistory()) { 603 return; 604 } 605 r.setForceSendResultForMediaProjection(); 606 } 607 } 608 609 @Override isTopOfTask(IBinder token)610 public boolean isTopOfTask(IBinder token) { 611 synchronized (mGlobalLock) { 612 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token); 613 return r != null && r.getTask().getTopNonFinishingActivity() == r; 614 } 615 } 616 617 @Override willActivityBeVisible(IBinder token)618 public boolean willActivityBeVisible(IBinder token) { 619 synchronized (mGlobalLock) { 620 final Task rootTask = ActivityRecord.getRootTask(token); 621 return rootTask != null && rootTask.willActivityBeVisible(token); 622 } 623 } 624 625 @Override getDisplayId(IBinder activityToken)626 public int getDisplayId(IBinder activityToken) { 627 synchronized (mGlobalLock) { 628 final Task rootTask = ActivityRecord.getRootTask(activityToken); 629 if (rootTask != null) { 630 final int displayId = rootTask.getDisplayId(); 631 return displayId != INVALID_DISPLAY ? displayId : DEFAULT_DISPLAY; 632 } 633 return DEFAULT_DISPLAY; 634 } 635 } 636 637 @Override getTaskForActivity(IBinder token, boolean onlyRoot)638 public int getTaskForActivity(IBinder token, boolean onlyRoot) { 639 synchronized (mGlobalLock) { 640 final ActivityRecord r = ActivityRecord.forTokenLocked(token); 641 if (r == null) { 642 return INVALID_TASK_ID; 643 } 644 final Task task = r.getTask(); 645 if (onlyRoot) { 646 return task.getRootActivity() == r ? task.mTaskId : INVALID_TASK_ID; 647 } 648 return task.mTaskId; 649 } 650 } 651 652 /** 653 * Returns the {@link Configuration} of the task which hosts the Activity, or {@code null} if 654 * the task {@link Configuration} cannot be obtained. 655 */ 656 @Override 657 @Nullable getTaskConfiguration(IBinder activityToken)658 public Configuration getTaskConfiguration(IBinder activityToken) { 659 synchronized (mGlobalLock) { 660 final ActivityRecord ar = ActivityRecord.isInAnyTask(activityToken); 661 if (ar == null) { 662 return null; 663 } 664 return ar.getTask().getConfiguration(); 665 } 666 } 667 668 @Override 669 @Nullable getActivityTokenBelow(IBinder activityToken)670 public IBinder getActivityTokenBelow(IBinder activityToken) { 671 final long ident = Binder.clearCallingIdentity(); 672 try { 673 synchronized (mGlobalLock) { 674 final ActivityRecord ar = ActivityRecord.isInAnyTask(activityToken); 675 if (ar == null) { 676 return null; 677 } 678 // Exclude finishing activity. 679 final ActivityRecord below = ar.getTask().getActivity((r) -> !r.finishing, 680 ar, false /*includeBoundary*/, true /*traverseTopToBottom*/); 681 if (below != null && below.getUid() == ar.getUid()) { 682 return below.token; 683 } 684 } 685 } finally { 686 Binder.restoreCallingIdentity(ident); 687 } 688 return null; 689 } 690 691 @Override getCallingActivity(IBinder token)692 public ComponentName getCallingActivity(IBinder token) { 693 synchronized (mGlobalLock) { 694 final ActivityRecord r = getCallingRecord(token); 695 return r != null ? r.intent.getComponent() : null; 696 } 697 } 698 699 @Override getCallingPackage(IBinder token)700 public String getCallingPackage(IBinder token) { 701 synchronized (mGlobalLock) { 702 final ActivityRecord r = getCallingRecord(token); 703 return r != null ? r.info.packageName : null; 704 } 705 } 706 getCallingRecord(IBinder token)707 private static ActivityRecord getCallingRecord(IBinder token) { 708 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token); 709 return r != null ? r.resultTo : null; 710 } 711 712 @Override getLaunchedFromUid(IBinder token)713 public int getLaunchedFromUid(IBinder token) { 714 return getUid(token, /* callerToken */ null, /* isActivityCallerCall */ false); 715 } 716 717 @Override getLaunchedFromPackage(IBinder token)718 public String getLaunchedFromPackage(IBinder token) { 719 return getPackage(token, /* callerToken */ null, /* isActivityCallerCall */ false); 720 } 721 722 @Override getActivityCallerUid(IBinder activityToken, IBinder callerToken)723 public int getActivityCallerUid(IBinder activityToken, IBinder callerToken) { 724 return getUid(activityToken, callerToken, /* isActivityCallerCall */ true); 725 } 726 727 @Override getActivityCallerPackage(IBinder activityToken, IBinder callerToken)728 public String getActivityCallerPackage(IBinder activityToken, IBinder callerToken) { 729 return getPackage(activityToken, callerToken, /* isActivityCallerCall */ true); 730 } 731 getUid(IBinder activityToken, IBinder callerToken, boolean isActivityCallerCall)732 private int getUid(IBinder activityToken, IBinder callerToken, boolean isActivityCallerCall) { 733 final int uid = Binder.getCallingUid(); 734 final boolean isInternalCaller = isInternalCallerGetLaunchedFrom(uid); 735 synchronized (mGlobalLock) { 736 final ActivityRecord r = ActivityRecord.forTokenLocked(activityToken); 737 if (r != null && (isInternalCaller || canGetLaunchedFromLocked(uid, r, callerToken, 738 isActivityCallerCall)) && isValidCaller(r, callerToken, isActivityCallerCall)) { 739 return isActivityCallerCall ? r.getCallerUid(callerToken) : r.launchedFromUid; 740 } 741 } 742 return INVALID_UID; 743 } 744 getPackage(IBinder activityToken, IBinder callerToken, boolean isActivityCallerCall)745 private String getPackage(IBinder activityToken, IBinder callerToken, 746 boolean isActivityCallerCall) { 747 final int uid = Binder.getCallingUid(); 748 final boolean isInternalCaller = isInternalCallerGetLaunchedFrom(uid); 749 synchronized (mGlobalLock) { 750 final ActivityRecord r = ActivityRecord.forTokenLocked(activityToken); 751 if (r != null && (isInternalCaller || canGetLaunchedFromLocked(uid, r, callerToken, 752 isActivityCallerCall)) && isValidCaller(r, callerToken, isActivityCallerCall)) { 753 return isActivityCallerCall 754 ? r.getCallerPackage(callerToken) : r.launchedFromPackage; 755 } 756 } 757 return null; 758 } 759 isValidCaller(ActivityRecord r, IBinder callerToken, boolean isActivityCallerCall)760 private boolean isValidCaller(ActivityRecord r, IBinder callerToken, 761 boolean isActivityCallerCall) { 762 return isActivityCallerCall ? r.hasCaller(callerToken) : callerToken == null; 763 } 764 765 /** 766 * @param uri This uri must NOT contain an embedded userId. 767 * @param userId The userId in which the uri is to be resolved. 768 */ 769 @Override checkActivityCallerContentUriPermission(IBinder activityToken, IBinder callerToken, Uri uri, int modeFlags, int userId)770 public int checkActivityCallerContentUriPermission(IBinder activityToken, IBinder callerToken, 771 Uri uri, int modeFlags, int userId) { 772 // 1. Check if we have access to the URI - > throw if we don't 773 GrantUri grantUri = new GrantUri(userId, uri, modeFlags); 774 if (!mService.mUgmInternal.checkUriPermission(grantUri, Binder.getCallingUid(), modeFlags, 775 /* isFullAccessForContentUri */ true)) { 776 throw new SecurityException("You don't have access to the content URI, hence can't" 777 + " check if the caller has access to it: " + uri); 778 } 779 780 // 2. Get the permission result for the caller 781 synchronized (mGlobalLock) { 782 final ActivityRecord r = ActivityRecord.forTokenLocked(activityToken); 783 if (r != null) { 784 boolean granted = r.checkContentUriPermission(callerToken, grantUri, modeFlags); 785 return granted ? PERMISSION_GRANTED : PERMISSION_DENIED; 786 } 787 } 788 return PERMISSION_DENIED; 789 } 790 791 /** Whether the call to one of the getLaunchedFrom APIs is performed by an internal caller. */ isInternalCallerGetLaunchedFrom(int uid)792 private boolean isInternalCallerGetLaunchedFrom(int uid) { 793 if (UserHandle.getAppId(uid) == SYSTEM_UID) { 794 return true; 795 } 796 final PackageManagerInternal pm = mService.mWindowManager.mPmInternal; 797 final AndroidPackage callingPkg = pm.getPackage(uid); 798 if (callingPkg == null) { 799 return false; 800 } 801 if (callingPkg.isSignedWithPlatformKey()) { 802 return true; 803 } 804 final String[] installerNames = pm.getKnownPackageNames( 805 KnownPackages.PACKAGE_INSTALLER, UserHandle.getUserId(uid)); 806 return installerNames.length > 0 && callingPkg.getPackageName().equals(installerNames[0]); 807 } 808 809 /** 810 * Returns whether the specified {@code uid} can access the launching app's identity by 811 * verifying whether the provided {@code ActivityRecord r} has opted in to sharing its 812 * identity or if the uid of the activity matches that of the launching app. 813 */ canGetLaunchedFromLocked(int uid, ActivityRecord r, IBinder callerToken, boolean isActivityCallerCall)814 private static boolean canGetLaunchedFromLocked(int uid, ActivityRecord r, 815 IBinder callerToken, boolean isActivityCallerCall) { 816 if (CompatChanges.isChangeEnabled(ACCESS_SHARED_IDENTITY, uid)) { 817 boolean isShareIdentityEnabled = isActivityCallerCall 818 ? r.isCallerShareIdentityEnabled(callerToken) : r.mShareIdentity; 819 int callerUid = isActivityCallerCall ? r.getCallerUid(callerToken) : r.launchedFromUid; 820 return isShareIdentityEnabled || callerUid == uid; 821 } 822 return false; 823 } 824 825 @Override setRequestedOrientation(IBinder token, int requestedOrientation)826 public void setRequestedOrientation(IBinder token, int requestedOrientation) { 827 final long origId = Binder.clearCallingIdentity(); 828 try { 829 synchronized (mGlobalLock) { 830 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token); 831 if (r != null) { 832 EventLogTags.writeWmSetRequestedOrientation(requestedOrientation, 833 r.shortComponentName); 834 r.setRequestedOrientation(requestedOrientation); 835 } 836 } 837 } finally { 838 Binder.restoreCallingIdentity(origId); 839 } 840 } 841 842 @Override getRequestedOrientation(IBinder token)843 public int getRequestedOrientation(IBinder token) { 844 synchronized (mGlobalLock) { 845 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token); 846 return r != null 847 ? r.getOverrideOrientation() 848 : ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 849 } 850 } 851 852 @Override convertFromTranslucent(IBinder token)853 public boolean convertFromTranslucent(IBinder token) { 854 final long origId = Binder.clearCallingIdentity(); 855 try { 856 synchronized (mGlobalLock) { 857 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token); 858 if (r == null) { 859 return false; 860 } 861 // Create a transition if the activity is playing in case the below activity didn't 862 // commit invisible. That's because if any activity below this one has changed its 863 // visibility while playing transition, there won't able to commit visibility until 864 // the running transition finish. 865 final Transition transition = r.mTransitionController.isShellTransitionsEnabled() 866 && !r.mTransitionController.isCollecting() 867 ? r.mTransitionController.createTransition(TRANSIT_TO_BACK) : null; 868 final boolean changed = r.setOccludesParent(true); 869 if (transition != null) { 870 if (changed) { 871 // Always set as scene transition because it expects to be a jump-cut. 872 transition.setOverrideAnimation( 873 TransitionInfo.AnimationOptions.makeSceneTransitionAnimOptions(), r, 874 null, null); 875 r.mTransitionController.requestStartTransition(transition, 876 null /*startTask */, null /* remoteTransition */, 877 null /* displayChange */); 878 r.mTransitionController.setReady(r.getDisplayContent()); 879 } else { 880 transition.abort(); 881 } 882 } 883 return changed; 884 } 885 } finally { 886 Binder.restoreCallingIdentity(origId); 887 } 888 } 889 890 @Override convertToTranslucent(IBinder token, Bundle options)891 public boolean convertToTranslucent(IBinder token, Bundle options) { 892 final int callingPid = Binder.getCallingPid(); 893 final int callingUid = Binder.getCallingUid(); 894 final SafeActivityOptions safeOptions = SafeActivityOptions.fromBundle( 895 options, callingPid, callingUid); 896 final long origId = Binder.clearCallingIdentity(); 897 try { 898 synchronized (mGlobalLock) { 899 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token); 900 if (r == null) { 901 return false; 902 } 903 final ActivityRecord under = r.getTask().getActivityBelow(r); 904 if (under != null) { 905 under.returningOptions = safeOptions != null ? safeOptions.getOptions(r) : null; 906 } 907 // Create a transition to make sure the activity change is collected. 908 final Transition transition = r.mTransitionController.isShellTransitionsEnabled() 909 && !r.mTransitionController.isCollecting() 910 ? r.mTransitionController.createTransition(TRANSIT_TO_FRONT) : null; 911 final boolean changed = r.setOccludesParent(false); 912 if (transition != null) { 913 if (changed) { 914 r.mTransitionController.requestStartTransition(transition, 915 null /*startTask */, null /* remoteTransition */, 916 null /* displayChange */); 917 r.mTransitionController.setReady(r.getDisplayContent()); 918 if (under != null && under.returningOptions != null 919 && under.returningOptions.getAnimationType() 920 == ANIM_SCENE_TRANSITION) { 921 // Pass along the scene-transition animation-type 922 transition.setOverrideAnimation(TransitionInfo 923 .AnimationOptions.makeSceneTransitionAnimOptions(), r, 924 null, null); 925 } 926 } else { 927 transition.abort(); 928 } 929 } 930 return changed; 931 } 932 } finally { 933 Binder.restoreCallingIdentity(origId); 934 } 935 } 936 937 @Override isImmersive(IBinder token)938 public boolean isImmersive(IBinder token) { 939 synchronized (mGlobalLock) { 940 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token); 941 if (r == null) { 942 throw new IllegalArgumentException(); 943 } 944 return r.immersive; 945 } 946 } 947 948 @Override setImmersive(IBinder token, boolean immersive)949 public void setImmersive(IBinder token, boolean immersive) { 950 synchronized (mGlobalLock) { 951 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token); 952 if (r == null) { 953 throw new IllegalArgumentException(); 954 } 955 r.immersive = immersive; 956 957 // Update associated state if we're frontmost. 958 if (r.isFocusedActivityOnDisplay()) { 959 ProtoLog.d(WM_DEBUG_IMMERSIVE, "Frontmost changed immersion: %s", r); 960 mService.applyUpdateLockStateLocked(r); 961 } 962 } 963 } 964 965 @Override enterPictureInPictureMode(IBinder token, final PictureInPictureParams params)966 public boolean enterPictureInPictureMode(IBinder token, final PictureInPictureParams params) { 967 final long origId = Binder.clearCallingIdentity(); 968 try { 969 ensureSetPipAspectRatioQuotaTracker(); 970 synchronized (mGlobalLock) { 971 final ActivityRecord r = ensureValidPictureInPictureActivityParams( 972 "enterPictureInPictureMode", token, params); 973 return mService.enterPictureInPictureMode(r, params, true /* fromClient */); 974 } 975 } finally { 976 Binder.restoreCallingIdentity(origId); 977 } 978 } 979 980 @Override setPictureInPictureParams(IBinder token, final PictureInPictureParams params)981 public void setPictureInPictureParams(IBinder token, final PictureInPictureParams params) { 982 final long origId = Binder.clearCallingIdentity(); 983 try { 984 ensureSetPipAspectRatioQuotaTracker(); 985 synchronized (mGlobalLock) { 986 final ActivityRecord r = ensureValidPictureInPictureActivityParams( 987 "setPictureInPictureParams", token, params); 988 r.setPictureInPictureParams(params); 989 } 990 } finally { 991 Binder.restoreCallingIdentity(origId); 992 } 993 } 994 995 @Override setShouldDockBigOverlays(IBinder token, boolean shouldDockBigOverlays)996 public void setShouldDockBigOverlays(IBinder token, boolean shouldDockBigOverlays) { 997 final long origId = Binder.clearCallingIdentity(); 998 try { 999 synchronized (mGlobalLock) { 1000 final ActivityRecord r = ActivityRecord.forTokenLocked(token); 1001 r.setShouldDockBigOverlays(shouldDockBigOverlays); 1002 } 1003 } finally { 1004 Binder.restoreCallingIdentity(origId); 1005 } 1006 } 1007 1008 /** 1009 * Splash screen view is attached to activity. 1010 */ 1011 @Override splashScreenAttached(IBinder token)1012 public void splashScreenAttached(IBinder token) { 1013 final long origId = Binder.clearCallingIdentity(); 1014 synchronized (mGlobalLock) { 1015 ActivityRecord.splashScreenAttachedLocked(token); 1016 } 1017 Binder.restoreCallingIdentity(origId); 1018 } 1019 1020 /** 1021 * Initialize the {@link #mSetPipAspectRatioQuotaTracker} if applicable, which should happen 1022 * out of {@link #mGlobalLock} to avoid deadlock (AM lock is used in QuotaTrack ctor). 1023 */ ensureSetPipAspectRatioQuotaTracker()1024 private void ensureSetPipAspectRatioQuotaTracker() { 1025 if (mSetPipAspectRatioQuotaTracker == null) { 1026 mSetPipAspectRatioQuotaTracker = new CountQuotaTracker(mContext, 1027 Categorizer.SINGLE_CATEGORIZER); 1028 mSetPipAspectRatioQuotaTracker.setCountLimit(Category.SINGLE_CATEGORY, 1029 SET_PIP_ASPECT_RATIO_LIMIT, SET_PIP_ASPECT_RATIO_TIME_WINDOW_MS); 1030 } 1031 } 1032 1033 /** 1034 * Checks the state of the system and the activity associated with the given {@param token} to 1035 * verify that picture-in-picture is supported for that activity. 1036 * 1037 * @return the activity record for the given {@param token} if all the checks pass. 1038 */ ensureValidPictureInPictureActivityParams(String caller, IBinder token, PictureInPictureParams params)1039 private ActivityRecord ensureValidPictureInPictureActivityParams(String caller, 1040 IBinder token, PictureInPictureParams params) { 1041 if (!mService.mSupportsPictureInPicture) { 1042 throw new IllegalStateException(caller 1043 + ": Device doesn't support picture-in-picture mode."); 1044 } 1045 1046 final ActivityRecord r = ActivityRecord.forTokenLocked(token); 1047 if (r == null) { 1048 throw new IllegalStateException(caller 1049 + ": Can't find activity for token=" + token); 1050 } 1051 1052 if (!r.supportsPictureInPicture()) { 1053 throw new IllegalStateException(caller 1054 + ": Current activity does not support picture-in-picture."); 1055 } 1056 1057 // Rate limit how frequent an app can request aspect ratio change via 1058 // Activity#setPictureInPictureParams 1059 final int userId = UserHandle.getCallingUserId(); 1060 if (r.pictureInPictureArgs.hasSetAspectRatio() 1061 && params.hasSetAspectRatio() 1062 && !r.pictureInPictureArgs.getAspectRatio().equals( 1063 params.getAspectRatio()) 1064 && !mSetPipAspectRatioQuotaTracker.noteEvent( 1065 userId, r.packageName, "setPipAspectRatio")) { 1066 throw new IllegalStateException(caller 1067 + ": Too many PiP aspect ratio change requests from " + r.packageName); 1068 } 1069 1070 final float minAspectRatio = mContext.getResources().getFloat( 1071 com.android.internal.R.dimen.config_pictureInPictureMinAspectRatio); 1072 final float maxAspectRatio = mContext.getResources().getFloat( 1073 com.android.internal.R.dimen.config_pictureInPictureMaxAspectRatio); 1074 1075 if (params.hasSetAspectRatio() 1076 && !mService.mWindowManager.isValidPictureInPictureAspectRatio( 1077 r.mDisplayContent, params.getAspectRatioFloat())) { 1078 throw new IllegalArgumentException(String.format(caller 1079 + ": Aspect ratio is too extreme (must be between %f and %f).", 1080 minAspectRatio, maxAspectRatio)); 1081 } 1082 1083 if (mService.mSupportsExpandedPictureInPicture && params.hasSetExpandedAspectRatio() 1084 && !mService.mWindowManager.isValidExpandedPictureInPictureAspectRatio( 1085 r.mDisplayContent, params.getExpandedAspectRatioFloat())) { 1086 throw new IllegalArgumentException(String.format(caller 1087 + ": Expanded aspect ratio is not extreme enough (must not be between" 1088 + " %f and %f).", 1089 minAspectRatio, maxAspectRatio)); 1090 } 1091 1092 // Truncate the number of actions if necessary. 1093 params.truncateActions(ActivityTaskManager.getMaxNumPictureInPictureActions(mContext)); 1094 return r; 1095 } 1096 1097 /** 1098 * Requests that an activity should enter picture-in-picture mode if possible. This method may 1099 * be used by the implementation of non-phone form factors. 1100 * 1101 * @return false if the activity cannot enter PIP mode. 1102 */ requestPictureInPictureMode(@onNull ActivityRecord r)1103 boolean requestPictureInPictureMode(@NonNull ActivityRecord r) { 1104 if (r.inPinnedWindowingMode()) { 1105 return false; 1106 } 1107 1108 final boolean canEnterPictureInPicture = r.checkEnterPictureInPictureState( 1109 "requestPictureInPictureMode", /* beforeStopping */ false); 1110 if (!canEnterPictureInPicture) { 1111 return false; 1112 } 1113 1114 if (r.pictureInPictureArgs.isAutoEnterEnabled()) { 1115 return mService.enterPictureInPictureMode(r, r.pictureInPictureArgs, 1116 false /* fromClient */); 1117 } 1118 1119 final EnterPipRequestedItem item = new EnterPipRequestedItem(r.token); 1120 try { 1121 return mService.getLifecycleManager().scheduleTransactionItem(r.app.getThread(), item); 1122 } catch (RemoteException e) { 1123 // TODO(b/323801078): remove Exception when cleanup 1124 Slog.w(TAG, "Failed to send enter pip requested item: " 1125 + r.intent.getComponent(), e); 1126 return false; 1127 } 1128 } 1129 1130 /** 1131 * Alert the client that the Picture-in-Picture state has changed. 1132 */ onPictureInPictureUiStateChanged(@onNull ActivityRecord r, PictureInPictureUiState pipState)1133 void onPictureInPictureUiStateChanged(@NonNull ActivityRecord r, 1134 PictureInPictureUiState pipState) { 1135 final PipStateTransactionItem item = new PipStateTransactionItem(r.token, pipState); 1136 try { 1137 mService.getLifecycleManager().scheduleTransactionItem(r.app.getThread(), item); 1138 } catch (RemoteException e) { 1139 // TODO(b/323801078): remove Exception when cleanup 1140 Slog.w(TAG, "Failed to send pip state transaction item: " 1141 + r.intent.getComponent(), e); 1142 } 1143 } 1144 1145 @Override toggleFreeformWindowingMode(IBinder token)1146 public void toggleFreeformWindowingMode(IBinder token) { 1147 final long ident = Binder.clearCallingIdentity(); 1148 try { 1149 synchronized (mGlobalLock) { 1150 final ActivityRecord r = ActivityRecord.forTokenLocked(token); 1151 if (r == null) { 1152 throw new IllegalArgumentException( 1153 "toggleFreeformWindowingMode: No activity record matching token=" 1154 + token); 1155 } 1156 1157 final Task rootTask = r.getRootTask(); 1158 if (rootTask == null) { 1159 throw new IllegalStateException("toggleFreeformWindowingMode: the activity " 1160 + "doesn't have a root task"); 1161 } 1162 1163 if (!rootTask.inFreeformWindowingMode() 1164 && rootTask.getWindowingMode() != WINDOWING_MODE_FULLSCREEN) { 1165 throw new IllegalStateException("toggleFreeformWindowingMode: You can only " 1166 + "toggle between fullscreen and freeform."); 1167 } 1168 1169 if (rootTask.inFreeformWindowingMode()) { 1170 rootTask.setRootTaskWindowingMode(WINDOWING_MODE_FULLSCREEN); 1171 rootTask.setBounds(null); 1172 } else if (!r.supportsFreeform()) { 1173 throw new IllegalStateException( 1174 "This activity is currently not freeform-enabled"); 1175 } else if (rootTask.getParent().inFreeformWindowingMode()) { 1176 // If the window is on a freeform display, set it to undefined. It will be 1177 // resolved to freeform and it can adjust windowing mode when the display mode 1178 // changes in runtime. 1179 rootTask.setRootTaskWindowingMode(WINDOWING_MODE_UNDEFINED); 1180 } else { 1181 rootTask.setRootTaskWindowingMode(WINDOWING_MODE_FREEFORM); 1182 } 1183 } 1184 } finally { 1185 Binder.restoreCallingIdentity(ident); 1186 } 1187 } 1188 validateMultiwindowFullscreenRequestLocked( Task topFocusedRootTask, int fullscreenRequest, ActivityRecord requesterActivity)1189 private @FullscreenRequestHandler.RequestResult int validateMultiwindowFullscreenRequestLocked( 1190 Task topFocusedRootTask, int fullscreenRequest, ActivityRecord requesterActivity) { 1191 if (requesterActivity.getWindowingMode() == WINDOWING_MODE_PINNED) { 1192 return RESULT_APPROVED; 1193 } 1194 final int taskWindowingMode = topFocusedRootTask.getWindowingMode(); 1195 // If this is not coming from the currently top-most activity, reject the request. 1196 if (requesterActivity != topFocusedRootTask.getTopMostActivity()) { 1197 return RESULT_FAILED_NOT_TOP_FOCUSED; 1198 } 1199 if (fullscreenRequest == FULLSCREEN_MODE_REQUEST_EXIT) { 1200 if (taskWindowingMode != WINDOWING_MODE_FULLSCREEN) { 1201 return RESULT_FAILED_NOT_IN_FULLSCREEN_WITH_HISTORY; 1202 } 1203 if (topFocusedRootTask.mMultiWindowRestoreWindowingMode == INVALID_WINDOWING_MODE) { 1204 return RESULT_FAILED_NOT_IN_FULLSCREEN_WITH_HISTORY; 1205 } 1206 return RESULT_APPROVED; 1207 } 1208 1209 if (DesktopModeFlags.ENABLE_REQUEST_FULLSCREEN_BUGFIX.isTrue() 1210 && (taskWindowingMode == WINDOWING_MODE_FULLSCREEN 1211 || taskWindowingMode == WINDOWING_MODE_MULTI_WINDOW)) { 1212 return RESULT_FAILED_ALREADY_FULLY_EXPANDED; 1213 } 1214 return RESULT_APPROVED; 1215 } 1216 1217 @Override requestMultiwindowFullscreen(IBinder callingActivity, int fullscreenRequest, IRemoteCallback callback)1218 public void requestMultiwindowFullscreen(IBinder callingActivity, int fullscreenRequest, 1219 IRemoteCallback callback) { 1220 final long ident = Binder.clearCallingIdentity(); 1221 try { 1222 synchronized (mGlobalLock) { 1223 requestMultiwindowFullscreenLocked(callingActivity, fullscreenRequest, callback); 1224 } 1225 } finally { 1226 Binder.restoreCallingIdentity(ident); 1227 } 1228 } 1229 requestMultiwindowFullscreenLocked(IBinder callingActivity, int fullscreenRequest, IRemoteCallback callback)1230 private void requestMultiwindowFullscreenLocked(IBinder callingActivity, int fullscreenRequest, 1231 IRemoteCallback callback) { 1232 final ActivityRecord r = ActivityRecord.forTokenLocked(callingActivity); 1233 if (r == null) { 1234 return; 1235 } 1236 1237 // If the shell transition is not enabled, just execute and done. 1238 final TransitionController controller = r.mTransitionController; 1239 if (!controller.isShellTransitionsEnabled()) { 1240 final @FullscreenRequestHandler.RequestResult int validateResult; 1241 final Task topFocusedRootTask; 1242 topFocusedRootTask = mService.getTopDisplayFocusedRootTask(); 1243 validateResult = validateMultiwindowFullscreenRequestLocked(topFocusedRootTask, 1244 fullscreenRequest, r); 1245 reportMultiwindowFullscreenRequestValidatingResult(callback, validateResult); 1246 if (validateResult == RESULT_APPROVED) { 1247 executeMultiWindowFullscreenRequest(fullscreenRequest, topFocusedRootTask); 1248 } 1249 return; 1250 } 1251 // Initiate the transition. 1252 final Transition transition = new Transition(TRANSIT_CHANGE, 0 /* flags */, controller, 1253 mService.mWindowManager.mSyncEngine); 1254 r.mTransitionController.startCollectOrQueue(transition, 1255 (deferred) -> { 1256 executeFullscreenRequestTransition(fullscreenRequest, callback, r, 1257 transition, deferred); 1258 }); 1259 } 1260 executeFullscreenRequestTransition(int fullscreenRequest, IRemoteCallback callback, ActivityRecord r, Transition transition, boolean queued)1261 private void executeFullscreenRequestTransition(int fullscreenRequest, IRemoteCallback callback, 1262 ActivityRecord r, Transition transition, boolean queued) { 1263 final @FullscreenRequestHandler.RequestResult int validateResult; 1264 final Task topFocusedRootTask; 1265 topFocusedRootTask = mService.getTopDisplayFocusedRootTask(); 1266 validateResult = validateMultiwindowFullscreenRequestLocked(topFocusedRootTask, 1267 fullscreenRequest, r); 1268 reportMultiwindowFullscreenRequestValidatingResult(callback, validateResult); 1269 if (validateResult != RESULT_APPROVED) { 1270 transition.abort(); 1271 return; 1272 } 1273 final Task requestingTask = r.getTask(); 1274 transition.collect(requestingTask); 1275 executeMultiWindowFullscreenRequest(fullscreenRequest, requestingTask); 1276 r.mTransitionController.requestStartTransition(transition, requestingTask, 1277 null /* remoteTransition */, null /* displayChange */); 1278 transition.setReady(requestingTask, true); 1279 } 1280 reportMultiwindowFullscreenRequestValidatingResult(IRemoteCallback callback, @FullscreenRequestHandler.RequestResult int result)1281 private static void reportMultiwindowFullscreenRequestValidatingResult(IRemoteCallback callback, 1282 @FullscreenRequestHandler.RequestResult int result) { 1283 if (callback == null) { 1284 return; 1285 } 1286 Bundle res = new Bundle(); 1287 res.putInt(REMOTE_CALLBACK_RESULT_KEY, result); 1288 try { 1289 callback.sendResult(res); 1290 } catch (RemoteException e) { 1291 Slog.w(TAG, "client throws an exception back to the server, ignore it"); 1292 } 1293 } 1294 executeMultiWindowFullscreenRequest(int fullscreenRequest, Task requester)1295 private void executeMultiWindowFullscreenRequest(int fullscreenRequest, Task requester) { 1296 final int targetWindowingMode; 1297 if (fullscreenRequest == FULLSCREEN_MODE_REQUEST_ENTER) { 1298 final int restoreWindowingMode = requester.getRequestedOverrideWindowingMode(); 1299 targetWindowingMode = WINDOWING_MODE_FULLSCREEN; 1300 requester.setRootTaskWindowingMode(targetWindowingMode); 1301 // The restore windowing mode must be set after the windowing mode is set since 1302 // Task#setWindowingMode resets the restore windowing mode to WINDOWING_MODE_INVALID. 1303 requester.mMultiWindowRestoreWindowingMode = restoreWindowingMode; 1304 requester.mMultiWindowRestoreParent = 1305 requester.getParent().mRemoteToken.toWindowContainerToken(); 1306 } else { 1307 targetWindowingMode = requester.mMultiWindowRestoreWindowingMode; 1308 if (DesktopModeFlags.ENABLE_REQUEST_FULLSCREEN_BUGFIX.isTrue() 1309 && targetWindowingMode == WINDOWING_MODE_PINNED) { 1310 final ActivityRecord r = requester.topRunningActivity(); 1311 enterPictureInPictureMode(r.token, r.pictureInPictureArgs); 1312 } else { 1313 requester.restoreWindowingMode(); 1314 } 1315 } 1316 if (targetWindowingMode == WINDOWING_MODE_FULLSCREEN) { 1317 requester.setBounds(null); 1318 } 1319 } 1320 1321 @Override startLockTaskModeByToken(IBinder token)1322 public void startLockTaskModeByToken(IBinder token) { 1323 synchronized (mGlobalLock) { 1324 final ActivityRecord r = ActivityRecord.forTokenLocked(token); 1325 if (r == null) return; 1326 mService.startLockTaskMode(r.getTask(), false /* isSystemCaller */); 1327 } 1328 } 1329 1330 @Override stopLockTaskModeByToken(IBinder token)1331 public void stopLockTaskModeByToken(IBinder token) { 1332 mService.stopLockTaskModeInternal(token, false /* isSystemCaller */); 1333 } 1334 1335 @Override showLockTaskEscapeMessage(IBinder token)1336 public void showLockTaskEscapeMessage(IBinder token) { 1337 synchronized (mGlobalLock) { 1338 if (ActivityRecord.forTokenLocked(token) != null) { 1339 mService.getLockTaskController().showLockTaskToast(); 1340 } 1341 } 1342 } 1343 1344 @Override setTaskDescription(IBinder token, ActivityManager.TaskDescription td)1345 public void setTaskDescription(IBinder token, ActivityManager.TaskDescription td) { 1346 synchronized (mGlobalLock) { 1347 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token); 1348 if (r != null) { 1349 r.setTaskDescription(td); 1350 } 1351 } 1352 } 1353 1354 @Override showAssistFromActivity(IBinder token, Bundle args)1355 public boolean showAssistFromActivity(IBinder token, Bundle args) { 1356 final long ident = Binder.clearCallingIdentity(); 1357 try { 1358 final String callingAttributionTag; 1359 synchronized (mGlobalLock) { 1360 final ActivityRecord caller = ActivityRecord.forTokenLocked(token); 1361 final Task topRootTask = mService.getTopDisplayFocusedRootTask(); 1362 final ActivityRecord top = topRootTask != null 1363 ? topRootTask.getTopNonFinishingActivity() : null; 1364 if (top != caller) { 1365 Slog.w(TAG, "showAssistFromActivity failed: caller " + caller 1366 + " is not current top " + top); 1367 return false; 1368 } 1369 if (!top.nowVisible) { 1370 Slog.w(TAG, "showAssistFromActivity failed: caller " + caller 1371 + " is not visible"); 1372 return false; 1373 } 1374 callingAttributionTag = top.launchedFromFeatureId; 1375 } 1376 return mAssistUtils.showSessionForActiveService(args, SHOW_SOURCE_APPLICATION, 1377 callingAttributionTag, null /* showCallback */, token); 1378 } finally { 1379 Binder.restoreCallingIdentity(ident); 1380 } 1381 } 1382 1383 @Override isRootVoiceInteraction(IBinder token)1384 public boolean isRootVoiceInteraction(IBinder token) { 1385 synchronized (mGlobalLock) { 1386 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token); 1387 return r != null && r.rootVoiceInteraction; 1388 } 1389 } 1390 1391 @Override startLocalVoiceInteraction(IBinder callingActivity, Bundle options)1392 public void startLocalVoiceInteraction(IBinder callingActivity, Bundle options) { 1393 Slog.i(TAG, "Activity tried to startLocalVoiceInteraction"); 1394 final String callingAttributionTag; 1395 synchronized (mGlobalLock) { 1396 final Task topRootTask = mService.getTopDisplayFocusedRootTask(); 1397 final ActivityRecord activity = topRootTask != null 1398 ? topRootTask.getTopNonFinishingActivity() : null; 1399 if (ActivityRecord.forTokenLocked(callingActivity) != activity) { 1400 throw new SecurityException("Only focused activity can call startVoiceInteraction"); 1401 } 1402 if (mService.mRunningVoice != null || activity.getTask().voiceSession != null 1403 || activity.voiceSession != null) { 1404 Slog.w(TAG, "Already in a voice interaction, cannot start new voice interaction"); 1405 return; 1406 } 1407 if (activity.pendingVoiceInteractionStart) { 1408 Slog.w(TAG, "Pending start of voice interaction already."); 1409 return; 1410 } 1411 activity.pendingVoiceInteractionStart = true; 1412 callingAttributionTag = activity.launchedFromFeatureId; 1413 } 1414 LocalServices.getService(VoiceInteractionManagerInternal.class) 1415 .startLocalVoiceInteraction(callingActivity, callingAttributionTag, options); 1416 } 1417 1418 @Override stopLocalVoiceInteraction(IBinder callingActivity)1419 public void stopLocalVoiceInteraction(IBinder callingActivity) { 1420 LocalServices.getService(VoiceInteractionManagerInternal.class) 1421 .stopLocalVoiceInteraction(callingActivity); 1422 } 1423 1424 @Override setShowWhenLocked(IBinder token, boolean showWhenLocked)1425 public void setShowWhenLocked(IBinder token, boolean showWhenLocked) { 1426 final long origId = Binder.clearCallingIdentity(); 1427 try { 1428 synchronized (mGlobalLock) { 1429 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token); 1430 if (r != null) { 1431 r.setShowWhenLocked(showWhenLocked); 1432 } 1433 } 1434 } finally { 1435 Binder.restoreCallingIdentity(origId); 1436 } 1437 } 1438 1439 @Override setInheritShowWhenLocked(IBinder token, boolean inheritShowWhenLocked)1440 public void setInheritShowWhenLocked(IBinder token, boolean inheritShowWhenLocked) { 1441 final long origId = Binder.clearCallingIdentity(); 1442 try { 1443 synchronized (mGlobalLock) { 1444 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token); 1445 if (r != null) { 1446 r.setInheritShowWhenLocked(inheritShowWhenLocked); 1447 } 1448 } 1449 } finally { 1450 Binder.restoreCallingIdentity(origId); 1451 } 1452 } 1453 1454 @Override setTurnScreenOn(IBinder token, boolean turnScreenOn)1455 public void setTurnScreenOn(IBinder token, boolean turnScreenOn) { 1456 final long origId = Binder.clearCallingIdentity(); 1457 try { 1458 synchronized (mGlobalLock) { 1459 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token); 1460 if (r != null) { 1461 r.setTurnScreenOn(turnScreenOn); 1462 } 1463 } 1464 } finally { 1465 Binder.restoreCallingIdentity(origId); 1466 } 1467 } 1468 setAllowCrossUidActivitySwitchFromBelow(IBinder token, boolean allowed)1469 public void setAllowCrossUidActivitySwitchFromBelow(IBinder token, boolean allowed) { 1470 final long origId = Binder.clearCallingIdentity(); 1471 try { 1472 synchronized (mGlobalLock) { 1473 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token); 1474 if (r != null) { 1475 r.setAllowCrossUidActivitySwitchFromBelow(allowed); 1476 } 1477 } 1478 } finally { 1479 Binder.restoreCallingIdentity(origId); 1480 } 1481 } 1482 1483 @Override reportActivityFullyDrawn(IBinder token, boolean restoredFromBundle)1484 public void reportActivityFullyDrawn(IBinder token, boolean restoredFromBundle) { 1485 final long origId = Binder.clearCallingIdentity(); 1486 try { 1487 synchronized (mGlobalLock) { 1488 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token); 1489 if (r != null) { 1490 mTaskSupervisor.getActivityMetricsLogger().notifyFullyDrawn(r, 1491 restoredFromBundle); 1492 } 1493 } 1494 } finally { 1495 Binder.restoreCallingIdentity(origId); 1496 } 1497 } 1498 1499 @Override overrideActivityTransition(IBinder token, boolean open, int enterAnim, int exitAnim, int backgroundColor)1500 public void overrideActivityTransition(IBinder token, boolean open, int enterAnim, int exitAnim, 1501 int backgroundColor) { 1502 final long origId = Binder.clearCallingIdentity(); 1503 synchronized (mGlobalLock) { 1504 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token); 1505 if (r != null) { 1506 r.overrideCustomTransition(open, enterAnim, exitAnim, backgroundColor); 1507 } 1508 } 1509 Binder.restoreCallingIdentity(origId); 1510 } 1511 1512 @Override clearOverrideActivityTransition(IBinder token, boolean open)1513 public void clearOverrideActivityTransition(IBinder token, boolean open) { 1514 final long origId = Binder.clearCallingIdentity(); 1515 synchronized (mGlobalLock) { 1516 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token); 1517 if (r != null) { 1518 r.clearCustomTransition(open); 1519 } 1520 } 1521 Binder.restoreCallingIdentity(origId); 1522 } 1523 1524 @Override overridePendingTransition(IBinder token, String packageName, int enterAnim, int exitAnim, @ColorInt int backgroundColor)1525 public void overridePendingTransition(IBinder token, String packageName, 1526 int enterAnim, int exitAnim, @ColorInt int backgroundColor) { 1527 final long origId = Binder.clearCallingIdentity(); 1528 synchronized (mGlobalLock) { 1529 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token); 1530 if (r != null && r.isState(RESUMED, PAUSING)) { 1531 r.mTransitionController.setOverrideAnimation( 1532 TransitionInfo.AnimationOptions.makeCustomAnimOptions(packageName, 1533 enterAnim, 0 /* changeResId */, exitAnim, 1534 r.mOverrideTaskTransition), 1535 r, null /* startCallback */, null /* finishCallback */); 1536 r.mTransitionController.setOverrideBackgroundColor(backgroundColor); 1537 } 1538 } 1539 Binder.restoreCallingIdentity(origId); 1540 } 1541 1542 @Override setVrMode(IBinder token, boolean enabled, ComponentName packageName)1543 public int setVrMode(IBinder token, boolean enabled, ComponentName packageName) { 1544 mService.enforceSystemHasVrFeature(); 1545 1546 final VrManagerInternal vrService = LocalServices.getService(VrManagerInternal.class); 1547 final ActivityRecord r; 1548 synchronized (mGlobalLock) { 1549 r = ActivityRecord.isInRootTaskLocked(token); 1550 } 1551 if (r == null) { 1552 throw new IllegalArgumentException(); 1553 } 1554 1555 final int err; 1556 if ((err = vrService.hasVrPackage(packageName, r.mUserId)) != VrManagerInternal.NO_ERROR) { 1557 return err; 1558 } 1559 1560 // Clear the binder calling uid since this path may call moveToTask(). 1561 final long callingId = Binder.clearCallingIdentity(); 1562 try { 1563 synchronized (mGlobalLock) { 1564 r.requestedVrComponent = (enabled) ? packageName : null; 1565 1566 // Update associated state if this activity is currently focused. 1567 if (r.isFocusedActivityOnDisplay()) { 1568 mService.applyUpdateVrModeLocked(r); 1569 } 1570 return 0; 1571 } 1572 } finally { 1573 Binder.restoreCallingIdentity(callingId); 1574 } 1575 } 1576 1577 @Override setRecentsScreenshotEnabled(IBinder token, boolean enabled)1578 public void setRecentsScreenshotEnabled(IBinder token, boolean enabled) { 1579 final long origId = Binder.clearCallingIdentity(); 1580 try { 1581 synchronized (mGlobalLock) { 1582 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token); 1583 if (r != null) { 1584 r.setRecentsScreenshotEnabled(enabled); 1585 } 1586 } 1587 } finally { 1588 Binder.restoreCallingIdentity(origId); 1589 } 1590 } 1591 restartActivityProcessIfVisible(IBinder token)1592 void restartActivityProcessIfVisible(IBinder token) { 1593 ActivityTaskManagerService.enforceTaskPermission("restartActivityProcess"); 1594 final long callingId = Binder.clearCallingIdentity(); 1595 try { 1596 synchronized (mGlobalLock) { 1597 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token); 1598 if (r != null) { 1599 r.restartProcessIfVisible(); 1600 } 1601 } 1602 } finally { 1603 Binder.restoreCallingIdentity(callingId); 1604 } 1605 } 1606 1607 /** 1608 * Removes the outdated home task snapshot. 1609 * 1610 * @param token The token of the home task, or null if you have the 1611 * {@link android.Manifest.permission#MANAGE_ACTIVITY_TASKS} 1612 * permission and want us to find the home task token for you. 1613 */ 1614 @Override invalidateHomeTaskSnapshot(IBinder token)1615 public void invalidateHomeTaskSnapshot(IBinder token) { 1616 if (token == null) { 1617 ActivityTaskManagerService.enforceTaskPermission("invalidateHomeTaskSnapshot"); 1618 } 1619 1620 synchronized (mGlobalLock) { 1621 final ActivityRecord r; 1622 if (token == null) { 1623 final Task rootTask = 1624 mService.mRootWindowContainer.getDefaultTaskDisplayArea().getRootHomeTask(); 1625 r = rootTask != null ? rootTask.topRunningActivity() : null; 1626 } else { 1627 r = ActivityRecord.isInRootTaskLocked(token); 1628 } 1629 1630 if (r != null && r.isActivityTypeHome()) { 1631 mService.mWindowManager.mTaskSnapshotController.removeSnapshotCache( 1632 r.getTask().mTaskId); 1633 } 1634 } 1635 } 1636 1637 @Override dismissKeyguard(IBinder token, IKeyguardDismissCallback callback, CharSequence message)1638 public void dismissKeyguard(IBinder token, IKeyguardDismissCallback callback, 1639 CharSequence message) { 1640 if (message != null) { 1641 mService.mAmInternal.enforceCallingPermission( 1642 android.Manifest.permission.SHOW_KEYGUARD_MESSAGE, "dismissKeyguard"); 1643 } 1644 final long callingId = Binder.clearCallingIdentity(); 1645 try { 1646 synchronized (mGlobalLock) { 1647 mService.mKeyguardController.dismissKeyguard(token, callback, message); 1648 } 1649 } finally { 1650 Binder.restoreCallingIdentity(callingId); 1651 } 1652 } 1653 1654 @Override registerRemoteAnimations(IBinder token, RemoteAnimationDefinition definition)1655 public void registerRemoteAnimations(IBinder token, RemoteAnimationDefinition definition) { 1656 mService.mAmInternal.enforceCallingPermission(CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS, 1657 "registerRemoteAnimations"); 1658 definition.setCallingPidUid(Binder.getCallingPid(), Binder.getCallingUid()); 1659 final long origId = Binder.clearCallingIdentity(); 1660 try { 1661 synchronized (mGlobalLock) { 1662 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token); 1663 if (r != null) { 1664 r.registerRemoteAnimations(definition); 1665 } 1666 } 1667 } finally { 1668 Binder.restoreCallingIdentity(origId); 1669 } 1670 } 1671 1672 @Override unregisterRemoteAnimations(IBinder token)1673 public void unregisterRemoteAnimations(IBinder token) { 1674 mService.mAmInternal.enforceCallingPermission(CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS, 1675 "unregisterRemoteAnimations"); 1676 final long origId = Binder.clearCallingIdentity(); 1677 try { 1678 synchronized (mGlobalLock) { 1679 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token); 1680 if (r != null) { 1681 r.unregisterRemoteAnimations(); 1682 } 1683 } 1684 } finally { 1685 Binder.restoreCallingIdentity(origId); 1686 } 1687 } 1688 1689 /** 1690 * Return {@code true} when the given Activity is a relative Task root. That is, the rest of 1691 * the Activities in the Task should be finished when it finishes. Otherwise, return {@code 1692 * false}. 1693 */ isRelativeTaskRootActivity(ActivityRecord r, ActivityRecord taskRoot)1694 private static boolean isRelativeTaskRootActivity(ActivityRecord r, ActivityRecord taskRoot) { 1695 // Not a relative root if the given Activity is not the root Activity of its TaskFragment. 1696 final TaskFragment taskFragment = r.getTaskFragment(); 1697 if (r != taskFragment.getActivity(ar -> !ar.finishing || ar == r, 1698 false /* traverseTopToBottom */)) { 1699 return false; 1700 } 1701 1702 // The given Activity is the relative Task root if its TaskFragment is a companion 1703 // TaskFragment to the taskRoot (i.e. the taskRoot TF will be finished together). 1704 return taskRoot.getTaskFragment().getCompanionTaskFragment() == taskFragment; 1705 } 1706 isTopActivityInTaskFragment(ActivityRecord activity)1707 private static boolean isTopActivityInTaskFragment(ActivityRecord activity) { 1708 return activity.getTaskFragment().topRunningActivity() == activity; 1709 } 1710 requestCallbackFinish(IRequestFinishCallback callback)1711 private void requestCallbackFinish(IRequestFinishCallback callback) { 1712 try { 1713 callback.requestFinish(); 1714 } catch (RemoteException e) { 1715 Slog.e(TAG, "Failed to invoke request finish callback", e); 1716 } 1717 } 1718 1719 @Override onBackPressed(IBinder token, IRequestFinishCallback callback)1720 public void onBackPressed(IBinder token, IRequestFinishCallback callback) { 1721 final long origId = Binder.clearCallingIdentity(); 1722 try { 1723 synchronized (mGlobalLock) { 1724 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(token); 1725 if (r == null) return; 1726 1727 final Task task = r.getTask(); 1728 final ActivityRecord root = task.getRootActivity(false /*ignoreRelinquishIdentity*/, 1729 true /*setToBottomIfNone*/); 1730 if (r == root && mService.mWindowOrganizerController.mTaskOrganizerController 1731 .handleInterceptBackPressedOnTaskRoot(r.getRootTask())) { 1732 // This task is handled by a task organizer that has requested the back 1733 // pressed callback. 1734 return; 1735 } 1736 if (shouldMoveTaskToBack(r, root)) { 1737 moveActivityTaskToBack(token, true /* nonRoot */); 1738 return; 1739 } 1740 } 1741 1742 // The default option for handling the back button is to finish the Activity. 1743 requestCallbackFinish(callback); 1744 } finally { 1745 Binder.restoreCallingIdentity(origId); 1746 } 1747 } 1748 shouldMoveTaskToBack(ActivityRecord r, ActivityRecord rootActivity)1749 static boolean shouldMoveTaskToBack(ActivityRecord r, ActivityRecord rootActivity) { 1750 if (r != rootActivity && !isRelativeTaskRootActivity(r, rootActivity)) { 1751 return false; 1752 } 1753 final boolean isBaseActivity = rootActivity.mActivityComponent.equals( 1754 r.getTask().realActivity); 1755 final Intent baseActivityIntent = isBaseActivity ? rootActivity.intent : null; 1756 1757 // If the activity was launched directly from the home screen, then we should 1758 // refrain from finishing the activity and instead move it to the back to keep it in 1759 // memory. The requirements for this are: 1760 // 1. The activity is the last running activity in the task. 1761 // 2. The current activity is the base activity for the task. 1762 // 3. The activity was launched by the home process, and is one of the main entry 1763 // points for the application. 1764 return baseActivityIntent != null 1765 && isTopActivityInTaskFragment(r) 1766 && rootActivity.isLaunchSourceType(ActivityRecord.LAUNCH_SOURCE_TYPE_HOME) 1767 && ActivityRecord.isMainIntent(baseActivityIntent); 1768 } 1769 1770 @Override enableTaskLocaleOverride(IBinder token)1771 public void enableTaskLocaleOverride(IBinder token) { 1772 if (UserHandle.getAppId(Binder.getCallingUid()) != SYSTEM_UID) { 1773 // Only allow system to align locale. 1774 return; 1775 } 1776 1777 synchronized (mGlobalLock) { 1778 final ActivityRecord r = ActivityRecord.forTokenLocked(token); 1779 if (r != null) { 1780 r.getTask().mAlignActivityLocaleWithTask = true; 1781 } 1782 } 1783 } 1784 1785 /** 1786 * Returns {@code true} if the activity was explicitly requested to be launched in its 1787 * current TaskFragment. 1788 * 1789 * @see ActivityRecord#mRequestedLaunchingTaskFragmentToken 1790 */ isRequestedToLaunchInTaskFragment(IBinder activityToken, IBinder taskFragmentToken)1791 public boolean isRequestedToLaunchInTaskFragment(IBinder activityToken, 1792 IBinder taskFragmentToken) { 1793 synchronized (mGlobalLock) { 1794 final ActivityRecord r = ActivityRecord.isInRootTaskLocked(activityToken); 1795 if (r == null) return false; 1796 1797 return r.mRequestedLaunchingTaskFragmentToken == taskFragmentToken; 1798 } 1799 } 1800 1801 @Override setActivityRecordInputSinkEnabled(IBinder activityToken, boolean enabled)1802 public void setActivityRecordInputSinkEnabled(IBinder activityToken, boolean enabled) { 1803 if (!allowDisableActivityRecordInputSink()) { 1804 return; 1805 } 1806 1807 mService.mAmInternal.enforceCallingPermission( 1808 Manifest.permission.INTERNAL_SYSTEM_WINDOW, "setActivityRecordInputSinkEnabled"); 1809 synchronized (mGlobalLock) { 1810 final ActivityRecord r = ActivityRecord.forTokenLocked(activityToken); 1811 if (r != null) { 1812 r.mActivityRecordInputSinkEnabled = enabled; 1813 } 1814 } 1815 } 1816 } 1817