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

来源:互联网 发布:linux 编辑 grub 编辑:程序博客网 时间:2024/06/03 18:26

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 ready1557        if (!mService.mBooting && !mService.mBooted) {1558            // Not ready yet!1559            return false;1560        }15611562        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        }15691570        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); 15741575        // Remember how we'll process this pause/resume situation, and ensure1576        // 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 stack1580        final TaskRecord prevTask = prev != null ? prev.task : null;1581        if (next == null) {1582            // There are no more activities!  Let's just start up the1583            // 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 display1588            final int returnTaskType = prevTask == null || !prevTask.isOverHomeStack() ?1589                    HOME_ACTIVITY_TYPE : prevTask.getTaskToReturnTo();1590            return isOnHomeDisplay() &&1591                    mStackSupervisor.resumeHomeStackTask(returnTaskType, prev, "noMoreActivities");1592        }15931594        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 there1623            // 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        }16311632        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        }16531654        // If we are sleeping, and there is no resumed activity, and the top1655        // activity is paused, well that is the state we want.1656        if (mService.isSleepingOrShuttingDown()1657                && mLastPausedActivity == next1658                && mStackSupervisor.allPausedActivitiesComplete()) {1659            // Make sure we have executed any pending transitions, since there1660            // 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        }16681669        // 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 bringing1671        // 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 " + next1674                    + ": user " + next.userId + " is stopped");1675            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();1676            return false;1677        }16781679        // The activity may be waiting for stop, but that is no longer1680        // appropriate for it.1681        mStackSupervisor.mStoppingActivities.remove(next);1682        mStackSupervisor.mGoingToSleepActivities.remove(next);1683        next.sleeping = false;1684        mStackSupervisor.mWaitingVisibleActivities.remove(next);16851686        if (DEBUG_SWITCH) Slog.v(TAG, "Resuming " + next);16871688        // If we are currently pausing an activity, then don't do anything1689        // 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        }17251726        // We need to start pausing the current activity so the top one1727        // 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 process1738            // at the top of the LRU list, since we know we will be needing it1739            // very soon and it would be a waste to let it get killed if it1740            // 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        }17471748        // If the most recent activity was noHistory but was only stopped rather1749        // than stopped+finished because the device went to sleep, we need to make1750        // 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        }17591760        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 previous1768                // 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 mean1770                // it is on top of the one being resumed so hiding it quickly1771                // is good.  Otherwise, we want to do the normal route of allowing1772                // the resumed activity to be shown so we can decide if the1773                // previous should actually be hidden depending on whether the1774                // 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        }17891790        // Launching this app's activity, make sure the app is no longer1791        // 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        }18001801        // We are starting up the next activity, so tell the window manager1802        // that the previous one will be hidden soon.  This way it can know1803        // 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.task1819                            ? AppTransition.TRANSIT_ACTIVITY_CLOSE1820                            : 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.task1831                            ? AppTransition.TRANSIT_ACTIVITY_OPEN1832                            : next.mLaunchTaskBehind1833                                    ? AppTransition.TRANSIT_TASK_OPEN_BEHIND1834                                    : 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        }18501851        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        }18611862        ActivityStack lastStack = mStackSupervisor.getLastStack();1863        if (next.app != null && next.app.thread != null) {18711872            if (DEBUG_SWITCH) Slog.v(TAG, "Resume running: " + next);18731874            // This activity is now becoming visible.1875            mWindowManager.setAppVisibility(next.appToken, true);18761877            // schedule launch ticks to collect information about slow apps.1878            next.startLaunchTickingLocked();18791880            ActivityRecord lastResumedActivity =1881                    lastStack == null ? null :lastStack.mResumedActivity;1882            ActivityState lastState = next.state;18831884            mService.updateCpuStats();18851886            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();18941895            // Have the window manager re-evaluate the orientation of1896            // 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            }19071908            if (notUpdated) {1909                // The configuration update wasn't able to keep the existing1910                // instance of the activity, and instead started a new one.1911                // We should be all done, but let's just make sure our activity1912                // is still at the top and schedule another run if something1913                // weird happened.1914                ActivityRecord nextNext = topRunningActivityLocked(null);1915                if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG,1916                        "Activity config changed during resume: " + next1917                        + ", 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            }19301931            try {1932                // Deliver all pending results.1933                ArrayList<ResultInfo> 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 " + next1939                                + ": " + a);1940                        next.app.thread.scheduleSendResult(next.appToken, a);1941                    }1942                }19431944                if (next.newIntents != null) {1945                    next.app.thread.scheduleNewIntent(next.newIntents, next.appToken);1946                }19471948                EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY, next.userId,1949                        System.identityHashCode(next), next.task.taskId, next.shortComponentName);19541955                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);19621963                mStackSupervisor.checkReadyForSleepLocked();19641965                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            }19891990            // From this point on, if something goes wrong there is no way1991            // 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 this1997                // 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        }20252026        if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();20272034        return true;2035    }
原创粉丝点击