前言
本周重点介绍上章末尾resumeTopActivityInnerLocked接口中的一些逻辑
相关逻辑
ActivityStack#allPausedActivitiesComplete
只要有一个Activity不处于r.isState(PAUSED, STOPPED, STOPPING)状态,就等待
1100 boolean allPausedActivitiesComplete() {
1101 boolean pausing = true;
1102 for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
1103 final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
1104 for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
1105 final ActivityStack stack = display.getChildAt(stackNdx);
1106 final ActivityRecord r = stack.mPausingActivity;
1107 if (r != null && !r.isState(PAUSED, STOPPED, STOPPING)) {
1108 if (DEBUG_STATES) {
1109 Slog.d(TAG_STATES,
1110 "allPausedActivitiesComplete: r=" + r + " state=" + r.getState());
1111 pausing = false;
1112 } else {
1113 return false;
1114 }
1115 }
1116 }
1117 }
1118 return pausing;
1119 }
ActivityStack#pauseBackStacks
对后台stack中原来的resumed Activity执行startPausingLocked操作,针对startActivity的过程中切换了stack的情况
1075 /**
1076 * Pause all activities in either all of the stacks or just the back stacks.
1077 * @param userLeaving Passed to pauseActivity() to indicate whether to call onUserLeaving().
1078 * @param resuming The resuming activity.
1079 * @param dontWait The resuming activity isn't going to wait for all activities to be paused
1080 * before resuming.
1081 * @return true if any activity was paused as a result of this call.
1082 */
1083 boolean pauseBackStacks(boolean userLeaving, ActivityRecord resuming, boolean dontWait) {
1084 boolean someActivityPaused = false;
1085 for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
1086 final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
1087 for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
1088 final ActivityStack stack = display.getChildAt(stackNdx);
1089 if (!isFocusedStack(stack) && stack.getResumedActivity() != null) {
1090 if (DEBUG_STATES) Slog.d(TAG_STATES, "pauseBackStacks: stack=" + stack +
1091 " mResumedActivity=" + stack.getResumedActivity());
1092 someActivityPaused |= stack.startPausingLocked(userLeaving, false, resuming,
1093 dontWait);
1094 }
1095 }
1096 }
1097 return someActivityPaused;
1098 }
注意,stack.getResumedActivity返回相应的 mResumedActivity 属性,在startPausingLocked中会置为null
ActivityStack#startPausingLocked
1408 /**
1409 * Start pausing the currently resumed activity. It is an error to call this if there
1410 * is already an activity being paused or there is no resumed activity.
1411 *
1412 * @param userLeaving True if this should result in an onUserLeaving to the current activity.
1413 * @param uiSleeping True if this is happening with the user interface going to sleep (the
1414 * screen turning off).
1415 * @param resuming The activity we are currently trying to resume or null if this is not being
1416 * called as part of resuming the top activity, so we shouldn't try to instigate
1417 * a resume here if not null.
1418 * @param pauseImmediately True if the caller does not want to wait for the activity callback to
1419 * complete pausing.
1420 * @return Returns true if an activity now is in the PAUSING state, and we are waiting for
1421 * it to tell us when it is done.
1422 */
1423 final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping,
1424 ActivityRecord resuming, boolean pauseImmediately) {
1425 if (mPausingActivity != null) {
1426 Slog.wtf(TAG, "Going to pause when pause is already pending for " + mPausingActivity
1427 + " state=" + mPausingActivity.getState());
1428 if (!shouldSleepActivities()) {
1429 // Avoid recursion among check for sleep and complete pause during sleeping.
1430 // Because activity will be paused immediately after resume, just let pause
1431 // be completed by the order of activity paused from clients.
1432 completePauseLocked(false, resuming); //如果stack中有正在pausing的Activity,那么直接走completePauseLocked逻辑
1433 }
1434 }
1435 ActivityRecord prev = mResumedActivity; //将当前stack的resumed Activity保存下来
1436
1437 if (prev == null) {
1438 if (resuming == null) {
1439 Slog.wtf(TAG, "Trying to pause when nothing is resumed");
1440 mStackSupervisor.resumeFocusedStackTopActivityLocked();
1441 }
1442 return false;
1443 }
1444
1445 if (prev == resuming) {
1446 Slog.wtf(TAG, "Trying to pause activity that is in process of being resumed");
1447 return false;
1448 }
1449
1450 if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to PAUSING: " + prev);
1451 else if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Start pausing: " + prev);
1452
1453 if (mActivityTrigger != null) {
1454 mActivityTrigger.activityPauseTrigger(prev.intent, prev.info, prev.appInfo);
1455 }
1456
1457 if (mActivityPluginDelegate != null && getWindowingMode() != WINDOWING_MODE_UNDEFINED) {
1458 mActivityPluginDelegate.activitySuspendNotification
1459 (prev.appInfo.packageName, getWindowingMode() == WINDOWING_MODE_FULLSCREEN, true);
1460 }
1461
1462 mResumedActivity = null; //mResumedActivity置空
1463 mPausingActivity = prev; //mPausingActivity为上一个resumed的Activity
1464 mLastPausedActivity = prev;
1465 mLastNoHistoryActivity = (prev.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
1466 || (prev.info.flags & ActivityInfo.FLAG_NO_HISTORY) != 0 ? prev : null;
1467 prev.setState(PAUSING, "startPausingLocked");
1468 prev.getTask().touchActiveTime();
1469 clearLaunchTime(prev);
1470
1471 mStackSupervisor.getLaunchTimeTracker().stopFullyDrawnTraceIfNeeded(getWindowingMode());
1472
1473 mService.updateCpuStats();
1474
1475 if (prev.app != null && prev.app.thread != null) {
1476 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending pause: " + prev);
1477 try {
1478 EventLogTags.writeAmPauseActivity(prev.userId, System.identityHashCode(prev),
1479 prev.shortComponentName, "userLeaving=" + userLeaving);
1480 mService.updateUsageStats(prev, false);
1481
1482 mService.getLifecycleManager().scheduleTransaction(prev.app.thread, prev.appToken,
1483 PauseActivityItem.obtain(prev.finishing, userLeaving,
1484 prev.configChangeFlags, pauseImmediately)); //相当于执行PauseActivityItem 的excuete
1485 } catch (Exception e) {
1486 // Ignore exception, if process died other code will cleanup.
1487 Slog.w(TAG, "Exception thrown during pause", e);
1488 mPausingActivity = null;
1489 mLastPausedActivity = null;
1490 mLastNoHistoryActivity = null;
1491 }
1492 } else {
1493 mPausingActivity = null;
1494 mLastPausedActivity = null;
1495 mLastNoHistoryActivity = null;
1496 }
1497
1498 // If we are not going to sleep, we want to ensure the device is
1499 // awake until the next activity is started.
1500 if (!uiSleeping && !mService.isSleepingOrShuttingDownLocked()) {
1501 mStackSupervisor.acquireLaunchWakelock();
1502 }
1503
1504 if (mPausingActivity != null) {
1505 // Have the window manager pause its key dispatching until the new
1506 // activity has started. If we're pausing the activity just because
1507 // the screen is being turned off and the UI is sleeping, don't interrupt
1508 // key dispatch; the same activity will pick it up again on wakeup.
1509 if (!uiSleeping) {
1510 prev.pauseKeyDispatchingLocked();
1511 } else if (DEBUG_PAUSE) {
1512 Slog.v(TAG_PAUSE, "Key dispatch not paused for screen off");
1513 }
1514
1515 if (pauseImmediately) {
1516 // If the caller said they don't want to wait for the pause, then complete
1517 // the pause now.
1518 completePauseLocked(false, resuming); //立即开始执行 completePauseLocked,并返回false,代表此时要pause的Activity已经不处于pausing状态
//因为进入了completePauseLocked立即就会将pausing状态改为paused状态
1519 return false;
1520
1521 } else {
1522 schedulePauseTimeout(prev);
1523 return true; //此时prev处于pausing状态
1524 }
1525
1526 } else {
1527 // This activity failed to schedule the
1528 // pause, so just treat it as being paused now.
1529 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Activity not running, resuming next.");
1530 if (resuming == null) {
1531 mStackSupervisor.resumeFocusedStackTopActivityLocked();
1532 }
1533 return false;
1534 }
1535 }
pause的相关逻辑
PauseActivityItem
28/**
29 * Request to move an activity to paused state.
30 * @hide
31 */
32public class PauseActivityItem extends ActivityLifecycleItem {
33
34 private static final String TAG = "PauseActivityItem";
35
36 private boolean mFinished;
37 private boolean mUserLeaving;
38 private int mConfigChanges;
39 private boolean mDontReport;
40
41 @Override
42 public void execute(ClientTransactionHandler client, IBinder token,
43 PendingTransactionActions pendingActions) {
44 Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
45 client.handlePauseActivity(token, mFinished, mUserLeaving, mConfigChanges, pendingActions,
46 "PAUSE_ACTIVITY_ITEM");
47 Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
48 }
ActivityThread#handlePauseActivity
3931 @Override
3932 public void handlePauseActivity(IBinder token, boolean finished, boolean userLeaving,
3933 int configChanges, PendingTransactionActions pendingActions, String reason) {
3934 ActivityClientRecord r = mActivities.get(token);
3935 if (r != null) {
3936 if (userLeaving) {
3937 performUserLeavingActivity(r);
3938 }
3939
3940 r.activity.mConfigChangeFlags |= configChanges;
3941 performPauseActivity(r, finished, reason, pendingActions);
3942
3943 // Make sure any pending writes are now committed.
3944 if (r.isPreHoneycomb()) {
3945 QueuedWork.waitToFinish();
3946 }
3947 mSomeActivitiesChanged = true;
3948 }
3949 }
ActivityThread#performPauseActivity
3955 final Bundle performPauseActivity(IBinder token, boolean finished, String reason,
3956 PendingTransactionActions pendingActions) {
3957 ActivityClientRecord r = mActivities.get(token);
3958 return r != null ? performPauseActivity(r, finished, reason, pendingActions) : null;
3959 }
3960
3961 /**
3962 * Pause the activity.
3963 * @return Saved instance state for pre-Honeycomb apps if it was saved, {@code null} otherwise.
3964 */
3965 private Bundle performPauseActivity(ActivityClientRecord r, boolean finished, String reason,
3966 PendingTransactionActions pendingActions) {
3967 if (r.paused) {
3968 if (r.activity.mFinished) {
3969 // If we are finishing, we won't call onResume() in certain cases.
3970 // So here we likewise don't want to call onPause() if the activity
3971 // isn't resumed.
3972 return null;
3973 }
3974 RuntimeException e = new RuntimeException(
3975 "Performing pause of activity that is not resumed: "
3976 + r.intent.getComponent().toShortString());
3977 Slog.e(TAG, e.getMessage(), e);
3978 }
3979 if (finished) {
3980 r.activity.mFinished = true;
3981 }
3982
3983 // Pre-Honeycomb apps always save their state before pausing
3984 final boolean shouldSaveState = !r.activity.mFinished && r.isPreHoneycomb();
3985 if (shouldSaveState) {
3986 callActivityOnSaveInstanceState(r);
3987 }
3988
3989 performPauseActivityIfNeeded(r, reason);
3990
3991 // Notify any outstanding on paused listeners
3992 ArrayList<OnActivityPausedListener> listeners;
3993 synchronized (mOnPauseListeners) {
3994 listeners = mOnPauseListeners.remove(r.activity);
3995 }
3996 int size = (listeners != null ? listeners.size() : 0);
3997 for (int i = 0; i < size; i++) {
3998 listeners.get(i).onPaused(r.activity);
3999 }
4000
4001 final Bundle oldState = pendingActions != null ? pendingActions.getOldState() : null;
4002 if (oldState != null) {
4003 // We need to keep around the original state, in case we need to be created again.
4004 // But we only do this for pre-Honeycomb apps, which always save their state when
4005 // pausing, so we can not have them save their state when restarting from a paused
4006 // state. For HC and later, we want to (and can) let the state be saved as the
4007 // normal part of stopping the activity.
4008 if (r.isPreHoneycomb()) {
4009 r.state = oldState;
4010 }
4011 }
4012
4013 return shouldSaveState ? r.state : null;
4014 }
4015
4016 private void performPauseActivityIfNeeded(ActivityClientRecord r, String reason) {
4017 if (r.paused) {
4018 // You are already paused silly...
4019 return;
4020 }
4021
4022 try {
4023 r.activity.mCalled = false;
4024 mInstrumentation.callActivityOnPause(r.activity);
4025 if (!r.activity.mCalled) {
4026 throw new SuperNotCalledException("Activity " + safeToComponentShortString(r.intent)
4027 + " did not call through to super.onPause()");
4028 }
4029 } catch (SuperNotCalledException e) {
4030 throw e;
4031 } catch (Exception e) {
4032 if (!mInstrumentation.onException(r.activity, e)) {
4033 throw new RuntimeException("Unable to pause activity "
4034 + safeToComponentShortString(r.intent) + ": " + e.toString(), e);
4035 }
4036 }
4037 r.setState(ON_PAUSE);
4038 }
ActivityStack#schedulePauseTimeout
1396 /**
1397 * Schedule a pause timeout in case the app doesn't respond. We don't give it much time because
1398 * this directly impacts the responsiveness seen by the user.
1399 */
1400 private void schedulePauseTimeout(ActivityRecord r) {
1401 final Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);
1402 msg.obj = r;
1403 r.pauseTime = SystemClock.uptimeMillis();
1404 mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
1405 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Waiting for pause to complete...");
1406 }
394 @Override
395 public void handleMessage(Message msg) {
396 switch (msg.what) {
397 case PAUSE_TIMEOUT_MSG: {
398 ActivityRecord r = (ActivityRecord)msg.obj;
399 // We don't at this point know if the activity is fullscreen,
400 // so we need to be conservative and assume it isn't.
401 Slog.w(TAG, "Activity pause timeout for " + r);
402 synchronized (mService) {
403 if (r.app != null) {
404 mService.logAppTooSlow(r.app, r.pauseTime, "pausing " + r);
405 }
406 activityPausedLocked(r.appToken, true); //为true代表真的超时了
407 }
408 } break;
ActivityManagerService#activityPaused
PauseActivityItem执行完excute之后会执行相应的postExecute
lifecycleItem.postExecute(mTransactionHandler, token, mPendingActions);
55 @Override
56 public void postExecute(ClientTransactionHandler client, IBinder token,
57 PendingTransactionActions pendingActions) {
58 if (mDontReport) {
59 return;
60 }
61 try {
62 // TODO(lifecycler): Use interface callback instead of AMS.
63 ActivityManager.getService().activityPaused(token); //调用AMS的activityPaused接口
64 } catch (RemoteException ex) {
65 throw ex.rethrowFromSystemServer();
66 }
67 }
8311 @Override
8312 public final void activityPaused(IBinder token) {
8313 final long origId = Binder.clearCallingIdentity();
8314 synchronized(this) {
8315 ActivityStack stack = ActivityRecord.getStackLocked(token);
8316 if (stack != null) {
8317 stack.activityPausedLocked(token, false); //为false代表pause完成 (类似ANR的原理)
8318 }
8319 }
8320 Binder.restoreCallingIdentity(origId);
8321 }
ActivityStack#activityPausedLocked
1537 final void activityPausedLocked(IBinder token, boolean timeout) {
1538 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE,
1539 "Activity paused: token=" + token + ", timeout=" + timeout);
1540
1541 final ActivityRecord r = isInStackLocked(token);
1542 if (r != null) {
1543 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
//取消超时消息
1544 if (mPausingActivity == r) {
1545 if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to PAUSED: " + r
1546 + (timeout ? " (due to timeout)" : " (pause complete)"));
1547 mService.mWindowManager.deferSurfaceLayout();
1548 try {
1549 completePauseLocked(true /* resumeNext */, null /* resumingActivity */);
1550 } finally {
1551 mService.mWindowManager.continueSurfaceLayout();
1552 }
1553 return;
1554 } else {
1555 EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE,
1556 r.userId, System.identityHashCode(r), r.shortComponentName,
1557 mPausingActivity != null
1558 ? mPausingActivity.shortComponentName : "(none)");
1559 if (r.isState(PAUSING)) {
1560 r.setState(PAUSED, "activityPausedLocked");
1561 if (r.finishing) {
1562 if (DEBUG_PAUSE) Slog.v(TAG,
1563 "Executing finish of failed to pause activity: " + r);
1564 finishCurrentActivityLocked(r, FINISH_AFTER_VISIBLE, false,
1565 "activityPausedLocked");
1566 }
1567 }
1568 }
1569 }
1570 mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
1571 }
不管是因为Activity onPause执行完了直接回调AMS端的activityPaused,还是因为startPausingLocked中的schedulePauseTimeout发送消息PAUSE_TIMEOUT_MSG(运行在ActivityStackHandler,依附于子线程ActivityMananger)都可能触发completePauseLocked,(如果没超时,那么实在AMS中的binder线程中执行,但如果超时了,那么就会在AMS中的ActivityManager线程中执行)在其中将pausing的Activity的state改为PAUSED状态,并根据情况决定是否结束该Activity;参考一个AMS相关的稳定性问题;然后走要resume的Activity的相关流程;
ActivityStack#completePauseLocked
1573 private void completePauseLocked(boolean resumeNext, ActivityRecord resuming) {
1574 ActivityRecord prev = mPausingActivity;
1575 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Complete pause: " + prev);
1576
1577 if (prev != null) {
1578 prev.setWillCloseOrEnterPip(false);
1579 final boolean wasStopping = prev.isState(STOPPING);
1580 prev.setState(PAUSED, "completePausedLocked");
1581 if (prev.finishing) {
1582 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Executing finish of activity: " + prev);
1583 prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE, false,
1584 "completedPausedLocked");
1585 } else if (prev.app != null) {
1586 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueue pending stop if needed: " + prev
1587 + " wasStopping=" + wasStopping + " visible=" + prev.visible);
1588 if (mStackSupervisor.mActivitiesWaitingForVisibleActivity.remove(prev)) {
1589 if (DEBUG_SWITCH || DEBUG_PAUSE) Slog.v(TAG_PAUSE,
1590 "Complete pause, no longer waiting: " + prev);
1591 }
1592 if (prev.deferRelaunchUntilPaused) {
1593 // Complete the deferred relaunch that was waiting for pause to complete.
1594 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Re-launching after pause: " + prev);
1595 prev.relaunchActivityLocked(false /* andResume */,
1596 prev.preserveWindowOnDeferredRelaunch);
1597 } else if (wasStopping) {
1598 // We are also stopping, the stop request must have gone soon after the pause.
1599 // We can't clobber it, because the stop confirmation will not be handled.
1600 // We don't need to schedule another stop, we only need to let it happen.
1601 prev.setState(STOPPING, "completePausedLocked");
1602 } else if (!prev.visible || shouldSleepOrShutDownActivities()) {
1603 // Clear out any deferred client hide we might currently have.
1604 prev.setDeferHidingClient(false);
1605 // If we were visible then resumeTopActivities will release resources before
1606 // stopping.
1607 addToStopping(prev, true /* scheduleIdle */, false /* idleDelayed */);
1608 }
1609 } else {
1610 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "App died during pause, not stopping: " + prev);
1611 prev = null;
1612 }
1613 // It is possible the activity was freezing the screen before it was paused.
1614 // In that case go ahead and remove the freeze this activity has on the screen
1615 // since it is no longer visible.
1616 if (prev != null) {
1617 prev.stopFreezingScreenLocked(true /*force*/);
1618 }
1619 mPausingActivity = null;
1620 }
1621
1622 if (resumeNext) {
1623 final ActivityStack topStack = mStackSupervisor.getFocusedStack();
1624 if (!topStack.shouldSleepOrShutDownActivities()) {
1625 mStackSupervisor.resumeFocusedStackTopActivityLocked(topStack, prev, null); //重新调用resumeFocusedStackTopActivityLocked的逻辑
1626 } else {
1627 checkReadyForSleep();
1628 ActivityRecord top = topStack.topRunningActivityLocked();
1629 if (top == null || (prev != null && top != prev)) {
1630 // If there are no more activities available to run, do resume anyway to start
1631 // something. Also if the top activity on the stack is not the just paused
1632 // activity, we need to go ahead and resume it to ensure we complete an
1633 // in-flight app switch.
1634 mStackSupervisor.resumeFocusedStackTopActivityLocked();
1635 }
1636 }
1637 }
1638
1639 if (prev != null) {
1640 prev.resumeKeyDispatchingLocked();
1641
1642 if (prev.app != null && prev.cpuTimeAtResume > 0
1643 && mService.mBatteryStatsService.isOnBattery()) {
1644 long diff = mService.mProcessCpuTracker.getCpuTimeForPid(prev.app.pid)
1645 - prev.cpuTimeAtResume;
1646 if (diff > 0) {
1647 BatteryStatsImpl bsi = mService.mBatteryStatsService.getActiveStatistics();
1648 synchronized (bsi) {
1649 BatteryStatsImpl.Uid.Proc ps =
1650 bsi.getProcessStatsLocked(prev.info.applicationInfo.uid,
1651 prev.info.packageName);
1652 if (ps != null) {
1653 ps.addForegroundTimeLocked(diff);
1654 }
1655 }
1656 }
1657 }
1658 prev.cpuTimeAtResume = 0; // reset it
1659 }
1660
1661 // Notify when the task stack has changed, but only if visibilities changed (not just
1662 // focus). Also if there is an active pinned stack - we always want to notify it about
1663 // task stack changes, because its positioning may depend on it.
1664 boolean hasPinnedStack = getDisplay() != null && getDisplay().hasPinnedStack();
1665 if (mStackSupervisor.mAppVisibilitiesChangedSinceLastPause
1666 || hasPinnedStack) {
1667 mService.mTaskChangeNotificationController.notifyTaskStackChanged();
1668 mStackSupervisor.mAppVisibilitiesChangedSinceLastPause = false;
1669 }
1670
1671 mStackSupervisor.ensureActivitiesVisibleLocked(resuming, 0, !PRESERVE_WINDOWS); //调整Activity的可见性
1672 }
activityPaused.png
在completePauseLocked之后,上一个resumed Activity已经变成了paused状态,下面重新进行resume的相关操作,会重新走到这里resumeTopActivityInnerLocked,根据是否有复用Activity决定是直接resume,还是创建相关的Activity,再走resume相关逻辑;看第二种情况
else {
2800 // Whoops, need to restart this activity!
2801 if (!next.hasBeenLaunched) {
2802 next.hasBeenLaunched = true;
2803 } else {
2804 if (SHOW_APP_STARTING_PREVIEW) {
2805 next.showStartingWindow(null /* prev */, false /* newTask */,
2806 false /* taskSwich */);
2807 }
2808 if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Restarting: " + next);
2809 }
2810 if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Restarting " + next);
2811 mStackSupervisor.startSpecificActivityLocked(next, true, true); //第一次创建时调用startSpecificActivityLocked
2812 }
ActivityStackSupervisor#startSpecificActivityLocked
1692 void startSpecificActivityLocked(ActivityRecord r,
1693 boolean andResume, boolean checkConfig) {
1694 // Is this activity's application already running?
1695 ProcessRecord app = mService.getProcessRecordLocked(r.processName,
1696 r.info.applicationInfo.uid, true);
1697
1698 getLaunchTimeTracker().setLaunchTime(r);
1699
1700 if (app != null && app.thread != null) {
//Activity对应进程已经启动的情况
1701 try {
1702 if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
1703 || !"android".equals(r.info.packageName)) {
1704 // Don't add this if it is a platform component that is marked
1705 // to run in multiple processes, because this is actually
1706 // part of the framework so doesn't make sense to track as a
1707 // separate apk in the process.
1708 app.addPackage(r.info.packageName, r.info.applicationInfo.longVersionCode,
1709 mService.mProcessStats);
1710 }
1711 realStartActivityLocked(r, app, andResume, checkConfig);
1712 return;
1713 } catch (RemoteException e) {
1714 Slog.w(TAG, "Exception when starting activity "
1715 + r.intent.getComponent().flattenToShortString(), e);
1716 }
1717
1718 // If a dead object exception was thrown -- fall through to
1719 // restart the application.
1720 }
1721
1722 mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
1723 "activity", r.intent.getComponent(), false, false, true);
//对应进程未启动,先启动进程,启动后会启动相应的Activity
1724 }
ActivityStackSupervisor# realStartActivityLocked
1384 final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
1385 boolean andResume, boolean checkConfig) throws RemoteException {
1386
1387 if (!allPausedActivitiesComplete()) {
1388 // While there are activities pausing we skipping starting any new activities until
1389 // pauses are complete. NOTE: that we also do this for activities that are starting in
1390 // the paused state because they will first be resumed then paused on the client side.
1391 if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG_PAUSE,
1392 "realStartActivityLocked: Skipping start of r=" + r
1393 + " some activities pausing...");
1394 return false;
1395 }
1396
1397 final TaskRecord task = r.getTask();
1398 final ActivityStack stack = task.getStack();
1399
1400 beginDeferResume();
1401
1402 try {
1403 r.startFreezingScreenLocked(app, 0);
1404
1405 // schedule launch ticks to collect information about slow apps.
1406 r.startLaunchTickingLocked();
1407
1408 r.setProcess(app); //为ActivityRecord设置app属性
1409
1410 if (getKeyguardController().isKeyguardLocked()) {
1411 r.notifyUnknownVisibilityLaunched();
1412 }
1413
1414 // Have the window manager re-evaluate the orientation of the screen based on the new
1415 // activity order. Note that as a result of this, it can call back into the activity
1416 // manager with a new orientation. We don't care about that, because the activity is
1417 // not currently running so we are just restarting it anyway.
1418 if (checkConfig) {
1419 // Deferring resume here because we're going to launch new activity shortly.
1420 // We don't want to perform a redundant launch of the same record while ensuring
1421 // configurations and trying to resume top activity of focused stack.
1422 ensureVisibilityAndConfig(r, r.getDisplayId(),
1423 false /* markFrozenIfConfigChanged */, true /* deferResume */);
1424 }
1425
1426 if (r.getStack().checkKeyguardVisibility(r, true /* shouldBeVisible */,
1427 true /* isTop */)) {
1428 // We only set the visibility to true if the activity is allowed to be visible
1429 // based on
1430 // keyguard state. This avoids setting this into motion in window manager that is
1431 // later cancelled due to later calls to ensure visible activities that set
1432 // visibility back to false.
1433 r.setVisibility(true);
1434 }
1435
1436 final int applicationInfoUid =
1437 (r.info.applicationInfo != null) ? r.info.applicationInfo.uid : -1;
1438 if ((r.userId != app.userId) || (r.appInfo.uid != applicationInfoUid)) {
1439 Slog.wtf(TAG,
1440 "User ID for activity changing for " + r
1441 + " appInfo.uid=" + r.appInfo.uid
1442 + " info.ai.uid=" + applicationInfoUid
1443 + " old=" + r.app + " new=" + app);
1444 }
1445
1446 app.waitingToKill = null;
1447 r.launchCount++;
1448 r.lastLaunchTime = SystemClock.uptimeMillis();
1449
1450 if (DEBUG_ALL) Slog.v(TAG, "Launching: " + r);
1451
1452 int idx = app.activities.indexOf(r);
1453 if (idx < 0) {
1454 app.activities.add(r);
1455 }
1456 mService.updateLruProcessLocked(app, true, null);
1457 mService.updateOomAdjLocked();
1458
1459 final LockTaskController lockTaskController = mService.getLockTaskController();
1460 if (task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE
1461 || task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE_PRIV
1462 || (task.mLockTaskAuth == LOCK_TASK_AUTH_WHITELISTED
1463 && lockTaskController.getLockTaskModeState()
1464 == LOCK_TASK_MODE_LOCKED)) {
1465 lockTaskController.startLockTaskMode(task, false, 0 /* blank UID */);
1466 }
1467
1468 try {
1469 if (app.thread == null) {
1470 throw new RemoteException();
1471 }
1472 List<ResultInfo> results = null;
1473 List<ReferrerIntent> newIntents = null;
1474 if (andResume) {
1475 // We don't need to deliver new intents and/or set results if activity is going
1476 // to pause immediately after launch.
1477 results = r.results;
1478 newIntents = r.newIntents;
1479 }
1480 if (DEBUG_SWITCH) Slog.v(TAG_SWITCH,
1481 "Launching: " + r + " icicle=" + r.icicle + " with results=" + results
1482 + " newIntents=" + newIntents + " andResume=" + andResume);
1483 EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY, r.userId,
1484 System.identityHashCode(r), task.taskId, r.shortComponentName);
1485 if (r.isActivityTypeHome()) {
1486 // Home process is the root process of the task.
1487 mService.mHomeProcess = task.mActivities.get(0).app;
1488 }
1489 mService.notifyPackageUse(r.intent.getComponent().getPackageName(),
1490 PackageManager.NOTIFY_PACKAGE_USE_ACTIVITY);
1491 r.sleeping = false;
1492 r.forceNewConfig = false;
1493 mService.getAppWarningsLocked().onStartActivity(r);
1494 mService.showAskCompatModeDialogLocked(r);
1495 r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo);
1496 ProfilerInfo profilerInfo = null;
1497 if (mService.mProfileApp != null && mService.mProfileApp.equals(app.processName)) {
1498 if (mService.mProfileProc == null || mService.mProfileProc == app) {
1499 mService.mProfileProc = app;
1500 ProfilerInfo profilerInfoSvc = mService.mProfilerInfo;
1501 if (profilerInfoSvc != null && profilerInfoSvc.profileFile != null) {
1502 if (profilerInfoSvc.profileFd != null) {
1503 try {
1504 profilerInfoSvc.profileFd = profilerInfoSvc.profileFd.dup();
1505 } catch (IOException e) {
1506 profilerInfoSvc.closeFd();
1507 }
1508 }
1509
1510 profilerInfo = new ProfilerInfo(profilerInfoSvc);
1511 }
1512 }
1513 }
1514
1515 app.hasShownUi = true;
1516 app.pendingUiClean = true;
1517 app.forceProcessStateUpTo(mService.mTopProcessState);
1518 // Because we could be starting an Activity in the system process this may not go
1519 // across a Binder interface which would create a new Configuration. Consequently
1520 // we have to always create a new Configuration here.
1521
1522 final MergedConfiguration mergedConfiguration = new MergedConfiguration(
1523 mService.getGlobalConfiguration(), r.getMergedOverrideConfiguration());
1524 r.setLastReportedConfiguration(mergedConfiguration);
1525
1526 logIfTransactionTooLarge(r.intent, r.icicle);
1527
1528
1529 // Create activity launch transaction.
1530 final ClientTransaction clientTransaction = ClientTransaction.obtain(app.thread,
1531 r.appToken);
1532 clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),
1533 System.identityHashCode(r), r.info,
1534 // TODO: Have this take the merged configuration instead of separate global
1535 // and override configs.
1536 mergedConfiguration.getGlobalConfiguration(),
1537 mergedConfiguration.getOverrideConfiguration(), r.compat,
1538 r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
1539 r.persistentState, results, newIntents, mService.isNextTransitionForward(),
1540 profilerInfo));
1541
1542 // Set desired final state.
1543 final ActivityLifecycleItem lifecycleItem;
1544 if (andResume) {
1545 lifecycleItem = ResumeActivityItem.obtain(mService.isNextTransitionForward());
1546 } else {
1547 lifecycleItem = PauseActivityItem.obtain();
1548 }
1549 clientTransaction.setLifecycleStateRequest(lifecycleItem);
1550
1551 // Schedule transaction.
1552 mService.getLifecycleManager().scheduleTransaction(clientTransaction);
1553
1554
1555 if ((app.info.privateFlags & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0
1556 && mService.mHasHeavyWeightFeature) {
1557 // This may be a heavy-weight process! Note that the package
1558 // manager will ensure that only activity can run in the main
1559 // process of the .apk, which is the only thing that will be
1560 // considered heavy-weight.
1561 if (app.processName.equals(app.info.packageName)) {
1562 if (mService.mHeavyWeightProcess != null
1563 && mService.mHeavyWeightProcess != app) {
1564 Slog.w(TAG, "Starting new heavy weight process " + app
1565 + " when already running "
1566 + mService.mHeavyWeightProcess);
1567 }
1568 mService.mHeavyWeightProcess = app;
1569 Message msg = mService.mHandler.obtainMessage(
1570 ActivityManagerService.POST_HEAVY_NOTIFICATION_MSG);
1571 msg.obj = r;
1572 mService.mHandler.sendMessage(msg);
1573 }
1574 }
1575
1576 } catch (RemoteException e) {
1577 if (r.launchFailed) {
1578 // This is the second time we failed -- finish activity
1579 // and give up.
1580 Slog.e(TAG, "Second failure launching "
1581 + r.intent.getComponent().flattenToShortString()
1582 + ", giving up", e);
1583 mService.appDiedLocked(app);
1584 stack.requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
1585 "2nd-crash", false);
1586 return false;
1587 }
1588
1589 // This is the first time we failed -- restart process and
1590 // retry.
1591 r.launchFailed = true;
1592 app.activities.remove(r);
1593 throw e;
1594 }
1595 } finally {
1596 endDeferResume();
1597 }
1598
1599 r.launchFailed = false;
1600 if (stack.updateLRUListLocked(r)) {
1601 Slog.w(TAG, "Activity " + r + " being launched, but already in LRU list");
1602 }
1603
1604 // TODO(lifecycler): Resume or pause requests are done as part of launch transaction,
1605 // so updating the state should be done accordingly.
1606 if (andResume && readyToResume()) {
1607 // As part of the process of launching, ActivityThread also performs
1608 // a resume.
1609 stack.minimalResumeActivityLocked(r);
1610 } else {
1611 // This activity is not starting in the resumed state... which should look like we asked
1612 // it to pause+stop (but remain visible), and it has done so and reported back the
1613 // current icicle and other state.
1614 if (DEBUG_STATES) Slog.v(TAG_STATES,
1615 "Moving to PAUSED: " + r + " (starting in paused state)");
1616 r.setState(PAUSED, "realStartActivityLocked");
1617 }
1618
1619 // Launch the new version setup screen if needed. We do this -after-
1620 // launching the initial activity (that is, home), so that it can have
1621 // a chance to initialize itself while in the background, making the
1622 // switch back to it faster and look better.
1623 if (isFocusedStack(stack)) {
1624 mService.getActivityStartController().startSetupActivity();
1625 }
1626
1627 // Update any services we are bound to that might care about whether
1628 // their client may have activities.
1629 if (r.app != null) {
1630 mService.mServices.updateServiceConnectionActivitiesLocked(r.app);
1631 }
1632
1633 return true;
1634 }
走到realStartActivityLocked就开始了真正启动,resume;其为等待start的Activity的逻辑,在下一章中介绍
startActivity.png
网友评论