How to start next activity if the top activity is stopped/killed

In Android system, activities are managed with stack/task model.

Sometimes the top activity may stop due to crash, ANR, app OTA, LMK, .... In this situation, AMS have to remove the top activity and start another activity as top.

1. Back trace

04-16 18:58:52.646   523   552 W ActivityManager:     at com.android.server.am.ActivityManagerService.startProcessLocked(ActivityManagerService.java:3220)
04-16 18:58:52.646   523   552 W ActivityManager:     at com.android.server.am.ActivityManagerService.startProcessLocked(ActivityManagerService.java:3165)
04-16 18:58:52.646   523   552 W ActivityManager:     at com.android.server.am.ActivityManagerService.startProcessLocked(ActivityManagerService.java:3043)
04-16 18:58:52.646   523   552 W ActivityManager:     at com.android.server.am.ActivityStackSupervisor.startSpecificActivityLocked(ActivityStackSupervisor.java:1352)
04-16 18:58:52.646   523   552 W ActivityManager:     at com.android.server.am.ActivityStack.resumeTopActivityInnerLocked(ActivityStack.java:2023)
04-16 18:58:52.646   523   552 W ActivityManager:     at com.android.server.am.ActivityStack.resumeTopActivityLocked(ActivityStack.java:1547)
04-16 18:58:52.646   523   552 W ActivityManager:     at com.android.server.am.ActivityStack.resumeTopActivityLocked(ActivityStack.java:1530)
04-16 18:58:52.646   523   552 W ActivityManager:     at com.android.server.am.ActivityStack.finishCurrentActivityLocked(ActivityStack.java:2996)
04-16 18:58:52.646   523   552 W ActivityManager:     at com.android.server.am.ActivityStack.finishActivityLocked(ActivityStack.java:2924)
04-16 18:58:52.646   523   552 W ActivityManager:     at com.android.server.am.ActivityStack.forceStopPackageLocked(ActivityStack.java:4091)
04-16 18:58:52.646   523   552 W ActivityManager:     at com.android.server.am.ActivityStackSupervisor.forceStopPackageLocked(ActivityStackSupervisor.java:2567)
04-16 18:58:52.646   523   552 W ActivityManager:     at com.android.server.am.ActivityManagerService.forceStopPackageLocked(ActivityManagerService.java:6228)
04-16 18:58:52.646   523   552 W ActivityManager:     at com.android.server.am.ActivityManagerService.access$400(ActivityManagerService.java:279)
04-16 18:58:52.646   523   552 W ActivityManager:     at com.android.server.am.ActivityManagerService$MainHandler.handleMessage(ActivityManagerService.java:1702)
04-16 18:58:52.646   523   552 W ActivityManager:     at android.os.Handler.dispatchMessage(Handler.java:102)
04-16 18:58:52.646   523   552 W ActivityManager:     at android.os.Looper.loop(Looper.java:135)
04-16 18:58:52.646   523   552 W ActivityManager:     at android.os.HandlerThread.run(HandlerThread.java:61)
04-16 18:58:52.646   523   552 W ActivityManager:     at com.android.server.ServiceThread.run(ServiceThread.java:46)

2. How to select next activity

It is implemented in ActivityStack.resumeTopActivityInnerLocked method.

