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