1 /* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.wm; 18 19 import static android.app.ITaskStackListener.FORCED_RESIZEABLE_REASON_SPLIT_SCREEN; 20 import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT; 21 import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; 22 import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS; 23 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; 24 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; 25 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; 26 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; 27 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; 28 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; 29 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; 30 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; 31 import static android.app.WindowConfiguration.activityTypeToString; 32 import static android.app.WindowConfiguration.windowingModeToString; 33 import static android.content.pm.ActivityInfo.CONFIG_SCREEN_LAYOUT; 34 import static android.content.pm.ActivityInfo.FLAG_RESUME_WHILE_PAUSING; 35 import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS; 36 import static android.view.Display.DEFAULT_DISPLAY; 37 import static android.view.Display.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD; 38 import static android.view.Display.INVALID_DISPLAY; 39 import static android.view.WindowManager.TRANSIT_ACTIVITY_CLOSE; 40 import static android.view.WindowManager.TRANSIT_ACTIVITY_OPEN; 41 import static android.view.WindowManager.TRANSIT_CRASHING_ACTIVITY_CLOSE; 42 import static android.view.WindowManager.TRANSIT_NONE; 43 import static android.view.WindowManager.TRANSIT_SHOW_SINGLE_TASK_DISPLAY; 44 import static android.view.WindowManager.TRANSIT_TASK_CLOSE; 45 import static android.view.WindowManager.TRANSIT_TASK_OPEN; 46 import static android.view.WindowManager.TRANSIT_TASK_OPEN_BEHIND; 47 import static android.view.WindowManager.TRANSIT_TASK_TO_BACK; 48 import static android.view.WindowManager.TRANSIT_TASK_TO_FRONT; 49 50 import static com.android.server.am.ActivityStackProto.BOUNDS; 51 import static com.android.server.am.ActivityStackProto.CONFIGURATION_CONTAINER; 52 import static com.android.server.am.ActivityStackProto.DISPLAY_ID; 53 import static com.android.server.am.ActivityStackProto.FULLSCREEN; 54 import static com.android.server.am.ActivityStackProto.ID; 55 import static com.android.server.am.ActivityStackProto.RESUMED_ACTIVITY; 56 import static com.android.server.am.ActivityStackProto.TASKS; 57 import static com.android.server.wm.ActivityDisplay.POSITION_BOTTOM; 58 import static com.android.server.wm.ActivityDisplay.POSITION_TOP; 59 import static com.android.server.wm.ActivityStack.ActivityState.DESTROYED; 60 import static com.android.server.wm.ActivityStack.ActivityState.DESTROYING; 61 import static com.android.server.wm.ActivityStack.ActivityState.FINISHING; 62 import static com.android.server.wm.ActivityStack.ActivityState.PAUSED; 63 import static com.android.server.wm.ActivityStack.ActivityState.PAUSING; 64 import static com.android.server.wm.ActivityStack.ActivityState.RESUMED; 65 import static com.android.server.wm.ActivityStack.ActivityState.STOPPED; 66 import static com.android.server.wm.ActivityStack.ActivityState.STOPPING; 67 import static com.android.server.wm.ActivityStackSupervisor.PAUSE_IMMEDIATELY; 68 import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS; 69 import static com.android.server.wm.ActivityStackSupervisor.REMOVE_FROM_RECENTS; 70 import static com.android.server.wm.ActivityStackSupervisor.dumpHistoryList; 71 import static com.android.server.wm.ActivityStackSupervisor.printThisActivity; 72 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ADD_REMOVE; 73 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ALL; 74 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_APP; 75 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_CLEANUP; 76 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_CONTAINERS; 77 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_PAUSE; 78 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RELEASE; 79 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RESULTS; 80 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SAVED_STATE; 81 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STACK; 82 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STATES; 83 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH; 84 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TASKS; 85 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TRANSITION; 86 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_USER_LEAVING; 87 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_VISIBILITY; 88 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_ADD_REMOVE; 89 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_APP; 90 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_CLEANUP; 91 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_CONTAINERS; 92 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_PAUSE; 93 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RELEASE; 94 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RESULTS; 95 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_SAVED_STATE; 96 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_STACK; 97 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_STATES; 98 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_SWITCH; 99 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_TASKS; 100 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_TRANSITION; 101 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_USER_LEAVING; 102 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_VISIBILITY; 103 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM; 104 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME; 105 import static com.android.server.wm.ActivityTaskManagerService.H.FIRST_ACTIVITY_STACK_MSG; 106 import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_FREE_RESIZE; 107 import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_WINDOWING_MODE_RESIZE; 108 import static com.android.server.wm.RootActivityContainer.FindTaskResult; 109 110 import static java.lang.Integer.MAX_VALUE; 111 112 import android.annotation.IntDef; 113 import android.app.Activity; 114 import android.app.ActivityManager; 115 import android.app.ActivityManagerInternal; 116 import android.app.ActivityOptions; 117 import android.app.AppGlobals; 118 import android.app.IActivityController; 119 import android.app.RemoteAction; 120 import android.app.ResultInfo; 121 import android.app.WindowConfiguration.ActivityType; 122 import android.app.WindowConfiguration.WindowingMode; 123 import android.app.servertransaction.ActivityResultItem; 124 import android.app.servertransaction.ClientTransaction; 125 import android.app.servertransaction.DestroyActivityItem; 126 import android.app.servertransaction.NewIntentItem; 127 import android.app.servertransaction.PauseActivityItem; 128 import android.app.servertransaction.ResumeActivityItem; 129 import android.app.servertransaction.StopActivityItem; 130 import android.app.servertransaction.WindowVisibilityItem; 131 import android.content.ComponentName; 132 import android.content.Intent; 133 import android.content.pm.ActivityInfo; 134 import android.content.pm.ApplicationInfo; 135 import android.content.res.Configuration; 136 import android.graphics.Rect; 137 import android.net.Uri; 138 import android.os.Binder; 139 import android.os.Debug; 140 import android.os.Handler; 141 import android.os.IBinder; 142 import android.os.Looper; 143 import android.os.Message; 144 import android.os.RemoteException; 145 import android.os.SystemClock; 146 import android.os.UserHandle; 147 import android.service.voice.IVoiceInteractionSession; 148 import android.util.ArraySet; 149 import android.util.EventLog; 150 import android.util.IntArray; 151 import android.util.Log; 152 import android.util.Slog; 153 import android.util.proto.ProtoOutputStream; 154 import android.view.Display; 155 156 import com.android.internal.annotations.GuardedBy; 157 import com.android.internal.annotations.VisibleForTesting; 158 import com.android.internal.app.IVoiceInteractor; 159 import com.android.internal.util.function.pooled.PooledLambda; 160 import com.android.server.Watchdog; 161 import com.android.server.am.ActivityManagerService; 162 import com.android.server.am.ActivityManagerService.ItemMatcher; 163 import com.android.server.am.AppTimeTracker; 164 import com.android.server.am.EventLogTags; 165 import com.android.server.am.PendingIntentRecord; 166 167 import com.google.android.collect.Sets; 168 169 import java.io.FileDescriptor; 170 import java.io.PrintWriter; 171 import java.lang.ref.WeakReference; 172 import java.util.ArrayList; 173 import java.util.List; 174 import java.util.Objects; 175 import java.util.Set; 176 177 /** 178 * State and management of a single stack of activities. 179 */ 180 class ActivityStack extends ConfigurationContainer { 181 private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStack" : TAG_ATM; 182 private static final String TAG_ADD_REMOVE = TAG + POSTFIX_ADD_REMOVE; 183 private static final String TAG_APP = TAG + POSTFIX_APP; 184 private static final String TAG_CLEANUP = TAG + POSTFIX_CLEANUP; 185 private static final String TAG_CONTAINERS = TAG + POSTFIX_CONTAINERS; 186 private static final String TAG_PAUSE = TAG + POSTFIX_PAUSE; 187 private static final String TAG_RELEASE = TAG + POSTFIX_RELEASE; 188 private static final String TAG_RESULTS = TAG + POSTFIX_RESULTS; 189 private static final String TAG_SAVED_STATE = TAG + POSTFIX_SAVED_STATE; 190 private static final String TAG_STACK = TAG + POSTFIX_STACK; 191 private static final String TAG_STATES = TAG + POSTFIX_STATES; 192 private static final String TAG_SWITCH = TAG + POSTFIX_SWITCH; 193 private static final String TAG_TASKS = TAG + POSTFIX_TASKS; 194 private static final String TAG_TRANSITION = TAG + POSTFIX_TRANSITION; 195 private static final String TAG_USER_LEAVING = TAG + POSTFIX_USER_LEAVING; 196 private static final String TAG_VISIBILITY = TAG + POSTFIX_VISIBILITY; 197 198 // Ticks during which we check progress while waiting for an app to launch. 199 static final int LAUNCH_TICK = 500; 200 201 // How long we wait until giving up on the last activity to pause. This 202 // is short because it directly impacts the responsiveness of starting the 203 // next activity. 204 private static final int PAUSE_TIMEOUT = 500; 205 206 // How long we wait for the activity to tell us it has stopped before 207 // giving up. This is a good amount of time because we really need this 208 // from the application in order to get its saved state. Once the stop 209 // is complete we may start destroying client resources triggering 210 // crashes if the UI thread was hung. We put this timeout one second behind 211 // the ANR timeout so these situations will generate ANR instead of 212 // Surface lost or other errors. 213 private static final int STOP_TIMEOUT = 11 * 1000; 214 215 // How long we wait until giving up on an activity telling us it has 216 // finished destroying itself. 217 private static final int DESTROY_TIMEOUT = 10 * 1000; 218 219 // Set to false to disable the preview that is shown while a new activity 220 // is being started. 221 private static final boolean SHOW_APP_STARTING_PREVIEW = true; 222 223 // How long to wait for all background Activities to redraw following a call to 224 // convertToTranslucent(). 225 private static final long TRANSLUCENT_CONVERSION_TIMEOUT = 2000; 226 227 // How many activities have to be scheduled to stop to force a stop pass. 228 private static final int MAX_STOPPING_TO_FORCE = 3; 229 230 @IntDef(prefix = {"STACK_VISIBILITY"}, value = { 231 STACK_VISIBILITY_VISIBLE, 232 STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT, 233 STACK_VISIBILITY_INVISIBLE, 234 }) 235 @interface StackVisibility {} 236 237 /** Stack is visible. No other stacks on top that fully or partially occlude it. */ 238 static final int STACK_VISIBILITY_VISIBLE = 0; 239 240 /** Stack is partially occluded by other translucent stack(s) on top of it. */ 241 static final int STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT = 1; 242 243 /** Stack is completely invisible. */ 244 static final int STACK_VISIBILITY_INVISIBLE = 2; 245 246 @Override getChildCount()247 protected int getChildCount() { 248 return mTaskHistory.size(); 249 } 250 251 @Override getChildAt(int index)252 protected TaskRecord getChildAt(int index) { 253 return mTaskHistory.get(index); 254 } 255 256 @Override getParent()257 protected ActivityDisplay getParent() { 258 return getDisplay(); 259 } 260 setParent(ActivityDisplay parent)261 void setParent(ActivityDisplay parent) { 262 ActivityDisplay current = getParent(); 263 if (current != parent) { 264 mDisplayId = parent.mDisplayId; 265 onParentChanged(); 266 } 267 } 268 269 @Override onParentChanged()270 protected void onParentChanged() { 271 ActivityDisplay display = getParent(); 272 if (display != null) { 273 // Rotations are relative to the display. This means if there are 2 displays rotated 274 // differently (eg. 2 monitors with one landscape and one portrait), moving a stack 275 // from one to the other could look like a rotation change. To prevent this 276 // apparent rotation change (and corresponding bounds rotation), pretend like our 277 // current rotation is already the same as the new display. 278 // Note, if ActivityStack or related logic ever gets nested, this logic will need 279 // to move to onConfigurationChanged. 280 getConfiguration().windowConfiguration.setRotation( 281 display.getWindowConfiguration().getRotation()); 282 } 283 super.onParentChanged(); 284 if (display != null && inSplitScreenPrimaryWindowingMode()) { 285 // If we created a docked stack we want to resize it so it resizes all other stacks 286 // in the system. 287 getStackDockedModeBounds(null /* dockedBounds */, null /* currentTempTaskBounds */, 288 mTmpRect /* outStackBounds */, mTmpRect2 /* outTempTaskBounds */); 289 mStackSupervisor.resizeDockedStackLocked(getRequestedOverrideBounds(), mTmpRect, 290 mTmpRect2, null, null, PRESERVE_WINDOWS); 291 } 292 mRootActivityContainer.updateUIDsPresentOnDisplay(); 293 } 294 295 enum ActivityState { 296 INITIALIZING, 297 RESUMED, 298 PAUSING, 299 PAUSED, 300 STOPPING, 301 STOPPED, 302 FINISHING, 303 DESTROYING, 304 DESTROYED, 305 RESTARTING_PROCESS 306 } 307 308 @VisibleForTesting 309 /* The various modes for the method {@link #removeTask}. */ 310 // Task is being completely removed from all stacks in the system. 311 protected static final int REMOVE_TASK_MODE_DESTROYING = 0; 312 // Task is being removed from this stack so we can add it to another stack. In the case we are 313 // moving we don't want to perform some operations on the task like removing it from window 314 // manager or recents. 315 static final int REMOVE_TASK_MODE_MOVING = 1; 316 // Similar to {@link #REMOVE_TASK_MODE_MOVING} and the task will be added to the top of its new 317 // stack and the new stack will be on top of all stacks. 318 static final int REMOVE_TASK_MODE_MOVING_TO_TOP = 2; 319 320 final ActivityTaskManagerService mService; 321 final WindowManagerService mWindowManager; 322 323 /** 324 * The back history of all previous (and possibly still 325 * running) activities. It contains #TaskRecord objects. 326 */ 327 private final ArrayList<TaskRecord> mTaskHistory = new ArrayList<>(); 328 329 /** 330 * List of running activities, sorted by recent usage. 331 * The first entry in the list is the least recently used. 332 * It contains HistoryRecord objects. 333 */ 334 private final ArrayList<ActivityRecord> mLRUActivities = new ArrayList<>(); 335 336 /** 337 * When we are in the process of pausing an activity, before starting the 338 * next one, this variable holds the activity that is currently being paused. 339 */ 340 ActivityRecord mPausingActivity = null; 341 342 /** 343 * This is the last activity that we put into the paused state. This is 344 * used to determine if we need to do an activity transition while sleeping, 345 * when we normally hold the top activity paused. 346 */ 347 ActivityRecord mLastPausedActivity = null; 348 349 /** 350 * Activities that specify No History must be removed once the user navigates away from them. 351 * If the device goes to sleep with such an activity in the paused state then we save it here 352 * and finish it later if another activity replaces it on wakeup. 353 */ 354 ActivityRecord mLastNoHistoryActivity = null; 355 356 /** 357 * Current activity that is resumed, or null if there is none. 358 */ 359 ActivityRecord mResumedActivity = null; 360 361 // The topmost Activity passed to convertToTranslucent(). When non-null it means we are 362 // waiting for all Activities in mUndrawnActivitiesBelowTopTranslucent to be removed as they 363 // are drawn. When the last member of mUndrawnActivitiesBelowTopTranslucent is removed the 364 // Activity in mTranslucentActivityWaiting is notified via 365 // Activity.onTranslucentConversionComplete(false). If a timeout occurs prior to the last 366 // background activity being drawn then the same call will be made with a true value. 367 ActivityRecord mTranslucentActivityWaiting = null; 368 ArrayList<ActivityRecord> mUndrawnActivitiesBelowTopTranslucent = new ArrayList<>(); 369 370 /** 371 * Set when we know we are going to be calling updateConfiguration() 372 * soon, so want to skip intermediate config checks. 373 */ 374 boolean mConfigWillChange; 375 376 /** 377 * When set, will force the stack to report as invisible. 378 */ 379 boolean mForceHidden = false; 380 381 /** 382 * Used to keep resumeTopActivityUncheckedLocked() from being entered recursively 383 */ 384 boolean mInResumeTopActivity = false; 385 386 private boolean mUpdateBoundsDeferred; 387 private boolean mUpdateBoundsDeferredCalled; 388 private boolean mUpdateDisplayedBoundsDeferredCalled; 389 private final Rect mDeferredBounds = new Rect(); 390 private final Rect mDeferredDisplayedBounds = new Rect(); 391 392 int mCurrentUser; 393 394 final int mStackId; 395 /** The attached Display's unique identifier, or -1 if detached */ 396 int mDisplayId; 397 398 /** Stores the override windowing-mode from before a transient mode change (eg. split) */ 399 private int mRestoreOverrideWindowingMode = WINDOWING_MODE_UNDEFINED; 400 401 private final Rect mTmpRect = new Rect(); 402 private final Rect mTmpRect2 = new Rect(); 403 private final ActivityOptions mTmpOptions = ActivityOptions.makeBasic(); 404 405 /** List for processing through a set of activities */ 406 private final ArrayList<ActivityRecord> mTmpActivities = new ArrayList<>(); 407 408 /** Run all ActivityStacks through this */ 409 protected final ActivityStackSupervisor mStackSupervisor; 410 protected final RootActivityContainer mRootActivityContainer; 411 412 private boolean mTopActivityOccludesKeyguard; 413 private ActivityRecord mTopDismissingKeyguardActivity; 414 415 static final int PAUSE_TIMEOUT_MSG = FIRST_ACTIVITY_STACK_MSG + 1; 416 static final int DESTROY_TIMEOUT_MSG = FIRST_ACTIVITY_STACK_MSG + 2; 417 static final int LAUNCH_TICK_MSG = FIRST_ACTIVITY_STACK_MSG + 3; 418 static final int STOP_TIMEOUT_MSG = FIRST_ACTIVITY_STACK_MSG + 4; 419 static final int DESTROY_ACTIVITIES_MSG = FIRST_ACTIVITY_STACK_MSG + 5; 420 static final int TRANSLUCENT_TIMEOUT_MSG = FIRST_ACTIVITY_STACK_MSG + 6; 421 422 // TODO: remove after unification. 423 TaskStack mTaskStack; 424 425 private static class ScheduleDestroyArgs { 426 final WindowProcessController mOwner; 427 final String mReason; ScheduleDestroyArgs(WindowProcessController owner, String reason)428 ScheduleDestroyArgs(WindowProcessController owner, String reason) { 429 mOwner = owner; 430 mReason = reason; 431 } 432 } 433 434 final Handler mHandler; 435 436 private class ActivityStackHandler extends Handler { 437 ActivityStackHandler(Looper looper)438 ActivityStackHandler(Looper looper) { 439 super(looper); 440 } 441 442 @Override handleMessage(Message msg)443 public void handleMessage(Message msg) { 444 switch (msg.what) { 445 case PAUSE_TIMEOUT_MSG: { 446 ActivityRecord r = (ActivityRecord)msg.obj; 447 // We don't at this point know if the activity is fullscreen, 448 // so we need to be conservative and assume it isn't. 449 Slog.w(TAG, "Activity pause timeout for " + r); 450 synchronized (mService.mGlobalLock) { 451 if (r.hasProcess()) { 452 mService.logAppTooSlow(r.app, r.pauseTime, "pausing " + r); 453 } 454 activityPausedLocked(r.appToken, true); 455 } 456 } break; 457 case LAUNCH_TICK_MSG: { 458 ActivityRecord r = (ActivityRecord)msg.obj; 459 synchronized (mService.mGlobalLock) { 460 if (r.continueLaunchTickingLocked()) { 461 mService.logAppTooSlow(r.app, r.launchTickTime, "launching " + r); 462 } 463 } 464 } break; 465 case DESTROY_TIMEOUT_MSG: { 466 ActivityRecord r = (ActivityRecord)msg.obj; 467 // We don't at this point know if the activity is fullscreen, 468 // so we need to be conservative and assume it isn't. 469 Slog.w(TAG, "Activity destroy timeout for " + r); 470 synchronized (mService.mGlobalLock) { 471 activityDestroyedLocked(r != null ? r.appToken : null, "destroyTimeout"); 472 } 473 } break; 474 case STOP_TIMEOUT_MSG: { 475 ActivityRecord r = (ActivityRecord)msg.obj; 476 // We don't at this point know if the activity is fullscreen, 477 // so we need to be conservative and assume it isn't. 478 Slog.w(TAG, "Activity stop timeout for " + r); 479 synchronized (mService.mGlobalLock) { 480 if (r.isInHistory()) { 481 r.activityStoppedLocked(null /* icicle */, 482 null /* persistentState */, null /* description */); 483 } 484 } 485 } break; 486 case DESTROY_ACTIVITIES_MSG: { 487 ScheduleDestroyArgs args = (ScheduleDestroyArgs)msg.obj; 488 synchronized (mService.mGlobalLock) { 489 destroyActivitiesLocked(args.mOwner, args.mReason); 490 } 491 } break; 492 case TRANSLUCENT_TIMEOUT_MSG: { 493 synchronized (mService.mGlobalLock) { 494 notifyActivityDrawnLocked(null); 495 } 496 } break; 497 } 498 } 499 } 500 numActivities()501 int numActivities() { 502 int count = 0; 503 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 504 count += mTaskHistory.get(taskNdx).mActivities.size(); 505 } 506 return count; 507 } 508 ActivityStack(ActivityDisplay display, int stackId, ActivityStackSupervisor supervisor, int windowingMode, int activityType, boolean onTop)509 ActivityStack(ActivityDisplay display, int stackId, ActivityStackSupervisor supervisor, 510 int windowingMode, int activityType, boolean onTop) { 511 mStackSupervisor = supervisor; 512 mService = supervisor.mService; 513 mRootActivityContainer = mService.mRootActivityContainer; 514 mHandler = new ActivityStackHandler(supervisor.mLooper); 515 mWindowManager = mService.mWindowManager; 516 mStackId = stackId; 517 mCurrentUser = mService.mAmInternal.getCurrentUserId(); 518 // Set display id before setting activity and window type to make sure it won't affect 519 // stacks on a wrong display. 520 mDisplayId = display.mDisplayId; 521 setActivityType(activityType); 522 createTaskStack(display.mDisplayId, onTop, mTmpRect2); 523 setWindowingMode(windowingMode, false /* animate */, false /* showRecents */, 524 false /* enteringSplitScreenMode */, false /* deferEnsuringVisibility */, 525 true /* creating */); 526 display.addChild(this, onTop ? POSITION_TOP : POSITION_BOTTOM); 527 } 528 createTaskStack(int displayId, boolean onTop, Rect outBounds)529 void createTaskStack(int displayId, boolean onTop, Rect outBounds) { 530 final DisplayContent dc = mWindowManager.mRoot.getDisplayContent(displayId); 531 if (dc == null) { 532 throw new IllegalArgumentException("Trying to add stackId=" + mStackId 533 + " to unknown displayId=" + displayId); 534 } 535 mTaskStack = new TaskStack(mWindowManager, mStackId, this); 536 dc.setStackOnDisplay(mStackId, onTop, mTaskStack); 537 if (mTaskStack.matchParentBounds()) { 538 outBounds.setEmpty(); 539 } else { 540 mTaskStack.getRawBounds(outBounds); 541 } 542 } 543 getTaskStack()544 TaskStack getTaskStack() { 545 return mTaskStack; 546 } 547 548 /** 549 * This should be called when an activity in a child task changes state. This should only 550 * be called from 551 * {@link TaskRecord#onActivityStateChanged(ActivityRecord, ActivityState, String)}. 552 * @param record The {@link ActivityRecord} whose state has changed. 553 * @param state The new state. 554 * @param reason The reason for the change. 555 */ onActivityStateChanged(ActivityRecord record, ActivityState state, String reason)556 void onActivityStateChanged(ActivityRecord record, ActivityState state, String reason) { 557 if (record == mResumedActivity && state != RESUMED) { 558 setResumedActivity(null, reason + " - onActivityStateChanged"); 559 } 560 561 if (state == RESUMED) { 562 if (DEBUG_STACK) Slog.v(TAG_STACK, "set resumed activity to:" + record + " reason:" 563 + reason); 564 setResumedActivity(record, reason + " - onActivityStateChanged"); 565 if (record == mRootActivityContainer.getTopResumedActivity()) { 566 // TODO(b/111361570): Support multiple focused apps in WM 567 mService.setResumedActivityUncheckLocked(record, reason); 568 } 569 mStackSupervisor.mRecentTasks.add(record.getTaskRecord()); 570 } 571 } 572 573 @Override onConfigurationChanged(Configuration newParentConfig)574 public void onConfigurationChanged(Configuration newParentConfig) { 575 final int prevWindowingMode = getWindowingMode(); 576 final boolean prevIsAlwaysOnTop = isAlwaysOnTop(); 577 final int prevRotation = getWindowConfiguration().getRotation(); 578 final int prevDensity = getConfiguration().densityDpi; 579 final int prevScreenW = getConfiguration().screenWidthDp; 580 final int prevScreenH = getConfiguration().screenHeightDp; 581 final Rect newBounds = mTmpRect; 582 // Initialize the new bounds by previous bounds as the input and output for calculating 583 // override bounds in pinned (pip) or split-screen mode. 584 getBounds(newBounds); 585 586 super.onConfigurationChanged(newParentConfig); 587 final ActivityDisplay display = getDisplay(); 588 if (display == null || getTaskStack() == null) { 589 return; 590 } 591 592 final boolean windowingModeChanged = prevWindowingMode != getWindowingMode(); 593 final int overrideWindowingMode = getRequestedOverrideWindowingMode(); 594 // Update bounds if applicable 595 boolean hasNewOverrideBounds = false; 596 // Use override windowing mode to prevent extra bounds changes if inheriting the mode. 597 if (overrideWindowingMode == WINDOWING_MODE_PINNED) { 598 // Pinned calculation already includes rotation 599 hasNewOverrideBounds = getTaskStack().calculatePinnedBoundsForConfigChange(newBounds); 600 } else if (!matchParentBounds()) { 601 // If the parent (display) has rotated, rotate our bounds to best-fit where their 602 // bounds were on the pre-rotated display. 603 final int newRotation = getWindowConfiguration().getRotation(); 604 final boolean rotationChanged = prevRotation != newRotation; 605 if (rotationChanged) { 606 display.mDisplayContent.rotateBounds( 607 newParentConfig.windowConfiguration.getBounds(), prevRotation, newRotation, 608 newBounds); 609 hasNewOverrideBounds = true; 610 } 611 612 // Use override windowing mode to prevent extra bounds changes if inheriting the mode. 613 if (overrideWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY 614 || overrideWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) { 615 // If entering split screen or if something about the available split area changes, 616 // recalculate the split windows to match the new configuration. 617 if (rotationChanged || windowingModeChanged 618 || prevDensity != getConfiguration().densityDpi 619 || prevScreenW != getConfiguration().screenWidthDp 620 || prevScreenH != getConfiguration().screenHeightDp) { 621 getTaskStack().calculateDockedBoundsForConfigChange(newParentConfig, newBounds); 622 hasNewOverrideBounds = true; 623 } 624 } 625 } 626 627 if (windowingModeChanged) { 628 // Use override windowing mode to prevent extra bounds changes if inheriting the mode. 629 if (overrideWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) { 630 getStackDockedModeBounds(null /* dockedBounds */, null /* currentTempTaskBounds */, 631 newBounds /* outStackBounds */, mTmpRect2 /* outTempTaskBounds */); 632 // immediately resize so docked bounds are available in onSplitScreenModeActivated 633 setTaskDisplayedBounds(null); 634 setTaskBounds(newBounds); 635 setBounds(newBounds); 636 newBounds.set(newBounds); 637 } else if (overrideWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) { 638 Rect dockedBounds = display.getSplitScreenPrimaryStack().getBounds(); 639 final boolean isMinimizedDock = 640 display.mDisplayContent.getDockedDividerController().isMinimizedDock(); 641 if (isMinimizedDock) { 642 TaskRecord topTask = display.getSplitScreenPrimaryStack().topTask(); 643 if (topTask != null) { 644 dockedBounds = topTask.getBounds(); 645 } 646 } 647 getStackDockedModeBounds(dockedBounds, null /* currentTempTaskBounds */, 648 newBounds /* outStackBounds */, mTmpRect2 /* outTempTaskBounds */); 649 hasNewOverrideBounds = true; 650 } 651 display.onStackWindowingModeChanged(this); 652 } 653 if (hasNewOverrideBounds) { 654 // Note the resizeStack may enter onConfigurationChanged recursively, so we make a copy 655 // of the temporary bounds (newBounds is mTmpRect) to avoid it being modified. 656 mRootActivityContainer.resizeStack(this, new Rect(newBounds), null /* tempTaskBounds */, 657 null /* tempTaskInsetBounds */, PRESERVE_WINDOWS, 658 true /* allowResizeInDockedMode */, true /* deferResume */); 659 } 660 if (prevIsAlwaysOnTop != isAlwaysOnTop()) { 661 // Since always on top is only on when the stack is freeform or pinned, the state 662 // can be toggled when the windowing mode changes. We must make sure the stack is 663 // placed properly when always on top state changes. 664 display.positionChildAtTop(this, false /* includingParents */); 665 } 666 } 667 668 @Override setWindowingMode(int windowingMode)669 public void setWindowingMode(int windowingMode) { 670 setWindowingMode(windowingMode, false /* animate */, false /* showRecents */, 671 false /* enteringSplitScreenMode */, false /* deferEnsuringVisibility */, 672 false /* creating */); 673 } 674 675 /** 676 * A transient windowing mode is one which activities enter into temporarily. Examples of this 677 * are Split window modes and pip. Non-transient modes are modes that displays can adopt. 678 * 679 * @param windowingMode the windowingMode to test for transient-ness. 680 * @return {@code true} if the windowing mode is transient, {@code false} otherwise. 681 */ isTransientWindowingMode(int windowingMode)682 private static boolean isTransientWindowingMode(int windowingMode) { 683 // TODO(b/114842032): add PIP if/when it uses mode transitions instead of task reparenting 684 return windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY 685 || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; 686 } 687 688 /** 689 * Specialization of {@link #setWindowingMode(int)} for this subclass. 690 * 691 * @param preferredWindowingMode the preferred windowing mode. This may not be honored depending 692 * on the state of things. For example, WINDOWING_MODE_UNDEFINED will resolve to the 693 * previous non-transient mode if this stack is currently in a transient mode. 694 * @param animate Can be used to prevent animation. 695 * @param showRecents Controls whether recents is shown on the other side of a split while 696 * entering split mode. 697 * @param enteringSplitScreenMode {@code true} if entering split mode. 698 * @param deferEnsuringVisibility Whether visibility updates are deferred. This is set when 699 * many operations (which can effect visibility) are being performed in bulk. 700 * @param creating {@code true} if this is being run during ActivityStack construction. 701 */ setWindowingMode(int preferredWindowingMode, boolean animate, boolean showRecents, boolean enteringSplitScreenMode, boolean deferEnsuringVisibility, boolean creating)702 void setWindowingMode(int preferredWindowingMode, boolean animate, boolean showRecents, 703 boolean enteringSplitScreenMode, boolean deferEnsuringVisibility, boolean creating) { 704 mWindowManager.inSurfaceTransaction(() -> setWindowingModeInSurfaceTransaction( 705 preferredWindowingMode, animate, showRecents, enteringSplitScreenMode, 706 deferEnsuringVisibility, creating)); 707 } 708 setWindowingModeInSurfaceTransaction(int preferredWindowingMode, boolean animate, boolean showRecents, boolean enteringSplitScreenMode, boolean deferEnsuringVisibility, boolean creating)709 private void setWindowingModeInSurfaceTransaction(int preferredWindowingMode, boolean animate, 710 boolean showRecents, boolean enteringSplitScreenMode, boolean deferEnsuringVisibility, 711 boolean creating) { 712 final int currentMode = getWindowingMode(); 713 final int currentOverrideMode = getRequestedOverrideWindowingMode(); 714 final ActivityDisplay display = getDisplay(); 715 final TaskRecord topTask = topTask(); 716 final ActivityStack splitScreenStack = display.getSplitScreenPrimaryStack(); 717 int windowingMode = preferredWindowingMode; 718 if (preferredWindowingMode == WINDOWING_MODE_UNDEFINED 719 && isTransientWindowingMode(currentMode)) { 720 // Leaving a transient mode. Interpret UNDEFINED as "restore" 721 windowingMode = mRestoreOverrideWindowingMode; 722 } 723 mTmpOptions.setLaunchWindowingMode(windowingMode); 724 725 // Need to make sure windowing mode is supported. If we in the process of creating the stack 726 // no need to resolve the windowing mode again as it is already resolved to the right mode. 727 if (!creating) { 728 windowingMode = display.validateWindowingMode(windowingMode, 729 null /* ActivityRecord */, topTask, getActivityType()); 730 } 731 if (splitScreenStack == this 732 && windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) { 733 // Resolution to split-screen secondary for the primary split-screen stack means 734 // we want to leave split-screen mode. 735 windowingMode = mRestoreOverrideWindowingMode; 736 } 737 738 final boolean alreadyInSplitScreenMode = display.hasSplitScreenPrimaryStack(); 739 740 // Don't send non-resizeable notifications if the windowing mode changed was a side effect 741 // of us entering split-screen mode. 742 final boolean sendNonResizeableNotification = !enteringSplitScreenMode; 743 // Take any required action due to us not supporting the preferred windowing mode. 744 if (alreadyInSplitScreenMode && windowingMode == WINDOWING_MODE_FULLSCREEN 745 && sendNonResizeableNotification && isActivityTypeStandardOrUndefined()) { 746 final boolean preferredSplitScreen = 747 preferredWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY 748 || preferredWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; 749 if (preferredSplitScreen || creating) { 750 // Looks like we can't launch in split screen mode or the stack we are launching 751 // doesn't support split-screen mode, go ahead an dismiss split-screen and display a 752 // warning toast about it. 753 mService.getTaskChangeNotificationController().notifyActivityDismissingDockedStack(); 754 final ActivityStack primarySplitStack = display.getSplitScreenPrimaryStack(); 755 primarySplitStack.setWindowingModeInSurfaceTransaction(WINDOWING_MODE_UNDEFINED, 756 false /* animate */, false /* showRecents */, 757 false /* enteringSplitScreenMode */, true /* deferEnsuringVisibility */, 758 primarySplitStack == this ? creating : false); 759 } 760 } 761 762 if (currentMode == windowingMode) { 763 // You are already in the window mode, so we can skip most of the work below. However, 764 // it's possible that we have inherited the current windowing mode from a parent. So, 765 // fulfill this method's contract by setting the override mode directly. 766 getRequestedOverrideConfiguration().windowConfiguration.setWindowingMode(windowingMode); 767 return; 768 } 769 770 final WindowManagerService wm = mService.mWindowManager; 771 final ActivityRecord topActivity = getTopActivity(); 772 773 // For now, assume that the Stack's windowing mode is what will actually be used 774 // by it's activities. In the future, there may be situations where this doesn't 775 // happen; so at that point, this message will need to handle that. 776 int likelyResolvedMode = windowingMode; 777 if (windowingMode == WINDOWING_MODE_UNDEFINED) { 778 final ConfigurationContainer parent = getParent(); 779 likelyResolvedMode = parent != null ? parent.getWindowingMode() 780 : WINDOWING_MODE_FULLSCREEN; 781 } 782 if (sendNonResizeableNotification && likelyResolvedMode != WINDOWING_MODE_FULLSCREEN 783 && topActivity != null && topActivity.isNonResizableOrForcedResizable() 784 && !topActivity.noDisplay) { 785 // Inform the user that they are starting an app that may not work correctly in 786 // multi-window mode. 787 final String packageName = topActivity.appInfo.packageName; 788 mService.getTaskChangeNotificationController().notifyActivityForcedResizable( 789 topTask.taskId, FORCED_RESIZEABLE_REASON_SPLIT_SCREEN, packageName); 790 } 791 792 wm.deferSurfaceLayout(); 793 try { 794 if (!animate && topActivity != null) { 795 mStackSupervisor.mNoAnimActivities.add(topActivity); 796 } 797 super.setWindowingMode(windowingMode); 798 // setWindowingMode triggers an onConfigurationChanged cascade which can result in a 799 // different resolved windowing mode (usually when preferredWindowingMode is UNDEFINED). 800 windowingMode = getWindowingMode(); 801 802 if (creating) { 803 // Nothing else to do if we don't have a window container yet. E.g. call from ctor. 804 return; 805 } 806 807 if (windowingMode == WINDOWING_MODE_PINNED || currentMode == WINDOWING_MODE_PINNED) { 808 // TODO: Need to remove use of PinnedActivityStack for this to be supported. 809 // NOTE: Need to ASS.scheduleUpdatePictureInPictureModeIfNeeded() in 810 // setWindowModeUnchecked() when this support is added. See TaskRecord.reparent() 811 throw new IllegalArgumentException( 812 "Changing pinned windowing mode not currently supported"); 813 } 814 815 if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY && splitScreenStack != null) { 816 // We already have a split-screen stack in this display, so just move the tasks over. 817 // TODO: Figure-out how to do all the stuff in 818 // AMS.setTaskWindowingModeSplitScreenPrimary 819 throw new IllegalArgumentException("Setting primary split-screen windowing mode" 820 + " while there is already one isn't currently supported"); 821 //return; 822 } 823 if (isTransientWindowingMode(windowingMode) && !isTransientWindowingMode(currentMode)) { 824 mRestoreOverrideWindowingMode = currentOverrideMode; 825 } 826 827 mTmpRect2.setEmpty(); 828 if (windowingMode != WINDOWING_MODE_FULLSCREEN) { 829 if (mTaskStack.matchParentBounds()) { 830 mTmpRect2.setEmpty(); 831 } else { 832 mTaskStack.getRawBounds(mTmpRect2); 833 } 834 } 835 836 if (!Objects.equals(getRequestedOverrideBounds(), mTmpRect2)) { 837 resize(mTmpRect2, null /* tempTaskBounds */, null /* tempTaskInsetBounds */); 838 } 839 } finally { 840 if (showRecents && !alreadyInSplitScreenMode && mDisplayId == DEFAULT_DISPLAY 841 && windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) { 842 // Make sure recents stack exist when creating a dock stack as it normally needs to 843 // be on the other side of the docked stack and we make visibility decisions based 844 // on that. 845 // TODO: This is only here to help out with the case where recents stack doesn't 846 // exist yet. For that case the initial size of the split-screen stack will be the 847 // the one where the home stack is visible since recents isn't visible yet, but the 848 // divider will be off. I think we should just make the initial bounds that of home 849 // so that the divider matches and remove this logic. 850 // TODO: This is currently only called when entering split-screen while in another 851 // task, and from the tests 852 // TODO (b/78247419): Check if launcher and overview are same then move home stack 853 // instead of recents stack. Then fix the rotation animation from fullscreen to 854 // minimized mode 855 final ActivityStack recentStack = display.getOrCreateStack( 856 WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_RECENTS, 857 true /* onTop */); 858 recentStack.moveToFront("setWindowingMode"); 859 // If task moved to docked stack - show recents if needed. 860 mService.mWindowManager.showRecentApps(); 861 } 862 wm.continueSurfaceLayout(); 863 } 864 865 if (!deferEnsuringVisibility) { 866 mRootActivityContainer.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS); 867 mRootActivityContainer.resumeFocusedStacksTopActivities(); 868 } 869 } 870 871 @Override isCompatible(int windowingMode, int activityType)872 public boolean isCompatible(int windowingMode, int activityType) { 873 // TODO: Should we just move this to ConfigurationContainer? 874 if (activityType == ACTIVITY_TYPE_UNDEFINED) { 875 // Undefined activity types end up in a standard stack once the stack is created on a 876 // display, so they should be considered compatible. 877 activityType = ACTIVITY_TYPE_STANDARD; 878 } 879 return super.isCompatible(windowingMode, activityType); 880 } 881 882 /** Adds the stack to specified display and calls WindowManager to do the same. */ reparent(ActivityDisplay activityDisplay, boolean onTop, boolean displayRemoved)883 void reparent(ActivityDisplay activityDisplay, boolean onTop, boolean displayRemoved) { 884 // TODO: We should probably resolve the windowing mode for the stack on the new display here 885 // so that it end up in a compatible mode in the new display. e.g. split-screen secondary. 886 removeFromDisplay(); 887 // Reparent the window container before we try to update the position when adding it to 888 // the new display below 889 mTmpRect2.setEmpty(); 890 if (mTaskStack == null) { 891 // TODO: Remove after unification. 892 Log.w(TAG, "Task stack is not valid when reparenting."); 893 } else { 894 mTaskStack.reparent(activityDisplay.mDisplayId, mTmpRect2, onTop); 895 } 896 setBounds(mTmpRect2.isEmpty() ? null : mTmpRect2); 897 activityDisplay.addChild(this, onTop ? POSITION_TOP : POSITION_BOTTOM); 898 if (!displayRemoved) { 899 postReparent(); 900 } 901 } 902 903 /** Resume next focusable stack after reparenting to another display. */ postReparent()904 void postReparent() { 905 adjustFocusToNextFocusableStack("reparent", true /* allowFocusSelf */); 906 mRootActivityContainer.resumeFocusedStacksTopActivities(); 907 // Update visibility of activities before notifying WM. This way it won't try to resize 908 // windows that are no longer visible. 909 mRootActivityContainer.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */, 910 !PRESERVE_WINDOWS); 911 } 912 913 /** 914 * Updates the inner state of the stack to remove it from its current parent, so it can be 915 * either destroyed completely or re-parented. 916 */ removeFromDisplay()917 private void removeFromDisplay() { 918 final ActivityDisplay display = getDisplay(); 919 if (display != null) { 920 display.removeChild(this); 921 } 922 mDisplayId = INVALID_DISPLAY; 923 } 924 925 /** Removes the stack completely. Also calls WindowManager to do the same on its side. */ remove()926 void remove() { 927 removeFromDisplay(); 928 if (mTaskStack != null) { 929 mTaskStack.removeIfPossible(); 930 mTaskStack = null; 931 } 932 onParentChanged(); 933 } 934 getDisplay()935 ActivityDisplay getDisplay() { 936 return mRootActivityContainer.getActivityDisplay(mDisplayId); 937 } 938 939 /** 940 * @see #getStackDockedModeBounds(Rect, Rect, Rect, Rect) 941 */ getStackDockedModeBounds(Rect dockedBounds, Rect currentTempTaskBounds, Rect outStackBounds, Rect outTempTaskBounds)942 void getStackDockedModeBounds(Rect dockedBounds, Rect currentTempTaskBounds, 943 Rect outStackBounds, Rect outTempTaskBounds) { 944 if (mTaskStack != null) { 945 mTaskStack.getStackDockedModeBoundsLocked(getParent().getConfiguration(), dockedBounds, 946 currentTempTaskBounds, outStackBounds, outTempTaskBounds); 947 } else { 948 outStackBounds.setEmpty(); 949 outTempTaskBounds.setEmpty(); 950 } 951 } 952 prepareFreezingTaskBounds()953 void prepareFreezingTaskBounds() { 954 if (mTaskStack != null) { 955 // TODO: This cannot be false after unification. 956 mTaskStack.prepareFreezingTaskBounds(); 957 } 958 } 959 getWindowContainerBounds(Rect outBounds)960 void getWindowContainerBounds(Rect outBounds) { 961 if (mTaskStack != null) { 962 mTaskStack.getBounds(outBounds); 963 return; 964 } 965 outBounds.setEmpty(); 966 } 967 positionChildWindowContainerAtTop(TaskRecord child)968 void positionChildWindowContainerAtTop(TaskRecord child) { 969 if (mTaskStack != null) { 970 // TODO: Remove after unification. This cannot be false after that. 971 mTaskStack.positionChildAtTop(child.getTask(), true /* includingParents */); 972 } 973 } 974 positionChildWindowContainerAtBottom(TaskRecord child)975 void positionChildWindowContainerAtBottom(TaskRecord child) { 976 // If there are other focusable stacks on the display, the z-order of the display should not 977 // be changed just because a task was placed at the bottom. E.g. if it is moving the topmost 978 // task to bottom, the next focusable stack on the same display should be focused. 979 final ActivityStack nextFocusableStack = getDisplay().getNextFocusableStack( 980 child.getStack(), true /* ignoreCurrent */); 981 if (mTaskStack != null) { 982 // TODO: Remove after unification. This cannot be false after that. 983 mTaskStack.positionChildAtBottom(child.getTask(), 984 nextFocusableStack == null /* includingParents */); 985 } 986 } 987 988 /** 989 * Returns whether to defer the scheduling of the multi-window mode. 990 */ deferScheduleMultiWindowModeChanged()991 boolean deferScheduleMultiWindowModeChanged() { 992 if (inPinnedWindowingMode()) { 993 // For the pinned stack, the deferring of the multi-window mode changed is tied to the 994 // transition animation into picture-in-picture, and is called once the animation 995 // completes, or is interrupted in a way that would leave the stack in a non-fullscreen 996 // state. 997 // @see BoundsAnimationController 998 // @see BoundsAnimationControllerTests 999 if (getTaskStack() == null) return false; 1000 return getTaskStack().deferScheduleMultiWindowModeChanged(); 1001 } 1002 return false; 1003 } 1004 1005 /** 1006 * Defers updating the bounds of the stack. If the stack was resized/repositioned while 1007 * deferring, the bounds will update in {@link #continueUpdateBounds()}. 1008 */ deferUpdateBounds()1009 void deferUpdateBounds() { 1010 if (!mUpdateBoundsDeferred) { 1011 mUpdateBoundsDeferred = true; 1012 mUpdateBoundsDeferredCalled = false; 1013 } 1014 } 1015 1016 /** 1017 * Continues updating bounds after updates have been deferred. If there was a resize attempt 1018 * between {@link #deferUpdateBounds()} and {@link #continueUpdateBounds()}, the stack will 1019 * be resized to that bounds. 1020 */ continueUpdateBounds()1021 void continueUpdateBounds() { 1022 if (mUpdateBoundsDeferred) { 1023 mUpdateBoundsDeferred = false; 1024 if (mUpdateBoundsDeferredCalled) { 1025 setTaskBounds(mDeferredBounds); 1026 setBounds(mDeferredBounds); 1027 } 1028 if (mUpdateDisplayedBoundsDeferredCalled) { 1029 setTaskDisplayedBounds(mDeferredDisplayedBounds); 1030 } 1031 } 1032 } 1033 updateBoundsAllowed(Rect bounds)1034 boolean updateBoundsAllowed(Rect bounds) { 1035 if (!mUpdateBoundsDeferred) { 1036 return true; 1037 } 1038 if (bounds != null) { 1039 mDeferredBounds.set(bounds); 1040 } else { 1041 mDeferredBounds.setEmpty(); 1042 } 1043 mUpdateBoundsDeferredCalled = true; 1044 return false; 1045 } 1046 updateDisplayedBoundsAllowed(Rect bounds)1047 boolean updateDisplayedBoundsAllowed(Rect bounds) { 1048 if (!mUpdateBoundsDeferred) { 1049 return true; 1050 } 1051 if (bounds != null) { 1052 mDeferredDisplayedBounds.set(bounds); 1053 } else { 1054 mDeferredDisplayedBounds.setEmpty(); 1055 } 1056 mUpdateDisplayedBoundsDeferredCalled = true; 1057 return false; 1058 } 1059 1060 @Override setBounds(Rect bounds)1061 public int setBounds(Rect bounds) { 1062 return super.setBounds(!inMultiWindowMode() ? null : bounds); 1063 } 1064 topRunningActivityLocked()1065 ActivityRecord topRunningActivityLocked() { 1066 return topRunningActivityLocked(false /* focusableOnly */); 1067 } 1068 getAllRunningVisibleActivitiesLocked(ArrayList<ActivityRecord> outActivities)1069 void getAllRunningVisibleActivitiesLocked(ArrayList<ActivityRecord> outActivities) { 1070 outActivities.clear(); 1071 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 1072 mTaskHistory.get(taskNdx).getAllRunningVisibleActivitiesLocked(outActivities); 1073 } 1074 } 1075 topRunningActivityLocked(boolean focusableOnly)1076 ActivityRecord topRunningActivityLocked(boolean focusableOnly) { 1077 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 1078 ActivityRecord r = mTaskHistory.get(taskNdx).topRunningActivityLocked(); 1079 if (r != null && (!focusableOnly || r.isFocusable())) { 1080 return r; 1081 } 1082 } 1083 return null; 1084 } 1085 topRunningNonOverlayTaskActivity()1086 ActivityRecord topRunningNonOverlayTaskActivity() { 1087 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 1088 final TaskRecord task = mTaskHistory.get(taskNdx); 1089 final ArrayList<ActivityRecord> activities = task.mActivities; 1090 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { 1091 final ActivityRecord r = activities.get(activityNdx); 1092 if (!r.finishing && !r.mTaskOverlay) { 1093 return r; 1094 } 1095 } 1096 } 1097 return null; 1098 } 1099 topRunningNonDelayedActivityLocked(ActivityRecord notTop)1100 ActivityRecord topRunningNonDelayedActivityLocked(ActivityRecord notTop) { 1101 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 1102 final TaskRecord task = mTaskHistory.get(taskNdx); 1103 final ArrayList<ActivityRecord> activities = task.mActivities; 1104 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { 1105 ActivityRecord r = activities.get(activityNdx); 1106 if (!r.finishing && !r.delayedResume && r != notTop && r.okToShowLocked()) { 1107 return r; 1108 } 1109 } 1110 } 1111 return null; 1112 } 1113 1114 /** 1115 * This is a simplified version of topRunningActivity that provides a number of 1116 * optional skip-over modes. It is intended for use with the ActivityController hook only. 1117 * 1118 * @param token If non-null, any history records matching this token will be skipped. 1119 * @param taskId If non-zero, we'll attempt to skip over records with the same task ID. 1120 * 1121 * @return Returns the HistoryRecord of the next activity on the stack. 1122 */ topRunningActivityLocked(IBinder token, int taskId)1123 final ActivityRecord topRunningActivityLocked(IBinder token, int taskId) { 1124 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 1125 TaskRecord task = mTaskHistory.get(taskNdx); 1126 if (task.taskId == taskId) { 1127 continue; 1128 } 1129 ArrayList<ActivityRecord> activities = task.mActivities; 1130 for (int i = activities.size() - 1; i >= 0; --i) { 1131 final ActivityRecord r = activities.get(i); 1132 // Note: the taskId check depends on real taskId fields being non-zero 1133 if (!r.finishing && (token != r.appToken) && r.okToShowLocked()) { 1134 return r; 1135 } 1136 } 1137 } 1138 return null; 1139 } 1140 getTopActivity()1141 ActivityRecord getTopActivity() { 1142 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 1143 final ActivityRecord r = mTaskHistory.get(taskNdx).getTopActivity(); 1144 if (r != null) { 1145 return r; 1146 } 1147 } 1148 return null; 1149 } 1150 topTask()1151 final TaskRecord topTask() { 1152 final int size = mTaskHistory.size(); 1153 if (size > 0) { 1154 return mTaskHistory.get(size - 1); 1155 } 1156 return null; 1157 } 1158 bottomTask()1159 private TaskRecord bottomTask() { 1160 if (mTaskHistory.isEmpty()) { 1161 return null; 1162 } 1163 return mTaskHistory.get(0); 1164 } 1165 taskForIdLocked(int id)1166 TaskRecord taskForIdLocked(int id) { 1167 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 1168 final TaskRecord task = mTaskHistory.get(taskNdx); 1169 if (task.taskId == id) { 1170 return task; 1171 } 1172 } 1173 return null; 1174 } 1175 isInStackLocked(IBinder token)1176 ActivityRecord isInStackLocked(IBinder token) { 1177 final ActivityRecord r = ActivityRecord.forTokenLocked(token); 1178 return isInStackLocked(r); 1179 } 1180 isInStackLocked(ActivityRecord r)1181 ActivityRecord isInStackLocked(ActivityRecord r) { 1182 if (r == null) { 1183 return null; 1184 } 1185 final TaskRecord task = r.getTaskRecord(); 1186 final ActivityStack stack = r.getActivityStack(); 1187 if (stack != null && task.mActivities.contains(r) && mTaskHistory.contains(task)) { 1188 if (stack != this) Slog.w(TAG, 1189 "Illegal state! task does not point to stack it is in."); 1190 return r; 1191 } 1192 return null; 1193 } 1194 isInStackLocked(TaskRecord task)1195 boolean isInStackLocked(TaskRecord task) { 1196 return mTaskHistory.contains(task); 1197 } 1198 1199 /** Checks if there are tasks with specific UID in the stack. */ isUidPresent(int uid)1200 boolean isUidPresent(int uid) { 1201 for (TaskRecord task : mTaskHistory) { 1202 for (ActivityRecord r : task.mActivities) { 1203 if (r.getUid() == uid) { 1204 return true; 1205 } 1206 } 1207 } 1208 return false; 1209 } 1210 1211 /** Get all UIDs that are present in the stack. */ getPresentUIDs(IntArray presentUIDs)1212 void getPresentUIDs(IntArray presentUIDs) { 1213 for (TaskRecord task : mTaskHistory) { 1214 for (ActivityRecord r : task.mActivities) { 1215 presentUIDs.add(r.getUid()); 1216 } 1217 } 1218 } 1219 1220 /** @return true if the stack can only contain one task */ isSingleTaskInstance()1221 boolean isSingleTaskInstance() { 1222 final ActivityDisplay display = getDisplay(); 1223 return display != null && display.isSingleTaskInstance(); 1224 } 1225 removeActivitiesFromLRUListLocked(TaskRecord task)1226 final void removeActivitiesFromLRUListLocked(TaskRecord task) { 1227 for (ActivityRecord r : task.mActivities) { 1228 mLRUActivities.remove(r); 1229 } 1230 } 1231 updateLRUListLocked(ActivityRecord r)1232 final boolean updateLRUListLocked(ActivityRecord r) { 1233 final boolean hadit = mLRUActivities.remove(r); 1234 mLRUActivities.add(r); 1235 return hadit; 1236 } 1237 isHomeOrRecentsStack()1238 final boolean isHomeOrRecentsStack() { 1239 return isActivityTypeHome() || isActivityTypeRecents(); 1240 } 1241 isOnHomeDisplay()1242 final boolean isOnHomeDisplay() { 1243 return mDisplayId == DEFAULT_DISPLAY; 1244 } 1245 returnsToHomeStack()1246 private boolean returnsToHomeStack() { 1247 return !inMultiWindowMode() 1248 && !mTaskHistory.isEmpty() 1249 && mTaskHistory.get(0).returnsToHomeStack(); 1250 } 1251 moveToFront(String reason)1252 void moveToFront(String reason) { 1253 moveToFront(reason, null); 1254 } 1255 1256 /** 1257 * @param reason The reason for moving the stack to the front. 1258 * @param task If non-null, the task will be moved to the top of the stack. 1259 * */ moveToFront(String reason, TaskRecord task)1260 void moveToFront(String reason, TaskRecord task) { 1261 if (!isAttached()) { 1262 return; 1263 } 1264 1265 final ActivityDisplay display = getDisplay(); 1266 1267 if (inSplitScreenSecondaryWindowingMode()) { 1268 // If the stack is in split-screen seconardy mode, we need to make sure we move the 1269 // primary split-screen stack forward in the case it is currently behind a fullscreen 1270 // stack so both halves of the split-screen appear on-top and the fullscreen stack isn't 1271 // cutting between them. 1272 // TODO(b/70677280): This is a workaround until we can fix as part of b/70677280. 1273 final ActivityStack topFullScreenStack = 1274 display.getTopStackInWindowingMode(WINDOWING_MODE_FULLSCREEN); 1275 if (topFullScreenStack != null) { 1276 final ActivityStack primarySplitScreenStack = display.getSplitScreenPrimaryStack(); 1277 if (display.getIndexOf(topFullScreenStack) 1278 > display.getIndexOf(primarySplitScreenStack)) { 1279 primarySplitScreenStack.moveToFront(reason + " splitScreenToTop"); 1280 } 1281 } 1282 } 1283 1284 if (!isActivityTypeHome() && returnsToHomeStack()) { 1285 // Make sure the home stack is behind this stack since that is where we should return to 1286 // when this stack is no longer visible. 1287 display.moveHomeStackToFront(reason + " returnToHome"); 1288 } 1289 1290 final boolean movingTask = task != null; 1291 display.positionChildAtTop(this, !movingTask /* includingParents */, reason); 1292 if (movingTask) { 1293 // This also moves the entire hierarchy branch to top, including parents 1294 insertTaskAtTop(task, null /* starting */); 1295 } 1296 } 1297 1298 /** 1299 * @param reason The reason for moving the stack to the back. 1300 * @param task If non-null, the task will be moved to the bottom of the stack. 1301 **/ moveToBack(String reason, TaskRecord task)1302 void moveToBack(String reason, TaskRecord task) { 1303 if (!isAttached()) { 1304 return; 1305 } 1306 1307 /** 1308 * The intent behind moving a primary split screen stack to the back is usually to hide 1309 * behind the home stack. Exit split screen in this case. 1310 */ 1311 if (getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) { 1312 setWindowingMode(WINDOWING_MODE_UNDEFINED); 1313 } 1314 1315 getDisplay().positionChildAtBottom(this, reason); 1316 if (task != null) { 1317 insertTaskAtBottom(task); 1318 } 1319 } 1320 isFocusable()1321 boolean isFocusable() { 1322 final ActivityRecord r = topRunningActivityLocked(); 1323 return mRootActivityContainer.isFocusable(this, r != null && r.isFocusable()); 1324 } 1325 isFocusableAndVisible()1326 boolean isFocusableAndVisible() { 1327 return isFocusable() && shouldBeVisible(null /* starting */); 1328 } 1329 isAttached()1330 final boolean isAttached() { 1331 final ActivityDisplay display = getDisplay(); 1332 return display != null && !display.isRemoved(); 1333 } 1334 1335 /** 1336 * Returns the top activity in any existing task matching the given Intent in the input result. 1337 * Returns null if no such task is found. 1338 */ findTaskLocked(ActivityRecord target, FindTaskResult result)1339 void findTaskLocked(ActivityRecord target, FindTaskResult result) { 1340 Intent intent = target.intent; 1341 ActivityInfo info = target.info; 1342 ComponentName cls = intent.getComponent(); 1343 if (info.targetActivity != null) { 1344 cls = new ComponentName(info.packageName, info.targetActivity); 1345 } 1346 final int userId = UserHandle.getUserId(info.applicationInfo.uid); 1347 boolean isDocument = intent != null & intent.isDocument(); 1348 // If documentData is non-null then it must match the existing task data. 1349 Uri documentData = isDocument ? intent.getData() : null; 1350 1351 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Looking for task of " + target + " in " + this); 1352 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 1353 final TaskRecord task = mTaskHistory.get(taskNdx); 1354 if (task.voiceSession != null) { 1355 // We never match voice sessions; those always run independently. 1356 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": voice session"); 1357 continue; 1358 } 1359 if (task.userId != userId) { 1360 // Looking for a different task. 1361 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": different user"); 1362 continue; 1363 } 1364 1365 // Overlays should not be considered as the task's logical top activity. 1366 final ActivityRecord r = task.getTopActivity(false /* includeOverlays */); 1367 if (r == null || r.finishing || r.mUserId != userId || 1368 r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) { 1369 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": mismatch root " + r); 1370 continue; 1371 } 1372 if (!r.hasCompatibleActivityType(target)) { 1373 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": mismatch activity type"); 1374 continue; 1375 } 1376 1377 final Intent taskIntent = task.intent; 1378 final Intent affinityIntent = task.affinityIntent; 1379 final boolean taskIsDocument; 1380 final Uri taskDocumentData; 1381 if (taskIntent != null && taskIntent.isDocument()) { 1382 taskIsDocument = true; 1383 taskDocumentData = taskIntent.getData(); 1384 } else if (affinityIntent != null && affinityIntent.isDocument()) { 1385 taskIsDocument = true; 1386 taskDocumentData = affinityIntent.getData(); 1387 } else { 1388 taskIsDocument = false; 1389 taskDocumentData = null; 1390 } 1391 1392 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Comparing existing cls=" 1393 + (task.realActivity != null ? task.realActivity.flattenToShortString() : "") 1394 + "/aff=" + r.getTaskRecord().rootAffinity + " to new cls=" 1395 + intent.getComponent().flattenToShortString() + "/aff=" + info.taskAffinity); 1396 // TODO Refactor to remove duplications. Check if logic can be simplified. 1397 if (task.realActivity != null && task.realActivity.compareTo(cls) == 0 1398 && Objects.equals(documentData, taskDocumentData)) { 1399 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Found matching class!"); 1400 //dump(); 1401 if (DEBUG_TASKS) Slog.d(TAG_TASKS, 1402 "For Intent " + intent + " bringing to top: " + r.intent); 1403 result.mRecord = r; 1404 result.mIdealMatch = true; 1405 break; 1406 } else if (affinityIntent != null && affinityIntent.getComponent() != null && 1407 affinityIntent.getComponent().compareTo(cls) == 0 && 1408 Objects.equals(documentData, taskDocumentData)) { 1409 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Found matching class!"); 1410 //dump(); 1411 if (DEBUG_TASKS) Slog.d(TAG_TASKS, 1412 "For Intent " + intent + " bringing to top: " + r.intent); 1413 result.mRecord = r; 1414 result.mIdealMatch = true; 1415 break; 1416 } else if (!isDocument && !taskIsDocument 1417 && result.mRecord == null && task.rootAffinity != null) { 1418 if (task.rootAffinity.equals(target.taskAffinity)) { 1419 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Found matching affinity candidate!"); 1420 // It is possible for multiple tasks to have the same root affinity especially 1421 // if they are in separate stacks. We save off this candidate, but keep looking 1422 // to see if there is a better candidate. 1423 result.mRecord = r; 1424 result.mIdealMatch = false; 1425 } 1426 } else if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Not a match: " + task); 1427 } 1428 } 1429 1430 /** 1431 * Returns the first activity (starting from the top of the stack) that 1432 * is the same as the given activity. Returns null if no such activity 1433 * is found. 1434 */ findActivityLocked(Intent intent, ActivityInfo info, boolean compareIntentFilters)1435 ActivityRecord findActivityLocked(Intent intent, ActivityInfo info, 1436 boolean compareIntentFilters) { 1437 ComponentName cls = intent.getComponent(); 1438 if (info.targetActivity != null) { 1439 cls = new ComponentName(info.packageName, info.targetActivity); 1440 } 1441 final int userId = UserHandle.getUserId(info.applicationInfo.uid); 1442 1443 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 1444 final TaskRecord task = mTaskHistory.get(taskNdx); 1445 final ArrayList<ActivityRecord> activities = task.mActivities; 1446 1447 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { 1448 ActivityRecord r = activities.get(activityNdx); 1449 if (!r.okToShowLocked()) { 1450 continue; 1451 } 1452 if (!r.finishing && r.mUserId == userId) { 1453 if (compareIntentFilters) { 1454 if (r.intent.filterEquals(intent)) { 1455 return r; 1456 } 1457 } else { 1458 if (r.intent.getComponent().equals(cls)) { 1459 return r; 1460 } 1461 } 1462 } 1463 } 1464 } 1465 1466 return null; 1467 } 1468 1469 /* 1470 * Move the activities around in the stack to bring a user to the foreground. 1471 */ switchUserLocked(int userId)1472 final void switchUserLocked(int userId) { 1473 if (mCurrentUser == userId) { 1474 return; 1475 } 1476 mCurrentUser = userId; 1477 1478 // Move userId's tasks to the top. 1479 int index = mTaskHistory.size(); 1480 for (int i = 0; i < index; ) { 1481 final TaskRecord task = mTaskHistory.get(i); 1482 1483 if (task.okToShowLocked()) { 1484 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "switchUser: stack=" + getStackId() + 1485 " moving " + task + " to top"); 1486 mTaskHistory.remove(i); 1487 mTaskHistory.add(task); 1488 --index; 1489 // Use same value for i. 1490 } else { 1491 ++i; 1492 } 1493 } 1494 } 1495 minimalResumeActivityLocked(ActivityRecord r)1496 void minimalResumeActivityLocked(ActivityRecord r) { 1497 if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to RESUMED: " + r + " (starting new instance)" 1498 + " callers=" + Debug.getCallers(5)); 1499 r.setState(RESUMED, "minimalResumeActivityLocked"); 1500 r.completeResumeLocked(); 1501 if (DEBUG_SAVED_STATE) Slog.i(TAG_SAVED_STATE, 1502 "Launch completed; removing icicle of " + r.icicle); 1503 } 1504 clearLaunchTime(ActivityRecord r)1505 private void clearLaunchTime(ActivityRecord r) { 1506 // Make sure that there is no activity waiting for this to launch. 1507 if (!mStackSupervisor.mWaitingActivityLaunched.isEmpty()) { 1508 mStackSupervisor.removeTimeoutsForActivityLocked(r); 1509 mStackSupervisor.scheduleIdleTimeoutLocked(r); 1510 } 1511 } 1512 awakeFromSleepingLocked()1513 void awakeFromSleepingLocked() { 1514 // Ensure activities are no longer sleeping. 1515 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 1516 final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities; 1517 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { 1518 activities.get(activityNdx).setSleeping(false); 1519 } 1520 } 1521 if (mPausingActivity != null) { 1522 Slog.d(TAG, "awakeFromSleepingLocked: previously pausing activity didn't pause"); 1523 activityPausedLocked(mPausingActivity.appToken, true); 1524 } 1525 } 1526 updateActivityApplicationInfoLocked(ApplicationInfo aInfo)1527 void updateActivityApplicationInfoLocked(ApplicationInfo aInfo) { 1528 final String packageName = aInfo.packageName; 1529 final int userId = UserHandle.getUserId(aInfo.uid); 1530 1531 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 1532 final List<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities; 1533 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { 1534 final ActivityRecord ar = activities.get(activityNdx); 1535 1536 if ((userId == ar.mUserId) && packageName.equals(ar.packageName)) { 1537 ar.updateApplicationInfo(aInfo); 1538 } 1539 } 1540 } 1541 } 1542 checkReadyForSleep()1543 void checkReadyForSleep() { 1544 if (shouldSleepActivities() && goToSleepIfPossible(false /* shuttingDown */)) { 1545 mStackSupervisor.checkReadyForSleepLocked(true /* allowDelay */); 1546 } 1547 } 1548 1549 /** 1550 * Tries to put the activities in the stack to sleep. 1551 * 1552 * If the stack is not in a state where its activities can be put to sleep, this function will 1553 * start any necessary actions to move the stack into such a state. It is expected that this 1554 * function get called again when those actions complete. 1555 * 1556 * @param shuttingDown true when the called because the device is shutting down. 1557 * @return true if the stack finished going to sleep, false if the stack only started the 1558 * process of going to sleep (checkReadyForSleep will be called when that process finishes). 1559 */ goToSleepIfPossible(boolean shuttingDown)1560 boolean goToSleepIfPossible(boolean shuttingDown) { 1561 boolean shouldSleep = true; 1562 1563 if (mResumedActivity != null) { 1564 // Still have something resumed; can't sleep until it is paused. 1565 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Sleep needs to pause " + mResumedActivity); 1566 if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING, 1567 "Sleep => pause with userLeaving=false"); 1568 1569 startPausingLocked(false, true, null, false); 1570 shouldSleep = false ; 1571 } else if (mPausingActivity != null) { 1572 // Still waiting for something to pause; can't sleep yet. 1573 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Sleep still waiting to pause " + mPausingActivity); 1574 shouldSleep = false; 1575 } 1576 1577 if (!shuttingDown) { 1578 if (containsActivityFromStack(mStackSupervisor.mStoppingActivities)) { 1579 // Still need to tell some activities to stop; can't sleep yet. 1580 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Sleep still need to stop " 1581 + mStackSupervisor.mStoppingActivities.size() + " activities"); 1582 1583 mStackSupervisor.scheduleIdleLocked(); 1584 shouldSleep = false; 1585 } 1586 1587 if (containsActivityFromStack(mStackSupervisor.mGoingToSleepActivities)) { 1588 // Still need to tell some activities to sleep; can't sleep yet. 1589 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Sleep still need to sleep " 1590 + mStackSupervisor.mGoingToSleepActivities.size() + " activities"); 1591 shouldSleep = false; 1592 } 1593 } 1594 1595 if (shouldSleep) { 1596 goToSleep(); 1597 } 1598 1599 return shouldSleep; 1600 } 1601 goToSleep()1602 void goToSleep() { 1603 // Ensure visibility without updating configuration, as activities are about to sleep. 1604 ensureActivitiesVisibleLocked(null /* starting */, 0 /* configChanges */, 1605 !PRESERVE_WINDOWS); 1606 1607 // Make sure any paused or stopped but visible activities are now sleeping. 1608 // This ensures that the activity's onStop() is called. 1609 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 1610 final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities; 1611 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { 1612 final ActivityRecord r = activities.get(activityNdx); 1613 if (r.isState(STOPPING, STOPPED, PAUSED, PAUSING)) { 1614 r.setSleeping(true); 1615 } 1616 } 1617 } 1618 } 1619 containsActivityFromStack(List<ActivityRecord> rs)1620 private boolean containsActivityFromStack(List<ActivityRecord> rs) { 1621 for (ActivityRecord r : rs) { 1622 if (r.getActivityStack() == this) { 1623 return true; 1624 } 1625 } 1626 return false; 1627 } 1628 1629 /** 1630 * Schedule a pause timeout in case the app doesn't respond. We don't give it much time because 1631 * this directly impacts the responsiveness seen by the user. 1632 */ schedulePauseTimeout(ActivityRecord r)1633 private void schedulePauseTimeout(ActivityRecord r) { 1634 final Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG); 1635 msg.obj = r; 1636 r.pauseTime = SystemClock.uptimeMillis(); 1637 mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT); 1638 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Waiting for pause to complete..."); 1639 } 1640 1641 /** 1642 * Start pausing the currently resumed activity. It is an error to call this if there 1643 * is already an activity being paused or there is no resumed activity. 1644 * 1645 * @param userLeaving True if this should result in an onUserLeaving to the current activity. 1646 * @param uiSleeping True if this is happening with the user interface going to sleep (the 1647 * screen turning off). 1648 * @param resuming The activity we are currently trying to resume or null if this is not being 1649 * called as part of resuming the top activity, so we shouldn't try to instigate 1650 * a resume here if not null. 1651 * @param pauseImmediately True if the caller does not want to wait for the activity callback to 1652 * complete pausing. 1653 * @return Returns true if an activity now is in the PAUSING state, and we are waiting for 1654 * it to tell us when it is done. 1655 */ startPausingLocked(boolean userLeaving, boolean uiSleeping, ActivityRecord resuming, boolean pauseImmediately)1656 final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping, 1657 ActivityRecord resuming, boolean pauseImmediately) { 1658 if (mPausingActivity != null) { 1659 Slog.wtf(TAG, "Going to pause when pause is already pending for " + mPausingActivity 1660 + " state=" + mPausingActivity.getState()); 1661 if (!shouldSleepActivities()) { 1662 // Avoid recursion among check for sleep and complete pause during sleeping. 1663 // Because activity will be paused immediately after resume, just let pause 1664 // be completed by the order of activity paused from clients. 1665 completePauseLocked(false, resuming); 1666 } 1667 } 1668 ActivityRecord prev = mResumedActivity; 1669 1670 if (prev == null) { 1671 if (resuming == null) { 1672 Slog.wtf(TAG, "Trying to pause when nothing is resumed"); 1673 mRootActivityContainer.resumeFocusedStacksTopActivities(); 1674 } 1675 return false; 1676 } 1677 1678 if (prev == resuming) { 1679 Slog.wtf(TAG, "Trying to pause activity that is in process of being resumed"); 1680 return false; 1681 } 1682 1683 if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to PAUSING: " + prev); 1684 else if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Start pausing: " + prev); 1685 mPausingActivity = prev; 1686 mLastPausedActivity = prev; 1687 mLastNoHistoryActivity = (prev.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_HISTORY) != 0 1688 || (prev.info.flags & ActivityInfo.FLAG_NO_HISTORY) != 0 ? prev : null; 1689 prev.setState(PAUSING, "startPausingLocked"); 1690 prev.getTaskRecord().touchActiveTime(); 1691 clearLaunchTime(prev); 1692 1693 mService.updateCpuStats(); 1694 1695 if (prev.attachedToProcess()) { 1696 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending pause: " + prev); 1697 try { 1698 EventLogTags.writeAmPauseActivity(prev.mUserId, System.identityHashCode(prev), 1699 prev.shortComponentName, "userLeaving=" + userLeaving); 1700 1701 mService.getLifecycleManager().scheduleTransaction(prev.app.getThread(), 1702 prev.appToken, PauseActivityItem.obtain(prev.finishing, userLeaving, 1703 prev.configChangeFlags, pauseImmediately)); 1704 } catch (Exception e) { 1705 // Ignore exception, if process died other code will cleanup. 1706 Slog.w(TAG, "Exception thrown during pause", e); 1707 mPausingActivity = null; 1708 mLastPausedActivity = null; 1709 mLastNoHistoryActivity = null; 1710 } 1711 } else { 1712 mPausingActivity = null; 1713 mLastPausedActivity = null; 1714 mLastNoHistoryActivity = null; 1715 } 1716 1717 // If we are not going to sleep, we want to ensure the device is 1718 // awake until the next activity is started. 1719 if (!uiSleeping && !mService.isSleepingOrShuttingDownLocked()) { 1720 mStackSupervisor.acquireLaunchWakelock(); 1721 } 1722 1723 if (mPausingActivity != null) { 1724 // Have the window manager pause its key dispatching until the new 1725 // activity has started. If we're pausing the activity just because 1726 // the screen is being turned off and the UI is sleeping, don't interrupt 1727 // key dispatch; the same activity will pick it up again on wakeup. 1728 if (!uiSleeping) { 1729 prev.pauseKeyDispatchingLocked(); 1730 } else if (DEBUG_PAUSE) { 1731 Slog.v(TAG_PAUSE, "Key dispatch not paused for screen off"); 1732 } 1733 1734 if (pauseImmediately) { 1735 // If the caller said they don't want to wait for the pause, then complete 1736 // the pause now. 1737 completePauseLocked(false, resuming); 1738 return false; 1739 1740 } else { 1741 schedulePauseTimeout(prev); 1742 return true; 1743 } 1744 1745 } else { 1746 // This activity failed to schedule the 1747 // pause, so just treat it as being paused now. 1748 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Activity not running, resuming next."); 1749 if (resuming == null) { 1750 mRootActivityContainer.resumeFocusedStacksTopActivities(); 1751 } 1752 return false; 1753 } 1754 } 1755 activityPausedLocked(IBinder token, boolean timeout)1756 final void activityPausedLocked(IBinder token, boolean timeout) { 1757 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, 1758 "Activity paused: token=" + token + ", timeout=" + timeout); 1759 1760 final ActivityRecord r = isInStackLocked(token); 1761 1762 if (r != null) { 1763 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r); 1764 if (mPausingActivity == r) { 1765 if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to PAUSED: " + r 1766 + (timeout ? " (due to timeout)" : " (pause complete)")); 1767 mService.mWindowManager.deferSurfaceLayout(); 1768 try { 1769 completePauseLocked(true /* resumeNext */, null /* resumingActivity */); 1770 } finally { 1771 mService.mWindowManager.continueSurfaceLayout(); 1772 } 1773 return; 1774 } else { 1775 EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE, 1776 r.mUserId, System.identityHashCode(r), r.shortComponentName, 1777 mPausingActivity != null 1778 ? mPausingActivity.shortComponentName : "(none)"); 1779 if (r.isState(PAUSING)) { 1780 r.setState(PAUSED, "activityPausedLocked"); 1781 if (r.finishing) { 1782 if (DEBUG_PAUSE) Slog.v(TAG, 1783 "Executing finish of failed to pause activity: " + r); 1784 finishCurrentActivityLocked(r, FINISH_AFTER_VISIBLE, false, 1785 "activityPausedLocked"); 1786 } 1787 } 1788 } 1789 } 1790 mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS); 1791 } 1792 completePauseLocked(boolean resumeNext, ActivityRecord resuming)1793 private void completePauseLocked(boolean resumeNext, ActivityRecord resuming) { 1794 ActivityRecord prev = mPausingActivity; 1795 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Complete pause: " + prev); 1796 1797 if (prev != null) { 1798 prev.setWillCloseOrEnterPip(false); 1799 final boolean wasStopping = prev.isState(STOPPING); 1800 prev.setState(PAUSED, "completePausedLocked"); 1801 if (prev.finishing) { 1802 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Executing finish of activity: " + prev); 1803 prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE, false, 1804 "completePausedLocked"); 1805 } else if (prev.hasProcess()) { 1806 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueue pending stop if needed: " + prev 1807 + " wasStopping=" + wasStopping + " visible=" + prev.visible); 1808 if (prev.deferRelaunchUntilPaused) { 1809 // Complete the deferred relaunch that was waiting for pause to complete. 1810 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Re-launching after pause: " + prev); 1811 prev.relaunchActivityLocked(false /* andResume */, 1812 prev.preserveWindowOnDeferredRelaunch); 1813 } else if (wasStopping) { 1814 // We are also stopping, the stop request must have gone soon after the pause. 1815 // We can't clobber it, because the stop confirmation will not be handled. 1816 // We don't need to schedule another stop, we only need to let it happen. 1817 prev.setState(STOPPING, "completePausedLocked"); 1818 } else if (!prev.visible || shouldSleepOrShutDownActivities()) { 1819 // Clear out any deferred client hide we might currently have. 1820 prev.setDeferHidingClient(false); 1821 // If we were visible then resumeTopActivities will release resources before 1822 // stopping. 1823 addToStopping(prev, true /* scheduleIdle */, false /* idleDelayed */, 1824 "completePauseLocked"); 1825 } 1826 } else { 1827 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "App died during pause, not stopping: " + prev); 1828 prev = null; 1829 } 1830 // It is possible the activity was freezing the screen before it was paused. 1831 // In that case go ahead and remove the freeze this activity has on the screen 1832 // since it is no longer visible. 1833 if (prev != null) { 1834 prev.stopFreezingScreenLocked(true /*force*/); 1835 } 1836 mPausingActivity = null; 1837 } 1838 1839 if (resumeNext) { 1840 final ActivityStack topStack = mRootActivityContainer.getTopDisplayFocusedStack(); 1841 if (!topStack.shouldSleepOrShutDownActivities()) { 1842 mRootActivityContainer.resumeFocusedStacksTopActivities(topStack, prev, null); 1843 } else { 1844 checkReadyForSleep(); 1845 ActivityRecord top = topStack.topRunningActivityLocked(); 1846 if (top == null || (prev != null && top != prev)) { 1847 // If there are no more activities available to run, do resume anyway to start 1848 // something. Also if the top activity on the stack is not the just paused 1849 // activity, we need to go ahead and resume it to ensure we complete an 1850 // in-flight app switch. 1851 mRootActivityContainer.resumeFocusedStacksTopActivities(); 1852 } 1853 } 1854 } 1855 1856 if (prev != null) { 1857 prev.resumeKeyDispatchingLocked(); 1858 1859 if (prev.hasProcess() && prev.cpuTimeAtResume > 0) { 1860 final long diff = prev.app.getCpuTime() - prev.cpuTimeAtResume; 1861 if (diff > 0) { 1862 final Runnable r = PooledLambda.obtainRunnable( 1863 ActivityManagerInternal::updateForegroundTimeIfOnBattery, 1864 mService.mAmInternal, prev.info.packageName, 1865 prev.info.applicationInfo.uid, 1866 diff); 1867 mService.mH.post(r); 1868 } 1869 } 1870 prev.cpuTimeAtResume = 0; // reset it 1871 } 1872 1873 // Notify when the task stack has changed, but only if visibilities changed (not just 1874 // focus). Also if there is an active pinned stack - we always want to notify it about 1875 // task stack changes, because its positioning may depend on it. 1876 if (mStackSupervisor.mAppVisibilitiesChangedSinceLastPause 1877 || (getDisplay() != null && getDisplay().hasPinnedStack())) { 1878 mService.getTaskChangeNotificationController().notifyTaskStackChanged(); 1879 mStackSupervisor.mAppVisibilitiesChangedSinceLastPause = false; 1880 } 1881 1882 mRootActivityContainer.ensureActivitiesVisible(resuming, 0, !PRESERVE_WINDOWS); 1883 } 1884 addToStopping(ActivityRecord r, boolean scheduleIdle, boolean idleDelayed, String reason)1885 void addToStopping(ActivityRecord r, boolean scheduleIdle, boolean idleDelayed, String reason) { 1886 if (!mStackSupervisor.mStoppingActivities.contains(r)) { 1887 EventLog.writeEvent(EventLogTags.AM_ADD_TO_STOPPING, r.mUserId, 1888 System.identityHashCode(r), r.shortComponentName, reason); 1889 mStackSupervisor.mStoppingActivities.add(r); 1890 } 1891 1892 // If we already have a few activities waiting to stop, then give up 1893 // on things going idle and start clearing them out. Or if r is the 1894 // last of activity of the last task the stack will be empty and must 1895 // be cleared immediately. 1896 boolean forceIdle = mStackSupervisor.mStoppingActivities.size() > MAX_STOPPING_TO_FORCE 1897 || (r.frontOfTask && mTaskHistory.size() <= 1); 1898 if (scheduleIdle || forceIdle) { 1899 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Scheduling idle now: forceIdle=" 1900 + forceIdle + "immediate=" + !idleDelayed); 1901 if (!idleDelayed) { 1902 mStackSupervisor.scheduleIdleLocked(); 1903 } else { 1904 mStackSupervisor.scheduleIdleTimeoutLocked(r); 1905 } 1906 } else { 1907 checkReadyForSleep(); 1908 } 1909 } 1910 1911 /** 1912 * Returns true if the stack is translucent and can have other contents visible behind it if 1913 * needed. A stack is considered translucent if it don't contain a visible or 1914 * starting (about to be visible) activity that is fullscreen (opaque). 1915 * @param starting The currently starting activity or null if there is none. 1916 */ 1917 @VisibleForTesting isStackTranslucent(ActivityRecord starting)1918 boolean isStackTranslucent(ActivityRecord starting) { 1919 if (!isAttached() || mForceHidden) { 1920 return true; 1921 } 1922 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 1923 final TaskRecord task = mTaskHistory.get(taskNdx); 1924 final ArrayList<ActivityRecord> activities = task.mActivities; 1925 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { 1926 final ActivityRecord r = activities.get(activityNdx); 1927 1928 if (r.finishing) { 1929 // We don't factor in finishing activities when determining translucency since 1930 // they will be gone soon. 1931 continue; 1932 } 1933 1934 if (!r.visibleIgnoringKeyguard && r != starting) { 1935 // Also ignore invisible activities that are not the currently starting 1936 // activity (about to be visible). 1937 continue; 1938 } 1939 1940 if (r.fullscreen || r.hasWallpaper) { 1941 // Stack isn't translucent if it has at least one fullscreen activity 1942 // that is visible. 1943 return false; 1944 } 1945 } 1946 } 1947 return true; 1948 } 1949 isTopStackOnDisplay()1950 boolean isTopStackOnDisplay() { 1951 final ActivityDisplay display = getDisplay(); 1952 return display != null && display.isTopStack(this); 1953 } 1954 1955 /** 1956 * @return {@code true} if this is the focused stack on its current display, {@code false} 1957 * otherwise. 1958 */ isFocusedStackOnDisplay()1959 boolean isFocusedStackOnDisplay() { 1960 final ActivityDisplay display = getDisplay(); 1961 return display != null && this == display.getFocusedStack(); 1962 } 1963 isTopActivityVisible()1964 boolean isTopActivityVisible() { 1965 final ActivityRecord topActivity = getTopActivity(); 1966 return topActivity != null && topActivity.visible; 1967 } 1968 1969 /** 1970 * Returns true if the stack should be visible. 1971 * 1972 * @param starting The currently starting activity or null if there is none. 1973 */ shouldBeVisible(ActivityRecord starting)1974 boolean shouldBeVisible(ActivityRecord starting) { 1975 return getVisibility(starting) != STACK_VISIBILITY_INVISIBLE; 1976 } 1977 1978 /** 1979 * Returns true if the stack should be visible. 1980 * 1981 * @param starting The currently starting activity or null if there is none. 1982 */ 1983 @StackVisibility getVisibility(ActivityRecord starting)1984 int getVisibility(ActivityRecord starting) { 1985 if (!isAttached() || mForceHidden) { 1986 return STACK_VISIBILITY_INVISIBLE; 1987 } 1988 1989 final ActivityDisplay display = getDisplay(); 1990 boolean gotSplitScreenStack = false; 1991 boolean gotOpaqueSplitScreenPrimary = false; 1992 boolean gotOpaqueSplitScreenSecondary = false; 1993 boolean gotTranslucentFullscreen = false; 1994 boolean gotTranslucentSplitScreenPrimary = false; 1995 boolean gotTranslucentSplitScreenSecondary = false; 1996 boolean shouldBeVisible = true; 1997 final int windowingMode = getWindowingMode(); 1998 final boolean isAssistantType = isActivityTypeAssistant(); 1999 for (int i = display.getChildCount() - 1; i >= 0; --i) { 2000 final ActivityStack other = display.getChildAt(i); 2001 final boolean hasRunningActivities = other.topRunningActivityLocked() != null; 2002 if (other == this) { 2003 // Should be visible if there is no other stack occluding it, unless it doesn't 2004 // have any running activities, not starting one and not home stack. 2005 shouldBeVisible = hasRunningActivities || isInStackLocked(starting) != null 2006 || isActivityTypeHome(); 2007 break; 2008 } 2009 2010 if (!hasRunningActivities) { 2011 continue; 2012 } 2013 2014 final int otherWindowingMode = other.getWindowingMode(); 2015 2016 if (otherWindowingMode == WINDOWING_MODE_FULLSCREEN) { 2017 // In this case the home stack isn't resizeable even though we are in split-screen 2018 // mode. We still want the primary splitscreen stack to be visible as there will be 2019 // a slight hint of it in the status bar area above the non-resizeable home 2020 // activity. In addition, if the fullscreen assistant is over primary splitscreen 2021 // stack, the stack should still be visible in the background as long as the recents 2022 // animation is running. 2023 final int activityType = other.getActivityType(); 2024 if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) { 2025 if (activityType == ACTIVITY_TYPE_HOME 2026 || (activityType == ACTIVITY_TYPE_ASSISTANT 2027 && mWindowManager.getRecentsAnimationController() != null)) { 2028 break; 2029 } 2030 } 2031 if (other.isStackTranslucent(starting)) { 2032 // Can be visible behind a translucent fullscreen stack. 2033 gotTranslucentFullscreen = true; 2034 continue; 2035 } 2036 return STACK_VISIBILITY_INVISIBLE; 2037 } else if (otherWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY 2038 && !gotOpaqueSplitScreenPrimary) { 2039 gotSplitScreenStack = true; 2040 gotTranslucentSplitScreenPrimary = other.isStackTranslucent(starting); 2041 gotOpaqueSplitScreenPrimary = !gotTranslucentSplitScreenPrimary; 2042 if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY 2043 && gotOpaqueSplitScreenPrimary) { 2044 // Can not be visible behind another opaque stack in split-screen-primary mode. 2045 return STACK_VISIBILITY_INVISIBLE; 2046 } 2047 } else if (otherWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY 2048 && !gotOpaqueSplitScreenSecondary) { 2049 gotSplitScreenStack = true; 2050 gotTranslucentSplitScreenSecondary = other.isStackTranslucent(starting); 2051 gotOpaqueSplitScreenSecondary = !gotTranslucentSplitScreenSecondary; 2052 if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY 2053 && gotOpaqueSplitScreenSecondary) { 2054 // Can not be visible behind another opaque stack in split-screen-secondary mode. 2055 return STACK_VISIBILITY_INVISIBLE; 2056 } 2057 } 2058 if (gotOpaqueSplitScreenPrimary && gotOpaqueSplitScreenSecondary) { 2059 // Can not be visible if we are in split-screen windowing mode and both halves of 2060 // the screen are opaque. 2061 return STACK_VISIBILITY_INVISIBLE; 2062 } 2063 if (isAssistantType && gotSplitScreenStack) { 2064 // Assistant stack can't be visible behind split-screen. In addition to this not 2065 // making sense, it also works around an issue here we boost the z-order of the 2066 // assistant window surfaces in window manager whenever it is visible. 2067 return STACK_VISIBILITY_INVISIBLE; 2068 } 2069 } 2070 2071 if (!shouldBeVisible) { 2072 return STACK_VISIBILITY_INVISIBLE; 2073 } 2074 2075 // Handle cases when there can be a translucent split-screen stack on top. 2076 switch (windowingMode) { 2077 case WINDOWING_MODE_FULLSCREEN: 2078 if (gotTranslucentSplitScreenPrimary || gotTranslucentSplitScreenSecondary) { 2079 // At least one of the split-screen stacks that covers this one is translucent. 2080 return STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT; 2081 } 2082 break; 2083 case WINDOWING_MODE_SPLIT_SCREEN_PRIMARY: 2084 if (gotTranslucentSplitScreenPrimary) { 2085 // Covered by translucent primary split-screen on top. 2086 return STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT; 2087 } 2088 break; 2089 case WINDOWING_MODE_SPLIT_SCREEN_SECONDARY: 2090 if (gotTranslucentSplitScreenSecondary) { 2091 // Covered by translucent secondary split-screen on top. 2092 return STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT; 2093 } 2094 break; 2095 } 2096 2097 // Lastly - check if there is a translucent fullscreen stack on top. 2098 return gotTranslucentFullscreen ? STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT 2099 : STACK_VISIBILITY_VISIBLE; 2100 } 2101 rankTaskLayers(int baseLayer)2102 final int rankTaskLayers(int baseLayer) { 2103 int layer = 0; 2104 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 2105 final TaskRecord task = mTaskHistory.get(taskNdx); 2106 ActivityRecord r = task.topRunningActivityLocked(); 2107 if (r == null || r.finishing || !r.visible) { 2108 task.mLayerRank = -1; 2109 } else { 2110 task.mLayerRank = baseLayer + layer++; 2111 } 2112 } 2113 return layer; 2114 } 2115 2116 /** 2117 * Make sure that all activities that need to be visible in the stack (that is, they 2118 * currently can be seen by the user) actually are and update their configuration. 2119 */ ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges, boolean preserveWindows)2120 final void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges, 2121 boolean preserveWindows) { 2122 ensureActivitiesVisibleLocked(starting, configChanges, preserveWindows, 2123 true /* notifyClients */); 2124 } 2125 2126 /** 2127 * Ensure visibility with an option to also update the configuration of visible activities. 2128 * @see #ensureActivitiesVisibleLocked(ActivityRecord, int, boolean) 2129 * @see RootActivityContainer#ensureActivitiesVisible(ActivityRecord, int, boolean) 2130 */ 2131 // TODO: Should be re-worked based on the fact that each task as a stack in most cases. ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges, boolean preserveWindows, boolean notifyClients)2132 final void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges, 2133 boolean preserveWindows, boolean notifyClients) { 2134 mTopActivityOccludesKeyguard = false; 2135 mTopDismissingKeyguardActivity = null; 2136 mStackSupervisor.getKeyguardController().beginActivityVisibilityUpdate(); 2137 try { 2138 ActivityRecord top = topRunningActivityLocked(); 2139 if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "ensureActivitiesVisible behind " + top 2140 + " configChanges=0x" + Integer.toHexString(configChanges)); 2141 if (top != null) { 2142 checkTranslucentActivityWaiting(top); 2143 } 2144 2145 // If the top activity is not fullscreen, then we need to 2146 // make sure any activities under it are now visible. 2147 boolean aboveTop = top != null; 2148 final boolean stackShouldBeVisible = shouldBeVisible(starting); 2149 boolean behindFullscreenActivity = !stackShouldBeVisible; 2150 boolean resumeNextActivity = isFocusable() && isInStackLocked(starting) == null; 2151 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 2152 final TaskRecord task = mTaskHistory.get(taskNdx); 2153 final ArrayList<ActivityRecord> activities = task.mActivities; 2154 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { 2155 final ActivityRecord r = activities.get(activityNdx); 2156 if (r.finishing) { 2157 continue; 2158 } 2159 final boolean isTop = r == top; 2160 if (aboveTop && !isTop) { 2161 continue; 2162 } 2163 aboveTop = false; 2164 2165 // Check whether activity should be visible without Keyguard influence 2166 final boolean visibleIgnoringKeyguard = r.shouldBeVisibleIgnoringKeyguard( 2167 behindFullscreenActivity); 2168 final boolean reallyVisible = r.shouldBeVisible(behindFullscreenActivity); 2169 if (visibleIgnoringKeyguard) { 2170 behindFullscreenActivity = updateBehindFullscreen(!stackShouldBeVisible, 2171 behindFullscreenActivity, r); 2172 } 2173 if (reallyVisible) { 2174 if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Make visible? " + r 2175 + " finishing=" + r.finishing + " state=" + r.getState()); 2176 // First: if this is not the current activity being started, make 2177 // sure it matches the current configuration. 2178 if (r != starting && notifyClients) { 2179 r.ensureActivityConfiguration(0 /* globalChanges */, preserveWindows, 2180 true /* ignoreVisibility */); 2181 } 2182 2183 if (!r.attachedToProcess()) { 2184 if (makeVisibleAndRestartIfNeeded(starting, configChanges, isTop, 2185 resumeNextActivity, r)) { 2186 if (activityNdx >= activities.size()) { 2187 // Record may be removed if its process needs to restart. 2188 activityNdx = activities.size() - 1; 2189 } else { 2190 resumeNextActivity = false; 2191 } 2192 } 2193 } else if (r.visible) { 2194 // If this activity is already visible, then there is nothing to do here. 2195 if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, 2196 "Skipping: already visible at " + r); 2197 2198 if (r.mClientVisibilityDeferred && notifyClients) { 2199 r.makeClientVisible(); 2200 } 2201 2202 if (r.handleAlreadyVisible()) { 2203 resumeNextActivity = false; 2204 } 2205 2206 if (notifyClients) { 2207 r.makeActiveIfNeeded(starting); 2208 } 2209 } else { 2210 r.makeVisibleIfNeeded(starting, notifyClients); 2211 } 2212 // Aggregate current change flags. 2213 configChanges |= r.configChangeFlags; 2214 } else { 2215 if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Make invisible? " + r 2216 + " finishing=" + r.finishing + " state=" + r.getState() 2217 + " stackShouldBeVisible=" + stackShouldBeVisible 2218 + " behindFullscreenActivity=" + behindFullscreenActivity 2219 + " mLaunchTaskBehind=" + r.mLaunchTaskBehind); 2220 makeInvisible(r); 2221 } 2222 } 2223 final int windowingMode = getWindowingMode(); 2224 if (windowingMode == WINDOWING_MODE_FREEFORM) { 2225 // The visibility of tasks and the activities they contain in freeform stack are 2226 // determined individually unlike other stacks where the visibility or fullscreen 2227 // status of an activity in a previous task affects other. 2228 behindFullscreenActivity = !stackShouldBeVisible; 2229 } else if (isActivityTypeHome()) { 2230 if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Home task: at " + task 2231 + " stackShouldBeVisible=" + stackShouldBeVisible 2232 + " behindFullscreenActivity=" + behindFullscreenActivity); 2233 // No other task in the home stack should be visible behind the home activity. 2234 // Home activities is usually a translucent activity with the wallpaper behind 2235 // them. However, when they don't have the wallpaper behind them, we want to 2236 // show activities in the next application stack behind them vs. another 2237 // task in the home stack like recents. 2238 behindFullscreenActivity = true; 2239 } 2240 } 2241 2242 if (mTranslucentActivityWaiting != null && 2243 mUndrawnActivitiesBelowTopTranslucent.isEmpty()) { 2244 // Nothing is getting drawn or everything was already visible, don't wait for timeout. 2245 notifyActivityDrawnLocked(null); 2246 } 2247 } finally { 2248 mStackSupervisor.getKeyguardController().endActivityVisibilityUpdate(); 2249 } 2250 } 2251 addStartingWindowsForVisibleActivities(boolean taskSwitch)2252 void addStartingWindowsForVisibleActivities(boolean taskSwitch) { 2253 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 2254 mTaskHistory.get(taskNdx).addStartingWindowsForVisibleActivities(taskSwitch); 2255 } 2256 } 2257 2258 /** 2259 * @return true if the top visible activity wants to occlude the Keyguard, false otherwise 2260 */ topActivityOccludesKeyguard()2261 boolean topActivityOccludesKeyguard() { 2262 return mTopActivityOccludesKeyguard; 2263 } 2264 2265 /** 2266 * Returns true if this stack should be resized to match the bounds specified by 2267 * {@link ActivityOptions#setLaunchBounds} when launching an activity into the stack. 2268 */ resizeStackWithLaunchBounds()2269 boolean resizeStackWithLaunchBounds() { 2270 return inPinnedWindowingMode(); 2271 } 2272 2273 @Override supportsSplitScreenWindowingMode()2274 public boolean supportsSplitScreenWindowingMode() { 2275 final TaskRecord topTask = topTask(); 2276 return super.supportsSplitScreenWindowingMode() 2277 && (topTask == null || topTask.supportsSplitScreenWindowingMode()); 2278 } 2279 2280 /** @return True if the resizing of the primary-split-screen stack affects this stack size. */ affectedBySplitScreenResize()2281 boolean affectedBySplitScreenResize() { 2282 if (!supportsSplitScreenWindowingMode()) { 2283 return false; 2284 } 2285 final int windowingMode = getWindowingMode(); 2286 return windowingMode != WINDOWING_MODE_FREEFORM && windowingMode != WINDOWING_MODE_PINNED; 2287 } 2288 2289 /** 2290 * @return the top most visible activity that wants to dismiss Keyguard 2291 */ getTopDismissingKeyguardActivity()2292 ActivityRecord getTopDismissingKeyguardActivity() { 2293 return mTopDismissingKeyguardActivity; 2294 } 2295 2296 /** 2297 * Checks whether {@param r} should be visible depending on Keyguard state and updates 2298 * {@link #mTopActivityOccludesKeyguard} and {@link #mTopDismissingKeyguardActivity} if 2299 * necessary. 2300 * 2301 * @return true if {@param r} is visible taken Keyguard state into account, false otherwise 2302 */ checkKeyguardVisibility(ActivityRecord r, boolean shouldBeVisible, boolean isTop)2303 boolean checkKeyguardVisibility(ActivityRecord r, boolean shouldBeVisible, boolean isTop) { 2304 final int displayId = mDisplayId != INVALID_DISPLAY ? mDisplayId : DEFAULT_DISPLAY; 2305 final boolean keyguardOrAodShowing = mStackSupervisor.getKeyguardController() 2306 .isKeyguardOrAodShowing(displayId); 2307 final boolean keyguardLocked = mStackSupervisor.getKeyguardController().isKeyguardLocked(); 2308 final boolean showWhenLocked = r.canShowWhenLocked(); 2309 final boolean dismissKeyguard = r.mAppWindowToken != null 2310 && r.mAppWindowToken.containsDismissKeyguardWindow(); 2311 if (shouldBeVisible) { 2312 if (dismissKeyguard && mTopDismissingKeyguardActivity == null) { 2313 mTopDismissingKeyguardActivity = r; 2314 } 2315 2316 // Only the top activity may control occluded, as we can't occlude the Keyguard if the 2317 // top app doesn't want to occlude it. 2318 if (isTop) { 2319 mTopActivityOccludesKeyguard |= showWhenLocked; 2320 } 2321 2322 final boolean canShowWithKeyguard = canShowWithInsecureKeyguard() 2323 && mStackSupervisor.getKeyguardController().canDismissKeyguard(); 2324 if (canShowWithKeyguard) { 2325 return true; 2326 } 2327 } 2328 if (keyguardOrAodShowing) { 2329 // If keyguard is showing, nothing is visible, except if we are able to dismiss Keyguard 2330 // right away and AOD isn't visible. 2331 return shouldBeVisible && mStackSupervisor.getKeyguardController() 2332 .canShowActivityWhileKeyguardShowing(r, dismissKeyguard); 2333 } else if (keyguardLocked) { 2334 return shouldBeVisible && mStackSupervisor.getKeyguardController().canShowWhileOccluded( 2335 dismissKeyguard, showWhenLocked); 2336 } else { 2337 return shouldBeVisible; 2338 } 2339 } 2340 2341 /** 2342 * Check if the display to which this stack is attached has 2343 * {@link Display#FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD} applied. 2344 */ canShowWithInsecureKeyguard()2345 boolean canShowWithInsecureKeyguard() { 2346 final ActivityDisplay activityDisplay = getDisplay(); 2347 if (activityDisplay == null) { 2348 throw new IllegalStateException("Stack is not attached to any display, stackId=" 2349 + mStackId); 2350 } 2351 2352 final int flags = activityDisplay.mDisplay.getFlags(); 2353 return (flags & FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD) != 0; 2354 } 2355 checkTranslucentActivityWaiting(ActivityRecord top)2356 private void checkTranslucentActivityWaiting(ActivityRecord top) { 2357 if (mTranslucentActivityWaiting != top) { 2358 mUndrawnActivitiesBelowTopTranslucent.clear(); 2359 if (mTranslucentActivityWaiting != null) { 2360 // Call the callback with a timeout indication. 2361 notifyActivityDrawnLocked(null); 2362 mTranslucentActivityWaiting = null; 2363 } 2364 mHandler.removeMessages(TRANSLUCENT_TIMEOUT_MSG); 2365 } 2366 } 2367 makeVisibleAndRestartIfNeeded(ActivityRecord starting, int configChanges, boolean isTop, boolean andResume, ActivityRecord r)2368 private boolean makeVisibleAndRestartIfNeeded(ActivityRecord starting, int configChanges, 2369 boolean isTop, boolean andResume, ActivityRecord r) { 2370 // We need to make sure the app is running if it's the top, or it is just made visible from 2371 // invisible. If the app is already visible, it must have died while it was visible. In this 2372 // case, we'll show the dead window but will not restart the app. Otherwise we could end up 2373 // thrashing. 2374 if (isTop || !r.visible) { 2375 // This activity needs to be visible, but isn't even running... 2376 // get it started and resume if no other stack in this stack is resumed. 2377 if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Start and freeze screen for " + r); 2378 if (r != starting) { 2379 r.startFreezingScreenLocked(r.app, configChanges); 2380 } 2381 if (!r.visible || r.mLaunchTaskBehind) { 2382 if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Starting and making visible: " + r); 2383 r.setVisible(true); 2384 } 2385 if (r != starting) { 2386 // We should not resume activities that being launched behind because these 2387 // activities are actually behind other fullscreen activities, but still required 2388 // to be visible (such as performing Recents animation). 2389 mStackSupervisor.startSpecificActivityLocked(r, andResume && !r.mLaunchTaskBehind, 2390 true /* checkConfig */); 2391 return true; 2392 } 2393 } 2394 return false; 2395 } 2396 2397 // TODO: Should probably be moved into ActivityRecord. makeInvisible(ActivityRecord r)2398 private void makeInvisible(ActivityRecord r) { 2399 if (!r.visible) { 2400 if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Already invisible: " + r); 2401 return; 2402 } 2403 // Now for any activities that aren't visible to the user, make sure they no longer are 2404 // keeping the screen frozen. 2405 if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Making invisible: " + r + " " + r.getState()); 2406 try { 2407 final boolean canEnterPictureInPicture = r.checkEnterPictureInPictureState( 2408 "makeInvisible", true /* beforeStopping */); 2409 // Defer telling the client it is hidden if it can enter Pip and isn't current paused, 2410 // stopped or stopping. This gives it a chance to enter Pip in onPause(). 2411 // TODO: There is still a question surrounding activities in multi-window mode that want 2412 // to enter Pip after they are paused, but are still visible. I they should be okay to 2413 // enter Pip in those cases, but not "auto-Pip" which is what this condition covers and 2414 // the current contract for "auto-Pip" is that the app should enter it before onPause 2415 // returns. Just need to confirm this reasoning makes sense. 2416 final boolean deferHidingClient = canEnterPictureInPicture 2417 && !r.isState(STOPPING, STOPPED, PAUSED); 2418 r.setDeferHidingClient(deferHidingClient); 2419 r.setVisible(false); 2420 2421 switch (r.getState()) { 2422 case STOPPING: 2423 case STOPPED: 2424 if (r.attachedToProcess()) { 2425 if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, 2426 "Scheduling invisibility: " + r); 2427 mService.getLifecycleManager().scheduleTransaction(r.app.getThread(), 2428 r.appToken, WindowVisibilityItem.obtain(false /* showWindow */)); 2429 } 2430 2431 // Reset the flag indicating that an app can enter picture-in-picture once the 2432 // activity is hidden 2433 r.supportsEnterPipOnTaskSwitch = false; 2434 break; 2435 2436 case INITIALIZING: 2437 case RESUMED: 2438 case PAUSING: 2439 case PAUSED: 2440 addToStopping(r, true /* scheduleIdle */, 2441 canEnterPictureInPicture /* idleDelayed */, "makeInvisible"); 2442 break; 2443 2444 default: 2445 break; 2446 } 2447 } catch (Exception e) { 2448 // Just skip on any failure; we'll make it visible when it next restarts. 2449 Slog.w(TAG, "Exception thrown making hidden: " + r.intent.getComponent(), e); 2450 } 2451 } 2452 updateBehindFullscreen(boolean stackInvisible, boolean behindFullscreenActivity, ActivityRecord r)2453 private boolean updateBehindFullscreen(boolean stackInvisible, boolean behindFullscreenActivity, 2454 ActivityRecord r) { 2455 if (r.fullscreen) { 2456 if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Fullscreen: at " + r 2457 + " stackInvisible=" + stackInvisible 2458 + " behindFullscreenActivity=" + behindFullscreenActivity); 2459 // At this point, nothing else needs to be shown in this task. 2460 behindFullscreenActivity = true; 2461 } 2462 return behindFullscreenActivity; 2463 } 2464 convertActivityToTranslucent(ActivityRecord r)2465 void convertActivityToTranslucent(ActivityRecord r) { 2466 mTranslucentActivityWaiting = r; 2467 mUndrawnActivitiesBelowTopTranslucent.clear(); 2468 mHandler.sendEmptyMessageDelayed(TRANSLUCENT_TIMEOUT_MSG, TRANSLUCENT_CONVERSION_TIMEOUT); 2469 } 2470 clearOtherAppTimeTrackers(AppTimeTracker except)2471 void clearOtherAppTimeTrackers(AppTimeTracker except) { 2472 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 2473 final TaskRecord task = mTaskHistory.get(taskNdx); 2474 final ArrayList<ActivityRecord> activities = task.mActivities; 2475 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { 2476 final ActivityRecord r = activities.get(activityNdx); 2477 if ( r.appTimeTracker != except) { 2478 r.appTimeTracker = null; 2479 } 2480 } 2481 } 2482 } 2483 2484 /** 2485 * Called as activities below the top translucent activity are redrawn. When the last one is 2486 * redrawn notify the top activity by calling 2487 * {@link Activity#onTranslucentConversionComplete}. 2488 * 2489 * @param r The most recent background activity to be drawn. Or, if r is null then a timeout 2490 * occurred and the activity will be notified immediately. 2491 */ notifyActivityDrawnLocked(ActivityRecord r)2492 void notifyActivityDrawnLocked(ActivityRecord r) { 2493 if ((r == null) 2494 || (mUndrawnActivitiesBelowTopTranslucent.remove(r) && 2495 mUndrawnActivitiesBelowTopTranslucent.isEmpty())) { 2496 // The last undrawn activity below the top has just been drawn. If there is an 2497 // opaque activity at the top, notify it that it can become translucent safely now. 2498 final ActivityRecord waitingActivity = mTranslucentActivityWaiting; 2499 mTranslucentActivityWaiting = null; 2500 mUndrawnActivitiesBelowTopTranslucent.clear(); 2501 mHandler.removeMessages(TRANSLUCENT_TIMEOUT_MSG); 2502 2503 if (waitingActivity != null) { 2504 mWindowManager.setWindowOpaque(waitingActivity.appToken, false); 2505 if (waitingActivity.attachedToProcess()) { 2506 try { 2507 waitingActivity.app.getThread().scheduleTranslucentConversionComplete( 2508 waitingActivity.appToken, r != null); 2509 } catch (RemoteException e) { 2510 } 2511 } 2512 } 2513 } 2514 } 2515 2516 /** If any activities below the top running one are in the INITIALIZING state and they have a 2517 * starting window displayed then remove that starting window. It is possible that the activity 2518 * in this state will never resumed in which case that starting window will be orphaned. */ cancelInitializingActivities()2519 void cancelInitializingActivities() { 2520 final ActivityRecord topActivity = topRunningActivityLocked(); 2521 boolean aboveTop = true; 2522 // We don't want to clear starting window for activities that aren't behind fullscreen 2523 // activities as we need to display their starting window until they are done initializing. 2524 boolean behindFullscreenActivity = false; 2525 2526 if (!shouldBeVisible(null)) { 2527 // The stack is not visible, so no activity in it should be displaying a starting 2528 // window. Mark all activities below top and behind fullscreen. 2529 aboveTop = false; 2530 behindFullscreenActivity = true; 2531 } 2532 2533 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 2534 final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities; 2535 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { 2536 final ActivityRecord r = activities.get(activityNdx); 2537 if (aboveTop) { 2538 if (r == topActivity) { 2539 aboveTop = false; 2540 } 2541 behindFullscreenActivity |= r.fullscreen; 2542 continue; 2543 } 2544 2545 r.removeOrphanedStartingWindow(behindFullscreenActivity); 2546 behindFullscreenActivity |= r.fullscreen; 2547 } 2548 } 2549 } 2550 2551 /** 2552 * Ensure that the top activity in the stack is resumed. 2553 * 2554 * @param prev The previously resumed activity, for when in the process 2555 * of pausing; can be null to call from elsewhere. 2556 * @param options Activity options. 2557 * 2558 * @return Returns true if something is being resumed, or false if 2559 * nothing happened. 2560 * 2561 * NOTE: It is not safe to call this method directly as it can cause an activity in a 2562 * non-focused stack to be resumed. 2563 * Use {@link RootActivityContainer#resumeFocusedStacksTopActivities} to resume the 2564 * right activity for the current system state. 2565 */ 2566 @GuardedBy("mService") resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options)2567 boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) { 2568 if (mInResumeTopActivity) { 2569 // Don't even start recursing. 2570 return false; 2571 } 2572 2573 boolean result = false; 2574 try { 2575 // Protect against recursion. 2576 mInResumeTopActivity = true; 2577 result = resumeTopActivityInnerLocked(prev, options); 2578 2579 // When resuming the top activity, it may be necessary to pause the top activity (for 2580 // example, returning to the lock screen. We suppress the normal pause logic in 2581 // {@link #resumeTopActivityUncheckedLocked}, since the top activity is resumed at the 2582 // end. We call the {@link ActivityStackSupervisor#checkReadyForSleepLocked} again here 2583 // to ensure any necessary pause logic occurs. In the case where the Activity will be 2584 // shown regardless of the lock screen, the call to 2585 // {@link ActivityStackSupervisor#checkReadyForSleepLocked} is skipped. 2586 final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */); 2587 if (next == null || !next.canTurnScreenOn()) { 2588 checkReadyForSleep(); 2589 } 2590 } finally { 2591 mInResumeTopActivity = false; 2592 } 2593 2594 return result; 2595 } 2596 2597 /** 2598 * Returns the currently resumed activity. 2599 */ getResumedActivity()2600 protected ActivityRecord getResumedActivity() { 2601 return mResumedActivity; 2602 } 2603 setResumedActivity(ActivityRecord r, String reason)2604 private void setResumedActivity(ActivityRecord r, String reason) { 2605 if (mResumedActivity == r) { 2606 return; 2607 } 2608 2609 if (DEBUG_STACK) Slog.d(TAG_STACK, "setResumedActivity stack:" + this + " + from: " 2610 + mResumedActivity + " to:" + r + " reason:" + reason); 2611 mResumedActivity = r; 2612 mStackSupervisor.updateTopResumedActivityIfNeeded(); 2613 } 2614 2615 @GuardedBy("mService") resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options)2616 private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) { 2617 if (!mService.isBooting() && !mService.isBooted()) { 2618 // Not ready yet! 2619 return false; 2620 } 2621 2622 // Find the next top-most activity to resume in this stack that is not finishing and is 2623 // focusable. If it is not focusable, we will fall into the case below to resume the 2624 // top activity in the next focusable task. 2625 ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */); 2626 2627 final boolean hasRunningActivity = next != null; 2628 2629 // TODO: Maybe this entire condition can get removed? 2630 if (hasRunningActivity && !isAttached()) { 2631 return false; 2632 } 2633 2634 mRootActivityContainer.cancelInitializingActivities(); 2635 2636 // Remember how we'll process this pause/resume situation, and ensure 2637 // that the state is reset however we wind up proceeding. 2638 boolean userLeaving = mStackSupervisor.mUserLeaving; 2639 mStackSupervisor.mUserLeaving = false; 2640 2641 if (!hasRunningActivity) { 2642 // There are no activities left in the stack, let's look somewhere else. 2643 return resumeNextFocusableActivityWhenStackIsEmpty(prev, options); 2644 } 2645 2646 next.delayedResume = false; 2647 final ActivityDisplay display = getDisplay(); 2648 2649 // If the top activity is the resumed one, nothing to do. 2650 if (mResumedActivity == next && next.isState(RESUMED) 2651 && display.allResumedActivitiesComplete()) { 2652 // Make sure we have executed any pending transitions, since there 2653 // should be nothing left to do at this point. 2654 executeAppTransition(options); 2655 if (DEBUG_STATES) Slog.d(TAG_STATES, 2656 "resumeTopActivityLocked: Top activity resumed " + next); 2657 return false; 2658 } 2659 2660 if (!next.canResumeByCompat()) { 2661 return false; 2662 } 2663 2664 // If we are sleeping, and there is no resumed activity, and the top 2665 // activity is paused, well that is the state we want. 2666 if (shouldSleepOrShutDownActivities() 2667 && mLastPausedActivity == next 2668 && mRootActivityContainer.allPausedActivitiesComplete()) { 2669 // If the current top activity may be able to occlude keyguard but the occluded state 2670 // has not been set, update visibility and check again if we should continue to resume. 2671 boolean nothingToResume = true; 2672 if (!mService.mShuttingDown) { 2673 final boolean canShowWhenLocked = !mTopActivityOccludesKeyguard 2674 && next.canShowWhenLocked(); 2675 final boolean mayDismissKeyguard = mTopDismissingKeyguardActivity != next 2676 && next.mAppWindowToken != null 2677 && next.mAppWindowToken.containsDismissKeyguardWindow(); 2678 2679 if (canShowWhenLocked || mayDismissKeyguard) { 2680 ensureActivitiesVisibleLocked(null /* starting */, 0 /* configChanges */, 2681 !PRESERVE_WINDOWS); 2682 nothingToResume = shouldSleepActivities(); 2683 } 2684 } 2685 if (nothingToResume) { 2686 // Make sure we have executed any pending transitions, since there 2687 // should be nothing left to do at this point. 2688 executeAppTransition(options); 2689 if (DEBUG_STATES) Slog.d(TAG_STATES, 2690 "resumeTopActivityLocked: Going to sleep and all paused"); 2691 return false; 2692 } 2693 } 2694 2695 // Make sure that the user who owns this activity is started. If not, 2696 // we will just leave it as is because someone should be bringing 2697 // another user's activities to the top of the stack. 2698 if (!mService.mAmInternal.hasStartedUserState(next.mUserId)) { 2699 Slog.w(TAG, "Skipping resume of top activity " + next 2700 + ": user " + next.mUserId + " is stopped"); 2701 return false; 2702 } 2703 2704 // The activity may be waiting for stop, but that is no longer 2705 // appropriate for it. 2706 mStackSupervisor.mStoppingActivities.remove(next); 2707 mStackSupervisor.mGoingToSleepActivities.remove(next); 2708 next.sleeping = false; 2709 2710 if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resuming " + next); 2711 2712 // If we are currently pausing an activity, then don't do anything until that is done. 2713 if (!mRootActivityContainer.allPausedActivitiesComplete()) { 2714 if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG_PAUSE, 2715 "resumeTopActivityLocked: Skip resume: some activity pausing."); 2716 2717 return false; 2718 } 2719 2720 mStackSupervisor.setLaunchSource(next.info.applicationInfo.uid); 2721 2722 boolean lastResumedCanPip = false; 2723 ActivityRecord lastResumed = null; 2724 final ActivityStack lastFocusedStack = display.getLastFocusedStack(); 2725 if (lastFocusedStack != null && lastFocusedStack != this) { 2726 // So, why aren't we using prev here??? See the param comment on the method. prev doesn't 2727 // represent the last resumed activity. However, the last focus stack does if it isn't null. 2728 lastResumed = lastFocusedStack.mResumedActivity; 2729 if (userLeaving && inMultiWindowMode() && lastFocusedStack.shouldBeVisible(next)) { 2730 // The user isn't leaving if this stack is the multi-window mode and the last 2731 // focused stack should still be visible. 2732 if(DEBUG_USER_LEAVING) Slog.i(TAG_USER_LEAVING, "Overriding userLeaving to false" 2733 + " next=" + next + " lastResumed=" + lastResumed); 2734 userLeaving = false; 2735 } 2736 lastResumedCanPip = lastResumed != null && lastResumed.checkEnterPictureInPictureState( 2737 "resumeTopActivity", userLeaving /* beforeStopping */); 2738 } 2739 // If the flag RESUME_WHILE_PAUSING is set, then continue to schedule the previous activity 2740 // to be paused, while at the same time resuming the new resume activity only if the 2741 // previous activity can't go into Pip since we want to give Pip activities a chance to 2742 // enter Pip before resuming the next activity. 2743 final boolean resumeWhilePausing = (next.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0 2744 && !lastResumedCanPip; 2745 2746 boolean pausing = display.pauseBackStacks(userLeaving, next, false); 2747 if (mResumedActivity != null) { 2748 if (DEBUG_STATES) Slog.d(TAG_STATES, 2749 "resumeTopActivityLocked: Pausing " + mResumedActivity); 2750 pausing |= startPausingLocked(userLeaving, false, next, false); 2751 } 2752 if (pausing && !resumeWhilePausing) { 2753 if (DEBUG_SWITCH || DEBUG_STATES) Slog.v(TAG_STATES, 2754 "resumeTopActivityLocked: Skip resume: need to start pausing"); 2755 // At this point we want to put the upcoming activity's process 2756 // at the top of the LRU list, since we know we will be needing it 2757 // very soon and it would be a waste to let it get killed if it 2758 // happens to be sitting towards the end. 2759 if (next.attachedToProcess()) { 2760 next.app.updateProcessInfo(false /* updateServiceConnectionActivities */, 2761 true /* activityChange */, false /* updateOomAdj */); 2762 } else if (!next.isProcessRunning()) { 2763 // Since the start-process is asynchronous, if we already know the process of next 2764 // activity isn't running, we can start the process earlier to save the time to wait 2765 // for the current activity to be paused. 2766 final boolean isTop = this == display.getFocusedStack(); 2767 mService.startProcessAsync(next, false /* knownToBeDead */, isTop, 2768 isTop ? "pre-top-activity" : "pre-activity"); 2769 } 2770 if (lastResumed != null) { 2771 lastResumed.setWillCloseOrEnterPip(true); 2772 } 2773 return true; 2774 } else if (mResumedActivity == next && next.isState(RESUMED) 2775 && display.allResumedActivitiesComplete()) { 2776 // It is possible for the activity to be resumed when we paused back stacks above if the 2777 // next activity doesn't have to wait for pause to complete. 2778 // So, nothing else to-do except: 2779 // Make sure we have executed any pending transitions, since there 2780 // should be nothing left to do at this point. 2781 executeAppTransition(options); 2782 if (DEBUG_STATES) Slog.d(TAG_STATES, 2783 "resumeTopActivityLocked: Top activity resumed (dontWaitForPause) " + next); 2784 return true; 2785 } 2786 2787 // If the most recent activity was noHistory but was only stopped rather 2788 // than stopped+finished because the device went to sleep, we need to make 2789 // sure to finish it as we're making a new activity topmost. 2790 if (shouldSleepActivities() && mLastNoHistoryActivity != null && 2791 !mLastNoHistoryActivity.finishing) { 2792 if (DEBUG_STATES) Slog.d(TAG_STATES, 2793 "no-history finish of " + mLastNoHistoryActivity + " on new resume"); 2794 requestFinishActivityLocked(mLastNoHistoryActivity.appToken, Activity.RESULT_CANCELED, 2795 null, "resume-no-history", false); 2796 mLastNoHistoryActivity = null; 2797 } 2798 2799 if (prev != null && prev != next && next.nowVisible) { 2800 2801 // The next activity is already visible, so hide the previous 2802 // activity's windows right now so we can show the new one ASAP. 2803 // We only do this if the previous is finishing, which should mean 2804 // it is on top of the one being resumed so hiding it quickly 2805 // is good. Otherwise, we want to do the normal route of allowing 2806 // the resumed activity to be shown so we can decide if the 2807 // previous should actually be hidden depending on whether the 2808 // new one is found to be full-screen or not. 2809 if (prev.finishing) { 2810 prev.setVisibility(false); 2811 if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, 2812 "Not waiting for visible to hide: " + prev 2813 + ", nowVisible=" + next.nowVisible); 2814 } else { 2815 if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, 2816 "Previous already visible but still waiting to hide: " + prev 2817 + ", nowVisible=" + next.nowVisible); 2818 } 2819 2820 } 2821 2822 // Launching this app's activity, make sure the app is no longer 2823 // considered stopped. 2824 try { 2825 AppGlobals.getPackageManager().setPackageStoppedState( 2826 next.packageName, false, next.mUserId); /* TODO: Verify if correct userid */ 2827 } catch (RemoteException e1) { 2828 } catch (IllegalArgumentException e) { 2829 Slog.w(TAG, "Failed trying to unstop package " 2830 + next.packageName + ": " + e); 2831 } 2832 2833 // We are starting up the next activity, so tell the window manager 2834 // that the previous one will be hidden soon. This way it can know 2835 // to ignore it when computing the desired screen orientation. 2836 boolean anim = true; 2837 final DisplayContent dc = display.mDisplayContent; 2838 if (prev != null) { 2839 if (prev.finishing) { 2840 if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, 2841 "Prepare close transition: prev=" + prev); 2842 if (mStackSupervisor.mNoAnimActivities.contains(prev)) { 2843 anim = false; 2844 dc.prepareAppTransition(TRANSIT_NONE, false); 2845 } else { 2846 dc.prepareAppTransition( 2847 prev.getTaskRecord() == next.getTaskRecord() ? TRANSIT_ACTIVITY_CLOSE 2848 : TRANSIT_TASK_CLOSE, false); 2849 } 2850 prev.setVisibility(false); 2851 } else { 2852 if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, 2853 "Prepare open transition: prev=" + prev); 2854 if (mStackSupervisor.mNoAnimActivities.contains(next)) { 2855 anim = false; 2856 dc.prepareAppTransition(TRANSIT_NONE, false); 2857 } else { 2858 dc.prepareAppTransition( 2859 prev.getTaskRecord() == next.getTaskRecord() ? TRANSIT_ACTIVITY_OPEN 2860 : next.mLaunchTaskBehind ? TRANSIT_TASK_OPEN_BEHIND 2861 : TRANSIT_TASK_OPEN, false); 2862 } 2863 } 2864 } else { 2865 if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare open transition: no previous"); 2866 if (mStackSupervisor.mNoAnimActivities.contains(next)) { 2867 anim = false; 2868 dc.prepareAppTransition(TRANSIT_NONE, false); 2869 } else { 2870 dc.prepareAppTransition(TRANSIT_ACTIVITY_OPEN, false); 2871 } 2872 } 2873 2874 if (anim) { 2875 next.applyOptionsLocked(); 2876 } else { 2877 next.clearOptionsLocked(); 2878 } 2879 2880 mStackSupervisor.mNoAnimActivities.clear(); 2881 2882 if (next.attachedToProcess()) { 2883 if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resume running: " + next 2884 + " stopped=" + next.stopped + " visible=" + next.visible); 2885 2886 // If the previous activity is translucent, force a visibility update of 2887 // the next activity, so that it's added to WM's opening app list, and 2888 // transition animation can be set up properly. 2889 // For example, pressing Home button with a translucent activity in focus. 2890 // Launcher is already visible in this case. If we don't add it to opening 2891 // apps, maybeUpdateTransitToWallpaper() will fail to identify this as a 2892 // TRANSIT_WALLPAPER_OPEN animation, and run some funny animation. 2893 final boolean lastActivityTranslucent = lastFocusedStack != null 2894 && (lastFocusedStack.inMultiWindowMode() 2895 || (lastFocusedStack.mLastPausedActivity != null 2896 && !lastFocusedStack.mLastPausedActivity.fullscreen)); 2897 2898 // This activity is now becoming visible. 2899 if (!next.visible || next.stopped || lastActivityTranslucent) { 2900 next.setVisibility(true); 2901 } 2902 2903 // schedule launch ticks to collect information about slow apps. 2904 next.startLaunchTickingLocked(); 2905 2906 ActivityRecord lastResumedActivity = 2907 lastFocusedStack == null ? null : lastFocusedStack.mResumedActivity; 2908 final ActivityState lastState = next.getState(); 2909 2910 mService.updateCpuStats(); 2911 2912 if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to RESUMED: " + next 2913 + " (in existing)"); 2914 2915 next.setState(RESUMED, "resumeTopActivityInnerLocked"); 2916 2917 next.app.updateProcessInfo(false /* updateServiceConnectionActivities */, 2918 true /* activityChange */, true /* updateOomAdj */); 2919 updateLRUListLocked(next); 2920 2921 // Have the window manager re-evaluate the orientation of 2922 // the screen based on the new activity order. 2923 boolean notUpdated = true; 2924 2925 // Activity should also be visible if set mLaunchTaskBehind to true (see 2926 // ActivityRecord#shouldBeVisibleIgnoringKeyguard()). 2927 if (shouldBeVisible(next)) { 2928 // We have special rotation behavior when here is some active activity that 2929 // requests specific orientation or Keyguard is locked. Make sure all activity 2930 // visibilities are set correctly as well as the transition is updated if needed 2931 // to get the correct rotation behavior. Otherwise the following call to update 2932 // the orientation may cause incorrect configurations delivered to client as a 2933 // result of invisible window resize. 2934 // TODO: Remove this once visibilities are set correctly immediately when 2935 // starting an activity. 2936 notUpdated = !mRootActivityContainer.ensureVisibilityAndConfig(next, mDisplayId, 2937 true /* markFrozenIfConfigChanged */, false /* deferResume */); 2938 } 2939 2940 if (notUpdated) { 2941 // The configuration update wasn't able to keep the existing 2942 // instance of the activity, and instead started a new one. 2943 // We should be all done, but let's just make sure our activity 2944 // is still at the top and schedule another run if something 2945 // weird happened. 2946 ActivityRecord nextNext = topRunningActivityLocked(); 2947 if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG_STATES, 2948 "Activity config changed during resume: " + next 2949 + ", new next: " + nextNext); 2950 if (nextNext != next) { 2951 // Do over! 2952 mStackSupervisor.scheduleResumeTopActivities(); 2953 } 2954 if (!next.visible || next.stopped) { 2955 next.setVisibility(true); 2956 } 2957 next.completeResumeLocked(); 2958 return true; 2959 } 2960 2961 try { 2962 final ClientTransaction transaction = 2963 ClientTransaction.obtain(next.app.getThread(), next.appToken); 2964 // Deliver all pending results. 2965 ArrayList<ResultInfo> a = next.results; 2966 if (a != null) { 2967 final int N = a.size(); 2968 if (!next.finishing && N > 0) { 2969 if (DEBUG_RESULTS) Slog.v(TAG_RESULTS, 2970 "Delivering results to " + next + ": " + a); 2971 transaction.addCallback(ActivityResultItem.obtain(a)); 2972 } 2973 } 2974 2975 if (next.newIntents != null) { 2976 transaction.addCallback( 2977 NewIntentItem.obtain(next.newIntents, true /* resume */)); 2978 } 2979 2980 // Well the app will no longer be stopped. 2981 // Clear app token stopped state in window manager if needed. 2982 next.notifyAppResumed(next.stopped); 2983 2984 EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY, next.mUserId, 2985 System.identityHashCode(next), next.getTaskRecord().taskId, 2986 next.shortComponentName); 2987 2988 next.sleeping = false; 2989 mService.getAppWarningsLocked().onResumeActivity(next); 2990 next.app.setPendingUiCleanAndForceProcessStateUpTo(mService.mTopProcessState); 2991 next.clearOptionsLocked(); 2992 transaction.setLifecycleStateRequest( 2993 ResumeActivityItem.obtain(next.app.getReportedProcState(), 2994 dc.isNextTransitionForward())); 2995 mService.getLifecycleManager().scheduleTransaction(transaction); 2996 2997 if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Resumed " 2998 + next); 2999 } catch (Exception e) { 3000 // Whoops, need to restart this activity! 3001 if (DEBUG_STATES) Slog.v(TAG_STATES, "Resume failed; resetting state to " 3002 + lastState + ": " + next); 3003 next.setState(lastState, "resumeTopActivityInnerLocked"); 3004 3005 // lastResumedActivity being non-null implies there is a lastStack present. 3006 if (lastResumedActivity != null) { 3007 lastResumedActivity.setState(RESUMED, "resumeTopActivityInnerLocked"); 3008 } 3009 3010 Slog.i(TAG, "Restarting because process died: " + next); 3011 if (!next.hasBeenLaunched) { 3012 next.hasBeenLaunched = true; 3013 } else if (SHOW_APP_STARTING_PREVIEW && lastFocusedStack != null 3014 && lastFocusedStack.isTopStackOnDisplay()) { 3015 next.showStartingWindow(null /* prev */, false /* newTask */, 3016 false /* taskSwitch */); 3017 } 3018 mStackSupervisor.startSpecificActivityLocked(next, true, false); 3019 return true; 3020 } 3021 3022 // From this point on, if something goes wrong there is no way 3023 // to recover the activity. 3024 try { 3025 next.completeResumeLocked(); 3026 } catch (Exception e) { 3027 // If any exception gets thrown, toss away this 3028 // activity and try the next one. 3029 Slog.w(TAG, "Exception thrown during resume of " + next, e); 3030 requestFinishActivityLocked(next.appToken, Activity.RESULT_CANCELED, null, 3031 "resume-exception", true); 3032 return true; 3033 } 3034 } else { 3035 // Whoops, need to restart this activity! 3036 if (!next.hasBeenLaunched) { 3037 next.hasBeenLaunched = true; 3038 } else { 3039 if (SHOW_APP_STARTING_PREVIEW) { 3040 next.showStartingWindow(null /* prev */, false /* newTask */, 3041 false /* taskSwich */); 3042 } 3043 if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Restarting: " + next); 3044 } 3045 if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Restarting " + next); 3046 mStackSupervisor.startSpecificActivityLocked(next, true, true); 3047 } 3048 3049 return true; 3050 } 3051 3052 /** 3053 * Resume the next eligible activity in a focusable stack when this one does not have any 3054 * running activities left. The focus will be adjusted to the next focusable stack and 3055 * top running activities will be resumed in all focusable stacks. However, if the current stack 3056 * is a home stack - we have to keep it focused, start and resume a home activity on the current 3057 * display instead to make sure that the display is not empty. 3058 */ resumeNextFocusableActivityWhenStackIsEmpty(ActivityRecord prev, ActivityOptions options)3059 private boolean resumeNextFocusableActivityWhenStackIsEmpty(ActivityRecord prev, 3060 ActivityOptions options) { 3061 final String reason = "noMoreActivities"; 3062 3063 if (!isActivityTypeHome()) { 3064 final ActivityStack nextFocusedStack = adjustFocusToNextFocusableStack(reason); 3065 if (nextFocusedStack != null) { 3066 // Try to move focus to the next visible stack with a running activity if this 3067 // stack is not covering the entire screen or is on a secondary display with no home 3068 // stack. 3069 return mRootActivityContainer.resumeFocusedStacksTopActivities(nextFocusedStack, 3070 prev, null /* targetOptions */); 3071 } 3072 } 3073 3074 // If the current stack is a home stack, or if focus didn't switch to a different stack - 3075 // just start up the Launcher... 3076 ActivityOptions.abort(options); 3077 if (DEBUG_STATES) Slog.d(TAG_STATES, 3078 "resumeNextFocusableActivityWhenStackIsEmpty: " + reason + ", go home"); 3079 return mRootActivityContainer.resumeHomeActivity(prev, reason, mDisplayId); 3080 } 3081 3082 /** Returns the position the input task should be placed in this stack. */ getAdjustedPositionForTask(TaskRecord task, int suggestedPosition, ActivityRecord starting)3083 int getAdjustedPositionForTask(TaskRecord task, int suggestedPosition, 3084 ActivityRecord starting) { 3085 3086 int maxPosition = mTaskHistory.size(); 3087 if ((starting != null && starting.okToShowLocked()) 3088 || (starting == null && task.okToShowLocked())) { 3089 // If the task or starting activity can be shown, then whatever position is okay. 3090 return Math.min(suggestedPosition, maxPosition); 3091 } 3092 3093 // The task can't be shown, put non-current user tasks below current user tasks. 3094 while (maxPosition > 0) { 3095 final TaskRecord tmpTask = mTaskHistory.get(maxPosition - 1); 3096 if (!mStackSupervisor.isCurrentProfileLocked(tmpTask.userId) 3097 || tmpTask.topRunningActivityLocked() == null) { 3098 break; 3099 } 3100 maxPosition--; 3101 } 3102 3103 return Math.min(suggestedPosition, maxPosition); 3104 } 3105 3106 /** 3107 * Used from {@link ActivityStack#positionTask(TaskRecord, int)}. 3108 * @see ActivityTaskManagerService#positionTaskInStack(int, int, int). 3109 */ insertTaskAtPosition(TaskRecord task, int position)3110 private void insertTaskAtPosition(TaskRecord task, int position) { 3111 if (position >= mTaskHistory.size()) { 3112 insertTaskAtTop(task, null); 3113 return; 3114 } else if (position <= 0) { 3115 insertTaskAtBottom(task); 3116 return; 3117 } 3118 position = getAdjustedPositionForTask(task, position, null /* starting */); 3119 mTaskHistory.remove(task); 3120 mTaskHistory.add(position, task); 3121 if (mTaskStack != null) { 3122 // TODO: this could not be false after unification. 3123 mTaskStack.positionChildAt(task.getTask(), position); 3124 } 3125 updateTaskMovement(task, true); 3126 } 3127 insertTaskAtTop(TaskRecord task, ActivityRecord starting)3128 private void insertTaskAtTop(TaskRecord task, ActivityRecord starting) { 3129 // TODO: Better place to put all the code below...may be addTask... 3130 mTaskHistory.remove(task); 3131 // Now put task at top. 3132 final int position = getAdjustedPositionForTask(task, mTaskHistory.size(), starting); 3133 mTaskHistory.add(position, task); 3134 updateTaskMovement(task, true); 3135 positionChildWindowContainerAtTop(task); 3136 } 3137 insertTaskAtBottom(TaskRecord task)3138 private void insertTaskAtBottom(TaskRecord task) { 3139 mTaskHistory.remove(task); 3140 final int position = getAdjustedPositionForTask(task, 0, null); 3141 mTaskHistory.add(position, task); 3142 updateTaskMovement(task, true); 3143 positionChildWindowContainerAtBottom(task); 3144 } 3145 startActivityLocked(ActivityRecord r, ActivityRecord focusedTopActivity, boolean newTask, boolean keepCurTransition, ActivityOptions options)3146 void startActivityLocked(ActivityRecord r, ActivityRecord focusedTopActivity, 3147 boolean newTask, boolean keepCurTransition, ActivityOptions options) { 3148 TaskRecord rTask = r.getTaskRecord(); 3149 final int taskId = rTask.taskId; 3150 final boolean allowMoveToFront = options == null || !options.getAvoidMoveToFront(); 3151 // mLaunchTaskBehind tasks get placed at the back of the task stack. 3152 if (!r.mLaunchTaskBehind && allowMoveToFront 3153 && (taskForIdLocked(taskId) == null || newTask)) { 3154 // Last activity in task had been removed or ActivityManagerService is reusing task. 3155 // Insert or replace. 3156 // Might not even be in. 3157 insertTaskAtTop(rTask, r); 3158 } 3159 TaskRecord task = null; 3160 if (!newTask) { 3161 // If starting in an existing task, find where that is... 3162 boolean startIt = true; 3163 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 3164 task = mTaskHistory.get(taskNdx); 3165 if (task.getTopActivity() == null) { 3166 // All activities in task are finishing. 3167 continue; 3168 } 3169 if (task == rTask) { 3170 // Here it is! Now, if this is not yet visible to the 3171 // user, then just add it without starting; it will 3172 // get started when the user navigates back to it. 3173 if (!startIt) { 3174 if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to task " 3175 + task, new RuntimeException("here").fillInStackTrace()); 3176 r.createAppWindowToken(); 3177 ActivityOptions.abort(options); 3178 return; 3179 } 3180 break; 3181 } else if (task.numFullscreen > 0) { 3182 startIt = false; 3183 } 3184 } 3185 } 3186 3187 // Place a new activity at top of stack, so it is next to interact with the user. 3188 3189 // If we are not placing the new activity frontmost, we do not want to deliver the 3190 // onUserLeaving callback to the actual frontmost activity 3191 final TaskRecord activityTask = r.getTaskRecord(); 3192 if (task == activityTask && mTaskHistory.indexOf(task) != (mTaskHistory.size() - 1)) { 3193 mStackSupervisor.mUserLeaving = false; 3194 if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING, 3195 "startActivity() behind front, mUserLeaving=false"); 3196 } 3197 3198 task = activityTask; 3199 3200 // Slot the activity into the history stack and proceed 3201 if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to stack to task " + task, 3202 new RuntimeException("here").fillInStackTrace()); 3203 // TODO: Need to investigate if it is okay for the controller to already be created by the 3204 // time we get to this point. I think it is, but need to double check. 3205 // Use test in b/34179495 to trace the call path. 3206 if (r.mAppWindowToken == null) { 3207 r.createAppWindowToken(); 3208 } 3209 3210 task.setFrontOfTask(); 3211 3212 // The transition animation and starting window are not needed if {@code allowMoveToFront} 3213 // is false, because the activity won't be visible. 3214 if ((!isHomeOrRecentsStack() || numActivities() > 0) && allowMoveToFront) { 3215 final DisplayContent dc = getDisplay().mDisplayContent; 3216 if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, 3217 "Prepare open transition: starting " + r); 3218 if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) { 3219 dc.prepareAppTransition(TRANSIT_NONE, keepCurTransition); 3220 mStackSupervisor.mNoAnimActivities.add(r); 3221 } else { 3222 int transit = TRANSIT_ACTIVITY_OPEN; 3223 if (newTask) { 3224 if (r.mLaunchTaskBehind) { 3225 transit = TRANSIT_TASK_OPEN_BEHIND; 3226 } else if (getDisplay().isSingleTaskInstance()) { 3227 transit = TRANSIT_SHOW_SINGLE_TASK_DISPLAY; 3228 } else { 3229 // If a new task is being launched, then mark the existing top activity as 3230 // supporting picture-in-picture while pausing only if the starting activity 3231 // would not be considered an overlay on top of the current activity 3232 // (eg. not fullscreen, or the assistant) 3233 if (canEnterPipOnTaskSwitch(focusedTopActivity, 3234 null /* toFrontTask */, r, options)) { 3235 focusedTopActivity.supportsEnterPipOnTaskSwitch = true; 3236 } 3237 transit = TRANSIT_TASK_OPEN; 3238 } 3239 } 3240 dc.prepareAppTransition(transit, keepCurTransition); 3241 mStackSupervisor.mNoAnimActivities.remove(r); 3242 } 3243 boolean doShow = true; 3244 if (newTask) { 3245 // Even though this activity is starting fresh, we still need 3246 // to reset it to make sure we apply affinities to move any 3247 // existing activities from other tasks in to it. 3248 // If the caller has requested that the target task be 3249 // reset, then do so. 3250 if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) { 3251 resetTaskIfNeededLocked(r, r); 3252 doShow = topRunningNonDelayedActivityLocked(null) == r; 3253 } 3254 } else if (options != null && options.getAnimationType() 3255 == ActivityOptions.ANIM_SCENE_TRANSITION) { 3256 doShow = false; 3257 } 3258 if (r.mLaunchTaskBehind) { 3259 // Don't do a starting window for mLaunchTaskBehind. More importantly make sure we 3260 // tell WindowManager that r is visible even though it is at the back of the stack. 3261 r.setVisibility(true); 3262 ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); 3263 } else if (SHOW_APP_STARTING_PREVIEW && doShow) { 3264 // Figure out if we are transitioning from another activity that is 3265 // "has the same starting icon" as the next one. This allows the 3266 // window manager to keep the previous window it had previously 3267 // created, if it still had one. 3268 TaskRecord prevTask = r.getTaskRecord(); 3269 ActivityRecord prev = prevTask.topRunningActivityWithStartingWindowLocked(); 3270 if (prev != null) { 3271 // We don't want to reuse the previous starting preview if: 3272 // (1) The current activity is in a different task. 3273 if (prev.getTaskRecord() != prevTask) { 3274 prev = null; 3275 } 3276 // (2) The current activity is already displayed. 3277 else if (prev.nowVisible) { 3278 prev = null; 3279 } 3280 } 3281 r.showStartingWindow(prev, newTask, isTaskSwitch(r, focusedTopActivity)); 3282 } 3283 } else { 3284 // If this is the first activity, don't do any fancy animations, 3285 // because there is nothing for it to animate on top of. 3286 ActivityOptions.abort(options); 3287 } 3288 } 3289 3290 /** 3291 * @return Whether the switch to another task can trigger the currently running activity to 3292 * enter PiP while it is pausing (if supported). Only one of {@param toFrontTask} or 3293 * {@param toFrontActivity} should be set. 3294 */ canEnterPipOnTaskSwitch(ActivityRecord pipCandidate, TaskRecord toFrontTask, ActivityRecord toFrontActivity, ActivityOptions opts)3295 private boolean canEnterPipOnTaskSwitch(ActivityRecord pipCandidate, 3296 TaskRecord toFrontTask, ActivityRecord toFrontActivity, ActivityOptions opts) { 3297 if (opts != null && opts.disallowEnterPictureInPictureWhileLaunching()) { 3298 // Ensure the caller has requested not to trigger auto-enter PiP 3299 return false; 3300 } 3301 if (pipCandidate == null || pipCandidate.inPinnedWindowingMode()) { 3302 // Ensure that we do not trigger entering PiP an activity on the pinned stack 3303 return false; 3304 } 3305 final ActivityStack targetStack = toFrontTask != null 3306 ? toFrontTask.getStack() : toFrontActivity.getActivityStack(); 3307 if (targetStack != null && targetStack.isActivityTypeAssistant()) { 3308 // Ensure the task/activity being brought forward is not the assistant 3309 return false; 3310 } 3311 return true; 3312 } 3313 isTaskSwitch(ActivityRecord r, ActivityRecord topFocusedActivity)3314 private boolean isTaskSwitch(ActivityRecord r, 3315 ActivityRecord topFocusedActivity) { 3316 return topFocusedActivity != null && r.getTaskRecord() != topFocusedActivity.getTaskRecord(); 3317 } 3318 3319 /** 3320 * Perform a reset of the given task, if needed as part of launching it. 3321 * Returns the new HistoryRecord at the top of the task. 3322 */ 3323 /** 3324 * Helper method for #resetTaskIfNeededLocked. 3325 * We are inside of the task being reset... we'll either finish this activity, push it out 3326 * for another task, or leave it as-is. 3327 * @param task The task containing the Activity (taskTop) that might be reset. 3328 * @param forceReset 3329 * @return An ActivityOptions that needs to be processed. 3330 */ resetTargetTaskIfNeededLocked(TaskRecord task, boolean forceReset)3331 private ActivityOptions resetTargetTaskIfNeededLocked(TaskRecord task, boolean forceReset) { 3332 ActivityOptions topOptions = null; 3333 3334 int replyChainEnd = -1; 3335 boolean canMoveOptions = true; 3336 3337 // We only do this for activities that are not the root of the task (since if we finish 3338 // the root, we may no longer have the task!). 3339 final ArrayList<ActivityRecord> activities = task.mActivities; 3340 final int numActivities = activities.size(); 3341 final int rootActivityNdx = task.findEffectiveRootIndex(); 3342 for (int i = numActivities - 1; i > rootActivityNdx; --i ) { 3343 ActivityRecord target = activities.get(i); 3344 if (target.frontOfTask) 3345 break; 3346 3347 final int flags = target.info.flags; 3348 final boolean finishOnTaskLaunch = 3349 (flags & ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0; 3350 final boolean allowTaskReparenting = 3351 (flags & ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0; 3352 final boolean clearWhenTaskReset = 3353 (target.intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0; 3354 3355 if (!finishOnTaskLaunch 3356 && !clearWhenTaskReset 3357 && target.resultTo != null) { 3358 // If this activity is sending a reply to a previous 3359 // activity, we can't do anything with it now until 3360 // we reach the start of the reply chain. 3361 // XXX note that we are assuming the result is always 3362 // to the previous activity, which is almost always 3363 // the case but we really shouldn't count on. 3364 if (replyChainEnd < 0) { 3365 replyChainEnd = i; 3366 } 3367 } else if (!finishOnTaskLaunch 3368 && !clearWhenTaskReset 3369 && allowTaskReparenting 3370 && target.taskAffinity != null 3371 && !target.taskAffinity.equals(task.affinity)) { 3372 // If this activity has an affinity for another 3373 // task, then we need to move it out of here. We will 3374 // move it as far out of the way as possible, to the 3375 // bottom of the activity stack. This also keeps it 3376 // correctly ordered with any activities we previously 3377 // moved. 3378 final TaskRecord targetTask; 3379 final ActivityRecord bottom = 3380 !mTaskHistory.isEmpty() && !mTaskHistory.get(0).mActivities.isEmpty() ? 3381 mTaskHistory.get(0).mActivities.get(0) : null; 3382 if (bottom != null && target.taskAffinity != null 3383 && target.taskAffinity.equals(bottom.getTaskRecord().affinity)) { 3384 // If the activity currently at the bottom has the 3385 // same task affinity as the one we are moving, 3386 // then merge it into the same task. 3387 targetTask = bottom.getTaskRecord(); 3388 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Start pushing activity " + target 3389 + " out to bottom task " + targetTask); 3390 } else { 3391 targetTask = createTaskRecord( 3392 mStackSupervisor.getNextTaskIdForUserLocked(target.mUserId), 3393 target.info, null, null, null, false); 3394 targetTask.affinityIntent = target.intent; 3395 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Start pushing activity " + target 3396 + " out to new task " + targetTask); 3397 } 3398 3399 boolean noOptions = canMoveOptions; 3400 final int start = replyChainEnd < 0 ? i : replyChainEnd; 3401 for (int srcPos = start; srcPos >= i; --srcPos) { 3402 final ActivityRecord p = activities.get(srcPos); 3403 if (p.finishing) { 3404 continue; 3405 } 3406 3407 canMoveOptions = false; 3408 if (noOptions && topOptions == null) { 3409 topOptions = p.takeOptionsLocked(false /* fromClient */); 3410 if (topOptions != null) { 3411 noOptions = false; 3412 } 3413 } 3414 if (DEBUG_ADD_REMOVE) Slog.i(TAG_ADD_REMOVE, 3415 "Removing activity " + p + " from task=" + task + " adding to task=" 3416 + targetTask + " Callers=" + Debug.getCallers(4)); 3417 if (DEBUG_TASKS) Slog.v(TAG_TASKS, 3418 "Pushing next activity " + p + " out to target's task " + target); 3419 p.reparent(targetTask, 0 /* position - bottom */, "resetTargetTaskIfNeeded"); 3420 } 3421 3422 positionChildWindowContainerAtBottom(targetTask); 3423 replyChainEnd = -1; 3424 } else if (forceReset || finishOnTaskLaunch || clearWhenTaskReset) { 3425 // If the activity should just be removed -- either 3426 // because it asks for it, or the task should be 3427 // cleared -- then finish it and anything that is 3428 // part of its reply chain. 3429 int end; 3430 if (clearWhenTaskReset) { 3431 // In this case, we want to finish this activity 3432 // and everything above it, so be sneaky and pretend 3433 // like these are all in the reply chain. 3434 end = activities.size() - 1; 3435 } else if (replyChainEnd < 0) { 3436 end = i; 3437 } else { 3438 end = replyChainEnd; 3439 } 3440 boolean noOptions = canMoveOptions; 3441 for (int srcPos = i; srcPos <= end; srcPos++) { 3442 ActivityRecord p = activities.get(srcPos); 3443 if (p.finishing) { 3444 continue; 3445 } 3446 canMoveOptions = false; 3447 if (noOptions && topOptions == null) { 3448 topOptions = p.takeOptionsLocked(false /* fromClient */); 3449 if (topOptions != null) { 3450 noOptions = false; 3451 } 3452 } 3453 if (DEBUG_TASKS) Slog.w(TAG_TASKS, 3454 "resetTaskIntendedTask: calling finishActivity on " + p); 3455 if (finishActivityLocked( 3456 p, Activity.RESULT_CANCELED, null, "reset-task", false)) { 3457 end--; 3458 srcPos--; 3459 } 3460 } 3461 replyChainEnd = -1; 3462 } else { 3463 // If we were in the middle of a chain, well the 3464 // activity that started it all doesn't want anything 3465 // special, so leave it all as-is. 3466 replyChainEnd = -1; 3467 } 3468 } 3469 3470 return topOptions; 3471 } 3472 3473 /** 3474 * Helper method for #resetTaskIfNeededLocked. Processes all of the activities in a given 3475 * TaskRecord looking for an affinity with the task of resetTaskIfNeededLocked.taskTop. 3476 * @param affinityTask The task we are looking for an affinity to. 3477 * @param task Task that resetTaskIfNeededLocked.taskTop belongs to. 3478 * @param topTaskIsHigher True if #task has already been processed by resetTaskIfNeededLocked. 3479 * @param forceReset Flag passed in to resetTaskIfNeededLocked. 3480 */ resetAffinityTaskIfNeededLocked(TaskRecord affinityTask, TaskRecord task, boolean topTaskIsHigher, boolean forceReset, int taskInsertionPoint)3481 private int resetAffinityTaskIfNeededLocked(TaskRecord affinityTask, TaskRecord task, 3482 boolean topTaskIsHigher, boolean forceReset, int taskInsertionPoint) { 3483 int replyChainEnd = -1; 3484 final int taskId = task.taskId; 3485 final String taskAffinity = task.affinity; 3486 3487 final ArrayList<ActivityRecord> activities = affinityTask.mActivities; 3488 final int numActivities = activities.size(); 3489 final int rootActivityNdx = affinityTask.findEffectiveRootIndex(); 3490 3491 // Do not operate on or below the effective root Activity. 3492 for (int i = numActivities - 1; i > rootActivityNdx; --i) { 3493 ActivityRecord target = activities.get(i); 3494 if (target.frontOfTask) 3495 break; 3496 3497 final int flags = target.info.flags; 3498 boolean finishOnTaskLaunch = (flags & ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0; 3499 boolean allowTaskReparenting = (flags & ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0; 3500 3501 if (target.resultTo != null) { 3502 // If this activity is sending a reply to a previous 3503 // activity, we can't do anything with it now until 3504 // we reach the start of the reply chain. 3505 // XXX note that we are assuming the result is always 3506 // to the previous activity, which is almost always 3507 // the case but we really shouldn't count on. 3508 if (replyChainEnd < 0) { 3509 replyChainEnd = i; 3510 } 3511 } else if (topTaskIsHigher 3512 && allowTaskReparenting 3513 && taskAffinity != null 3514 && taskAffinity.equals(target.taskAffinity)) { 3515 // This activity has an affinity for our task. Either remove it if we are 3516 // clearing or move it over to our task. Note that 3517 // we currently punt on the case where we are resetting a 3518 // task that is not at the top but who has activities above 3519 // with an affinity to it... this is really not a normal 3520 // case, and we will need to later pull that task to the front 3521 // and usually at that point we will do the reset and pick 3522 // up those remaining activities. (This only happens if 3523 // someone starts an activity in a new task from an activity 3524 // in a task that is not currently on top.) 3525 if (forceReset || finishOnTaskLaunch) { 3526 final int start = replyChainEnd >= 0 ? replyChainEnd : i; 3527 if (DEBUG_TASKS) Slog.v(TAG_TASKS, 3528 "Finishing task at index " + start + " to " + i); 3529 for (int srcPos = start; srcPos >= i; --srcPos) { 3530 final ActivityRecord p = activities.get(srcPos); 3531 if (p.finishing) { 3532 continue; 3533 } 3534 finishActivityLocked( 3535 p, Activity.RESULT_CANCELED, null, "move-affinity", false); 3536 } 3537 } else { 3538 if (taskInsertionPoint < 0) { 3539 taskInsertionPoint = task.mActivities.size(); 3540 3541 } 3542 3543 final int start = replyChainEnd >= 0 ? replyChainEnd : i; 3544 if (DEBUG_TASKS) Slog.v(TAG_TASKS, 3545 "Reparenting from task=" + affinityTask + ":" + start + "-" + i 3546 + " to task=" + task + ":" + taskInsertionPoint); 3547 for (int srcPos = start; srcPos >= i; --srcPos) { 3548 final ActivityRecord p = activities.get(srcPos); 3549 p.reparent(task, taskInsertionPoint, "resetAffinityTaskIfNeededLocked"); 3550 3551 if (DEBUG_ADD_REMOVE) Slog.i(TAG_ADD_REMOVE, 3552 "Removing and adding activity " + p + " to stack at " + task 3553 + " callers=" + Debug.getCallers(3)); 3554 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Pulling activity " + p 3555 + " from " + srcPos + " in to resetting task " + task); 3556 } 3557 positionChildWindowContainerAtTop(task); 3558 3559 // Now we've moved it in to place... but what if this is 3560 // a singleTop activity and we have put it on top of another 3561 // instance of the same activity? Then we drop the instance 3562 // below so it remains singleTop. 3563 if (target.info.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) { 3564 ArrayList<ActivityRecord> taskActivities = task.mActivities; 3565 int targetNdx = taskActivities.indexOf(target); 3566 if (targetNdx > 0) { 3567 ActivityRecord p = taskActivities.get(targetNdx - 1); 3568 if (p.intent.getComponent().equals(target.intent.getComponent())) { 3569 finishActivityLocked(p, Activity.RESULT_CANCELED, null, "replace", 3570 false); 3571 } 3572 } 3573 } 3574 } 3575 3576 replyChainEnd = -1; 3577 } 3578 } 3579 return taskInsertionPoint; 3580 } 3581 resetTaskIfNeededLocked(ActivityRecord taskTop, ActivityRecord newActivity)3582 final ActivityRecord resetTaskIfNeededLocked(ActivityRecord taskTop, 3583 ActivityRecord newActivity) { 3584 final boolean forceReset = 3585 (newActivity.info.flags & ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0; 3586 final TaskRecord task = taskTop.getTaskRecord(); 3587 3588 /** False until we evaluate the TaskRecord associated with taskTop. Switches to true 3589 * for remaining tasks. Used for later tasks to reparent to task. */ 3590 boolean taskFound = false; 3591 3592 /** If ActivityOptions are moved out and need to be aborted or moved to taskTop. */ 3593 ActivityOptions topOptions = null; 3594 3595 // Preserve the location for reparenting in the new task. 3596 int reparentInsertionPoint = -1; 3597 3598 for (int i = mTaskHistory.size() - 1; i >= 0; --i) { 3599 final TaskRecord targetTask = mTaskHistory.get(i); 3600 3601 if (targetTask == task) { 3602 topOptions = resetTargetTaskIfNeededLocked(task, forceReset); 3603 taskFound = true; 3604 } else { 3605 reparentInsertionPoint = resetAffinityTaskIfNeededLocked(targetTask, task, 3606 taskFound, forceReset, reparentInsertionPoint); 3607 } 3608 } 3609 3610 int taskNdx = mTaskHistory.indexOf(task); 3611 if (taskNdx >= 0) { 3612 do { 3613 taskTop = mTaskHistory.get(taskNdx--).getTopActivity(); 3614 } while (taskTop == null && taskNdx >= 0); 3615 } 3616 3617 if (topOptions != null) { 3618 // If we got some ActivityOptions from an activity on top that 3619 // was removed from the task, propagate them to the new real top. 3620 if (taskTop != null) { 3621 taskTop.updateOptionsLocked(topOptions); 3622 } else { 3623 topOptions.abort(); 3624 } 3625 } 3626 3627 return taskTop; 3628 } 3629 sendActivityResultLocked(int callingUid, ActivityRecord r, String resultWho, int requestCode, int resultCode, Intent data)3630 void sendActivityResultLocked(int callingUid, ActivityRecord r, 3631 String resultWho, int requestCode, int resultCode, Intent data) { 3632 3633 if (callingUid > 0) { 3634 mService.mUgmInternal.grantUriPermissionFromIntent(callingUid, r.packageName, 3635 data, r.getUriPermissionsLocked(), r.mUserId); 3636 } 3637 3638 if (DEBUG_RESULTS) Slog.v(TAG, "Send activity result to " + r 3639 + " : who=" + resultWho + " req=" + requestCode 3640 + " res=" + resultCode + " data=" + data); 3641 if (mResumedActivity == r && r.attachedToProcess()) { 3642 try { 3643 ArrayList<ResultInfo> list = new ArrayList<ResultInfo>(); 3644 list.add(new ResultInfo(resultWho, requestCode, 3645 resultCode, data)); 3646 mService.getLifecycleManager().scheduleTransaction(r.app.getThread(), r.appToken, 3647 ActivityResultItem.obtain(list)); 3648 return; 3649 } catch (Exception e) { 3650 Slog.w(TAG, "Exception thrown sending result to " + r, e); 3651 } 3652 } 3653 3654 r.addResultLocked(null, resultWho, requestCode, resultCode, data); 3655 } 3656 3657 /** Returns true if the task is one of the task finishing on-top of the top running task. */ isATopFinishingTask(TaskRecord task)3658 private boolean isATopFinishingTask(TaskRecord task) { 3659 for (int i = mTaskHistory.size() - 1; i >= 0; --i) { 3660 final TaskRecord current = mTaskHistory.get(i); 3661 final ActivityRecord r = current.topRunningActivityLocked(); 3662 if (r != null) { 3663 // We got a top running activity, so there isn't a top finishing task... 3664 return false; 3665 } 3666 if (current == task) { 3667 return true; 3668 } 3669 } 3670 return false; 3671 } 3672 adjustFocusedActivityStack(ActivityRecord r, String reason)3673 private void adjustFocusedActivityStack(ActivityRecord r, String reason) { 3674 if (!mRootActivityContainer.isTopDisplayFocusedStack(this) || 3675 ((mResumedActivity != r) && (mResumedActivity != null))) { 3676 return; 3677 } 3678 3679 final ActivityRecord next = topRunningActivityLocked(); 3680 final String myReason = reason + " adjustFocus"; 3681 3682 if (next == r) { 3683 final ActivityRecord top = mRootActivityContainer.topRunningActivity(); 3684 if (top != null) { 3685 top.moveFocusableActivityToTop(myReason); 3686 } 3687 return; 3688 } 3689 3690 if (next != null && isFocusable()) { 3691 // Keep focus in stack if we have a top running activity and are focusable. 3692 return; 3693 } 3694 3695 // Task is not guaranteed to be non-null. For example, destroying the 3696 // {@link ActivityRecord} will disassociate the task from the activity. 3697 final TaskRecord task = r.getTaskRecord(); 3698 3699 if (task == null) { 3700 throw new IllegalStateException("activity no longer associated with task:" + r); 3701 } 3702 3703 // Move focus to next focusable stack if possible. 3704 final ActivityStack nextFocusableStack = adjustFocusToNextFocusableStack(myReason); 3705 if (nextFocusableStack != null) { 3706 final ActivityRecord top = nextFocusableStack.topRunningActivityLocked(); 3707 if (top != null && top == mRootActivityContainer.getTopResumedActivity()) { 3708 // TODO(b/111361570): Remove this and update focused app per-display in 3709 // WindowManager every time an activity becomes resumed in 3710 // ActivityTaskManagerService#setResumedActivityUncheckLocked(). 3711 mService.setResumedActivityUncheckLocked(top, reason); 3712 } 3713 return; 3714 } 3715 3716 // Whatever...go home. 3717 getDisplay().moveHomeActivityToTop(myReason); 3718 } 3719 3720 /** 3721 * Find next proper focusable stack and make it focused. 3722 * @return The stack that now got the focus, {@code null} if none found. 3723 */ adjustFocusToNextFocusableStack(String reason)3724 ActivityStack adjustFocusToNextFocusableStack(String reason) { 3725 return adjustFocusToNextFocusableStack(reason, false /* allowFocusSelf */); 3726 } 3727 3728 /** 3729 * Find next proper focusable stack and make it focused. 3730 * @param allowFocusSelf Is the focus allowed to remain on the same stack. 3731 * @return The stack that now got the focus, {@code null} if none found. 3732 */ adjustFocusToNextFocusableStack(String reason, boolean allowFocusSelf)3733 private ActivityStack adjustFocusToNextFocusableStack(String reason, boolean allowFocusSelf) { 3734 final ActivityStack stack = 3735 mRootActivityContainer.getNextFocusableStack(this, !allowFocusSelf); 3736 final String myReason = reason + " adjustFocusToNextFocusableStack"; 3737 if (stack == null) { 3738 return null; 3739 } 3740 3741 final ActivityRecord top = stack.topRunningActivityLocked(); 3742 3743 if (stack.isActivityTypeHome() && (top == null || !top.visible)) { 3744 // If we will be focusing on the home stack next and its current top activity isn't 3745 // visible, then use the move the home stack task to top to make the activity visible. 3746 stack.getDisplay().moveHomeActivityToTop(reason); 3747 return stack; 3748 } 3749 3750 stack.moveToFront(myReason); 3751 return stack; 3752 } 3753 stopActivityLocked(ActivityRecord r)3754 final void stopActivityLocked(ActivityRecord r) { 3755 if (DEBUG_SWITCH) Slog.d(TAG_SWITCH, "Stopping: " + r); 3756 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0 3757 || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) { 3758 if (!r.finishing) { 3759 if (!shouldSleepActivities()) { 3760 if (DEBUG_STATES) Slog.d(TAG_STATES, "no-history finish of " + r); 3761 if (requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null, 3762 "stop-no-history", false)) { 3763 // If {@link requestFinishActivityLocked} returns {@code true}, 3764 // {@link adjustFocusedActivityStack} would have been already called. 3765 r.resumeKeyDispatchingLocked(); 3766 return; 3767 } 3768 } else { 3769 if (DEBUG_STATES) Slog.d(TAG_STATES, "Not finishing noHistory " + r 3770 + " on stop because we're just sleeping"); 3771 } 3772 } 3773 } 3774 3775 if (r.attachedToProcess()) { 3776 adjustFocusedActivityStack(r, "stopActivity"); 3777 r.resumeKeyDispatchingLocked(); 3778 try { 3779 r.stopped = false; 3780 if (DEBUG_STATES) Slog.v(TAG_STATES, 3781 "Moving to STOPPING: " + r + " (stop requested)"); 3782 r.setState(STOPPING, "stopActivityLocked"); 3783 if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, 3784 "Stopping visible=" + r.visible + " for " + r); 3785 if (!r.visible) { 3786 r.setVisible(false); 3787 } 3788 EventLogTags.writeAmStopActivity( 3789 r.mUserId, System.identityHashCode(r), r.shortComponentName); 3790 mService.getLifecycleManager().scheduleTransaction(r.app.getThread(), r.appToken, 3791 StopActivityItem.obtain(r.visible, r.configChangeFlags)); 3792 if (shouldSleepOrShutDownActivities()) { 3793 r.setSleeping(true); 3794 } 3795 Message msg = mHandler.obtainMessage(STOP_TIMEOUT_MSG, r); 3796 mHandler.sendMessageDelayed(msg, STOP_TIMEOUT); 3797 } catch (Exception e) { 3798 // Maybe just ignore exceptions here... if the process 3799 // has crashed, our death notification will clean things 3800 // up. 3801 Slog.w(TAG, "Exception thrown during pause", e); 3802 // Just in case, assume it to be stopped. 3803 r.stopped = true; 3804 if (DEBUG_STATES) Slog.v(TAG_STATES, "Stop failed; moving to STOPPED: " + r); 3805 r.setState(STOPPED, "stopActivityLocked"); 3806 if (r.deferRelaunchUntilPaused) { 3807 destroyActivityLocked(r, true, "stop-except"); 3808 } 3809 } 3810 } 3811 } 3812 3813 /** 3814 * @return Returns true if the activity is being finished, false if for 3815 * some reason it is being left as-is. 3816 */ requestFinishActivityLocked(IBinder token, int resultCode, Intent resultData, String reason, boolean oomAdj)3817 final boolean requestFinishActivityLocked(IBinder token, int resultCode, 3818 Intent resultData, String reason, boolean oomAdj) { 3819 ActivityRecord r = isInStackLocked(token); 3820 if (DEBUG_RESULTS || DEBUG_STATES) Slog.v(TAG_STATES, 3821 "Finishing activity token=" + token + " r=" 3822 + ", result=" + resultCode + ", data=" + resultData 3823 + ", reason=" + reason); 3824 if (r == null) { 3825 return false; 3826 } 3827 3828 finishActivityLocked(r, resultCode, resultData, reason, oomAdj); 3829 return true; 3830 } 3831 finishSubActivityLocked(ActivityRecord self, String resultWho, int requestCode)3832 final void finishSubActivityLocked(ActivityRecord self, String resultWho, int requestCode) { 3833 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 3834 ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities; 3835 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { 3836 ActivityRecord r = activities.get(activityNdx); 3837 if (r.resultTo == self && r.requestCode == requestCode) { 3838 if ((r.resultWho == null && resultWho == null) || 3839 (r.resultWho != null && r.resultWho.equals(resultWho))) { 3840 finishActivityLocked(r, Activity.RESULT_CANCELED, null, "request-sub", 3841 false); 3842 } 3843 } 3844 } 3845 } 3846 mService.updateOomAdj(); 3847 } 3848 3849 /** 3850 * Finish the topmost activity that belongs to the crashed app. We may also finish the activity 3851 * that requested launch of the crashed one to prevent launch-crash loop. 3852 * @param app The app that crashed. 3853 * @param reason Reason to perform this action. 3854 * @return The task that was finished in this stack, {@code null} if top running activity does 3855 * not belong to the crashed app. 3856 */ finishTopCrashedActivityLocked(WindowProcessController app, String reason)3857 final TaskRecord finishTopCrashedActivityLocked(WindowProcessController app, String reason) { 3858 ActivityRecord r = topRunningActivityLocked(); 3859 TaskRecord finishedTask = null; 3860 if (r == null || r.app != app) { 3861 return null; 3862 } 3863 Slog.w(TAG, " Force finishing activity " 3864 + r.intent.getComponent().flattenToShortString()); 3865 finishedTask = r.getTaskRecord(); 3866 int taskNdx = mTaskHistory.indexOf(finishedTask); 3867 final TaskRecord task = finishedTask; 3868 int activityNdx = task.mActivities.indexOf(r); 3869 getDisplay().mDisplayContent.prepareAppTransition( 3870 TRANSIT_CRASHING_ACTIVITY_CLOSE, false /* alwaysKeepCurrent */); 3871 finishActivityLocked(r, Activity.RESULT_CANCELED, null, reason, false); 3872 finishedTask = task; 3873 // Also terminate any activities below it that aren't yet 3874 // stopped, to avoid a situation where one will get 3875 // re-start our crashing activity once it gets resumed again. 3876 --activityNdx; 3877 if (activityNdx < 0) { 3878 do { 3879 --taskNdx; 3880 if (taskNdx < 0) { 3881 break; 3882 } 3883 activityNdx = mTaskHistory.get(taskNdx).mActivities.size() - 1; 3884 } while (activityNdx < 0); 3885 } 3886 if (activityNdx >= 0) { 3887 r = mTaskHistory.get(taskNdx).mActivities.get(activityNdx); 3888 if (r.isState(RESUMED, PAUSING, PAUSED)) { 3889 if (!r.isActivityTypeHome() || mService.mHomeProcess != r.app) { 3890 Slog.w(TAG, " Force finishing activity " 3891 + r.intent.getComponent().flattenToShortString()); 3892 finishActivityLocked(r, Activity.RESULT_CANCELED, null, reason, false); 3893 } 3894 } 3895 } 3896 return finishedTask; 3897 } 3898 finishVoiceTask(IVoiceInteractionSession session)3899 final void finishVoiceTask(IVoiceInteractionSession session) { 3900 IBinder sessionBinder = session.asBinder(); 3901 boolean didOne = false; 3902 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 3903 TaskRecord tr = mTaskHistory.get(taskNdx); 3904 if (tr.voiceSession != null && tr.voiceSession.asBinder() == sessionBinder) { 3905 for (int activityNdx = tr.mActivities.size() - 1; activityNdx >= 0; --activityNdx) { 3906 ActivityRecord r = tr.mActivities.get(activityNdx); 3907 if (!r.finishing) { 3908 finishActivityLocked(r, Activity.RESULT_CANCELED, null, "finish-voice", 3909 false); 3910 didOne = true; 3911 } 3912 } 3913 } else { 3914 // Check if any of the activities are using voice 3915 for (int activityNdx = tr.mActivities.size() - 1; activityNdx >= 0; --activityNdx) { 3916 ActivityRecord r = tr.mActivities.get(activityNdx); 3917 if (r.voiceSession != null && r.voiceSession.asBinder() == sessionBinder) { 3918 // Inform of cancellation 3919 r.clearVoiceSessionLocked(); 3920 try { 3921 r.app.getThread().scheduleLocalVoiceInteractionStarted( 3922 r.appToken, null); 3923 } catch (RemoteException re) { 3924 // Ok 3925 } 3926 mService.finishRunningVoiceLocked(); 3927 break; 3928 } 3929 } 3930 } 3931 } 3932 3933 if (didOne) { 3934 mService.updateOomAdj(); 3935 } 3936 } 3937 finishActivityAffinityLocked(ActivityRecord r)3938 final boolean finishActivityAffinityLocked(ActivityRecord r) { 3939 ArrayList<ActivityRecord> activities = r.getTaskRecord().mActivities; 3940 for (int index = activities.indexOf(r); index >= 0; --index) { 3941 ActivityRecord cur = activities.get(index); 3942 if (!Objects.equals(cur.taskAffinity, r.taskAffinity)) { 3943 break; 3944 } 3945 finishActivityLocked(cur, Activity.RESULT_CANCELED, null, "request-affinity", true); 3946 } 3947 return true; 3948 } 3949 finishActivityResultsLocked(ActivityRecord r, int resultCode, Intent resultData)3950 private void finishActivityResultsLocked(ActivityRecord r, int resultCode, Intent resultData) { 3951 // send the result 3952 ActivityRecord resultTo = r.resultTo; 3953 if (resultTo != null) { 3954 if (DEBUG_RESULTS) Slog.v(TAG_RESULTS, "Adding result to " + resultTo 3955 + " who=" + r.resultWho + " req=" + r.requestCode 3956 + " res=" + resultCode + " data=" + resultData); 3957 if (resultTo.mUserId != r.mUserId) { 3958 if (resultData != null) { 3959 resultData.prepareToLeaveUser(r.mUserId); 3960 } 3961 } 3962 if (r.info.applicationInfo.uid > 0) { 3963 mService.mUgmInternal.grantUriPermissionFromIntent(r.info.applicationInfo.uid, 3964 resultTo.packageName, resultData, 3965 resultTo.getUriPermissionsLocked(), resultTo.mUserId); 3966 } 3967 resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode, resultData); 3968 r.resultTo = null; 3969 } 3970 else if (DEBUG_RESULTS) Slog.v(TAG_RESULTS, "No result destination from " + r); 3971 3972 // Make sure this HistoryRecord is not holding on to other resources, 3973 // because clients have remote IPC references to this object so we 3974 // can't assume that will go away and want to avoid circular IPC refs. 3975 r.results = null; 3976 r.pendingResults = null; 3977 r.newIntents = null; 3978 r.icicle = null; 3979 } 3980 3981 /** 3982 * See {@link #finishActivityLocked(ActivityRecord, int, Intent, String, boolean, boolean)} 3983 */ finishActivityLocked(ActivityRecord r, int resultCode, Intent resultData, String reason, boolean oomAdj)3984 final boolean finishActivityLocked(ActivityRecord r, int resultCode, Intent resultData, 3985 String reason, boolean oomAdj) { 3986 return finishActivityLocked(r, resultCode, resultData, reason, oomAdj, !PAUSE_IMMEDIATELY); 3987 } 3988 3989 /** 3990 * @return Returns true if this activity has been removed from the history 3991 * list, or false if it is still in the list and will be removed later. 3992 */ finishActivityLocked(ActivityRecord r, int resultCode, Intent resultData, String reason, boolean oomAdj, boolean pauseImmediately)3993 final boolean finishActivityLocked(ActivityRecord r, int resultCode, Intent resultData, 3994 String reason, boolean oomAdj, boolean pauseImmediately) { 3995 if (r.finishing) { 3996 Slog.w(TAG, "Duplicate finish request for " + r); 3997 return false; 3998 } 3999 4000 mWindowManager.deferSurfaceLayout(); 4001 try { 4002 r.makeFinishingLocked(); 4003 final TaskRecord task = r.getTaskRecord(); 4004 EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY, 4005 r.mUserId, System.identityHashCode(r), 4006 task.taskId, r.shortComponentName, reason); 4007 final ArrayList<ActivityRecord> activities = task.mActivities; 4008 final int index = activities.indexOf(r); 4009 if (index < (activities.size() - 1)) { 4010 task.setFrontOfTask(); 4011 if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) { 4012 // If the caller asked that this activity (and all above it) 4013 // be cleared when the task is reset, don't lose that information, 4014 // but propagate it up to the next activity. 4015 ActivityRecord next = activities.get(index+1); 4016 next.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); 4017 } 4018 } 4019 4020 r.pauseKeyDispatchingLocked(); 4021 4022 adjustFocusedActivityStack(r, "finishActivity"); 4023 4024 finishActivityResultsLocked(r, resultCode, resultData); 4025 4026 final boolean endTask = index <= 0 && !task.isClearingToReuseTask(); 4027 final int transit = endTask ? TRANSIT_TASK_CLOSE : TRANSIT_ACTIVITY_CLOSE; 4028 if (mResumedActivity == r) { 4029 if (DEBUG_VISIBILITY || DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, 4030 "Prepare close transition: finishing " + r); 4031 if (endTask) { 4032 mService.getTaskChangeNotificationController().notifyTaskRemovalStarted( 4033 task.getTaskInfo()); 4034 } 4035 getDisplay().mDisplayContent.prepareAppTransition(transit, false); 4036 4037 // When finishing the activity pre-emptively take the snapshot before the app window 4038 // is marked as hidden and any configuration changes take place 4039 if (mWindowManager.mTaskSnapshotController != null) { 4040 final ArraySet<Task> tasks = Sets.newArraySet(task.mTask); 4041 mWindowManager.mTaskSnapshotController.snapshotTasks(tasks); 4042 mWindowManager.mTaskSnapshotController.addSkipClosingAppSnapshotTasks(tasks); 4043 } 4044 4045 // Tell window manager to prepare for this one to be removed. 4046 r.setVisibility(false); 4047 4048 if (mPausingActivity == null) { 4049 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish needs to pause: " + r); 4050 if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING, 4051 "finish() => pause with userLeaving=false"); 4052 startPausingLocked(false, false, null, pauseImmediately); 4053 } 4054 4055 if (endTask) { 4056 mService.getLockTaskController().clearLockedTask(task); 4057 } 4058 } else if (!r.isState(PAUSING)) { 4059 // If the activity is PAUSING, we will complete the finish once 4060 // it is done pausing; else we can just directly finish it here. 4061 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish not pausing: " + r); 4062 if (r.visible) { 4063 prepareActivityHideTransitionAnimation(r, transit); 4064 } 4065 4066 final int finishMode = (r.visible || r.nowVisible) ? FINISH_AFTER_VISIBLE 4067 : FINISH_AFTER_PAUSE; 4068 final boolean removedActivity = finishCurrentActivityLocked(r, finishMode, oomAdj, 4069 "finishActivityLocked") == null; 4070 4071 // The following code is an optimization. When the last non-task overlay activity 4072 // is removed from the task, we remove the entire task from the stack. However, 4073 // since that is done after the scheduled destroy callback from the activity, that 4074 // call to change the visibility of the task overlay activities would be out of 4075 // sync with the activitiy visibility being set for this finishing activity above. 4076 // In this case, we can set the visibility of all the task overlay activities when 4077 // we detect the last one is finishing to keep them in sync. 4078 if (task.onlyHasTaskOverlayActivities(true /* excludeFinishing */)) { 4079 for (ActivityRecord taskOverlay : task.mActivities) { 4080 if (!taskOverlay.mTaskOverlay) { 4081 continue; 4082 } 4083 prepareActivityHideTransitionAnimation(taskOverlay, transit); 4084 } 4085 } 4086 return removedActivity; 4087 } else { 4088 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish waiting for pause of: " + r); 4089 } 4090 4091 return false; 4092 } finally { 4093 mWindowManager.continueSurfaceLayout(); 4094 } 4095 } 4096 prepareActivityHideTransitionAnimation(ActivityRecord r, int transit)4097 private void prepareActivityHideTransitionAnimation(ActivityRecord r, int transit) { 4098 final DisplayContent dc = getDisplay().mDisplayContent; 4099 dc.prepareAppTransition(transit, false); 4100 r.setVisibility(false); 4101 dc.executeAppTransition(); 4102 } 4103 4104 static final int FINISH_IMMEDIATELY = 0; 4105 static final int FINISH_AFTER_PAUSE = 1; 4106 static final int FINISH_AFTER_VISIBLE = 2; 4107 finishCurrentActivityLocked(ActivityRecord r, int mode, boolean oomAdj, String reason)4108 final ActivityRecord finishCurrentActivityLocked(ActivityRecord r, int mode, boolean oomAdj, 4109 String reason) { 4110 // First things first: if this activity is currently visible, 4111 // and the resumed activity is not yet visible, then hold off on 4112 // finishing until the resumed one becomes visible. 4113 4114 // The activity that we are finishing may be over the lock screen. In this case, we do not 4115 // want to consider activities that cannot be shown on the lock screen as running and should 4116 // proceed with finishing the activity if there is no valid next top running activity. 4117 // Note that if this finishing activity is floating task, we don't need to wait the 4118 // next activity resume and can destroy it directly. 4119 final ActivityDisplay display = getDisplay(); 4120 final ActivityRecord next = display.topRunningActivity(true /* considerKeyguardState */); 4121 final boolean isFloating = r.getConfiguration().windowConfiguration.tasksAreFloating(); 4122 // isNextNotYetVisible is to check if the next activity is invisible, or it has been 4123 // requested to be invisible but its windows haven't reported as invisible. If so, it 4124 // implied that the current finishing activity should be added into stopping list rather 4125 // than destroying it immediately. 4126 final boolean isNextNotYetVisible = next != null && (!next.nowVisible || !next.visible); 4127 if (mode == FINISH_AFTER_VISIBLE && (r.visible || r.nowVisible) && isNextNotYetVisible 4128 && !isFloating) { 4129 if (!mStackSupervisor.mStoppingActivities.contains(r)) { 4130 addToStopping(r, false /* scheduleIdle */, false /* idleDelayed */, 4131 "finishCurrentActivityLocked"); 4132 } 4133 if (DEBUG_STATES) Slog.v(TAG_STATES, 4134 "Moving to STOPPING: "+ r + " (finish requested)"); 4135 r.setState(STOPPING, "finishCurrentActivityLocked"); 4136 if (oomAdj) { 4137 mService.updateOomAdj(); 4138 } 4139 return r; 4140 } 4141 4142 // make sure the record is cleaned out of other places. 4143 mStackSupervisor.mStoppingActivities.remove(r); 4144 mStackSupervisor.mGoingToSleepActivities.remove(r); 4145 final ActivityState prevState = r.getState(); 4146 if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to FINISHING: " + r); 4147 4148 r.setState(FINISHING, "finishCurrentActivityLocked"); 4149 4150 // Don't destroy activity immediately if the display contains home stack, although there is 4151 // no next activity at the moment but another home activity should be started later. Keep 4152 // this activity alive until next home activity is resumed then user won't see a temporary 4153 // black screen. 4154 final boolean noRunningStack = next == null && display.topRunningActivity() == null 4155 && display.getHomeStack() == null; 4156 final boolean noFocusedStack = r.getActivityStack() != display.getFocusedStack(); 4157 final boolean finishingInNonFocusedStackOrNoRunning = mode == FINISH_AFTER_VISIBLE 4158 && prevState == PAUSED && (noFocusedStack || noRunningStack); 4159 4160 if (mode == FINISH_IMMEDIATELY 4161 || (prevState == PAUSED 4162 && (mode == FINISH_AFTER_PAUSE || inPinnedWindowingMode())) 4163 || finishingInNonFocusedStackOrNoRunning 4164 || prevState == STOPPING 4165 || prevState == STOPPED 4166 || prevState == ActivityState.INITIALIZING) { 4167 r.makeFinishingLocked(); 4168 boolean activityRemoved = destroyActivityLocked(r, true, "finish-imm:" + reason); 4169 4170 if (finishingInNonFocusedStackOrNoRunning) { 4171 // Finishing activity that was in paused state and it was in not currently focused 4172 // stack, need to make something visible in its place. Also if the display does not 4173 // have running activity, the configuration may need to be updated for restoring 4174 // original orientation of the display. 4175 mRootActivityContainer.ensureVisibilityAndConfig(next, mDisplayId, 4176 false /* markFrozenIfConfigChanged */, true /* deferResume */); 4177 } 4178 if (activityRemoved) { 4179 mRootActivityContainer.resumeFocusedStacksTopActivities(); 4180 } 4181 if (DEBUG_CONTAINERS) Slog.d(TAG_CONTAINERS, 4182 "destroyActivityLocked: finishCurrentActivityLocked r=" + r + 4183 " destroy returned removed=" + activityRemoved); 4184 return activityRemoved ? null : r; 4185 } 4186 4187 // Need to go through the full pause cycle to get this 4188 // activity into the stopped state and then finish it. 4189 if (DEBUG_ALL) Slog.v(TAG, "Enqueueing pending finish: " + r); 4190 mStackSupervisor.mFinishingActivities.add(r); 4191 r.resumeKeyDispatchingLocked(); 4192 mRootActivityContainer.resumeFocusedStacksTopActivities(); 4193 // If activity was not paused at this point - explicitly pause it to start finishing 4194 // process. Finishing will be completed once it reports pause back. 4195 if (r.isState(RESUMED) && mPausingActivity != null) { 4196 startPausingLocked(false /* userLeaving */, false /* uiSleeping */, next /* resuming */, 4197 false /* dontWait */); 4198 } 4199 return r; 4200 } 4201 finishAllActivitiesLocked(boolean immediately)4202 void finishAllActivitiesLocked(boolean immediately) { 4203 boolean noActivitiesInStack = true; 4204 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 4205 final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities; 4206 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { 4207 final ActivityRecord r = activities.get(activityNdx); 4208 noActivitiesInStack = false; 4209 if (r.finishing && !immediately) { 4210 continue; 4211 } 4212 Slog.d(TAG, "finishAllActivitiesLocked: finishing " + r + " immediately"); 4213 finishCurrentActivityLocked(r, FINISH_IMMEDIATELY, false, 4214 "finishAllActivitiesLocked"); 4215 } 4216 } 4217 if (noActivitiesInStack) { 4218 remove(); 4219 } 4220 } 4221 4222 /** @return true if the stack behind this one is a standard activity type. */ inFrontOfStandardStack()4223 boolean inFrontOfStandardStack() { 4224 final ActivityDisplay display = getDisplay(); 4225 if (display == null) { 4226 return false; 4227 } 4228 final int index = display.getIndexOf(this); 4229 if (index == 0) { 4230 return false; 4231 } 4232 final ActivityStack stackBehind = display.getChildAt(index - 1); 4233 return stackBehind.isActivityTypeStandard(); 4234 } 4235 shouldUpRecreateTaskLocked(ActivityRecord srec, String destAffinity)4236 boolean shouldUpRecreateTaskLocked(ActivityRecord srec, String destAffinity) { 4237 // Basic case: for simple app-centric recents, we need to recreate 4238 // the task if the affinity has changed. 4239 if (srec == null || srec.getTaskRecord().affinity == null || 4240 !srec.getTaskRecord().affinity.equals(destAffinity)) { 4241 return true; 4242 } 4243 // Document-centric case: an app may be split in to multiple documents; 4244 // they need to re-create their task if this current activity is the root 4245 // of a document, unless simply finishing it will return them to the the 4246 // correct app behind. 4247 final TaskRecord task = srec.getTaskRecord(); 4248 if (srec.frontOfTask && task.getBaseIntent() != null && task.getBaseIntent().isDocument()) { 4249 // Okay, this activity is at the root of its task. What to do, what to do... 4250 if (!inFrontOfStandardStack()) { 4251 // Finishing won't return to an application, so we need to recreate. 4252 return true; 4253 } 4254 // We now need to get the task below it to determine what to do. 4255 int taskIdx = mTaskHistory.indexOf(task); 4256 if (taskIdx <= 0) { 4257 Slog.w(TAG, "shouldUpRecreateTask: task not in history for " + srec); 4258 return false; 4259 } 4260 final TaskRecord prevTask = mTaskHistory.get(taskIdx); 4261 if (!task.affinity.equals(prevTask.affinity)) { 4262 // These are different apps, so need to recreate. 4263 return true; 4264 } 4265 } 4266 return false; 4267 } 4268 navigateUpToLocked(ActivityRecord srec, Intent destIntent, int resultCode, Intent resultData)4269 final boolean navigateUpToLocked(ActivityRecord srec, Intent destIntent, int resultCode, 4270 Intent resultData) { 4271 if (!srec.attachedToProcess()) { 4272 // Nothing to do if the caller is not attached, because this method should be called 4273 // from an alive activity. 4274 return false; 4275 } 4276 final TaskRecord task = srec.getTaskRecord(); 4277 final ArrayList<ActivityRecord> activities = task.mActivities; 4278 final int start = activities.indexOf(srec); 4279 if (!mTaskHistory.contains(task) || (start < 0)) { 4280 return false; 4281 } 4282 int finishTo = start - 1; 4283 ActivityRecord parent = finishTo < 0 ? null : activities.get(finishTo); 4284 boolean foundParentInTask = false; 4285 final ComponentName dest = destIntent.getComponent(); 4286 if (start > 0 && dest != null) { 4287 for (int i = finishTo; i >= 0; i--) { 4288 ActivityRecord r = activities.get(i); 4289 if (r.info.packageName.equals(dest.getPackageName()) && 4290 r.info.name.equals(dest.getClassName())) { 4291 finishTo = i; 4292 parent = r; 4293 foundParentInTask = true; 4294 break; 4295 } 4296 } 4297 } 4298 4299 // TODO: There is a dup. of this block of code in ActivityTaskManagerService.finishActivity 4300 // We should consolidate. 4301 IActivityController controller = mService.mController; 4302 if (controller != null) { 4303 ActivityRecord next = topRunningActivityLocked(srec.appToken, 0); 4304 if (next != null) { 4305 // ask watcher if this is allowed 4306 boolean resumeOK = true; 4307 try { 4308 resumeOK = controller.activityResuming(next.packageName); 4309 } catch (RemoteException e) { 4310 mService.mController = null; 4311 Watchdog.getInstance().setActivityController(null); 4312 } 4313 4314 if (!resumeOK) { 4315 return false; 4316 } 4317 } 4318 } 4319 final long origId = Binder.clearCallingIdentity(); 4320 for (int i = start; i > finishTo; i--) { 4321 ActivityRecord r = activities.get(i); 4322 requestFinishActivityLocked(r.appToken, resultCode, resultData, "navigate-up", true); 4323 // Only return the supplied result for the first activity finished 4324 resultCode = Activity.RESULT_CANCELED; 4325 resultData = null; 4326 } 4327 4328 if (parent != null && foundParentInTask) { 4329 final int callingUid = srec.info.applicationInfo.uid; 4330 final int parentLaunchMode = parent.info.launchMode; 4331 final int destIntentFlags = destIntent.getFlags(); 4332 if (parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE || 4333 parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_TASK || 4334 parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_TOP || 4335 (destIntentFlags & Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) { 4336 parent.deliverNewIntentLocked(callingUid, destIntent, srec.packageName); 4337 } else { 4338 try { 4339 ActivityInfo aInfo = AppGlobals.getPackageManager().getActivityInfo( 4340 destIntent.getComponent(), ActivityManagerService.STOCK_PM_FLAGS, 4341 srec.mUserId); 4342 // TODO(b/64750076): Check if calling pid should really be -1. 4343 final int res = mService.getActivityStartController() 4344 .obtainStarter(destIntent, "navigateUpTo") 4345 .setCaller(srec.app.getThread()) 4346 .setActivityInfo(aInfo) 4347 .setResultTo(parent.appToken) 4348 .setCallingPid(-1) 4349 .setCallingUid(callingUid) 4350 .setCallingPackage(srec.packageName) 4351 .setRealCallingPid(-1) 4352 .setRealCallingUid(callingUid) 4353 .setComponentSpecified(true) 4354 .execute(); 4355 foundParentInTask = res == ActivityManager.START_SUCCESS; 4356 } catch (RemoteException e) { 4357 foundParentInTask = false; 4358 } 4359 requestFinishActivityLocked(parent.appToken, resultCode, 4360 resultData, "navigate-top", true); 4361 } 4362 } 4363 Binder.restoreCallingIdentity(origId); 4364 return foundParentInTask; 4365 } 4366 4367 /** 4368 * Remove any state associated with the {@link ActivityRecord}. This should be called whenever 4369 * an activity moves away from the stack. 4370 */ onActivityRemovedFromStack(ActivityRecord r)4371 void onActivityRemovedFromStack(ActivityRecord r) { 4372 removeTimeoutsForActivityLocked(r); 4373 4374 if (mResumedActivity != null && mResumedActivity == r) { 4375 setResumedActivity(null, "onActivityRemovedFromStack"); 4376 } 4377 if (mPausingActivity != null && mPausingActivity == r) { 4378 mPausingActivity = null; 4379 } 4380 } 4381 onActivityAddedToStack(ActivityRecord r)4382 void onActivityAddedToStack(ActivityRecord r) { 4383 if(r.getState() == RESUMED) { 4384 setResumedActivity(r, "onActivityAddedToStack"); 4385 } 4386 } 4387 4388 /** 4389 * Perform the common clean-up of an activity record. This is called both 4390 * as part of destroyActivityLocked() (when destroying the client-side 4391 * representation) and cleaning things up as a result of its hosting 4392 * processing going away, in which case there is no remaining client-side 4393 * state to destroy so only the cleanup here is needed. 4394 * 4395 * Note: Call before #removeActivityFromHistoryLocked. 4396 */ cleanUpActivityLocked(ActivityRecord r, boolean cleanServices, boolean setState)4397 private void cleanUpActivityLocked(ActivityRecord r, boolean cleanServices, boolean setState) { 4398 onActivityRemovedFromStack(r); 4399 4400 r.deferRelaunchUntilPaused = false; 4401 r.frozenBeforeDestroy = false; 4402 4403 if (setState) { 4404 if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to DESTROYED: " + r + " (cleaning up)"); 4405 r.setState(DESTROYED, "cleanupActivityLocked"); 4406 if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during cleanUp for activity " + r); 4407 r.app = null; 4408 } 4409 4410 // Inform supervisor the activity has been removed. 4411 mStackSupervisor.cleanupActivity(r); 4412 4413 4414 // Remove any pending results. 4415 if (r.finishing && r.pendingResults != null) { 4416 for (WeakReference<PendingIntentRecord> apr : r.pendingResults) { 4417 PendingIntentRecord rec = apr.get(); 4418 if (rec != null) { 4419 mService.mPendingIntentController.cancelIntentSender(rec, false); 4420 } 4421 } 4422 r.pendingResults = null; 4423 } 4424 4425 if (cleanServices) { 4426 cleanUpActivityServicesLocked(r); 4427 } 4428 4429 // Get rid of any pending idle timeouts. 4430 removeTimeoutsForActivityLocked(r); 4431 // Clean-up activities are no longer relaunching (e.g. app process died). Notify window 4432 // manager so it can update its bookkeeping. 4433 mWindowManager.notifyAppRelaunchesCleared(r.appToken); 4434 } 4435 removeTimeoutsForActivityLocked(ActivityRecord r)4436 private void removeTimeoutsForActivityLocked(ActivityRecord r) { 4437 mStackSupervisor.removeTimeoutsForActivityLocked(r); 4438 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r); 4439 mHandler.removeMessages(STOP_TIMEOUT_MSG, r); 4440 mHandler.removeMessages(DESTROY_TIMEOUT_MSG, r); 4441 r.finishLaunchTickingLocked(); 4442 } 4443 removeActivityFromHistoryLocked(ActivityRecord r, String reason)4444 private void removeActivityFromHistoryLocked(ActivityRecord r, String reason) { 4445 finishActivityResultsLocked(r, Activity.RESULT_CANCELED, null); 4446 r.makeFinishingLocked(); 4447 if (DEBUG_ADD_REMOVE) Slog.i(TAG_ADD_REMOVE, 4448 "Removing activity " + r + " from stack callers=" + Debug.getCallers(5)); 4449 4450 r.takeFromHistory(); 4451 removeTimeoutsForActivityLocked(r); 4452 if (DEBUG_STATES) Slog.v(TAG_STATES, 4453 "Moving to DESTROYED: " + r + " (removed from history)"); 4454 r.setState(DESTROYED, "removeActivityFromHistoryLocked"); 4455 if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during remove for activity " + r); 4456 r.app = null; 4457 r.removeWindowContainer(); 4458 final TaskRecord task = r.getTaskRecord(); 4459 final boolean lastActivity = task != null ? task.removeActivity(r) : false; 4460 // If we are removing the last activity in the task, not including task overlay activities, 4461 // then fall through into the block below to remove the entire task itself 4462 final boolean onlyHasTaskOverlays = task != null 4463 ? task.onlyHasTaskOverlayActivities(false /* excludingFinishing */) : false; 4464 4465 if (lastActivity || onlyHasTaskOverlays) { 4466 if (DEBUG_STACK) { 4467 Slog.i(TAG_STACK, 4468 "removeActivityFromHistoryLocked: last activity removed from " + this 4469 + " onlyHasTaskOverlays=" + onlyHasTaskOverlays); 4470 } 4471 4472 // The following block can be executed multiple times if there is more than one overlay. 4473 // {@link ActivityStackSupervisor#removeTaskByIdLocked} handles this by reverse lookup 4474 // of the task by id and exiting early if not found. 4475 if (onlyHasTaskOverlays) { 4476 // When destroying a task, tell the supervisor to remove it so that any activity it 4477 // has can be cleaned up correctly. This is currently the only place where we remove 4478 // a task with the DESTROYING mode, so instead of passing the onlyHasTaskOverlays 4479 // state into removeTask(), we just clear the task here before the other residual 4480 // work. 4481 // TODO: If the callers to removeTask() changes such that we have multiple places 4482 // where we are destroying the task, move this back into removeTask() 4483 mStackSupervisor.removeTaskByIdLocked(task.taskId, false /* killProcess */, 4484 !REMOVE_FROM_RECENTS, PAUSE_IMMEDIATELY, reason); 4485 } 4486 4487 // We must keep the task around until all activities are destroyed. The following 4488 // statement will only execute once since overlays are also considered activities. 4489 if (lastActivity) { 4490 removeTask(task, reason, REMOVE_TASK_MODE_DESTROYING); 4491 } 4492 } 4493 cleanUpActivityServicesLocked(r); 4494 r.removeUriPermissionsLocked(); 4495 } 4496 4497 /** 4498 * Perform clean-up of service connections in an activity record. 4499 */ cleanUpActivityServicesLocked(ActivityRecord r)4500 private void cleanUpActivityServicesLocked(ActivityRecord r) { 4501 if (r.mServiceConnectionsHolder == null) { 4502 return; 4503 } 4504 // Throw away any services that have been bound by this activity. 4505 r.mServiceConnectionsHolder.disconnectActivityFromServices(); 4506 } 4507 scheduleDestroyActivities(WindowProcessController owner, String reason)4508 final void scheduleDestroyActivities(WindowProcessController owner, String reason) { 4509 Message msg = mHandler.obtainMessage(DESTROY_ACTIVITIES_MSG); 4510 msg.obj = new ScheduleDestroyArgs(owner, reason); 4511 mHandler.sendMessage(msg); 4512 } 4513 destroyActivitiesLocked(WindowProcessController owner, String reason)4514 private void destroyActivitiesLocked(WindowProcessController owner, String reason) { 4515 boolean lastIsOpaque = false; 4516 boolean activityRemoved = false; 4517 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 4518 final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities; 4519 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { 4520 final ActivityRecord r = activities.get(activityNdx); 4521 if (r.finishing) { 4522 continue; 4523 } 4524 if (r.fullscreen) { 4525 lastIsOpaque = true; 4526 } 4527 if (owner != null && r.app != owner) { 4528 continue; 4529 } 4530 if (!lastIsOpaque) { 4531 continue; 4532 } 4533 if (r.isDestroyable()) { 4534 if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Destroying " + r 4535 + " in state " + r.getState() 4536 + " resumed=" + mResumedActivity 4537 + " pausing=" + mPausingActivity + " for reason " + reason); 4538 if (destroyActivityLocked(r, true, reason)) { 4539 activityRemoved = true; 4540 } 4541 } 4542 } 4543 } 4544 if (activityRemoved) { 4545 mRootActivityContainer.resumeFocusedStacksTopActivities(); 4546 } 4547 } 4548 safelyDestroyActivityLocked(ActivityRecord r, String reason)4549 final boolean safelyDestroyActivityLocked(ActivityRecord r, String reason) { 4550 if (r.isDestroyable()) { 4551 if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, 4552 "Destroying " + r + " in state " + r.getState() + " resumed=" + mResumedActivity 4553 + " pausing=" + mPausingActivity + " for reason " + reason); 4554 return destroyActivityLocked(r, true, reason); 4555 } 4556 return false; 4557 } 4558 releaseSomeActivitiesLocked(WindowProcessController app, ArraySet<TaskRecord> tasks, String reason)4559 final int releaseSomeActivitiesLocked(WindowProcessController app, ArraySet<TaskRecord> tasks, 4560 String reason) { 4561 // Iterate over tasks starting at the back (oldest) first. 4562 if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Trying to release some activities in " + app); 4563 int maxTasks = tasks.size() / 4; 4564 if (maxTasks < 1) { 4565 maxTasks = 1; 4566 } 4567 int numReleased = 0; 4568 for (int taskNdx = 0; taskNdx < mTaskHistory.size() && maxTasks > 0; taskNdx++) { 4569 final TaskRecord task = mTaskHistory.get(taskNdx); 4570 if (!tasks.contains(task)) { 4571 continue; 4572 } 4573 if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Looking for activities to release in " + task); 4574 int curNum = 0; 4575 final ArrayList<ActivityRecord> activities = task.mActivities; 4576 for (int actNdx = 0; actNdx < activities.size(); actNdx++) { 4577 final ActivityRecord activity = activities.get(actNdx); 4578 if (activity.app == app && activity.isDestroyable()) { 4579 if (DEBUG_RELEASE) Slog.v(TAG_RELEASE, "Destroying " + activity 4580 + " in state " + activity.getState() + " resumed=" + mResumedActivity 4581 + " pausing=" + mPausingActivity + " for reason " + reason); 4582 destroyActivityLocked(activity, true, reason); 4583 if (activities.get(actNdx) != activity) { 4584 // Was removed from list, back up so we don't miss the next one. 4585 actNdx--; 4586 } 4587 curNum++; 4588 } 4589 } 4590 if (curNum > 0) { 4591 numReleased += curNum; 4592 maxTasks--; 4593 if (mTaskHistory.get(taskNdx) != task) { 4594 // The entire task got removed, back up so we don't miss the next one. 4595 taskNdx--; 4596 } 4597 } 4598 } 4599 if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, 4600 "Done releasing: did " + numReleased + " activities"); 4601 return numReleased; 4602 } 4603 4604 /** 4605 * Destroy the current CLIENT SIDE instance of an activity. This may be 4606 * called both when actually finishing an activity, or when performing 4607 * a configuration switch where we destroy the current client-side object 4608 * but then create a new client-side object for this same HistoryRecord. 4609 */ destroyActivityLocked(ActivityRecord r, boolean removeFromApp, String reason)4610 final boolean destroyActivityLocked(ActivityRecord r, boolean removeFromApp, String reason) { 4611 if (DEBUG_SWITCH || DEBUG_CLEANUP) Slog.v(TAG_SWITCH, 4612 "Removing activity from " + reason + ": token=" + r 4613 + ", app=" + (r.hasProcess() ? r.app.mName : "(null)")); 4614 4615 if (r.isState(DESTROYING, DESTROYED)) { 4616 if (DEBUG_STATES) Slog.v(TAG_STATES, "activity " + r + " already destroying." 4617 + "skipping request with reason:" + reason); 4618 return false; 4619 } 4620 4621 EventLog.writeEvent(EventLogTags.AM_DESTROY_ACTIVITY, 4622 r.mUserId, System.identityHashCode(r), 4623 r.getTaskRecord().taskId, r.shortComponentName, reason); 4624 4625 boolean removedFromHistory = false; 4626 4627 cleanUpActivityLocked(r, false, false); 4628 4629 final boolean hadApp = r.hasProcess(); 4630 4631 if (hadApp) { 4632 if (removeFromApp) { 4633 r.app.removeActivity(r); 4634 if (!r.app.hasActivities()) { 4635 mService.clearHeavyWeightProcessIfEquals(r.app); 4636 } 4637 if (!r.app.hasActivities()) { 4638 // Update any services we are bound to that might care about whether 4639 // their client may have activities. 4640 // No longer have activities, so update LRU list and oom adj. 4641 r.app.updateProcessInfo(true /* updateServiceConnectionActivities */, 4642 false /* activityChange */, true /* updateOomAdj */); 4643 } 4644 } 4645 4646 boolean skipDestroy = false; 4647 4648 try { 4649 if (DEBUG_SWITCH) Slog.i(TAG_SWITCH, "Destroying: " + r); 4650 mService.getLifecycleManager().scheduleTransaction(r.app.getThread(), r.appToken, 4651 DestroyActivityItem.obtain(r.finishing, r.configChangeFlags)); 4652 } catch (Exception e) { 4653 // We can just ignore exceptions here... if the process 4654 // has crashed, our death notification will clean things 4655 // up. 4656 //Slog.w(TAG, "Exception thrown during finish", e); 4657 if (r.finishing) { 4658 removeActivityFromHistoryLocked(r, reason + " exceptionInScheduleDestroy"); 4659 removedFromHistory = true; 4660 skipDestroy = true; 4661 } 4662 } 4663 4664 r.nowVisible = false; 4665 4666 // If the activity is finishing, we need to wait on removing it 4667 // from the list to give it a chance to do its cleanup. During 4668 // that time it may make calls back with its token so we need to 4669 // be able to find it on the list and so we don't want to remove 4670 // it from the list yet. Otherwise, we can just immediately put 4671 // it in the destroyed state since we are not removing it from the 4672 // list. 4673 if (r.finishing && !skipDestroy) { 4674 if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to DESTROYING: " + r 4675 + " (destroy requested)"); 4676 r.setState(DESTROYING, 4677 "destroyActivityLocked. finishing and not skipping destroy"); 4678 Message msg = mHandler.obtainMessage(DESTROY_TIMEOUT_MSG, r); 4679 mHandler.sendMessageDelayed(msg, DESTROY_TIMEOUT); 4680 } else { 4681 if (DEBUG_STATES) Slog.v(TAG_STATES, 4682 "Moving to DESTROYED: " + r + " (destroy skipped)"); 4683 r.setState(DESTROYED, 4684 "destroyActivityLocked. not finishing or skipping destroy"); 4685 if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during destroy for activity " + r); 4686 r.app = null; 4687 } 4688 } else { 4689 // remove this record from the history. 4690 if (r.finishing) { 4691 removeActivityFromHistoryLocked(r, reason + " hadNoApp"); 4692 removedFromHistory = true; 4693 } else { 4694 if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to DESTROYED: " + r + " (no app)"); 4695 r.setState(DESTROYED, "destroyActivityLocked. not finishing and had no app"); 4696 if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during destroy for activity " + r); 4697 r.app = null; 4698 } 4699 } 4700 4701 r.configChangeFlags = 0; 4702 4703 if (!mLRUActivities.remove(r) && hadApp) { 4704 Slog.w(TAG, "Activity " + r + " being finished, but not in LRU list"); 4705 } 4706 4707 return removedFromHistory; 4708 } 4709 activityDestroyedLocked(IBinder token, String reason)4710 final void activityDestroyedLocked(IBinder token, String reason) { 4711 final long origId = Binder.clearCallingIdentity(); 4712 try { 4713 activityDestroyedLocked(ActivityRecord.forTokenLocked(token), reason); 4714 } finally { 4715 Binder.restoreCallingIdentity(origId); 4716 } 4717 } 4718 4719 /** 4720 * This method is to only be called from the client via binder when the activity is destroyed 4721 * AND finished. 4722 */ activityDestroyedLocked(ActivityRecord record, String reason)4723 final void activityDestroyedLocked(ActivityRecord record, String reason) { 4724 if (record != null) { 4725 mHandler.removeMessages(DESTROY_TIMEOUT_MSG, record); 4726 } 4727 4728 if (DEBUG_CONTAINERS) Slog.d(TAG_CONTAINERS, "activityDestroyedLocked: r=" + record); 4729 4730 if (isInStackLocked(record) != null) { 4731 if (record.isState(DESTROYING, DESTROYED)) { 4732 cleanUpActivityLocked(record, true, false); 4733 removeActivityFromHistoryLocked(record, reason); 4734 } 4735 } 4736 4737 mRootActivityContainer.resumeFocusedStacksTopActivities(); 4738 } 4739 removeHistoryRecordsForAppLocked(ArrayList<ActivityRecord> list, WindowProcessController app, String listName)4740 private void removeHistoryRecordsForAppLocked(ArrayList<ActivityRecord> list, 4741 WindowProcessController app, String listName) { 4742 int i = list.size(); 4743 if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP, 4744 "Removing app " + app + " from list " + listName + " with " + i + " entries"); 4745 while (i > 0) { 4746 i--; 4747 ActivityRecord r = list.get(i); 4748 if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP, "Record #" + i + " " + r); 4749 if (r.app == app) { 4750 if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP, "---> REMOVING this entry!"); 4751 list.remove(i); 4752 removeTimeoutsForActivityLocked(r); 4753 } 4754 } 4755 } 4756 removeHistoryRecordsForAppLocked(WindowProcessController app)4757 private boolean removeHistoryRecordsForAppLocked(WindowProcessController app) { 4758 removeHistoryRecordsForAppLocked(mLRUActivities, app, "mLRUActivities"); 4759 removeHistoryRecordsForAppLocked(mStackSupervisor.mStoppingActivities, app, 4760 "mStoppingActivities"); 4761 removeHistoryRecordsForAppLocked(mStackSupervisor.mGoingToSleepActivities, app, 4762 "mGoingToSleepActivities"); 4763 removeHistoryRecordsForAppLocked(mStackSupervisor.mFinishingActivities, app, 4764 "mFinishingActivities"); 4765 4766 final boolean isProcessRemoved = app.isRemoved(); 4767 if (isProcessRemoved) { 4768 // The package of the died process should be force-stopped, so make its activities as 4769 // finishing to prevent the process from being started again if the next top (or being 4770 // visible) activity also resides in the same process. 4771 app.makeFinishingForProcessRemoved(); 4772 } 4773 4774 boolean hasVisibleActivities = false; 4775 4776 // Clean out the history list. 4777 int i = numActivities(); 4778 if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP, 4779 "Removing app " + app + " from history with " + i + " entries"); 4780 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 4781 final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities; 4782 mTmpActivities.clear(); 4783 mTmpActivities.addAll(activities); 4784 4785 while (!mTmpActivities.isEmpty()) { 4786 final int targetIndex = mTmpActivities.size() - 1; 4787 final ActivityRecord r = mTmpActivities.remove(targetIndex); 4788 if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP, 4789 "Record #" + targetIndex + " " + r + ": app=" + r.app); 4790 4791 if (r.app == app) { 4792 if (r.visible) { 4793 hasVisibleActivities = true; 4794 } 4795 final boolean remove; 4796 if ((r.mRelaunchReason == RELAUNCH_REASON_WINDOWING_MODE_RESIZE 4797 || r.mRelaunchReason == RELAUNCH_REASON_FREE_RESIZE) 4798 && r.launchCount < 3 && !r.finishing) { 4799 // If the process crashed during a resize, always try to relaunch it, unless 4800 // it has failed more than twice. Skip activities that's already finishing 4801 // cleanly by itself. 4802 remove = false; 4803 } else if ((!r.haveState && !r.stateNotNeeded 4804 && !r.isState(ActivityState.RESTARTING_PROCESS)) || r.finishing) { 4805 // Don't currently have state for the activity, or 4806 // it is finishing -- always remove it. 4807 remove = true; 4808 } else if (!r.visible && r.launchCount > 2 && 4809 r.lastLaunchTime > (SystemClock.uptimeMillis() - 60000)) { 4810 // We have launched this activity too many times since it was 4811 // able to run, so give up and remove it. 4812 // (Note if the activity is visible, we don't remove the record. 4813 // We leave the dead window on the screen but the process will 4814 // not be restarted unless user explicitly tap on it.) 4815 remove = true; 4816 } else { 4817 // The process may be gone, but the activity lives on! 4818 remove = false; 4819 } 4820 if (remove) { 4821 if (DEBUG_ADD_REMOVE || DEBUG_CLEANUP) Slog.i(TAG_ADD_REMOVE, 4822 "Removing activity " + r + " from stack at " + i 4823 + ": haveState=" + r.haveState 4824 + " stateNotNeeded=" + r.stateNotNeeded 4825 + " finishing=" + r.finishing 4826 + " state=" + r.getState() + " callers=" + Debug.getCallers(5)); 4827 if (!r.finishing || isProcessRemoved) { 4828 Slog.w(TAG, "Force removing " + r + ": app died, no saved state"); 4829 EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY, 4830 r.mUserId, System.identityHashCode(r), 4831 r.getTaskRecord().taskId, r.shortComponentName, 4832 "proc died without state saved"); 4833 } 4834 } else { 4835 // We have the current state for this activity, so 4836 // it can be restarted later when needed. 4837 if (DEBUG_ALL) Slog.v(TAG, "Keeping entry, setting app to null"); 4838 if (DEBUG_APP) Slog.v(TAG_APP, 4839 "Clearing app during removeHistory for activity " + r); 4840 r.app = null; 4841 // Set nowVisible to previous visible state. If the app was visible while 4842 // it died, we leave the dead window on screen so it's basically visible. 4843 // This is needed when user later tap on the dead window, we need to stop 4844 // other apps when user transfers focus to the restarted activity. 4845 r.nowVisible = r.visible; 4846 if (!r.haveState) { 4847 if (DEBUG_SAVED_STATE) Slog.i(TAG_SAVED_STATE, 4848 "App died, clearing saved state of " + r); 4849 r.icicle = null; 4850 } 4851 } 4852 cleanUpActivityLocked(r, true, true); 4853 if (remove) { 4854 removeActivityFromHistoryLocked(r, "appDied"); 4855 } 4856 } 4857 } 4858 } 4859 4860 return hasVisibleActivities; 4861 } 4862 updateTransitLocked(int transit, ActivityOptions options)4863 private void updateTransitLocked(int transit, ActivityOptions options) { 4864 if (options != null) { 4865 ActivityRecord r = topRunningActivityLocked(); 4866 if (r != null && !r.isState(RESUMED)) { 4867 r.updateOptionsLocked(options); 4868 } else { 4869 ActivityOptions.abort(options); 4870 } 4871 } 4872 getDisplay().mDisplayContent.prepareAppTransition(transit, false); 4873 } 4874 updateTaskMovement(TaskRecord task, boolean toFront)4875 private void updateTaskMovement(TaskRecord task, boolean toFront) { 4876 if (task.isPersistable) { 4877 task.mLastTimeMoved = System.currentTimeMillis(); 4878 // Sign is used to keep tasks sorted when persisted. Tasks sent to the bottom most 4879 // recently will be most negative, tasks sent to the bottom before that will be less 4880 // negative. Similarly for recent tasks moved to the top which will be most positive. 4881 if (!toFront) { 4882 task.mLastTimeMoved *= -1; 4883 } 4884 } 4885 mRootActivityContainer.invalidateTaskLayers(); 4886 } 4887 moveTaskToFrontLocked(TaskRecord tr, boolean noAnimation, ActivityOptions options, AppTimeTracker timeTracker, String reason)4888 final void moveTaskToFrontLocked(TaskRecord tr, boolean noAnimation, ActivityOptions options, 4889 AppTimeTracker timeTracker, String reason) { 4890 if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "moveTaskToFront: " + tr); 4891 4892 final ActivityStack topStack = getDisplay().getTopStack(); 4893 final ActivityRecord topActivity = topStack != null ? topStack.getTopActivity() : null; 4894 final int numTasks = mTaskHistory.size(); 4895 final int index = mTaskHistory.indexOf(tr); 4896 if (numTasks == 0 || index < 0) { 4897 // nothing to do! 4898 if (noAnimation) { 4899 ActivityOptions.abort(options); 4900 } else { 4901 updateTransitLocked(TRANSIT_TASK_TO_FRONT, options); 4902 } 4903 return; 4904 } 4905 4906 if (timeTracker != null) { 4907 // The caller wants a time tracker associated with this task. 4908 for (int i = tr.mActivities.size() - 1; i >= 0; i--) { 4909 tr.mActivities.get(i).appTimeTracker = timeTracker; 4910 } 4911 } 4912 4913 try { 4914 // Defer updating the IME target since the new IME target will try to get computed 4915 // before updating all closing and opening apps, which can cause the ime target to 4916 // get calculated incorrectly. 4917 getDisplay().deferUpdateImeTarget(); 4918 4919 // Shift all activities with this task up to the top 4920 // of the stack, keeping them in the same internal order. 4921 insertTaskAtTop(tr, null); 4922 4923 // Don't refocus if invisible to current user 4924 final ActivityRecord top = tr.getTopActivity(); 4925 if (top == null || !top.okToShowLocked()) { 4926 if (top != null) { 4927 mStackSupervisor.mRecentTasks.add(top.getTaskRecord()); 4928 } 4929 ActivityOptions.abort(options); 4930 return; 4931 } 4932 4933 // Set focus to the top running activity of this stack. 4934 final ActivityRecord r = topRunningActivityLocked(); 4935 if (r != null) { 4936 r.moveFocusableActivityToTop(reason); 4937 } 4938 4939 if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare to front transition: task=" + tr); 4940 if (noAnimation) { 4941 getDisplay().mDisplayContent.prepareAppTransition(TRANSIT_NONE, false); 4942 if (r != null) { 4943 mStackSupervisor.mNoAnimActivities.add(r); 4944 } 4945 ActivityOptions.abort(options); 4946 } else { 4947 updateTransitLocked(TRANSIT_TASK_TO_FRONT, options); 4948 } 4949 // If a new task is moved to the front, then mark the existing top activity as 4950 // supporting 4951 4952 // picture-in-picture while paused only if the task would not be considered an oerlay 4953 // on top 4954 // of the current activity (eg. not fullscreen, or the assistant) 4955 if (canEnterPipOnTaskSwitch(topActivity, tr, null /* toFrontActivity */, 4956 options)) { 4957 topActivity.supportsEnterPipOnTaskSwitch = true; 4958 } 4959 4960 mRootActivityContainer.resumeFocusedStacksTopActivities(); 4961 EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, tr.userId, tr.taskId); 4962 mService.getTaskChangeNotificationController().notifyTaskMovedToFront(tr.getTaskInfo()); 4963 } finally { 4964 getDisplay().continueUpdateImeTarget(); 4965 } 4966 } 4967 4968 /** 4969 * Worker method for rearranging history stack. Implements the function of moving all 4970 * activities for a specific task (gathering them if disjoint) into a single group at the 4971 * bottom of the stack. 4972 * 4973 * If a watcher is installed, the action is preflighted and the watcher has an opportunity 4974 * to premeptively cancel the move. 4975 * 4976 * @param taskId The taskId to collect and move to the bottom. 4977 * @return Returns true if the move completed, false if not. 4978 */ moveTaskToBackLocked(int taskId)4979 final boolean moveTaskToBackLocked(int taskId) { 4980 final TaskRecord tr = taskForIdLocked(taskId); 4981 if (tr == null) { 4982 Slog.i(TAG, "moveTaskToBack: bad taskId=" + taskId); 4983 return false; 4984 } 4985 Slog.i(TAG, "moveTaskToBack: " + tr); 4986 4987 // In LockTask mode, moving a locked task to the back of the stack may expose unlocked 4988 // ones. Therefore we need to check if this operation is allowed. 4989 if (!mService.getLockTaskController().canMoveTaskToBack(tr)) { 4990 return false; 4991 } 4992 4993 // If we have a watcher, preflight the move before committing to it. First check 4994 // for *other* available tasks, but if none are available, then try again allowing the 4995 // current task to be selected. 4996 if (isTopStackOnDisplay() && mService.mController != null) { 4997 ActivityRecord next = topRunningActivityLocked(null, taskId); 4998 if (next == null) { 4999 next = topRunningActivityLocked(null, 0); 5000 } 5001 if (next != null) { 5002 // ask watcher if this is allowed 5003 boolean moveOK = true; 5004 try { 5005 moveOK = mService.mController.activityResuming(next.packageName); 5006 } catch (RemoteException e) { 5007 mService.mController = null; 5008 Watchdog.getInstance().setActivityController(null); 5009 } 5010 if (!moveOK) { 5011 return false; 5012 } 5013 } 5014 } 5015 5016 if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare to back transition: task=" + taskId); 5017 5018 mTaskHistory.remove(tr); 5019 mTaskHistory.add(0, tr); 5020 updateTaskMovement(tr, false); 5021 5022 getDisplay().mDisplayContent.prepareAppTransition(TRANSIT_TASK_TO_BACK, false); 5023 moveToBack("moveTaskToBackLocked", tr); 5024 5025 if (inPinnedWindowingMode()) { 5026 mStackSupervisor.removeStack(this); 5027 return true; 5028 } 5029 5030 ActivityRecord topActivity = getDisplay().topRunningActivity(); 5031 ActivityStack topStack = topActivity.getActivityStack(); 5032 if (topStack != null && topStack != this && topActivity.isState(RESUMED)) { 5033 // The new top activity is already resumed, so there's a good chance that nothing will 5034 // get resumed below. So, update visibility now in case the transition is closed 5035 // prematurely. 5036 mRootActivityContainer.ensureVisibilityAndConfig(null /* starting */, 5037 getDisplay().mDisplayId, false /* markFrozenIfConfigChanged */, 5038 false /* deferResume */); 5039 } 5040 5041 mRootActivityContainer.resumeFocusedStacksTopActivities(); 5042 return true; 5043 } 5044 logStartActivity(int tag, ActivityRecord r, TaskRecord task)5045 static void logStartActivity(int tag, ActivityRecord r, TaskRecord task) { 5046 final Uri data = r.intent.getData(); 5047 final String strData = data != null ? data.toSafeString() : null; 5048 5049 EventLog.writeEvent(tag, 5050 r.mUserId, System.identityHashCode(r), task.taskId, 5051 r.shortComponentName, r.intent.getAction(), 5052 r.intent.getType(), strData, r.intent.getFlags()); 5053 } 5054 5055 /** 5056 * Ensures all visible activities at or below the input activity have the right configuration. 5057 */ ensureVisibleActivitiesConfigurationLocked(ActivityRecord start, boolean preserveWindow)5058 void ensureVisibleActivitiesConfigurationLocked(ActivityRecord start, boolean preserveWindow) { 5059 if (start == null || !start.visible) { 5060 return; 5061 } 5062 5063 final TaskRecord startTask = start.getTaskRecord(); 5064 boolean behindFullscreen = false; 5065 boolean updatedConfig = false; 5066 5067 for (int taskIndex = mTaskHistory.indexOf(startTask); taskIndex >= 0; --taskIndex) { 5068 final TaskRecord task = mTaskHistory.get(taskIndex); 5069 final ArrayList<ActivityRecord> activities = task.mActivities; 5070 int activityIndex = (start.getTaskRecord() == task) 5071 ? activities.indexOf(start) : activities.size() - 1; 5072 for (; activityIndex >= 0; --activityIndex) { 5073 final ActivityRecord r = activities.get(activityIndex); 5074 updatedConfig |= r.ensureActivityConfiguration(0 /* globalChanges */, 5075 preserveWindow); 5076 if (r.fullscreen) { 5077 behindFullscreen = true; 5078 break; 5079 } 5080 } 5081 if (behindFullscreen) { 5082 break; 5083 } 5084 } 5085 if (updatedConfig) { 5086 // Ensure the resumed state of the focus activity if we updated the configuration of 5087 // any activity. 5088 mRootActivityContainer.resumeFocusedStacksTopActivities(); 5089 } 5090 } 5091 5092 // TODO: Figure-out a way to consolidate with resize() method below. requestResize(Rect bounds)5093 void requestResize(Rect bounds) { 5094 mService.resizeStack(mStackId, bounds, 5095 true /* allowResizeInDockedMode */, false /* preserveWindows */, 5096 false /* animate */, -1 /* animationDuration */); 5097 } 5098 5099 // TODO: Can only be called from special methods in ActivityStackSupervisor. 5100 // Need to consolidate those calls points into this resize method so anyone can call directly. resize(Rect bounds, Rect tempTaskBounds, Rect tempTaskInsetBounds)5101 void resize(Rect bounds, Rect tempTaskBounds, Rect tempTaskInsetBounds) { 5102 if (!updateBoundsAllowed(bounds)) { 5103 return; 5104 } 5105 5106 // Update override configurations of all tasks in the stack. 5107 final Rect taskBounds = tempTaskBounds != null ? tempTaskBounds : bounds; 5108 5109 for (int i = mTaskHistory.size() - 1; i >= 0; i--) { 5110 final TaskRecord task = mTaskHistory.get(i); 5111 if (task.isResizeable()) { 5112 task.updateOverrideConfiguration(taskBounds, tempTaskInsetBounds); 5113 } 5114 } 5115 5116 setBounds(bounds); 5117 } 5118 onPipAnimationEndResize()5119 void onPipAnimationEndResize() { 5120 if (mTaskStack == null) return; 5121 mTaskStack.onPipAnimationEndResize(); 5122 } 5123 5124 5125 /** 5126 * Until we can break this "set task bounds to same as stack bounds" behavior, this 5127 * basically resizes both stack and task bounds to the same bounds. 5128 */ setTaskBounds(Rect bounds)5129 void setTaskBounds(Rect bounds) { 5130 if (!updateBoundsAllowed(bounds)) { 5131 return; 5132 } 5133 5134 for (int i = mTaskHistory.size() - 1; i >= 0; i--) { 5135 final TaskRecord task = mTaskHistory.get(i); 5136 if (task.isResizeable()) { 5137 task.setBounds(bounds); 5138 } else { 5139 task.setBounds(null); 5140 } 5141 } 5142 } 5143 5144 /** Helper to setDisplayedBounds on all child tasks */ setTaskDisplayedBounds(Rect bounds)5145 void setTaskDisplayedBounds(Rect bounds) { 5146 if (!updateDisplayedBoundsAllowed(bounds)) { 5147 return; 5148 } 5149 5150 for (int i = mTaskHistory.size() - 1; i >= 0; i--) { 5151 final TaskRecord task = mTaskHistory.get(i); 5152 if (bounds == null || bounds.isEmpty()) { 5153 task.setDisplayedBounds(null); 5154 } else if (task.isResizeable()) { 5155 task.setDisplayedBounds(bounds); 5156 } 5157 } 5158 } 5159 willActivityBeVisibleLocked(IBinder token)5160 boolean willActivityBeVisibleLocked(IBinder token) { 5161 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 5162 final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities; 5163 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { 5164 final ActivityRecord r = activities.get(activityNdx); 5165 if (r.appToken == token) { 5166 return true; 5167 } 5168 if (r.fullscreen && !r.finishing) { 5169 return false; 5170 } 5171 } 5172 } 5173 final ActivityRecord r = ActivityRecord.forTokenLocked(token); 5174 if (r == null) { 5175 return false; 5176 } 5177 if (r.finishing) Slog.e(TAG, "willActivityBeVisibleLocked: Returning false," 5178 + " would have returned true for r=" + r); 5179 return !r.finishing; 5180 } 5181 closeSystemDialogsLocked()5182 void closeSystemDialogsLocked() { 5183 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 5184 final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities; 5185 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { 5186 final ActivityRecord r = activities.get(activityNdx); 5187 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) { 5188 finishActivityLocked(r, Activity.RESULT_CANCELED, null, "close-sys", true); 5189 } 5190 } 5191 } 5192 } 5193 finishDisabledPackageActivitiesLocked(String packageName, Set<String> filterByClasses, boolean doit, boolean evenPersistent, int userId)5194 boolean finishDisabledPackageActivitiesLocked(String packageName, Set<String> filterByClasses, 5195 boolean doit, boolean evenPersistent, int userId) { 5196 boolean didSomething = false; 5197 TaskRecord lastTask = null; 5198 ComponentName homeActivity = null; 5199 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 5200 final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities; 5201 mTmpActivities.clear(); 5202 mTmpActivities.addAll(activities); 5203 5204 while (!mTmpActivities.isEmpty()) { 5205 ActivityRecord r = mTmpActivities.remove(0); 5206 final boolean sameComponent = 5207 (r.packageName.equals(packageName) && (filterByClasses == null 5208 || filterByClasses.contains(r.mActivityComponent.getClassName()))) 5209 || (packageName == null && r.mUserId == userId); 5210 if ((userId == UserHandle.USER_ALL || r.mUserId == userId) 5211 && (sameComponent || r.getTaskRecord() == lastTask) 5212 && (r.app == null || evenPersistent || !r.app.isPersistent())) { 5213 if (!doit) { 5214 if (r.finishing) { 5215 // If this activity is just finishing, then it is not 5216 // interesting as far as something to stop. 5217 continue; 5218 } 5219 return true; 5220 } 5221 if (r.isActivityTypeHome()) { 5222 if (homeActivity != null && homeActivity.equals(r.mActivityComponent)) { 5223 Slog.i(TAG, "Skip force-stop again " + r); 5224 continue; 5225 } else { 5226 homeActivity = r.mActivityComponent; 5227 } 5228 } 5229 didSomething = true; 5230 Slog.i(TAG, " Force finishing activity " + r); 5231 lastTask = r.getTaskRecord(); 5232 finishActivityLocked(r, Activity.RESULT_CANCELED, null, "force-stop", 5233 true); 5234 } 5235 } 5236 } 5237 return didSomething; 5238 } 5239 5240 /** 5241 * @return The set of running tasks through {@param tasksOut} that are available to the caller. 5242 * If {@param ignoreActivityType} or {@param ignoreWindowingMode} are not undefined, 5243 * then skip running tasks that match those types. 5244 */ getRunningTasks(List<TaskRecord> tasksOut, @ActivityType int ignoreActivityType, @WindowingMode int ignoreWindowingMode, int callingUid, boolean allowed, boolean crossUser, ArraySet<Integer> profileIds)5245 void getRunningTasks(List<TaskRecord> tasksOut, @ActivityType int ignoreActivityType, 5246 @WindowingMode int ignoreWindowingMode, int callingUid, boolean allowed, 5247 boolean crossUser, ArraySet<Integer> profileIds) { 5248 boolean focusedStack = mRootActivityContainer.getTopDisplayFocusedStack() == this; 5249 boolean topTask = true; 5250 int userId = UserHandle.getUserId(callingUid); 5251 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 5252 final TaskRecord task = mTaskHistory.get(taskNdx); 5253 if (task.getTopActivity() == null) { 5254 // Skip if there are no activities in the task 5255 continue; 5256 } 5257 if (task.effectiveUid != callingUid) { 5258 if (task.userId != userId && !crossUser && !profileIds.contains(task.userId)) { 5259 // Skip if the caller does not have cross user permission or cannot access 5260 // the task's profile 5261 continue; 5262 } 5263 if (!allowed && !task.isActivityTypeHome()) { 5264 // Skip if the caller isn't allowed to fetch this task, except for the home 5265 // task which we always return. 5266 continue; 5267 } 5268 } 5269 if (ignoreActivityType != ACTIVITY_TYPE_UNDEFINED 5270 && task.getActivityType() == ignoreActivityType) { 5271 // Skip ignored activity type 5272 continue; 5273 } 5274 if (ignoreWindowingMode != WINDOWING_MODE_UNDEFINED 5275 && task.getWindowingMode() == ignoreWindowingMode) { 5276 // Skip ignored windowing mode 5277 continue; 5278 } 5279 if (focusedStack && topTask) { 5280 // For the focused stack top task, update the last stack active time so that it can 5281 // be used to determine the order of the tasks (it may not be set for newly created 5282 // tasks) 5283 task.lastActiveTime = SystemClock.elapsedRealtime(); 5284 topTask = false; 5285 } 5286 tasksOut.add(task); 5287 } 5288 } 5289 unhandledBackLocked()5290 void unhandledBackLocked() { 5291 final int top = mTaskHistory.size() - 1; 5292 if (DEBUG_SWITCH) Slog.d(TAG_SWITCH, "Performing unhandledBack(): top activity at " + top); 5293 if (top >= 0) { 5294 final ArrayList<ActivityRecord> activities = mTaskHistory.get(top).mActivities; 5295 int activityTop = activities.size() - 1; 5296 if (activityTop >= 0) { 5297 finishActivityLocked(activities.get(activityTop), Activity.RESULT_CANCELED, null, 5298 "unhandled-back", true); 5299 } 5300 } 5301 } 5302 5303 /** 5304 * Reset local parameters because an app's activity died. 5305 * @param app The app of the activity that died. 5306 * @return result from removeHistoryRecordsForAppLocked. 5307 */ handleAppDiedLocked(WindowProcessController app)5308 boolean handleAppDiedLocked(WindowProcessController app) { 5309 if (mPausingActivity != null && mPausingActivity.app == app) { 5310 if (DEBUG_PAUSE || DEBUG_CLEANUP) Slog.v(TAG_PAUSE, 5311 "App died while pausing: " + mPausingActivity); 5312 mPausingActivity = null; 5313 } 5314 if (mLastPausedActivity != null && mLastPausedActivity.app == app) { 5315 mLastPausedActivity = null; 5316 mLastNoHistoryActivity = null; 5317 } 5318 5319 return removeHistoryRecordsForAppLocked(app); 5320 } 5321 handleAppCrash(WindowProcessController app)5322 void handleAppCrash(WindowProcessController app) { 5323 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 5324 final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities; 5325 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { 5326 final ActivityRecord r = activities.get(activityNdx); 5327 if (r.app == app) { 5328 Slog.w(TAG, " Force finishing activity " 5329 + r.intent.getComponent().flattenToShortString()); 5330 // Force the destroy to skip right to removal. 5331 r.app = null; 5332 getDisplay().mDisplayContent.prepareAppTransition( 5333 TRANSIT_CRASHING_ACTIVITY_CLOSE, false /* alwaysKeepCurrent */); 5334 finishCurrentActivityLocked(r, FINISH_IMMEDIATELY, false, 5335 "handleAppCrashedLocked"); 5336 } 5337 } 5338 } 5339 } 5340 dump(FileDescriptor fd, PrintWriter pw, boolean dumpAll, boolean dumpClient, String dumpPackage, boolean needSep)5341 boolean dump(FileDescriptor fd, PrintWriter pw, boolean dumpAll, boolean dumpClient, 5342 String dumpPackage, boolean needSep) { 5343 pw.println(" Stack #" + mStackId 5344 + ": type=" + activityTypeToString(getActivityType()) 5345 + " mode=" + windowingModeToString(getWindowingMode())); 5346 pw.println(" isSleeping=" + shouldSleepActivities()); 5347 pw.println(" mBounds=" + getRequestedOverrideBounds()); 5348 5349 boolean printed = dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage, 5350 needSep); 5351 5352 printed |= dumpHistoryList(fd, pw, mLRUActivities, " ", "Run", false, 5353 !dumpAll, false, dumpPackage, true, 5354 " Running activities (most recent first):", null); 5355 5356 needSep = printed; 5357 boolean pr = printThisActivity(pw, mPausingActivity, dumpPackage, needSep, 5358 " mPausingActivity: "); 5359 if (pr) { 5360 printed = true; 5361 needSep = false; 5362 } 5363 pr = printThisActivity(pw, getResumedActivity(), dumpPackage, needSep, 5364 " mResumedActivity: "); 5365 if (pr) { 5366 printed = true; 5367 needSep = false; 5368 } 5369 if (dumpAll) { 5370 pr = printThisActivity(pw, mLastPausedActivity, dumpPackage, needSep, 5371 " mLastPausedActivity: "); 5372 if (pr) { 5373 printed = true; 5374 needSep = true; 5375 } 5376 printed |= printThisActivity(pw, mLastNoHistoryActivity, dumpPackage, 5377 needSep, " mLastNoHistoryActivity: "); 5378 } 5379 return printed; 5380 } 5381 dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll, boolean dumpClient, String dumpPackage, boolean needSep)5382 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll, 5383 boolean dumpClient, String dumpPackage, boolean needSep) { 5384 5385 if (mTaskHistory.isEmpty()) { 5386 return false; 5387 } 5388 final String prefix = " "; 5389 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 5390 final TaskRecord task = mTaskHistory.get(taskNdx); 5391 if (needSep) { 5392 pw.println(""); 5393 } 5394 pw.println(prefix + "Task id #" + task.taskId); 5395 pw.println(prefix + "mBounds=" + task.getRequestedOverrideBounds()); 5396 pw.println(prefix + "mMinWidth=" + task.mMinWidth); 5397 pw.println(prefix + "mMinHeight=" + task.mMinHeight); 5398 pw.println(prefix + "mLastNonFullscreenBounds=" + task.mLastNonFullscreenBounds); 5399 pw.println(prefix + "* " + task); 5400 task.dump(pw, prefix + " "); 5401 dumpHistoryList(fd, pw, mTaskHistory.get(taskNdx).mActivities, 5402 prefix, "Hist", true, !dumpAll, dumpClient, dumpPackage, false, null, task); 5403 } 5404 return true; 5405 } 5406 getDumpActivitiesLocked(String name)5407 ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) { 5408 ArrayList<ActivityRecord> activities = new ArrayList<>(); 5409 5410 if ("all".equals(name)) { 5411 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 5412 activities.addAll(mTaskHistory.get(taskNdx).mActivities); 5413 } 5414 } else if ("top".equals(name)) { 5415 final int top = mTaskHistory.size() - 1; 5416 if (top >= 0) { 5417 final ArrayList<ActivityRecord> list = mTaskHistory.get(top).mActivities; 5418 int listTop = list.size() - 1; 5419 if (listTop >= 0) { 5420 activities.add(list.get(listTop)); 5421 } 5422 } 5423 } else { 5424 ItemMatcher matcher = new ItemMatcher(); 5425 matcher.build(name); 5426 5427 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 5428 for (ActivityRecord r1 : mTaskHistory.get(taskNdx).mActivities) { 5429 if (matcher.match(r1, r1.intent.getComponent())) { 5430 activities.add(r1); 5431 } 5432 } 5433 } 5434 } 5435 5436 return activities; 5437 } 5438 restartPackage(String packageName)5439 ActivityRecord restartPackage(String packageName) { 5440 ActivityRecord starting = topRunningActivityLocked(); 5441 5442 // All activities that came from the package must be 5443 // restarted as if there was a config change. 5444 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 5445 final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities; 5446 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { 5447 final ActivityRecord a = activities.get(activityNdx); 5448 if (a.info.packageName.equals(packageName)) { 5449 a.forceNewConfig = true; 5450 if (starting != null && a == starting && a.visible) { 5451 a.startFreezingScreenLocked(starting.app, 5452 CONFIG_SCREEN_LAYOUT); 5453 } 5454 } 5455 } 5456 } 5457 5458 return starting; 5459 } 5460 5461 /** 5462 * Removes the input task from this stack. 5463 * 5464 * @param task to remove. 5465 * @param reason for removal. 5466 * @param mode task removal mode. Either {@link #REMOVE_TASK_MODE_DESTROYING}, 5467 * {@link #REMOVE_TASK_MODE_MOVING}, {@link #REMOVE_TASK_MODE_MOVING_TO_TOP}. 5468 */ removeTask(TaskRecord task, String reason, int mode)5469 void removeTask(TaskRecord task, String reason, int mode) { 5470 final boolean removed = mTaskHistory.remove(task); 5471 5472 if (removed) { 5473 EventLog.writeEvent(EventLogTags.AM_REMOVE_TASK, task.taskId, getStackId()); 5474 } 5475 5476 removeActivitiesFromLRUListLocked(task); 5477 updateTaskMovement(task, true); 5478 5479 if (mode == REMOVE_TASK_MODE_DESTROYING) { 5480 task.cleanUpResourcesForDestroy(); 5481 } 5482 5483 final ActivityDisplay display = getDisplay(); 5484 if (mTaskHistory.isEmpty()) { 5485 if (DEBUG_STACK) Slog.i(TAG_STACK, "removeTask: removing stack=" + this); 5486 // We only need to adjust focused stack if this stack is in focus and we are not in the 5487 // process of moving the task to the top of the stack that will be focused. 5488 if (mode != REMOVE_TASK_MODE_MOVING_TO_TOP 5489 && mRootActivityContainer.isTopDisplayFocusedStack(this)) { 5490 String myReason = reason + " leftTaskHistoryEmpty"; 5491 if (!inMultiWindowMode() || adjustFocusToNextFocusableStack(myReason) == null) { 5492 display.moveHomeStackToFront(myReason); 5493 } 5494 } 5495 if (isAttached()) { 5496 display.positionChildAtBottom(this); 5497 } 5498 if (!isActivityTypeHome() || !isAttached()) { 5499 remove(); 5500 } 5501 } 5502 5503 task.setStack(null); 5504 5505 // Notify if a task from the pinned stack is being removed (or moved depending on the mode) 5506 if (inPinnedWindowingMode()) { 5507 mService.getTaskChangeNotificationController().notifyActivityUnpinned(); 5508 } 5509 if (display.isSingleTaskInstance()) { 5510 mService.notifySingleTaskDisplayEmpty(display.mDisplayId); 5511 } 5512 } 5513 createTaskRecord(int taskId, ActivityInfo info, Intent intent, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, boolean toTop)5514 TaskRecord createTaskRecord(int taskId, ActivityInfo info, Intent intent, 5515 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, 5516 boolean toTop) { 5517 return createTaskRecord(taskId, info, intent, voiceSession, voiceInteractor, toTop, 5518 null /*activity*/, null /*source*/, null /*options*/); 5519 } 5520 createTaskRecord(int taskId, ActivityInfo info, Intent intent, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, boolean toTop, ActivityRecord activity, ActivityRecord source, ActivityOptions options)5521 TaskRecord createTaskRecord(int taskId, ActivityInfo info, Intent intent, 5522 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, 5523 boolean toTop, ActivityRecord activity, ActivityRecord source, 5524 ActivityOptions options) { 5525 final TaskRecord task = TaskRecord.create( 5526 mService, taskId, info, intent, voiceSession, voiceInteractor); 5527 // add the task to stack first, mTaskPositioner might need the stack association 5528 addTask(task, toTop, "createTaskRecord"); 5529 final int displayId = mDisplayId != INVALID_DISPLAY ? mDisplayId : DEFAULT_DISPLAY; 5530 final boolean isLockscreenShown = mService.mStackSupervisor.getKeyguardController() 5531 .isKeyguardOrAodShowing(displayId); 5532 if (!mStackSupervisor.getLaunchParamsController() 5533 .layoutTask(task, info.windowLayout, activity, source, options) 5534 && !matchParentBounds() && task.isResizeable() && !isLockscreenShown) { 5535 task.updateOverrideConfiguration(getRequestedOverrideBounds()); 5536 } 5537 task.createTask(toTop, (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0); 5538 return task; 5539 } 5540 getAllTasks()5541 ArrayList<TaskRecord> getAllTasks() { 5542 return new ArrayList<>(mTaskHistory); 5543 } 5544 addTask(final TaskRecord task, final boolean toTop, String reason)5545 void addTask(final TaskRecord task, final boolean toTop, String reason) { 5546 addTask(task, toTop ? MAX_VALUE : 0, true /* schedulePictureInPictureModeChange */, reason); 5547 if (toTop) { 5548 // TODO: figure-out a way to remove this call. 5549 positionChildWindowContainerAtTop(task); 5550 } 5551 } 5552 5553 // TODO: This shouldn't allow automatic reparenting. Remove the call to preAddTask and deal 5554 // with the fall-out... addTask(final TaskRecord task, int position, boolean schedulePictureInPictureModeChange, String reason)5555 void addTask(final TaskRecord task, int position, boolean schedulePictureInPictureModeChange, 5556 String reason) { 5557 // TODO: Is this remove really needed? Need to look into the call path for the other addTask 5558 mTaskHistory.remove(task); 5559 if (isSingleTaskInstance() && !mTaskHistory.isEmpty()) { 5560 throw new IllegalStateException("Can only have one child on stack=" + this); 5561 } 5562 5563 position = getAdjustedPositionForTask(task, position, null /* starting */); 5564 final boolean toTop = position >= mTaskHistory.size(); 5565 final ActivityStack prevStack = preAddTask(task, reason, toTop); 5566 5567 mTaskHistory.add(position, task); 5568 task.setStack(this); 5569 5570 updateTaskMovement(task, toTop); 5571 5572 postAddTask(task, prevStack, schedulePictureInPictureModeChange); 5573 } 5574 positionChildAt(TaskRecord task, int index)5575 void positionChildAt(TaskRecord task, int index) { 5576 5577 if (task.getStack() != this) { 5578 throw new IllegalArgumentException("AS.positionChildAt: task=" + task 5579 + " is not a child of stack=" + this + " current parent=" + task.getStack()); 5580 } 5581 5582 task.updateOverrideConfigurationForStack(this); 5583 5584 final ActivityRecord topRunningActivity = task.topRunningActivityLocked(); 5585 final boolean wasResumed = topRunningActivity == task.getStack().mResumedActivity; 5586 insertTaskAtPosition(task, index); 5587 task.setStack(this); 5588 postAddTask(task, null /* prevStack */, true /* schedulePictureInPictureModeChange */); 5589 5590 if (wasResumed) { 5591 if (mResumedActivity != null) { 5592 Log.wtf(TAG, "mResumedActivity was already set when moving mResumedActivity from" 5593 + " other stack to this stack mResumedActivity=" + mResumedActivity 5594 + " other mResumedActivity=" + topRunningActivity); 5595 } 5596 topRunningActivity.setState(RESUMED, "positionChildAt"); 5597 } 5598 5599 // The task might have already been running and its visibility needs to be synchronized with 5600 // the visibility of the stack / windows. 5601 ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); 5602 mRootActivityContainer.resumeFocusedStacksTopActivities(); 5603 } 5604 preAddTask(TaskRecord task, String reason, boolean toTop)5605 private ActivityStack preAddTask(TaskRecord task, String reason, boolean toTop) { 5606 final ActivityStack prevStack = task.getStack(); 5607 if (prevStack != null && prevStack != this) { 5608 prevStack.removeTask(task, reason, 5609 toTop ? REMOVE_TASK_MODE_MOVING_TO_TOP : REMOVE_TASK_MODE_MOVING); 5610 } 5611 return prevStack; 5612 } 5613 5614 /** 5615 * @param schedulePictureInPictureModeChange specifies whether or not to schedule the PiP mode 5616 * change. Callers may set this to false if they are explicitly scheduling PiP mode 5617 * changes themselves, like during the PiP animation 5618 */ postAddTask(TaskRecord task, ActivityStack prevStack, boolean schedulePictureInPictureModeChange)5619 private void postAddTask(TaskRecord task, ActivityStack prevStack, 5620 boolean schedulePictureInPictureModeChange) { 5621 if (schedulePictureInPictureModeChange && prevStack != null) { 5622 mStackSupervisor.scheduleUpdatePictureInPictureModeIfNeeded(task, prevStack); 5623 } else if (task.voiceSession != null) { 5624 try { 5625 task.voiceSession.taskStarted(task.intent, task.taskId); 5626 } catch (RemoteException e) { 5627 } 5628 } 5629 } 5630 setAlwaysOnTop(boolean alwaysOnTop)5631 public void setAlwaysOnTop(boolean alwaysOnTop) { 5632 if (isAlwaysOnTop() == alwaysOnTop) { 5633 return; 5634 } 5635 super.setAlwaysOnTop(alwaysOnTop); 5636 final ActivityDisplay display = getDisplay(); 5637 // positionChildAtTop() must be called even when always on top gets turned off because we 5638 // need to make sure that the stack is moved from among always on top windows to below other 5639 // always on top windows. Since the position the stack should be inserted into is calculated 5640 // properly in {@link ActivityDisplay#getTopInsertPosition()} in both cases, we can just 5641 // request that the stack is put at top here. 5642 display.positionChildAtTop(this, false /* includingParents */); 5643 } 5644 5645 /** NOTE: Should only be called from {@link TaskRecord#reparent}. */ moveToFrontAndResumeStateIfNeeded(ActivityRecord r, boolean moveToFront, boolean setResume, boolean setPause, String reason)5646 void moveToFrontAndResumeStateIfNeeded(ActivityRecord r, boolean moveToFront, boolean setResume, 5647 boolean setPause, String reason) { 5648 if (!moveToFront) { 5649 return; 5650 } 5651 5652 final ActivityState origState = r.getState(); 5653 // If the activity owns the last resumed activity, transfer that together, 5654 // so that we don't resume the same activity again in the new stack. 5655 // Apps may depend on onResume()/onPause() being called in pairs. 5656 if (setResume) { 5657 r.setState(RESUMED, "moveToFrontAndResumeStateIfNeeded"); 5658 updateLRUListLocked(r); 5659 } 5660 // If the activity was previously pausing, then ensure we transfer that as well 5661 if (setPause) { 5662 mPausingActivity = r; 5663 schedulePauseTimeout(r); 5664 } 5665 // Move the stack in which we are placing the activity to the front. 5666 moveToFront(reason); 5667 // If the original state is resumed, there is no state change to update focused app. 5668 // So here makes sure the activity focus is set if it is the top. 5669 if (origState == RESUMED && r == mRootActivityContainer.getTopResumedActivity()) { 5670 // TODO(b/111361570): Support multiple focused apps in WM 5671 mService.setResumedActivityUncheckLocked(r, reason); 5672 } 5673 } 5674 5675 getDefaultPictureInPictureBounds(float aspectRatio)5676 Rect getDefaultPictureInPictureBounds(float aspectRatio) { 5677 if (getTaskStack() == null) return null; 5678 return getTaskStack().getPictureInPictureBounds(aspectRatio, null /* currentStackBounds */); 5679 } 5680 animateResizePinnedStack(Rect sourceHintBounds, Rect toBounds, int animationDuration, boolean fromFullscreen)5681 void animateResizePinnedStack(Rect sourceHintBounds, Rect toBounds, int animationDuration, 5682 boolean fromFullscreen) { 5683 if (!inPinnedWindowingMode()) return; 5684 if (toBounds == null /* toFullscreen */) { 5685 final Configuration parentConfig = getParent().getConfiguration(); 5686 final ActivityRecord top = topRunningNonOverlayTaskActivity(); 5687 if (top != null && !top.isConfigurationCompatible(parentConfig)) { 5688 // The final orientation of this activity will change after moving to full screen. 5689 // Start freezing screen here to prevent showing a temporary full screen window. 5690 top.startFreezingScreenLocked(top.app, CONFIG_SCREEN_LAYOUT); 5691 mService.moveTasksToFullscreenStack(mStackId, true /* onTop */); 5692 return; 5693 } 5694 } 5695 if (getTaskStack() == null) return; 5696 getTaskStack().animateResizePinnedStack(toBounds, sourceHintBounds, 5697 animationDuration, fromFullscreen); 5698 } 5699 5700 /** 5701 * Get current bounds of this stack, return empty when it is unavailable. 5702 * @see TaskStack#getAnimationOrCurrentBounds(Rect) 5703 */ getAnimationOrCurrentBounds(Rect outBounds)5704 void getAnimationOrCurrentBounds(Rect outBounds) { 5705 final TaskStack stack = getTaskStack(); 5706 if (stack == null) { 5707 outBounds.setEmpty(); 5708 return; 5709 } 5710 stack.getAnimationOrCurrentBounds(outBounds); 5711 } 5712 setPictureInPictureAspectRatio(float aspectRatio)5713 void setPictureInPictureAspectRatio(float aspectRatio) { 5714 if (getTaskStack() == null) return; 5715 getTaskStack().setPictureInPictureAspectRatio(aspectRatio); 5716 } 5717 setPictureInPictureActions(List<RemoteAction> actions)5718 void setPictureInPictureActions(List<RemoteAction> actions) { 5719 if (getTaskStack() == null) return; 5720 getTaskStack().setPictureInPictureActions(actions); 5721 } 5722 isAnimatingBoundsToFullscreen()5723 boolean isAnimatingBoundsToFullscreen() { 5724 if (getTaskStack() == null) return false; 5725 return getTaskStack().isAnimatingBoundsToFullscreen(); 5726 } 5727 updatePictureInPictureModeForPinnedStackAnimation(Rect targetStackBounds, boolean forceUpdate)5728 public void updatePictureInPictureModeForPinnedStackAnimation(Rect targetStackBounds, 5729 boolean forceUpdate) { 5730 // It is guaranteed that the activities requiring the update will be in the pinned stack at 5731 // this point (either reparented before the animation into PiP, or before reparenting after 5732 // the animation out of PiP) 5733 synchronized (mService.mGlobalLock) { 5734 if (!isAttached()) { 5735 return; 5736 } 5737 ArrayList<TaskRecord> tasks = getAllTasks(); 5738 for (int i = 0; i < tasks.size(); i++) { 5739 mStackSupervisor.updatePictureInPictureMode(tasks.get(i), targetStackBounds, 5740 forceUpdate); 5741 } 5742 } 5743 } 5744 getStackId()5745 public int getStackId() { 5746 return mStackId; 5747 } 5748 5749 @Override toString()5750 public String toString() { 5751 return "ActivityStack{" + Integer.toHexString(System.identityHashCode(this)) 5752 + " stackId=" + mStackId + " type=" + activityTypeToString(getActivityType()) 5753 + " mode=" + windowingModeToString(getWindowingMode()) 5754 + " visible=" + shouldBeVisible(null /* starting */) 5755 + " translucent=" + isStackTranslucent(null /* starting */) 5756 + ", " 5757 + mTaskHistory.size() + " tasks}"; 5758 } 5759 onLockTaskPackagesUpdated()5760 void onLockTaskPackagesUpdated() { 5761 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 5762 mTaskHistory.get(taskNdx).setLockTaskAuth(); 5763 } 5764 } 5765 executeAppTransition(ActivityOptions options)5766 void executeAppTransition(ActivityOptions options) { 5767 getDisplay().mDisplayContent.executeAppTransition(); 5768 ActivityOptions.abort(options); 5769 } 5770 shouldSleepActivities()5771 boolean shouldSleepActivities() { 5772 final ActivityDisplay display = getDisplay(); 5773 5774 // Do not sleep activities in this stack if we're marked as focused and the keyguard 5775 // is in the process of going away. 5776 if (isFocusedStackOnDisplay() 5777 && mStackSupervisor.getKeyguardController().isKeyguardGoingAway()) { 5778 return false; 5779 } 5780 5781 return display != null ? display.isSleeping() : mService.isSleepingLocked(); 5782 } 5783 shouldSleepOrShutDownActivities()5784 boolean shouldSleepOrShutDownActivities() { 5785 return shouldSleepActivities() || mService.mShuttingDown; 5786 } 5787 writeToProto(ProtoOutputStream proto, long fieldId, @WindowTraceLogLevel int logLevel)5788 public void writeToProto(ProtoOutputStream proto, long fieldId, 5789 @WindowTraceLogLevel int logLevel) { 5790 final long token = proto.start(fieldId); 5791 super.writeToProto(proto, CONFIGURATION_CONTAINER, logLevel); 5792 proto.write(ID, mStackId); 5793 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 5794 final TaskRecord task = mTaskHistory.get(taskNdx); 5795 task.writeToProto(proto, TASKS, logLevel); 5796 } 5797 if (mResumedActivity != null) { 5798 mResumedActivity.writeIdentifierToProto(proto, RESUMED_ACTIVITY); 5799 } 5800 proto.write(DISPLAY_ID, mDisplayId); 5801 if (!matchParentBounds()) { 5802 final Rect bounds = getRequestedOverrideBounds(); 5803 bounds.writeToProto(proto, BOUNDS); 5804 } 5805 5806 // TODO: Remove, no longer needed with windowingMode. 5807 proto.write(FULLSCREEN, matchParentBounds()); 5808 proto.end(token); 5809 } 5810 } 5811