1554    final boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) {
1555        if (ActivityManagerService.DEBUG_LOCKSCREEN) mService.logLockScreen("");
1556Return if AMS not ready
1557        if (!mService.mBooting && !mService.mBooted) {
1558            // Not ready yet!
1559            return false;
1560        }
1561
1562        ActivityRecord parent = mActivityContainer.mParentActivity;
1563        if ((parent != null && parent.state != ActivityState.RESUMED) ||
1564                !mActivityContainer.isAttachedLocked()) {
1565            // Do not resume this stack if its parent is not resumed.
1566            // TODO: If in a loop, make sure that parent stack resumeTopActivity is called 1st.
1567            return false;
1568        }
1569
1570        cancelInitializingActivities();
1571Find the next non-finish activity in current stack. Search activity from top task to bottom task.
1572        // Find the first activity that is not finishing.
1573        final ActivityRecord next = topRunningActivityOnStackLocked(null); 
1574
1575        // Remember how we'll process this pause/resume situation, and ensure
1576        // that the state is reset however we wind up proceeding.
1577        final boolean userLeaving = mStackSupervisor.mUserLeaving;
1578        mStackSupervisor.mUserLeaving = false;
1579Resume launcher instead if there is no non-finish activity in current stack
1580        final TaskRecord prevTask = prev != null ? prev.task : null;
1581        if (next == null) {
1582            // There are no more activities!  Let's just start up the
1583            // Launcher...
1584            ActivityOptions.abort(options);
1585            if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: No more activities go home");
1586            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
1587            // Only resume home if on home display
1588            final int returnTaskType = prevTask == null || !prevTask.isOverHomeStack() ?
1589                    HOME_ACTIVITY_TYPE : prevTask.getTaskToReturnTo();
1590            return isOnHomeDisplay() &&
1591                    mStackSupervisor.resumeHomeStackTask(returnTaskType, prev, "noMoreActivities");
1592        }
1593
1594        next.delayedResume = false;
1619        // If the top activity is the resumed one, nothing to do.
1620        if (mResumedActivity == next && next.state == ActivityState.RESUMED &&
1621                    mStackSupervisor.allResumedActivitiesComplete()) {
1622            // Make sure we have executed any pending transitions, since there
1623            // should be nothing left to do at this point.
1624            mWindowManager.executeAppTransition();
1625            mNoAnimActivities.clear();
1626            ActivityOptions.abort(options);
1627            if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Top activity resumed " + next);
1628            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
1629            return false;
1630        }
1631
1632        final TaskRecord nextTask = next.task;
1633        if (prevTask != null && prevTask.stack == this &&
1634                prevTask.isOverHomeStack() && prev.finishing && prev.frontOfTask) {
1635            if (DEBUG_STACK)  mStackSupervisor.validateTopActivitiesLocked();
1636            if (prevTask == nextTask) {
1637                prevTask.setFrontOfTask();
1638            } else if (prevTask != topTask()) {
1639                // This task is going away but it was supposed to return to the home stack.
1640                // Now the task above it has to return to the home task instead.
1641                final int taskNdx = mTaskHistory.indexOf(prevTask) + 1;
1642                mTaskHistory.get(taskNdx).setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1643            } else if (!isOnHomeDisplay()) {
1644                return false;
1645            } else if (!isHomeStack()){
1646                if (DEBUG_STATES) Slog.d(TAG,
1647                        "resumeTopActivityLocked: Launching home next");
1648                final int returnTaskType = prevTask == null || !prevTask.isOverHomeStack() ?
1649                        HOME_ACTIVITY_TYPE : prevTask.getTaskToReturnTo();
1650                return mStackSupervisor.resumeHomeStackTask(returnTaskType, prev, "prevFinished");
1651            }
1652        }
1653
1654        // If we are sleeping, and there is no resumed activity, and the top
1655        // activity is paused, well that is the state we want.
1656        if (mService.isSleepingOrShuttingDown()
1657                && mLastPausedActivity == next
1658                && mStackSupervisor.allPausedActivitiesComplete()) {
1659            // Make sure we have executed any pending transitions, since there
1660            // should be nothing left to do at this point.
1661            mWindowManager.executeAppTransition();
1662            mNoAnimActivities.clear();
1663            ActivityOptions.abort(options);
1664            if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Going to sleep and all paused");
1665            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
1666            return false;
1667        }
1668
1669        // Make sure that the user who owns this activity is started.  If not,
1670        // we will just leave it as is because someone should be bringing
1671        // another user's activities to the top of the stack.
1672        if (mService.mStartedUsers.get(next.userId) == null) {
1673            Slog.w(TAG, "Skipping resume of top activity " + next
1674                    + ": user " + next.userId + " is stopped");
1675            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
1676            return false;
1677        }
1678
1679        // The activity may be waiting for stop, but that is no longer
1680        // appropriate for it.
1681        mStackSupervisor.mStoppingActivities.remove(next);
1682        mStackSupervisor.mGoingToSleepActivities.remove(next);
1683        next.sleeping = false;
1684        mStackSupervisor.mWaitingVisibleActivities.remove(next);
1685
1686        if (DEBUG_SWITCH) Slog.v(TAG, "Resuming " + next);
1687
1688        // If we are currently pausing an activity, then don't do anything
1689        // until that is done.
1690        if (!mStackSupervisor.allPausedActivitiesComplete()) {
1691            if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG,
1692                    "resumeTopActivityLocked: Skip resume: some activity pausing.");
1693            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
1694            return false;
1695        }
1725
1726        // We need to start pausing the current activity so the top one
1727        // can be resumed...
1728        boolean dontWaitForPause = (next.info.flags&ActivityInfo.FLAG_RESUME_WHILE_PAUSING) != 0;
1729        boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, true, dontWaitForPause);
1730        if (mResumedActivity != null) {
1731            if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Pausing " + mResumedActivity);
1732            pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause);
1733        }
1734        if (pausing) {
1735            if (DEBUG_SWITCH || DEBUG_STATES) Slog.v(TAG,
1736                    "resumeTopActivityLocked: Skip resume: need to start pausing");
1737            // At this point we want to put the upcoming activity's process
1738            // at the top of the LRU list, since we know we will be needing it
1739            // very soon and it would be a waste to let it get killed if it
1740            // happens to be sitting towards the end.
1741            if (next.app != null && next.app.thread != null) {
1742                mService.updateLruProcessLocked(next.app, true, null);
1743            }
1744            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
1745            return true;
1746        }
1747
1748        // If the most recent activity was noHistory but was only stopped rather
1749        // than stopped+finished because the device went to sleep, we need to make
1750        // sure to finish it as we're making a new activity topmost.
1751        if (mService.isSleeping() && mLastNoHistoryActivity != null &&
1752                !mLastNoHistoryActivity.finishing) {
1753            if (DEBUG_STATES) Slog.d(TAG, "no-history finish of " + mLastNoHistoryActivity +
1754                    " on new resume");
1755            requestFinishActivityLocked(mLastNoHistoryActivity.appToken, Activity.RESULT_CANCELED,
1756                    null, "no-history", false);
1757            mLastNoHistoryActivity = null;
1758        }
1759
1760        if (prev != null && prev != next) {
1761            if (!prev.waitingVisible && next != null && !next.nowVisible) {
1762                prev.waitingVisible = true;
1763                mStackSupervisor.mWaitingVisibleActivities.add(prev);
1764                if (DEBUG_SWITCH) Slog.v(
1765                        TAG, "Resuming top, waiting visible to hide: " + prev);
1766            } else {
1767                // The next activity is already visible, so hide the previous
1768                // activity's windows right now so we can show the new one ASAP.
1769                // We only do this if the previous is finishing, which should mean
1770                // it is on top of the one being resumed so hiding it quickly
1771                // is good.  Otherwise, we want to do the normal route of allowing
1772                // the resumed activity to be shown so we can decide if the
1773                // previous should actually be hidden depending on whether the
1774                // new one is found to be full-screen or not.
1775                if (prev.finishing) {
1776                    mWindowManager.setAppVisibility(prev.appToken, false);
1777                    if (DEBUG_SWITCH) Slog.v(TAG, "Not waiting for visible to hide: "
1778                            + prev + ", waitingVisible="
1779                            + (prev != null ? prev.waitingVisible : null)
1780                            + ", nowVisible=" + next.nowVisible);
1781                } else {
1782                    if (DEBUG_SWITCH) Slog.v(TAG, "Previous already visible but still waiting to hide: "
1783                        + prev + ", waitingVisible="
1784                        + (prev != null ? prev.waitingVisible : null)
1785                        + ", nowVisible=" + next.nowVisible);
1786                }
1787            }
1788        }
1789
1790        // Launching this app's activity, make sure the app is no longer
1791        // considered stopped.
1792        try {
1793            AppGlobals.getPackageManager().setPackageStoppedState(
1794                    next.packageName, false, next.userId); /* TODO: Verify if correct userid */
1795        } catch (RemoteException e1) {
1796        } catch (IllegalArgumentException e) {
1797            Slog.w(TAG, "Failed trying to unstop package "
1798                    + next.packageName + ": " + e);
1799        }
1800
1801        // We are starting up the next activity, so tell the window manager
1802        // that the previous one will be hidden soon.  This way it can know
1803        // to ignore it when computing the desired screen orientation.
1804        boolean anim = true;
1810        if (prev != null) {
1811            if (prev.finishing) {
1812                if (DEBUG_TRANSITION) Slog.v(TAG,
1813                        "Prepare close transition: prev=" + prev);
1814                if (mNoAnimActivities.contains(prev)) {
1815                    anim = false;
1816                    mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);
1817                } else {
1818                    mWindowManager.prepareAppTransition(prev.task == next.task
1819                            ? AppTransition.TRANSIT_ACTIVITY_CLOSE
1820                            : AppTransition.TRANSIT_TASK_CLOSE, false);
1821                }
1822                mWindowManager.setAppWillBeHidden(prev.appToken);
1823                mWindowManager.setAppVisibility(prev.appToken, false);
1824            } else {
1825                if (DEBUG_TRANSITION) Slog.v(TAG, "Prepare open transition: prev=" + prev);
1826                if (mNoAnimActivities.contains(next)) {
1827                    anim = false;
1828                    mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);
1829                } else {
1830                    mWindowManager.prepareAppTransition(prev.task == next.task
1831                            ? AppTransition.TRANSIT_ACTIVITY_OPEN
1832                            : next.mLaunchTaskBehind
1833                                    ? AppTransition.TRANSIT_TASK_OPEN_BEHIND
1834                                    : AppTransition.TRANSIT_TASK_OPEN, false);
1835                }
1836            }
1841        } else {
1842            if (DEBUG_TRANSITION) Slog.v(TAG, "Prepare open transition: no previous");
1843            if (mNoAnimActivities.contains(next)) {
1844                anim = false;
1845                mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);
1846            } else {
1847                mWindowManager.prepareAppTransition(AppTransition.TRANSIT_ACTIVITY_OPEN, false);
1848            }
1849        }
1850
1851        Bundle resumeAnimOptions = null;
1852        if (anim) {
1853            ActivityOptions opts = next.getOptionsForTargetActivityLocked();
1854            if (opts != null) {
1855                resumeAnimOptions = opts.toBundle();
1856            }
1857            next.applyOptionsLocked();
1858        } else {
1859            next.clearOptionsLocked();
1860        }
1861
1862        ActivityStack lastStack = mStackSupervisor.getLastStack();
1863        if (next.app != null && next.app.thread != null) {
1871
1872            if (DEBUG_SWITCH) Slog.v(TAG, "Resume running: " + next);
1873
1874            // This activity is now becoming visible.
1875            mWindowManager.setAppVisibility(next.appToken, true);
1876
1877            // schedule launch ticks to collect information about slow apps.
1878            next.startLaunchTickingLocked();
1879
1880            ActivityRecord lastResumedActivity =
1881                    lastStack == null ? null :lastStack.mResumedActivity;
1882            ActivityState lastState = next.state;
1883
1884            mService.updateCpuStats();
1885
1886            if (DEBUG_STATES) Slog.v(TAG, "Moving to RESUMED: " + next + " (in existing)");
1887            next.state = ActivityState.RESUMED;
1888            mResumedActivity = next;
1889            next.task.touchActiveTime();
1890            mService.addRecentTaskLocked(next.task);
1891            mService.updateLruProcessLocked(next.app, true, null);
1892            updateLRUListLocked(next);
1893            mService.updateOomAdjLocked();
1894
1895            // Have the window manager re-evaluate the orientation of
1896            // the screen based on the new activity order.
1897            boolean notUpdated = true;
1898            if (mStackSupervisor.isFrontStack(this)) {
1899                Configuration config = mWindowManager.updateOrientationFromAppTokens(
1900                        mService.mConfiguration,
1901                        next.mayFreezeScreenLocked(next.app) ? next.appToken : null);
1902                if (config != null) {
1903                    next.frozenBeforeDestroy = true;
1904                }
1905                notUpdated = !mService.updateConfigurationLocked(config, next, false, false);
1906            }
1907
1908            if (notUpdated) {
1909                // The configuration update wasn't able to keep the existing
1910                // instance of the activity, and instead started a new one.
1911                // We should be all done, but let's just make sure our activity
1912                // is still at the top and schedule another run if something
1913                // weird happened.
1914                ActivityRecord nextNext = topRunningActivityLocked(null);
1915                if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG,
1916                        "Activity config changed during resume: " + next
1917                        + ", new next: " + nextNext);
1918                if (nextNext != next) {
1919                    // Do over!
1920                    mStackSupervisor.scheduleResumeTopActivities();
1921                }
1922                if (mStackSupervisor.reportResumedActivityLocked(next)) {
1923                    mNoAnimActivities.clear();
1924                    if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
1925                    return true;
1926                }
1927                if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
1928                return false;
1929            }
1930
1931            try {
1932                // Deliver all pending results.
1933                ArrayList a = next.results;
1934                if (a != null) {
1935                    final int N = a.size();
1936                    if (!next.finishing && N > 0) {
1937                        if (DEBUG_RESULTS) Slog.v(
1938                                TAG, "Delivering results to " + next
1939                                + ": " + a);
1940                        next.app.thread.scheduleSendResult(next.appToken, a);
1941                    }
1942                }
1943
1944                if (next.newIntents != null) {
1945                    next.app.thread.scheduleNewIntent(next.newIntents, next.appToken);
1946                }
1947
1948                EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY, next.userId,
1949                        System.identityHashCode(next), next.task.taskId, next.shortComponentName);
1954
1955                next.sleeping = false;
1956                mService.showAskCompatModeDialogLocked(next);
1957                next.app.pendingUiClean = true;
1958                next.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_TOP);
1959                next.clearOptionsLocked();
1960                next.app.thread.scheduleResumeActivity(next.appToken, next.app.repProcState,
1961                        mService.isNextTransitionForward(), resumeAnimOptions);
1962
1963                mStackSupervisor.checkReadyForSleepLocked();
1964
1965                if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Resumed " + next);
1966            } catch (Exception e) {
1967                // Whoops, need to restart this activity!
1968                if (DEBUG_STATES) Slog.v(TAG, "Resume failed; resetting state to "
1969                        + lastState + ": " + next);
1970                next.state = lastState;
1971                if (lastStack != null) {
1972                    lastStack.mResumedActivity = lastResumedActivity;
1973                }
1974                Slog.i(TAG, "Restarting because process died: " + next);
1975                if (!next.hasBeenLaunched) {
1976                    next.hasBeenLaunched = true;
1977                } else  if (SHOW_APP_STARTING_PREVIEW && lastStack != null &&
1978                        mStackSupervisor.isFrontStack(lastStack)) {
1979                    mWindowManager.setAppStartingWindow(
1980                            next.appToken, next.packageName, next.theme,
1981                            mService.compatibilityInfoForPackageLocked(next.info.applicationInfo),
1982                            next.nonLocalizedLabel, next.labelRes, next.icon, next.logo,
1983                            next.windowFlags, null, true);
1984                }
1985                mStackSupervisor.startSpecificActivityLocked(next, true, false);
1986                if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
1987                return true;
1988            }
1989
1990            // From this point on, if something goes wrong there is no way
1991            // to recover the activity.
1992            try {
1993                next.visible = true;
1994                completeResumeLocked(next);
1995            } catch (Exception e) {
1996                // If any exception gets thrown, toss away this
1997                // activity and try the next one.
1998                Slog.w(TAG, "Exception thrown during resume of " + next, e);
1999                requestFinishActivityLocked(next.appToken, Activity.RESULT_CANCELED, null,
2000                        "resume-exception", true);
2001                if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
2002                return true;
2003            }
2004            next.stopped = false;
2006        } else {
2007            // Whoops, need to restart this activity!
2008            if (!next.hasBeenLaunched) {
2009                next.hasBeenLaunched = true;
2010            } else {
2011                if (SHOW_APP_STARTING_PREVIEW) {
2012                    mWindowManager.setAppStartingWindow(
2013                            next.appToken, next.packageName, next.theme,
2014                            mService.compatibilityInfoForPackageLocked(
2015                                    next.info.applicationInfo),
2016                            next.nonLocalizedLabel,
2017                            next.labelRes, next.icon, next.logo, next.windowFlags,
2018                            null, true);
2019                }
2020                if (DEBUG_SWITCH) Slog.v(TAG, "Restarting: " + next);
2021            }
2022            if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Restarting " + next);
2023            mStackSupervisor.startSpecificActivityLocked(next, true, true);
2024        }
2025
2026        if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
2027
2034        return true;
2035    }

你可能感兴趣的:(Android开发)