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