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