private boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) { ///省略一波代码 if (mResumedActivity != null) { if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Pausing " + mResumedActivity); pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause); } if (pausing) { if (DEBUG_SWITCH || DEBUG_STATES) Slog.v(TAG_STATES, "resumeTopActivityLocked: Skip resume: need to start pausing"); // At this point we want to put the upcoming activity's process // at the top of the LRU list, since we know we will be needing it // very soon and it would be a waste to let it get killed if it // happens to be sitting towards the end. if (next.app != null && next.app.thread != null) { mService.updateLruProcessLocked(next.app, true, null); } if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); return true; } ///省略一波代码 mStackSupervisor.startSpecificActivityLocked(next, true, true);
if (prev != null) { prev.state = ActivityState.PAUSED; if (prev.finishing) { if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Executing finish of activity: " + prev); prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE, false); } else if (prev.app != null) { if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending stop: " + prev); if (mStackSupervisor.mWaitingVisibleActivities.remove(prev)) { if (DEBUG_SWITCH || DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Complete pause, no longer waiting: " + prev); } if (prev.configDestroy) { // The previous is being paused because the configuration // is changing, which means it is actually stopping... // To juggle the fact that we are also starting a new // instance right now, we need to first completely stop // the current instance before starting the new one. if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Destroying after pause: " + prev); destroyActivityLocked(prev, true, "pause-config"); } else if (!hasVisibleBehindActivity() || mService.isSleepingOrShuttingDown()) { // If we were visible then resumeTopActivities will release resources before // stopping. mStackSupervisor.mStoppingActivities.add(prev); if (mStackSupervisor.mStoppingActivities.size() > 3 || prev.frontOfTask && mTaskHistory.size() <= 1) { // If we already have a few activities waiting to stop, // then give up on things going idle and start clearing // them out. Or if r is the last of activity of the last task the stack // will be empty and must be cleared immediately. if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "To many pending stops, forcing idle"); mStackSupervisor.scheduleIdleLocked(); } else { mStackSupervisor.checkReadyForSleepLocked(); } } } else { if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "App died during pause, not stopping: " + prev); prev = null; } // It is possible the activity was freezing the screen before it was paused. // In that case go ahead and remove the freeze this activity has on the screen // since it is no longer visible. prev.stopFreezingScreenLocked(true /*force*/); mPausingActivity = null; }
if (resumeNext) { final ActivityStack topStack = mStackSupervisor.getFocusedStack(); if (!mService.isSleepingOrShuttingDown()) { mStackSupervisor.resumeTopActivitiesLocked(topStack, prev, null); } else { mStackSupervisor.checkReadyForSleepLocked(); ActivityRecord top = topStack.topRunningActivityLocked(null); if (top == null || (prev != null && top != prev)) { // If there are no more activities available to run, // do resume anyway to start something. Also if the top // activity on the stack is not the just paused activity, // we need to go ahead and resume it to ensure we complete // an in-flight app switch. mStackSupervisor.resumeTopActivitiesLocked(topStack, null, null); } } }
if (prev != null) { prev.resumeKeyDispatchingLocked();
if (app != null && app.thread != null) { try { if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0 || !"android".equals(r.info.packageName)) { // Don't add this if it is a platform component that is marked // to run in multiple processes, because this is actually // part of the framework so doesn't make sense to track as a // separate apk in the process. app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode, mService.mProcessStats); } realStartActivityLocked(r, app, andResume, checkConfig); return; } catch (RemoteException e) { Slog.w(TAG, "Exception when starting activity " + r.intent.getComponent().flattenToShortString(), e); }
// If a dead object exception was thrown -- fall through to // restart the application. }
public static void main(String[] args) { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain"); SamplingProfilerIntegration.start();
// CloseGuard defaults to true and can be quite spammy. We // disable it here, but selectively enable it later (via // StrictMode) on debug builds, but using DropBox, not logs. CloseGuard.setEnabled(false);
Environment.initForCurrentUser();
// Set the reporter for event logging in libcore EventLogger.setReporter(new EventLoggingReporter());
AndroidKeyStoreProvider.install();
// Make sure TrustedCertificateStore looks in the right place for CA certificates final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId()); TrustedCertificateStore.setDefaultUserDirectory(configDir);
Process.setArgV0("<pre-initialized>");
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread(); thread.attach(false);
if (sMainThreadHandler == null) { sMainThreadHandler = thread.getHandler(); }
if (false) { Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG, "ActivityThread")); }
// End of event ActivityThreadMain. Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited"); }
private final boolean attachApplicationLocked(IApplicationThread thread, int pid) {
...
// See if the top visible activity is waiting to run in this process... if (normalMode) { try { if (mStackSupervisor.attachApplicationLocked(app)) { didSomething = true; } } catch (Exception e) { Slog.wtf(TAG, "Exception thrown launching activities in " + app, e); badApp = true; } }
...
if (!didSomething) { //调用处理内存管理。不是很理解里面的机制,暂时不分析。 updateOomAdjLocked(); }
public void serviceDoneExecuting(IBinder token, int type, int startId, int res) { synchronized(this) { if (!(token instanceof ServiceRecord)) { Slog.e(TAG, "serviceDoneExecuting: Invalid service token=" + token); throw new IllegalArgumentException("Invalid service token"); } mServices.serviceDoneExecutingLocked((ServiceRecord)token, type, startId, res); } }
if (r.executeNesting <= 0) { if (r.app != null) { if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Nesting at 0 of " + r.shortName); r.app.execServicesFg = false; r.app.executingServices.remove(r); if (r.app.executingServices.size() == 0) {