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