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