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