ActivityStackSupervisor.java revision 4cd0c13f8f765118a24e31548c058b5029481bea
1/* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.server.am; 18 19import static android.Manifest.permission.START_ANY_ACTIVITY; 20import static android.content.pm.PackageManager.PERMISSION_GRANTED; 21import static com.android.server.am.ActivityManagerService.localLOGV; 22import static com.android.server.am.ActivityManagerService.DEBUG_CONFIGURATION; 23import static com.android.server.am.ActivityManagerService.DEBUG_RESULTS; 24import static com.android.server.am.ActivityManagerService.DEBUG_SWITCH; 25import static com.android.server.am.ActivityManagerService.DEBUG_TASKS; 26import static com.android.server.am.ActivityManagerService.DEBUG_USER_LEAVING; 27import static com.android.server.am.ActivityManagerService.TAG; 28 29import android.app.Activity; 30import android.app.ActivityManager; 31import android.app.ActivityOptions; 32import android.app.AppGlobals; 33import android.app.IApplicationThread; 34import android.app.IThumbnailReceiver; 35import android.app.PendingIntent; 36import android.app.ActivityManager.RunningTaskInfo; 37import android.app.IActivityManager.WaitResult; 38import android.app.ResultInfo; 39import android.content.ComponentName; 40import android.content.Context; 41import android.content.IIntentSender; 42import android.content.Intent; 43import android.content.IntentSender; 44import android.content.pm.ActivityInfo; 45import android.content.pm.ApplicationInfo; 46import android.content.pm.PackageManager; 47import android.content.pm.ResolveInfo; 48import android.content.res.Configuration; 49import android.os.Binder; 50import android.os.Bundle; 51import android.os.IBinder; 52import android.os.Looper; 53import android.os.Message; 54import android.os.ParcelFileDescriptor; 55import android.os.RemoteException; 56import android.os.SystemClock; 57import android.os.UserHandle; 58import android.util.EventLog; 59import android.util.Slog; 60 61import com.android.internal.app.HeavyWeightSwitcherActivity; 62import com.android.server.am.ActivityManagerService.PendingActivityLaunch; 63import com.android.server.am.ActivityStack.ActivityState; 64import com.android.server.wm.StackBox; 65 66import java.io.FileDescriptor; 67import java.io.IOException; 68import java.io.PrintWriter; 69import java.util.ArrayList; 70import java.util.List; 71 72public class ActivityStackSupervisor { 73 static final boolean DEBUG = ActivityManagerService.DEBUG || false; 74 static final boolean DEBUG_ADD_REMOVE = DEBUG || false; 75 static final boolean DEBUG_APP = DEBUG || false; 76 static final boolean DEBUG_SAVED_STATE = DEBUG || false; 77 static final boolean DEBUG_STATES = DEBUG || false; 78 79 public static final int HOME_STACK_ID = 0; 80 81 final ActivityManagerService mService; 82 final Context mContext; 83 final Looper mLooper; 84 85 /** Dismiss the keyguard after the next activity is displayed? */ 86 private boolean mDismissKeyguardOnNextActivity = false; 87 88 /** Identifier counter for all ActivityStacks */ 89 private int mLastStackId = HOME_STACK_ID; 90 91 /** Task identifier that activities are currently being started in. Incremented each time a 92 * new task is created. */ 93 private int mCurTaskId = 0; 94 95 /** The current user */ 96 private int mCurrentUser; 97 98 /** The stack containing the launcher app */ 99 private ActivityStack mHomeStack; 100 101 /** The non-home stack currently receiving input or launching the next activity. If home is 102 * in front then mHomeStack overrides mMainStack. */ 103 private ActivityStack mMainStack; 104 105 /** All the non-launcher stacks */ 106 private ArrayList<ActivityStack> mStacks = new ArrayList<ActivityStack>(); 107 108 private static final int STACK_STATE_HOME_IN_FRONT = 0; 109 private static final int STACK_STATE_HOME_TO_BACK = 1; 110 private static final int STACK_STATE_HOME_IN_BACK = 2; 111 private static final int STACK_STATE_HOME_TO_FRONT = 3; 112 private int mStackState = STACK_STATE_HOME_IN_FRONT; 113 114 /** List of activities that are waiting for a new activity to become visible before completing 115 * whatever operation they are supposed to do. */ 116 final ArrayList<ActivityRecord> mWaitingVisibleActivities = new ArrayList<ActivityRecord>(); 117 118 /** List of activities that are ready to be stopped, but waiting for the next activity to 119 * settle down before doing so. */ 120 final ArrayList<ActivityRecord> mStoppingActivities = new ArrayList<ActivityRecord>(); 121 122 /** Set to indicate whether to issue an onUserLeaving callback when a newly launched activity 123 * is being brought in front of us. */ 124 boolean mUserLeaving = false; 125 126 public ActivityStackSupervisor(ActivityManagerService service, Context context, 127 Looper looper) { 128 mService = service; 129 mContext = context; 130 mLooper = looper; 131 } 132 133 void init(int userId) { 134 mHomeStack = new ActivityStack(mService, mContext, mLooper, HOME_STACK_ID, this, userId); 135 mStacks.add(mHomeStack); 136 } 137 138 void dismissKeyguard() { 139 if (mDismissKeyguardOnNextActivity) { 140 mDismissKeyguardOnNextActivity = false; 141 mService.mWindowManager.dismissKeyguard(); 142 } 143 } 144 145 ActivityStack getTopStack() { 146 switch (mStackState) { 147 case STACK_STATE_HOME_IN_FRONT: 148 case STACK_STATE_HOME_TO_FRONT: 149 return mHomeStack; 150 case STACK_STATE_HOME_IN_BACK: 151 case STACK_STATE_HOME_TO_BACK: 152 default: 153 return mMainStack; 154 } 155 } 156 157 ActivityStack getLastStack() { 158 switch (mStackState) { 159 case STACK_STATE_HOME_IN_FRONT: 160 case STACK_STATE_HOME_TO_BACK: 161 return mHomeStack; 162 case STACK_STATE_HOME_TO_FRONT: 163 case STACK_STATE_HOME_IN_BACK: 164 default: 165 return mMainStack; 166 } 167 } 168 169 boolean isFrontStack(ActivityStack stack) { 170 return !(stack.isHomeStack() ^ getTopStack().isHomeStack()); 171 } 172 173 boolean homeIsInFront() { 174 return isFrontStack(mHomeStack); 175 } 176 177 void moveHomeStack(boolean toFront) { 178 final boolean homeInFront = isFrontStack(mHomeStack); 179 if (homeInFront ^ toFront) { 180 mStackState = homeInFront ? STACK_STATE_HOME_TO_BACK : STACK_STATE_HOME_TO_FRONT; 181 } 182 } 183 184 final void setLaunchHomeTaskNextFlag(ActivityRecord sourceRecord, ActivityRecord r, 185 ActivityStack stack) { 186 if (stack == mHomeStack) { 187 return; 188 } 189 if ((sourceRecord == null && getLastStack() == mHomeStack) || 190 (sourceRecord != null && sourceRecord.isHomeActivity)) { 191 if (r == null) { 192 r = stack.topRunningActivityLocked(null); 193 } 194 if (r != null && !r.isHomeActivity && r.isRootActivity()) { 195 r.mLaunchHomeTaskNext = true; 196 } 197 } 198 } 199 200 void setDismissKeyguard(boolean dismiss) { 201 mDismissKeyguardOnNextActivity = dismiss; 202 } 203 204 TaskRecord anyTaskForIdLocked(int id) { 205 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { 206 ActivityStack stack = mStacks.get(stackNdx); 207 TaskRecord task = stack.taskForIdLocked(id); 208 if (task != null) { 209 return task; 210 } 211 } 212 return null; 213 } 214 215 ActivityRecord isInAnyStackLocked(IBinder token) { 216 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { 217 final ActivityRecord r = mStacks.get(stackNdx).isInStackLocked(token); 218 if (r != null) { 219 return r; 220 } 221 } 222 return null; 223 } 224 225 int getNextTaskId() { 226 do { 227 mCurTaskId++; 228 if (mCurTaskId <= 0) { 229 mCurTaskId = 1; 230 } 231 } while (anyTaskForIdLocked(mCurTaskId) != null); 232 return mCurTaskId; 233 } 234 235 void removeTask(TaskRecord task) { 236 final ActivityStack stack = task.stack; 237 if (stack.removeTask(task) && !stack.isHomeStack()) { 238 mStacks.remove(stack); 239 final int stackId = stack.mStackId; 240 final int nextStackId = mService.mWindowManager.removeStack(stackId); 241 if (mMainStack.mStackId == stackId) { 242 mMainStack = nextStackId == HOME_STACK_ID ? null : getStack(nextStackId); 243 } 244 } 245 } 246 247 ActivityRecord resumedAppLocked() { 248 ActivityStack stack = getTopStack(); 249 ActivityRecord resumedActivity = stack.mResumedActivity; 250 if (resumedActivity == null || resumedActivity.app == null) { 251 resumedActivity = stack.mPausingActivity; 252 if (resumedActivity == null || resumedActivity.app == null) { 253 resumedActivity = stack.topRunningActivityLocked(null); 254 } 255 } 256 return resumedActivity; 257 } 258 259 boolean attachApplicationLocked(ProcessRecord app, boolean headless) throws Exception { 260 boolean didSomething = false; 261 final String processName = app.processName; 262 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { 263 final ActivityStack stack = mStacks.get(stackNdx); 264 ActivityRecord hr = stack.topRunningActivityLocked(null); 265 if (hr != null) { 266 if (hr.app == null && app.uid == hr.info.applicationInfo.uid 267 && processName.equals(hr.processName)) { 268 try { 269 if (headless) { 270 Slog.e(TAG, "Starting activities not supported on headless device: " 271 + hr); 272 } else if (realStartActivityLocked(hr, app, true, true)) { 273 didSomething = true; 274 } 275 } catch (Exception e) { 276 Slog.w(TAG, "Exception in new application when starting activity " 277 + hr.intent.getComponent().flattenToShortString(), e); 278 throw e; 279 } 280 } else { 281 stack.ensureActivitiesVisibleLocked(hr, null, processName, 0); 282 } 283 } 284 } 285 return didSomething; 286 } 287 288 boolean allResumedActivitiesIdle() { 289 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { 290 final ActivityRecord resumedActivity = mStacks.get(stackNdx).mResumedActivity; 291 if (resumedActivity == null || !resumedActivity.idle) { 292 return false; 293 } 294 } 295 return true; 296 } 297 298 boolean allResumedActivitiesComplete() { 299 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { 300 final ActivityStack stack = mStacks.get(stackNdx); 301 if (isFrontStack(stack)) { 302 final ActivityRecord r = stack.mResumedActivity; 303 if (r != null && r.state != ActivityState.RESUMED) { 304 return false; 305 } 306 } 307 } 308 // TODO: Not sure if this should check if all Paused are complete too. 309 switch (mStackState) { 310 case STACK_STATE_HOME_TO_BACK: 311 mStackState = STACK_STATE_HOME_IN_BACK; 312 break; 313 case STACK_STATE_HOME_TO_FRONT: 314 mStackState = STACK_STATE_HOME_IN_FRONT; 315 break; 316 } 317 return true; 318 } 319 320 boolean allResumedActivitiesVisible() { 321 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { 322 final ActivityStack stack = mStacks.get(stackNdx); 323 final ActivityRecord r = stack.mResumedActivity; 324 if (r != null && (!r.nowVisible || r.waitingVisible)) { 325 return false; 326 } 327 } 328 return true; 329 } 330 331 boolean allPausedActivitiesComplete() { 332 final boolean homeInBack = !homeIsInFront(); 333 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { 334 final ActivityStack stack = mStacks.get(stackNdx); 335 if (stack.isHomeStack() ^ homeInBack) { 336 final ActivityRecord r = stack.mLastPausedActivity; 337 if (r != null && r.state != ActivityState.PAUSED 338 && r.state != ActivityState.STOPPED 339 && r.state != ActivityState.STOPPING) { 340 return false; 341 } 342 } 343 } 344 // TODO: Not sure if this should check if all Resumed are complete too. 345 switch (mStackState) { 346 case STACK_STATE_HOME_TO_BACK: 347 mStackState = STACK_STATE_HOME_IN_BACK; 348 break; 349 case STACK_STATE_HOME_TO_FRONT: 350 mStackState = STACK_STATE_HOME_IN_FRONT; 351 break; 352 } 353 return true; 354 } 355 356 ActivityRecord getTasksLocked(int maxNum, IThumbnailReceiver receiver, 357 PendingThumbnailsRecord pending, List<RunningTaskInfo> list) { 358 ActivityRecord r = null; 359 final int numStacks = mStacks.size(); 360 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { 361 final ActivityStack stack = mStacks.get(stackNdx); 362 final ActivityRecord ar = 363 stack.getTasksLocked(maxNum - list.size(), receiver, pending, list); 364 if (isFrontStack(stack)) { 365 r = ar; 366 } 367 } 368 return r; 369 } 370 371 ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags, 372 String profileFile, ParcelFileDescriptor profileFd, int userId) { 373 // Collect information about the target of the Intent. 374 ActivityInfo aInfo; 375 try { 376 ResolveInfo rInfo = 377 AppGlobals.getPackageManager().resolveIntent( 378 intent, resolvedType, 379 PackageManager.MATCH_DEFAULT_ONLY 380 | ActivityManagerService.STOCK_PM_FLAGS, userId); 381 aInfo = rInfo != null ? rInfo.activityInfo : null; 382 } catch (RemoteException e) { 383 aInfo = null; 384 } 385 386 if (aInfo != null) { 387 // Store the found target back into the intent, because now that 388 // we have it we never want to do this again. For example, if the 389 // user navigates back to this point in the history, we should 390 // always restart the exact same activity. 391 intent.setComponent(new ComponentName( 392 aInfo.applicationInfo.packageName, aInfo.name)); 393 394 // Don't debug things in the system process 395 if ((startFlags&ActivityManager.START_FLAG_DEBUG) != 0) { 396 if (!aInfo.processName.equals("system")) { 397 mService.setDebugApp(aInfo.processName, true, false); 398 } 399 } 400 401 if ((startFlags&ActivityManager.START_FLAG_OPENGL_TRACES) != 0) { 402 if (!aInfo.processName.equals("system")) { 403 mService.setOpenGlTraceApp(aInfo.applicationInfo, aInfo.processName); 404 } 405 } 406 407 if (profileFile != null) { 408 if (!aInfo.processName.equals("system")) { 409 mService.setProfileApp(aInfo.applicationInfo, aInfo.processName, 410 profileFile, profileFd, 411 (startFlags&ActivityManager.START_FLAG_AUTO_STOP_PROFILER) != 0); 412 } 413 } 414 } 415 return aInfo; 416 } 417 418 void startHomeActivity(Intent intent, ActivityInfo aInfo) { 419 moveHomeStack(true); 420 startActivityLocked(null, intent, null, aInfo, null, null, 0, 0, 0, null, 0, 421 null, false, null); 422 } 423 424 final int startActivityMayWait(IApplicationThread caller, int callingUid, 425 String callingPackage, Intent intent, String resolvedType, IBinder resultTo, 426 String resultWho, int requestCode, int startFlags, String profileFile, 427 ParcelFileDescriptor profileFd, WaitResult outResult, Configuration config, 428 Bundle options, int userId) { 429 // Refuse possible leaked file descriptors 430 if (intent != null && intent.hasFileDescriptors()) { 431 throw new IllegalArgumentException("File descriptors passed in Intent"); 432 } 433 boolean componentSpecified = intent.getComponent() != null; 434 435 // Don't modify the client's object! 436 intent = new Intent(intent); 437 438 // Collect information about the target of the Intent. 439 ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags, 440 profileFile, profileFd, userId); 441 442 synchronized (mService) { 443 int callingPid; 444 if (callingUid >= 0) { 445 callingPid = -1; 446 } else if (caller == null) { 447 callingPid = Binder.getCallingPid(); 448 callingUid = Binder.getCallingUid(); 449 } else { 450 callingPid = callingUid = -1; 451 } 452 453 final ActivityStack stack = getTopStack(); 454 stack.mConfigWillChange = config != null 455 && mService.mConfiguration.diff(config) != 0; 456 if (DEBUG_CONFIGURATION) Slog.v(TAG, 457 "Starting activity when config will change = " + stack.mConfigWillChange); 458 459 final long origId = Binder.clearCallingIdentity(); 460 461 if (aInfo != null && 462 (aInfo.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) { 463 // This may be a heavy-weight process! Check to see if we already 464 // have another, different heavy-weight process running. 465 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) { 466 if (mService.mHeavyWeightProcess != null && 467 (mService.mHeavyWeightProcess.info.uid != aInfo.applicationInfo.uid || 468 !mService.mHeavyWeightProcess.processName.equals(aInfo.processName))) { 469 int realCallingPid = callingPid; 470 int realCallingUid = callingUid; 471 if (caller != null) { 472 ProcessRecord callerApp = mService.getRecordForAppLocked(caller); 473 if (callerApp != null) { 474 realCallingPid = callerApp.pid; 475 realCallingUid = callerApp.info.uid; 476 } else { 477 Slog.w(TAG, "Unable to find app for caller " + caller 478 + " (pid=" + realCallingPid + ") when starting: " 479 + intent.toString()); 480 ActivityOptions.abort(options); 481 return ActivityManager.START_PERMISSION_DENIED; 482 } 483 } 484 485 IIntentSender target = mService.getIntentSenderLocked( 486 ActivityManager.INTENT_SENDER_ACTIVITY, "android", 487 realCallingUid, userId, null, null, 0, new Intent[] { intent }, 488 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT 489 | PendingIntent.FLAG_ONE_SHOT, null); 490 491 Intent newIntent = new Intent(); 492 if (requestCode >= 0) { 493 // Caller is requesting a result. 494 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true); 495 } 496 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT, 497 new IntentSender(target)); 498 if (mService.mHeavyWeightProcess.activities.size() > 0) { 499 ActivityRecord hist = mService.mHeavyWeightProcess.activities.get(0); 500 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP, 501 hist.packageName); 502 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK, 503 hist.task.taskId); 504 } 505 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP, 506 aInfo.packageName); 507 newIntent.setFlags(intent.getFlags()); 508 newIntent.setClassName("android", 509 HeavyWeightSwitcherActivity.class.getName()); 510 intent = newIntent; 511 resolvedType = null; 512 caller = null; 513 callingUid = Binder.getCallingUid(); 514 callingPid = Binder.getCallingPid(); 515 componentSpecified = true; 516 try { 517 ResolveInfo rInfo = 518 AppGlobals.getPackageManager().resolveIntent( 519 intent, null, 520 PackageManager.MATCH_DEFAULT_ONLY 521 | ActivityManagerService.STOCK_PM_FLAGS, userId); 522 aInfo = rInfo != null ? rInfo.activityInfo : null; 523 aInfo = mService.getActivityInfoForUser(aInfo, userId); 524 } catch (RemoteException e) { 525 aInfo = null; 526 } 527 } 528 } 529 } 530 531 int res = startActivityLocked(caller, intent, resolvedType, 532 aInfo, resultTo, resultWho, requestCode, callingPid, callingUid, 533 callingPackage, startFlags, options, componentSpecified, null); 534 535 if (stack.mConfigWillChange) { 536 // If the caller also wants to switch to a new configuration, 537 // do so now. This allows a clean switch, as we are waiting 538 // for the current activity to pause (so we will not destroy 539 // it), and have not yet started the next activity. 540 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION, 541 "updateConfiguration()"); 542 stack.mConfigWillChange = false; 543 if (DEBUG_CONFIGURATION) Slog.v(TAG, 544 "Updating to new configuration after starting activity."); 545 mService.updateConfigurationLocked(config, null, false, false); 546 } 547 548 Binder.restoreCallingIdentity(origId); 549 550 if (outResult != null) { 551 outResult.result = res; 552 if (res == ActivityManager.START_SUCCESS) { 553 stack.mWaitingActivityLaunched.add(outResult); 554 do { 555 try { 556 mService.wait(); 557 } catch (InterruptedException e) { 558 } 559 } while (!outResult.timeout && outResult.who == null); 560 } else if (res == ActivityManager.START_TASK_TO_FRONT) { 561 ActivityRecord r = stack.topRunningActivityLocked(null); 562 if (r.nowVisible) { 563 outResult.timeout = false; 564 outResult.who = new ComponentName(r.info.packageName, r.info.name); 565 outResult.totalTime = 0; 566 outResult.thisTime = 0; 567 } else { 568 outResult.thisTime = SystemClock.uptimeMillis(); 569 stack.mWaitingActivityVisible.add(outResult); 570 do { 571 try { 572 mService.wait(); 573 } catch (InterruptedException e) { 574 } 575 } while (!outResult.timeout && outResult.who == null); 576 } 577 } 578 } 579 580 return res; 581 } 582 } 583 584 final int startActivities(IApplicationThread caller, int callingUid, String callingPackage, 585 Intent[] intents, String[] resolvedTypes, IBinder resultTo, 586 Bundle options, int userId) { 587 if (intents == null) { 588 throw new NullPointerException("intents is null"); 589 } 590 if (resolvedTypes == null) { 591 throw new NullPointerException("resolvedTypes is null"); 592 } 593 if (intents.length != resolvedTypes.length) { 594 throw new IllegalArgumentException("intents are length different than resolvedTypes"); 595 } 596 597 ActivityRecord[] outActivity = new ActivityRecord[1]; 598 599 int callingPid; 600 if (callingUid >= 0) { 601 callingPid = -1; 602 } else if (caller == null) { 603 callingPid = Binder.getCallingPid(); 604 callingUid = Binder.getCallingUid(); 605 } else { 606 callingPid = callingUid = -1; 607 } 608 final long origId = Binder.clearCallingIdentity(); 609 try { 610 synchronized (mService) { 611 612 for (int i=0; i<intents.length; i++) { 613 Intent intent = intents[i]; 614 if (intent == null) { 615 continue; 616 } 617 618 // Refuse possible leaked file descriptors 619 if (intent != null && intent.hasFileDescriptors()) { 620 throw new IllegalArgumentException("File descriptors passed in Intent"); 621 } 622 623 boolean componentSpecified = intent.getComponent() != null; 624 625 // Don't modify the client's object! 626 intent = new Intent(intent); 627 628 // Collect information about the target of the Intent. 629 ActivityInfo aInfo = resolveActivity(intent, resolvedTypes[i], 630 0, null, null, userId); 631 // TODO: New, check if this is correct 632 aInfo = mService.getActivityInfoForUser(aInfo, userId); 633 634 if (aInfo != null && 635 (aInfo.applicationInfo.flags & ApplicationInfo.FLAG_CANT_SAVE_STATE) 636 != 0) { 637 throw new IllegalArgumentException( 638 "FLAG_CANT_SAVE_STATE not supported here"); 639 } 640 641 Bundle theseOptions; 642 if (options != null && i == intents.length-1) { 643 theseOptions = options; 644 } else { 645 theseOptions = null; 646 } 647 int res = startActivityLocked(caller, intent, resolvedTypes[i], 648 aInfo, resultTo, null, -1, callingPid, callingUid, callingPackage, 649 0, theseOptions, componentSpecified, outActivity); 650 if (res < 0) { 651 return res; 652 } 653 654 resultTo = outActivity[0] != null ? outActivity[0].appToken : null; 655 } 656 } 657 } finally { 658 Binder.restoreCallingIdentity(origId); 659 } 660 661 return ActivityManager.START_SUCCESS; 662 } 663 664 final boolean realStartActivityLocked(ActivityRecord r, 665 ProcessRecord app, boolean andResume, boolean checkConfig) 666 throws RemoteException { 667 668 r.startFreezingScreenLocked(app, 0); 669 mService.mWindowManager.setAppVisibility(r.appToken, true); 670 671 // schedule launch ticks to collect information about slow apps. 672 r.startLaunchTickingLocked(); 673 674 // Have the window manager re-evaluate the orientation of 675 // the screen based on the new activity order. Note that 676 // as a result of this, it can call back into the activity 677 // manager with a new orientation. We don't care about that, 678 // because the activity is not currently running so we are 679 // just restarting it anyway. 680 if (checkConfig) { 681 Configuration config = mService.mWindowManager.updateOrientationFromAppTokens( 682 mService.mConfiguration, 683 r.mayFreezeScreenLocked(app) ? r.appToken : null); 684 mService.updateConfigurationLocked(config, r, false, false); 685 } 686 687 r.app = app; 688 app.waitingToKill = null; 689 r.launchCount++; 690 r.lastLaunchTime = SystemClock.uptimeMillis(); 691 692 if (localLOGV) Slog.v(TAG, "Launching: " + r); 693 694 int idx = app.activities.indexOf(r); 695 if (idx < 0) { 696 app.activities.add(r); 697 } 698 mService.updateLruProcessLocked(app, true); 699 700 final ActivityStack stack = r.task.stack; 701 try { 702 if (app.thread == null) { 703 throw new RemoteException(); 704 } 705 List<ResultInfo> results = null; 706 List<Intent> newIntents = null; 707 if (andResume) { 708 results = r.results; 709 newIntents = r.newIntents; 710 } 711 if (DEBUG_SWITCH) Slog.v(TAG, "Launching: " + r 712 + " icicle=" + r.icicle 713 + " with results=" + results + " newIntents=" + newIntents 714 + " andResume=" + andResume); 715 if (andResume) { 716 EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY, 717 r.userId, System.identityHashCode(r), 718 r.task.taskId, r.shortComponentName); 719 } 720 if (r.isHomeActivity) { 721 mService.mHomeProcess = app; 722 } 723 mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName()); 724 r.sleeping = false; 725 r.forceNewConfig = false; 726 mService.showAskCompatModeDialogLocked(r); 727 r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo); 728 String profileFile = null; 729 ParcelFileDescriptor profileFd = null; 730 boolean profileAutoStop = false; 731 if (mService.mProfileApp != null && mService.mProfileApp.equals(app.processName)) { 732 if (mService.mProfileProc == null || mService.mProfileProc == app) { 733 mService.mProfileProc = app; 734 profileFile = mService.mProfileFile; 735 profileFd = mService.mProfileFd; 736 profileAutoStop = mService.mAutoStopProfiler; 737 } 738 } 739 app.hasShownUi = true; 740 app.pendingUiClean = true; 741 if (profileFd != null) { 742 try { 743 profileFd = profileFd.dup(); 744 } catch (IOException e) { 745 if (profileFd != null) { 746 try { 747 profileFd.close(); 748 } catch (IOException o) { 749 } 750 profileFd = null; 751 } 752 } 753 } 754 app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken, 755 System.identityHashCode(r), r.info, 756 new Configuration(mService.mConfiguration), 757 r.compat, r.icicle, results, newIntents, !andResume, 758 mService.isNextTransitionForward(), profileFile, profileFd, 759 profileAutoStop); 760 761 if ((app.info.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) { 762 // This may be a heavy-weight process! Note that the package 763 // manager will ensure that only activity can run in the main 764 // process of the .apk, which is the only thing that will be 765 // considered heavy-weight. 766 if (app.processName.equals(app.info.packageName)) { 767 if (mService.mHeavyWeightProcess != null 768 && mService.mHeavyWeightProcess != app) { 769 Slog.w(TAG, "Starting new heavy weight process " + app 770 + " when already running " 771 + mService.mHeavyWeightProcess); 772 } 773 mService.mHeavyWeightProcess = app; 774 Message msg = mService.mHandler.obtainMessage( 775 ActivityManagerService.POST_HEAVY_NOTIFICATION_MSG); 776 msg.obj = r; 777 mService.mHandler.sendMessage(msg); 778 } 779 } 780 781 } catch (RemoteException e) { 782 if (r.launchFailed) { 783 // This is the second time we failed -- finish activity 784 // and give up. 785 Slog.e(TAG, "Second failure launching " 786 + r.intent.getComponent().flattenToShortString() 787 + ", giving up", e); 788 mService.appDiedLocked(app, app.pid, app.thread); 789 stack.requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null, 790 "2nd-crash", false); 791 return false; 792 } 793 794 // This is the first time we failed -- restart process and 795 // retry. 796 app.activities.remove(r); 797 throw e; 798 } 799 800 r.launchFailed = false; 801 if (stack.updateLRUListLocked(r)) { 802 Slog.w(TAG, "Activity " + r 803 + " being launched, but already in LRU list"); 804 } 805 806 if (andResume) { 807 // As part of the process of launching, ActivityThread also performs 808 // a resume. 809 stack.minimalResumeActivityLocked(r); 810 } else { 811 // This activity is not starting in the resumed state... which 812 // should look like we asked it to pause+stop (but remain visible), 813 // and it has done so and reported back the current icicle and 814 // other state. 815 if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPED: " + r 816 + " (starting in stopped state)"); 817 r.state = ActivityState.STOPPED; 818 r.stopped = true; 819 } 820 821 // Launch the new version setup screen if needed. We do this -after- 822 // launching the initial activity (that is, home), so that it can have 823 // a chance to initialize itself while in the background, making the 824 // switch back to it faster and look better. 825 if (isFrontStack(stack)) { 826 mService.startSetupActivityLocked(); 827 } 828 829 return true; 830 } 831 832 void startSpecificActivityLocked(ActivityRecord r, 833 boolean andResume, boolean checkConfig) { 834 // Is this activity's application already running? 835 ProcessRecord app = mService.getProcessRecordLocked(r.processName, 836 r.info.applicationInfo.uid); 837 838 r.task.stack.setLaunchTime(r); 839 840 if (app != null && app.thread != null) { 841 try { 842 app.addPackage(r.info.packageName); 843 realStartActivityLocked(r, app, andResume, checkConfig); 844 return; 845 } catch (RemoteException e) { 846 Slog.w(TAG, "Exception when starting activity " 847 + r.intent.getComponent().flattenToShortString(), e); 848 } 849 850 // If a dead object exception was thrown -- fall through to 851 // restart the application. 852 } 853 854 mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0, 855 "activity", r.intent.getComponent(), false, false); 856 } 857 858 final int startActivityLocked(IApplicationThread caller, 859 Intent intent, String resolvedType, ActivityInfo aInfo, IBinder resultTo, 860 String resultWho, int requestCode, 861 int callingPid, int callingUid, String callingPackage, int startFlags, Bundle options, 862 boolean componentSpecified, ActivityRecord[] outActivity) { 863 int err = ActivityManager.START_SUCCESS; 864 865 ProcessRecord callerApp = null; 866 if (caller != null) { 867 callerApp = mService.getRecordForAppLocked(caller); 868 if (callerApp != null) { 869 callingPid = callerApp.pid; 870 callingUid = callerApp.info.uid; 871 } else { 872 Slog.w(TAG, "Unable to find app for caller " + caller 873 + " (pid=" + callingPid + ") when starting: " 874 + intent.toString()); 875 err = ActivityManager.START_PERMISSION_DENIED; 876 } 877 } 878 879 if (err == ActivityManager.START_SUCCESS) { 880 final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0; 881 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false) 882 + "} from pid " + (callerApp != null ? callerApp.pid : callingPid)); 883 } 884 885 ActivityRecord sourceRecord = null; 886 ActivityRecord resultRecord = null; 887 if (resultTo != null) { 888 sourceRecord = isInAnyStackLocked(resultTo); 889 if (DEBUG_RESULTS) Slog.v( 890 TAG, "Will send result to " + resultTo + " " + sourceRecord); 891 if (sourceRecord != null) { 892 if (requestCode >= 0 && !sourceRecord.finishing) { 893 resultRecord = sourceRecord; 894 } 895 } 896 } 897 ActivityStack resultStack = resultRecord == null ? null : resultRecord.task.stack; 898 899 int launchFlags = intent.getFlags(); 900 901 if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 902 && sourceRecord != null) { 903 // Transfer the result target from the source activity to the new 904 // one being started, including any failures. 905 if (requestCode >= 0) { 906 ActivityOptions.abort(options); 907 return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT; 908 } 909 resultRecord = sourceRecord.resultTo; 910 resultWho = sourceRecord.resultWho; 911 requestCode = sourceRecord.requestCode; 912 sourceRecord.resultTo = null; 913 if (resultRecord != null) { 914 resultRecord.removeResultsLocked( 915 sourceRecord, resultWho, requestCode); 916 } 917 } 918 919 if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) { 920 // We couldn't find a class that can handle the given Intent. 921 // That's the end of that! 922 err = ActivityManager.START_INTENT_NOT_RESOLVED; 923 } 924 925 if (err == ActivityManager.START_SUCCESS && aInfo == null) { 926 // We couldn't find the specific class specified in the Intent. 927 // Also the end of the line. 928 err = ActivityManager.START_CLASS_NOT_FOUND; 929 } 930 931 if (err != ActivityManager.START_SUCCESS) { 932 if (resultRecord != null) { 933 resultStack.sendActivityResultLocked(-1, 934 resultRecord, resultWho, requestCode, 935 Activity.RESULT_CANCELED, null); 936 } 937 setDismissKeyguard(false); 938 ActivityOptions.abort(options); 939 return err; 940 } 941 942 final int startAnyPerm = mService.checkPermission( 943 START_ANY_ACTIVITY, callingPid, callingUid); 944 final int componentPerm = mService.checkComponentPermission(aInfo.permission, callingPid, 945 callingUid, aInfo.applicationInfo.uid, aInfo.exported); 946 if (startAnyPerm != PERMISSION_GRANTED && componentPerm != PERMISSION_GRANTED) { 947 if (resultRecord != null) { 948 resultStack.sendActivityResultLocked(-1, 949 resultRecord, resultWho, requestCode, 950 Activity.RESULT_CANCELED, null); 951 } 952 setDismissKeyguard(false); 953 String msg; 954 if (!aInfo.exported) { 955 msg = "Permission Denial: starting " + intent.toString() 956 + " from " + callerApp + " (pid=" + callingPid 957 + ", uid=" + callingUid + ")" 958 + " not exported from uid " + aInfo.applicationInfo.uid; 959 } else { 960 msg = "Permission Denial: starting " + intent.toString() 961 + " from " + callerApp + " (pid=" + callingPid 962 + ", uid=" + callingUid + ")" 963 + " requires " + aInfo.permission; 964 } 965 Slog.w(TAG, msg); 966 throw new SecurityException(msg); 967 } 968 969 boolean abort = !mService.mIntentFirewall.checkStartActivity(intent, 970 callerApp==null?null:callerApp.info, callingUid, callingPid, resolvedType, aInfo); 971 972 if (mService.mController != null) { 973 try { 974 // The Intent we give to the watcher has the extra data 975 // stripped off, since it can contain private information. 976 Intent watchIntent = intent.cloneFilter(); 977 abort |= !mService.mController.activityStarting(watchIntent, 978 aInfo.applicationInfo.packageName); 979 } catch (RemoteException e) { 980 mService.mController = null; 981 } 982 } 983 984 if (abort) { 985 if (resultRecord != null) { 986 resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode, 987 Activity.RESULT_CANCELED, null); 988 } 989 // We pretend to the caller that it was really started, but 990 // they will just get a cancel result. 991 setDismissKeyguard(false); 992 ActivityOptions.abort(options); 993 return ActivityManager.START_SUCCESS; 994 } 995 996 ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage, 997 intent, resolvedType, aInfo, mService.mConfiguration, 998 resultRecord, resultWho, requestCode, componentSpecified, this); 999 if (outActivity != null) { 1000 outActivity[0] = r; 1001 } 1002 1003 final ActivityStack stack = getTopStack(); 1004 if (stack.mResumedActivity == null 1005 || stack.mResumedActivity.info.applicationInfo.uid != callingUid) { 1006 if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) { 1007 PendingActivityLaunch pal = 1008 new PendingActivityLaunch(r, sourceRecord, startFlags, stack); 1009 mService.mPendingActivityLaunches.add(pal); 1010 setDismissKeyguard(false); 1011 ActivityOptions.abort(options); 1012 return ActivityManager.START_SWITCHES_CANCELED; 1013 } 1014 } 1015 1016 if (mService.mDidAppSwitch) { 1017 // This is the second allowed switch since we stopped switches, 1018 // so now just generally allow switches. Use case: user presses 1019 // home (switches disabled, switch to home, mDidAppSwitch now true); 1020 // user taps a home icon (coming from home so allowed, we hit here 1021 // and now allow anyone to switch again). 1022 mService.mAppSwitchesAllowedTime = 0; 1023 } else { 1024 mService.mDidAppSwitch = true; 1025 } 1026 1027 mService.doPendingActivityLaunchesLocked(false); 1028 1029 err = startActivityUncheckedLocked(r, sourceRecord, startFlags, true, options); 1030 if (stack.mPausingActivity == null) { 1031 // Someone asked to have the keyguard dismissed on the next 1032 // activity start, but we are not actually doing an activity 1033 // switch... just dismiss the keyguard now, because we 1034 // probably want to see whatever is behind it. 1035 dismissKeyguard(); 1036 } 1037 return err; 1038 } 1039 1040 ActivityStack getCorrectStack(ActivityRecord r) { 1041 if (!r.isHomeActivity) { 1042 if (mStacks.size() == 1) { 1043 // Time to create the first app stack. 1044 int stackId = mService.createStack(-1, HOME_STACK_ID, 1045 StackBox.TASK_STACK_GOES_OVER, 1.0f); 1046 mMainStack = getStack(stackId); 1047 } 1048 return mMainStack; 1049 } 1050 return mHomeStack; 1051 } 1052 1053 final int startActivityUncheckedLocked(ActivityRecord r, 1054 ActivityRecord sourceRecord, int startFlags, boolean doResume, 1055 Bundle options) { 1056 final Intent intent = r.intent; 1057 final int callingUid = r.launchedFromUid; 1058 1059 int launchFlags = intent.getFlags(); 1060 1061 // We'll invoke onUserLeaving before onPause only if the launching 1062 // activity did not explicitly state that this is an automated launch. 1063 mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0; 1064 if (DEBUG_USER_LEAVING) Slog.v(TAG, "startActivity() => mUserLeaving=" + mUserLeaving); 1065 1066 // If the caller has asked not to resume at this point, we make note 1067 // of this in the record so that we can skip it when trying to find 1068 // the top running activity. 1069 if (!doResume) { 1070 r.delayedResume = true; 1071 } 1072 1073 ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null; 1074 1075 // If the onlyIfNeeded flag is set, then we can do this if the activity 1076 // being launched is the same as the one making the call... or, as 1077 // a special case, if we do not know the caller then we count the 1078 // current top activity as the caller. 1079 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) { 1080 ActivityRecord checkedCaller = sourceRecord; 1081 if (checkedCaller == null) { 1082 checkedCaller = getTopStack().topRunningNonDelayedActivityLocked(notTop); 1083 } 1084 if (!checkedCaller.realActivity.equals(r.realActivity)) { 1085 // Caller is not the same as launcher, so always needed. 1086 startFlags &= ~ActivityManager.START_FLAG_ONLY_IF_NEEDED; 1087 } 1088 } 1089 1090 if (sourceRecord == null) { 1091 // This activity is not being started from another... in this 1092 // case we -always- start a new task. 1093 if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) { 1094 Slog.w(TAG, "startActivity called from non-Activity context; forcing Intent.FLAG_ACTIVITY_NEW_TASK for: " 1095 + intent); 1096 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK; 1097 } 1098 } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) { 1099 // The original activity who is starting us is running as a single 1100 // instance... this new activity it is starting must go on its 1101 // own task. 1102 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK; 1103 } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE 1104 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) { 1105 // The activity being started is a single instance... it always 1106 // gets launched into its own task. 1107 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK; 1108 } 1109 1110 final ActivityStack sourceStack; 1111 final TaskRecord sourceTask; 1112 if (sourceRecord != null) { 1113 sourceTask = sourceRecord.task; 1114 sourceStack = sourceTask.stack; 1115 } else { 1116 sourceTask = null; 1117 sourceStack = null; 1118 } 1119 1120 if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) { 1121 // For whatever reason this activity is being launched into a new 1122 // task... yet the caller has requested a result back. Well, that 1123 // is pretty messed up, so instead immediately send back a cancel 1124 // and let the new task continue launched as normal without a 1125 // dependency on its originator. 1126 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result."); 1127 r.resultTo.task.stack.sendActivityResultLocked(-1, 1128 r.resultTo, r.resultWho, r.requestCode, 1129 Activity.RESULT_CANCELED, null); 1130 r.resultTo = null; 1131 } 1132 1133 boolean addingToTask = false; 1134 boolean movedHome = false; 1135 TaskRecord reuseTask = null; 1136 ActivityStack targetStack; 1137 if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 && 1138 (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0) 1139 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK 1140 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) { 1141 // If bring to front is requested, and no result is requested, and 1142 // we can find a task that was started with this same 1143 // component, then instead of launching bring that one to the front. 1144 if (r.resultTo == null) { 1145 // See if there is a task to bring to the front. If this is 1146 // a SINGLE_INSTANCE activity, there can be one and only one 1147 // instance of it in the history, and it is always in its own 1148 // unique task, so we do a special search. 1149 ActivityRecord intentActivity = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE 1150 ? findTaskLocked(intent, r.info) 1151 : findActivityLocked(intent, r.info); 1152 if (intentActivity != null) { 1153 targetStack = intentActivity.task.stack; 1154 moveHomeStack(targetStack.isHomeStack()); 1155 if (intentActivity.task.intent == null) { 1156 // This task was started because of movement of 1157 // the activity based on affinity... now that we 1158 // are actually launching it, we can assign the 1159 // base intent. 1160 intentActivity.task.setIntent(intent, r.info); 1161 } 1162 // If the target task is not in the front, then we need 1163 // to bring it to the front... except... well, with 1164 // SINGLE_TASK_LAUNCH it's not entirely clear. We'd like 1165 // to have the same behavior as if a new instance was 1166 // being started, which means not bringing it to the front 1167 // if the caller is not itself in the front. 1168 ActivityRecord curTop = 1169 targetStack.topRunningNonDelayedActivityLocked(notTop); 1170 if (curTop != null && curTop.task != intentActivity.task) { 1171 r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT); 1172 if (sourceRecord == null || sourceStack.topActivity() == sourceRecord) { 1173 // We really do want to push this one into the 1174 // user's face, right now. 1175 movedHome = true; 1176 if ((launchFlags & 1177 (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME)) 1178 == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME)) { 1179 // Caller wants to appear on home activity, so before starting 1180 // their own activity we will bring home to the front. 1181 r.mLaunchHomeTaskNext = true; 1182 } 1183 targetStack.moveTaskToFrontLocked(intentActivity.task, r, options); 1184 options = null; 1185 } 1186 } 1187 // If the caller has requested that the target task be 1188 // reset, then do so. 1189 if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) { 1190 intentActivity = targetStack.resetTaskIfNeededLocked(intentActivity, r); 1191 } 1192 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) { 1193 // We don't need to start a new activity, and 1194 // the client said not to do anything if that 1195 // is the case, so this is it! And for paranoia, make 1196 // sure we have correctly resumed the top activity. 1197 if (doResume) { 1198 setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack); 1199 targetStack.resumeTopActivityLocked(null, options); 1200 } else { 1201 ActivityOptions.abort(options); 1202 } 1203 return ActivityManager.START_RETURN_INTENT_TO_CALLER; 1204 } 1205 if ((launchFlags & 1206 (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK)) 1207 == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK)) { 1208 // The caller has requested to completely replace any 1209 // existing task with its new activity. Well that should 1210 // not be too hard... 1211 reuseTask = intentActivity.task; 1212 reuseTask.performClearTaskLocked(); 1213 reuseTask.setIntent(r.intent, r.info); 1214 } else if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0 1215 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK 1216 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) { 1217 // In this situation we want to remove all activities 1218 // from the task up to the one being started. In most 1219 // cases this means we are resetting the task to its 1220 // initial state. 1221 ActivityRecord top = 1222 intentActivity.task.performClearTaskLocked(r, launchFlags); 1223 if (top != null) { 1224 if (top.frontOfTask) { 1225 // Activity aliases may mean we use different 1226 // intents for the top activity, so make sure 1227 // the task now has the identity of the new 1228 // intent. 1229 top.task.setIntent(r.intent, r.info); 1230 } 1231 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, 1232 r, top.task); 1233 top.deliverNewIntentLocked(callingUid, r.intent); 1234 } else { 1235 // A special case: we need to 1236 // start the activity because it is not currently 1237 // running, and the caller has asked to clear the 1238 // current task to have this activity at the top. 1239 addingToTask = true; 1240 // Now pretend like this activity is being started 1241 // by the top of its task, so it is put in the 1242 // right place. 1243 sourceRecord = intentActivity; 1244 } 1245 } else if (r.realActivity.equals(intentActivity.task.realActivity)) { 1246 // In this case the top activity on the task is the 1247 // same as the one being launched, so we take that 1248 // as a request to bring the task to the foreground. 1249 // If the top activity in the task is the root 1250 // activity, deliver this new intent to it if it 1251 // desires. 1252 if (((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0 1253 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) 1254 && intentActivity.realActivity.equals(r.realActivity)) { 1255 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, 1256 intentActivity.task); 1257 if (intentActivity.frontOfTask) { 1258 intentActivity.task.setIntent(r.intent, r.info); 1259 } 1260 intentActivity.deliverNewIntentLocked(callingUid, r.intent); 1261 } else if (!r.intent.filterEquals(intentActivity.task.intent)) { 1262 // In this case we are launching the root activity 1263 // of the task, but with a different intent. We 1264 // should start a new instance on top. 1265 addingToTask = true; 1266 sourceRecord = intentActivity; 1267 } 1268 } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) { 1269 // In this case an activity is being launched in to an 1270 // existing task, without resetting that task. This 1271 // is typically the situation of launching an activity 1272 // from a notification or shortcut. We want to place 1273 // the new activity on top of the current task. 1274 addingToTask = true; 1275 sourceRecord = intentActivity; 1276 } else if (!intentActivity.task.rootWasReset) { 1277 // In this case we are launching in to an existing task 1278 // that has not yet been started from its front door. 1279 // The current task has been brought to the front. 1280 // Ideally, we'd probably like to place this new task 1281 // at the bottom of its stack, but that's a little hard 1282 // to do with the current organization of the code so 1283 // for now we'll just drop it. 1284 intentActivity.task.setIntent(r.intent, r.info); 1285 } 1286 if (!addingToTask && reuseTask == null) { 1287 // We didn't do anything... but it was needed (a.k.a., client 1288 // don't use that intent!) And for paranoia, make 1289 // sure we have correctly resumed the top activity. 1290 if (doResume) { 1291 setLaunchHomeTaskNextFlag(sourceRecord, intentActivity, targetStack); 1292 targetStack.resumeTopActivityLocked(null, options); 1293 } else { 1294 ActivityOptions.abort(options); 1295 } 1296 return ActivityManager.START_TASK_TO_FRONT; 1297 } 1298 } 1299 } 1300 } 1301 1302 //String uri = r.intent.toURI(); 1303 //Intent intent2 = new Intent(uri); 1304 //Slog.i(TAG, "Given intent: " + r.intent); 1305 //Slog.i(TAG, "URI is: " + uri); 1306 //Slog.i(TAG, "To intent: " + intent2); 1307 1308 if (r.packageName != null) { 1309 // If the activity being launched is the same as the one currently 1310 // at the top, then we need to check if it should only be launched 1311 // once. 1312 ActivityStack topStack = getTopStack(); 1313 ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(notTop); 1314 if (top != null && r.resultTo == null) { 1315 if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) { 1316 if (top.app != null && top.app.thread != null) { 1317 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0 1318 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP 1319 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) { 1320 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, top, 1321 top.task); 1322 // For paranoia, make sure we have correctly 1323 // resumed the top activity. 1324 if (doResume) { 1325 setLaunchHomeTaskNextFlag(sourceRecord, null, topStack); 1326 topStack.resumeTopActivityLocked(null); 1327 } 1328 ActivityOptions.abort(options); 1329 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) { 1330 // We don't need to start a new activity, and 1331 // the client said not to do anything if that 1332 // is the case, so this is it! 1333 return ActivityManager.START_RETURN_INTENT_TO_CALLER; 1334 } 1335 top.deliverNewIntentLocked(callingUid, r.intent); 1336 return ActivityManager.START_DELIVERED_TO_TOP; 1337 } 1338 } 1339 } 1340 } 1341 1342 } else { 1343 if (r.resultTo != null) { 1344 r.resultTo.task.stack.sendActivityResultLocked(-1, r.resultTo, r.resultWho, 1345 r.requestCode, Activity.RESULT_CANCELED, null); 1346 } 1347 ActivityOptions.abort(options); 1348 return ActivityManager.START_CLASS_NOT_FOUND; 1349 } 1350 1351 boolean newTask = false; 1352 boolean keepCurTransition = false; 1353 1354 // Should this be considered a new task? 1355 if (r.resultTo == null && !addingToTask 1356 && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) { 1357 targetStack = getCorrectStack(r); 1358 moveHomeStack(targetStack.isHomeStack()); 1359 if (reuseTask == null) { 1360 r.setTask(targetStack.createTaskRecord(getNextTaskId(), r.info, intent, true), 1361 null, true); 1362 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r + " in new task " + 1363 r.task); 1364 } else { 1365 r.setTask(reuseTask, reuseTask, true); 1366 } 1367 newTask = true; 1368 if (!movedHome) { 1369 if ((launchFlags & 1370 (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME)) 1371 == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME)) { 1372 // Caller wants to appear on home activity, so before starting 1373 // their own activity we will bring home to the front. 1374 r.mLaunchHomeTaskNext = true; 1375 } 1376 } 1377 } else if (sourceRecord != null) { 1378 targetStack = sourceRecord.task.stack; 1379 moveHomeStack(targetStack.isHomeStack()); 1380 if (!addingToTask && 1381 (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) { 1382 // In this case, we are adding the activity to an existing 1383 // task, but the caller has asked to clear that task if the 1384 // activity is already running. 1385 ActivityRecord top = sourceRecord.task.performClearTaskLocked(r, launchFlags); 1386 keepCurTransition = true; 1387 if (top != null) { 1388 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task); 1389 top.deliverNewIntentLocked(callingUid, r.intent); 1390 // For paranoia, make sure we have correctly 1391 // resumed the top activity. 1392 if (doResume) { 1393 setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack); 1394 targetStack.resumeTopActivityLocked(null); 1395 } 1396 ActivityOptions.abort(options); 1397 return ActivityManager.START_DELIVERED_TO_TOP; 1398 } 1399 } else if (!addingToTask && 1400 (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) { 1401 // In this case, we are launching an activity in our own task 1402 // that may already be running somewhere in the history, and 1403 // we want to shuffle it to the front of the stack if so. 1404 final ActivityRecord top = 1405 targetStack.findActivityInHistoryLocked(r, sourceRecord.task); 1406 if (top != null) { 1407 final TaskRecord task = top.task; 1408 task.moveActivityToFrontLocked(top); 1409 ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, task); 1410 top.updateOptionsLocked(options); 1411 top.deliverNewIntentLocked(callingUid, r.intent); 1412 if (doResume) { 1413 setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack); 1414 targetStack.resumeTopActivityLocked(null); 1415 } 1416 return ActivityManager.START_DELIVERED_TO_TOP; 1417 } 1418 } 1419 // An existing activity is starting this new activity, so we want 1420 // to keep the new one in the same task as the one that is starting 1421 // it. 1422 r.setTask(sourceRecord.task, sourceRecord.thumbHolder, false); 1423 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r 1424 + " in existing task " + r.task); 1425 1426 } else { 1427 // This not being started from an existing activity, and not part 1428 // of a new task... just put it in the top task, though these days 1429 // this case should never happen. 1430 targetStack = getLastStack(); 1431 moveHomeStack(targetStack.isHomeStack()); 1432 ActivityRecord prev = targetStack.topActivity(); 1433 r.setTask(prev != null ? prev.task 1434 : targetStack.createTaskRecord(getNextTaskId(), r.info, intent, true), 1435 null, true); 1436 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r 1437 + " in new guessed " + r.task); 1438 } 1439 1440 mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName, 1441 intent, r.getUriPermissionsLocked()); 1442 1443 if (newTask) { 1444 EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.userId, r.task.taskId); 1445 } 1446 ActivityStack.logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task); 1447 setLaunchHomeTaskNextFlag(sourceRecord, r, targetStack); 1448 targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options); 1449 return ActivityManager.START_SUCCESS; 1450 } 1451 1452 void handleAppDiedLocked(ProcessRecord app, boolean restarting) { 1453 // Just in case. 1454 final int numStacks = mStacks.size(); 1455 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 1456 mStacks.get(stackNdx).handleAppDiedLocked(app, restarting); 1457 } 1458 } 1459 1460 void closeSystemDialogsLocked() { 1461 final int numStacks = mStacks.size(); 1462 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 1463 final ActivityStack stack = mStacks.get(stackNdx); 1464 stack.closeSystemDialogsLocked(); 1465 } 1466 } 1467 1468 /** 1469 * @return true if some activity was finished (or would have finished if doit were true). 1470 */ 1471 boolean forceStopPackageLocked(String name, boolean doit, boolean evenPersistent, int userId) { 1472 boolean didSomething = false; 1473 final int numStacks = mStacks.size(); 1474 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 1475 final ActivityStack stack = mStacks.get(stackNdx); 1476 if (stack.forceStopPackageLocked(name, doit, evenPersistent, userId)) { 1477 didSomething = true; 1478 } 1479 } 1480 return didSomething; 1481 } 1482 1483 void resumeTopActivityLocked() { 1484 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { 1485 mStacks.get(stackNdx).resumeTopActivityLocked(null); 1486 } 1487 } 1488 1489 void finishTopRunningActivityLocked(ProcessRecord app) { 1490 final int numStacks = mStacks.size(); 1491 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 1492 final ActivityStack stack = mStacks.get(stackNdx); 1493 stack.finishTopRunningActivityLocked(app); 1494 } 1495 } 1496 1497 void scheduleIdleLocked() { 1498 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { 1499 mStacks.get(stackNdx).scheduleIdleLocked(); 1500 } 1501 } 1502 1503 void findTaskToMoveToFrontLocked(int taskId, int flags, Bundle options) { 1504 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { 1505 if (mStacks.get(stackNdx).findTaskToMoveToFrontLocked(taskId, flags, options)) { 1506 return; 1507 } 1508 } 1509 } 1510 1511 ActivityStack getStack(int stackId) { 1512 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { 1513 final ActivityStack stack = mStacks.get(stackNdx); 1514 if (stack.getStackId() == stackId) { 1515 return stack; 1516 } 1517 } 1518 return null; 1519 } 1520 1521 ArrayList<ActivityStack> getStacks() { 1522 return new ArrayList<ActivityStack>(mStacks); 1523 } 1524 1525 int createStack() { 1526 synchronized (this) { 1527 while (true) { 1528 if (++mLastStackId <= HOME_STACK_ID) { 1529 mLastStackId = HOME_STACK_ID + 1; 1530 } 1531 if (getStack(mLastStackId) == null) { 1532 break; 1533 } 1534 } 1535 mStacks.add(new ActivityStack(mService, mContext, mLooper, mLastStackId, this, 1536 mCurrentUser)); 1537 return mLastStackId; 1538 } 1539 } 1540 1541 void moveTaskToStack(int taskId, int stackId, boolean toTop) { 1542 final ActivityStack stack = getStack(stackId); 1543 if (stack == null) { 1544 Slog.w(TAG, "moveTaskToStack: no stack for id=" + stackId); 1545 return; 1546 } 1547 stack.moveTask(taskId, toTop); 1548 stack.resumeTopActivityLocked(null); 1549 } 1550 1551 ActivityRecord findTaskLocked(Intent intent, ActivityInfo info) { 1552 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { 1553 final ActivityRecord ar = mStacks.get(stackNdx).findTaskLocked(intent, info); 1554 if (ar != null) { 1555 return ar; 1556 } 1557 } 1558 return null; 1559 } 1560 1561 ActivityRecord findActivityLocked(Intent intent, ActivityInfo info) { 1562 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { 1563 final ActivityRecord ar = mStacks.get(stackNdx).findActivityLocked(intent, info); 1564 if (ar != null) { 1565 return ar; 1566 } 1567 } 1568 return null; 1569 } 1570 1571 void goingToSleepLocked() { 1572 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { 1573 mStacks.get(stackNdx).stopIfSleepingLocked(); 1574 } 1575 } 1576 1577 boolean shutdownLocked(int timeout) { 1578 boolean timedout = false; 1579 final int numStacks = mStacks.size(); 1580 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 1581 final ActivityStack stack = mStacks.get(stackNdx); 1582 if (stack.mResumedActivity != null) { 1583 stack.stopIfSleepingLocked(); 1584 final long endTime = System.currentTimeMillis() + timeout; 1585 while (stack.mResumedActivity != null || stack.mPausingActivity != null) { 1586 long delay = endTime - System.currentTimeMillis(); 1587 if (delay <= 0) { 1588 Slog.w(TAG, "Activity manager shutdown timed out"); 1589 timedout = true; 1590 break; 1591 } 1592 try { 1593 mService.wait(); 1594 } catch (InterruptedException e) { 1595 } 1596 } 1597 } 1598 } 1599 return timedout; 1600 } 1601 1602 void comeOutOfSleepIfNeededLocked() { 1603 final boolean homeIsBack = !homeIsInFront(); 1604 final int numStacks = mStacks.size(); 1605 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 1606 final ActivityStack stack = mStacks.get(stackNdx); 1607 if (stack.isHomeStack() ^ homeIsBack) { 1608 stack.awakeFromSleepingLocked(); 1609 stack.resumeTopActivityLocked(null); 1610 } 1611 } 1612 } 1613 1614 void handleAppCrashLocked(ProcessRecord app) { 1615 final int numStacks = mStacks.size(); 1616 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 1617 final ActivityStack stack = mStacks.get(stackNdx); 1618 stack.handleAppCrashLocked(app); 1619 } 1620 } 1621 1622 void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges) { 1623 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { 1624 mStacks.get(stackNdx).ensureActivitiesVisibleLocked(starting, configChanges); 1625 } 1626 } 1627 1628 void scheduleDestroyAllActivities(ProcessRecord app, String reason) { 1629 final int numStacks = mStacks.size(); 1630 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 1631 final ActivityStack stack = mStacks.get(stackNdx); 1632 stack.scheduleDestroyActivities(app, false, reason); 1633 } 1634 } 1635 1636 boolean switchUserLocked(int userId, UserStartedState uss) { 1637 mCurrentUser = userId; 1638 boolean homeInBack = !homeIsInFront(); 1639 boolean haveActivities = false; 1640 final int numStacks = mStacks.size(); 1641 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 1642 final ActivityStack stack = mStacks.get(stackNdx); 1643 if (stack.isHomeStack() ^ homeInBack) { 1644 haveActivities |= stack.switchUserLocked(userId, uss); 1645 } 1646 } 1647 return haveActivities; 1648 } 1649 1650 final ArrayList<ActivityRecord> processStoppingActivitiesLocked(boolean remove) { 1651 int N = mStoppingActivities.size(); 1652 if (N <= 0) return null; 1653 1654 ArrayList<ActivityRecord> stops = null; 1655 1656 final boolean nowVisible = allResumedActivitiesVisible(); 1657 for (int i=0; i<N; i++) { 1658 ActivityRecord s = mStoppingActivities.get(i); 1659 if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible=" 1660 + nowVisible + " waitingVisible=" + s.waitingVisible 1661 + " finishing=" + s.finishing); 1662 if (s.waitingVisible && nowVisible) { 1663 mWaitingVisibleActivities.remove(s); 1664 s.waitingVisible = false; 1665 if (s.finishing) { 1666 // If this activity is finishing, it is sitting on top of 1667 // everyone else but we now know it is no longer needed... 1668 // so get rid of it. Otherwise, we need to go through the 1669 // normal flow and hide it once we determine that it is 1670 // hidden by the activities in front of it. 1671 if (localLOGV) Slog.v(TAG, "Before stopping, can hide: " + s); 1672 mService.mWindowManager.setAppVisibility(s.appToken, false); 1673 } 1674 } 1675 if ((!s.waitingVisible || mService.isSleepingOrShuttingDown()) && remove) { 1676 if (localLOGV) Slog.v(TAG, "Ready to stop: " + s); 1677 if (stops == null) { 1678 stops = new ArrayList<ActivityRecord>(); 1679 } 1680 stops.add(s); 1681 mStoppingActivities.remove(i); 1682 N--; 1683 i--; 1684 } 1685 } 1686 1687 return stops; 1688 } 1689 1690 public void dump(PrintWriter pw, String prefix) { 1691 pw.print(prefix); pw.print("mDismissKeyguardOnNextActivity:"); 1692 pw.println(mDismissKeyguardOnNextActivity); 1693 } 1694 1695 ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) { 1696 return getTopStack().getDumpActivitiesLocked(name); 1697 } 1698 1699 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll, 1700 boolean dumpClient, String dumpPackage) { 1701 final int numStacks = mStacks.size(); 1702 for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) { 1703 final ActivityStack stack = mStacks.get(stackNdx); 1704 pw.print(" Stack #"); pw.print(mStacks.indexOf(stack)); pw.println(":"); 1705 stack.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage); 1706 pw.println(" "); 1707 pw.println(" Running activities (most recent first):"); 1708 dumpHistoryList(fd, pw, stack.mLRUActivities, " ", "Run", false, !dumpAll, false, 1709 dumpPackage); 1710 if (stack.mGoingToSleepActivities.size() > 0) { 1711 pw.println(" "); 1712 pw.println(" Activities waiting to sleep:"); 1713 dumpHistoryList(fd, pw, stack.mGoingToSleepActivities, " ", "Sleep", false, 1714 !dumpAll, false, dumpPackage); 1715 } 1716 if (stack.mFinishingActivities.size() > 0) { 1717 pw.println(" "); 1718 pw.println(" Activities waiting to finish:"); 1719 dumpHistoryList(fd, pw, stack.mFinishingActivities, " ", "Fin", false, 1720 !dumpAll, false, dumpPackage); 1721 } 1722 1723 pw.print(" Stack #"); pw.println(mStacks.indexOf(stack)); 1724 if (stack.mPausingActivity != null) { 1725 pw.println(" mPausingActivity: " + stack.mPausingActivity); 1726 } 1727 pw.println(" mResumedActivity: " + stack.mResumedActivity); 1728 if (dumpAll) { 1729 pw.println(" mLastPausedActivity: " + stack.mLastPausedActivity); 1730 pw.println(" mSleepTimeout: " + stack.mSleepTimeout); 1731 } 1732 } 1733 1734 if (mStoppingActivities.size() > 0) { 1735 pw.println(" "); 1736 pw.println(" Activities waiting to stop:"); 1737 dumpHistoryList(fd, pw, mStoppingActivities, " ", "Stop", false, !dumpAll, false, 1738 dumpPackage); 1739 } 1740 1741 if (mWaitingVisibleActivities.size() > 0) { 1742 pw.println(" "); 1743 pw.println(" Activities waiting for another to become visible:"); 1744 dumpHistoryList(fd, pw, mWaitingVisibleActivities, " ", "Wait", false, !dumpAll, 1745 false, dumpPackage); 1746 } 1747 1748 if (dumpAll) { 1749 pw.println(" "); 1750 pw.println(" mCurTaskId: " + mCurTaskId); 1751 } 1752 return true; 1753 } 1754 1755 static final void dumpHistoryList(FileDescriptor fd, PrintWriter pw, List<ActivityRecord> list, 1756 String prefix, String label, boolean complete, boolean brief, boolean client, 1757 String dumpPackage) { 1758 TaskRecord lastTask = null; 1759 boolean needNL = false; 1760 final String innerPrefix = prefix + " "; 1761 final String[] args = new String[0]; 1762 for (int i=list.size()-1; i>=0; i--) { 1763 final ActivityRecord r = list.get(i); 1764 if (dumpPackage != null && !dumpPackage.equals(r.packageName)) { 1765 continue; 1766 } 1767 final boolean full = !brief && (complete || !r.isInHistory()); 1768 if (needNL) { 1769 pw.println(" "); 1770 needNL = false; 1771 } 1772 if (lastTask != r.task) { 1773 lastTask = r.task; 1774 pw.print(prefix); 1775 pw.print(full ? "* " : " "); 1776 pw.println(lastTask); 1777 if (full) { 1778 lastTask.dump(pw, prefix + " "); 1779 } else if (complete) { 1780 // Complete + brief == give a summary. Isn't that obvious?!? 1781 if (lastTask.intent != null) { 1782 pw.print(prefix); pw.print(" "); 1783 pw.println(lastTask.intent.toInsecureStringWithClip()); 1784 } 1785 } 1786 } 1787 pw.print(prefix); pw.print(full ? " * " : " "); pw.print(label); 1788 pw.print(" #"); pw.print(i); pw.print(": "); 1789 pw.println(r); 1790 if (full) { 1791 r.dump(pw, innerPrefix); 1792 } else if (complete) { 1793 // Complete + brief == give a summary. Isn't that obvious?!? 1794 pw.print(innerPrefix); pw.println(r.intent.toInsecureString()); 1795 if (r.app != null) { 1796 pw.print(innerPrefix); pw.println(r.app); 1797 } 1798 } 1799 if (client && r.app != null && r.app.thread != null) { 1800 // flush anything that is already in the PrintWriter since the thread is going 1801 // to write to the file descriptor directly 1802 pw.flush(); 1803 try { 1804 TransferPipe tp = new TransferPipe(); 1805 try { 1806 r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(), 1807 r.appToken, innerPrefix, args); 1808 // Short timeout, since blocking here can 1809 // deadlock with the application. 1810 tp.go(fd, 2000); 1811 } finally { 1812 tp.kill(); 1813 } 1814 } catch (IOException e) { 1815 pw.println(innerPrefix + "Failure while dumping the activity: " + e); 1816 } catch (RemoteException e) { 1817 pw.println(innerPrefix + "Got a RemoteException while dumping the activity"); 1818 } 1819 needNL = true; 1820 } 1821 } 1822 } 1823} 1824