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