Android源码——Activity启动流程

之前在Mac环境下搭建了Android源码,接下来会在简书记录阅读一些经典场景的源码过程, 本文主要是在阅读启动Activity源码过程中做的一些记录, 其中主要的思路是参考罗老师的文章:Android应用程序启动过程源代码分析

几个重要概念

在看Activity启动源码之前,先看几个概念, 这几个是理解Activity启动流程的重要概念:

ActivityManagerService: AMS,服务端的类, 管理着Activity相关的行为

ApplicationThread:实现了IApplicationThread接口,这个接口的说明是

/**
This is given to the activity manager by an application  when it starts up, for the activity manager to tell the application about things it needs to do
**/

它是用来实现ActivityManagerService和ActivityThread之间的交互

ActivityThread:

/**
 * This manages the execution of the main thread in an
 * application process, scheduling and executing activities,
 * broadcasts, and other operations on it as the activity
 * manager requests.
 */

ActivityThread是App主线程(UI线程)管理者,并且作为调度和执行Activity, broadcast的角色。所以,Activity相关的操作,都是由ActivityThread来调度的。

对于每一个应用程序来说,都有一个ActivityThread来表示应用程序的主进程,而每一个ActivityThread都包含有一个ApplicationThread实例,它是一个Binder对象,负责和其它进程进行通信。

  • instrumentation
    这里的mInstrumentation是ActivityThread类的成员变量,它的类型是Intrumentation,定义在frameworks/base/core/java/android/app/Instrumentation.java文件中,它用来监控应用程序和系统的交互。

源码

说完几个基础概念,下面我们来看startActivity(Intent)的源码:

  1. startActivity函数也是调用了startActivityResult, 然后跟进去可以看到如下代码:
Instrumentation.ActivityResult ar =
           mInstrumentation.execStartActivity(
               this, mMainThread.getApplicationThread(), mToken, this,
               intent, requestCode, options);

这里就出现了我们上面提到的Instrumentation对象,它是监控应用程序和系统交互的类。执行execStartActivity方法,这里有两个参数重点看一下:
mMainThread.getApplicationThread(): ApplicationThread对象,它是用来与服务端ActivityManagerServer交互的;
mToken: IBinder对象;

  1. 下面是execStartActivity的源代码:
public ActivityResult execStartActivity(
       Context who, IBinder contextThread, IBinder token, Activity target,
       Intent intent, int requestCode, Bundle options) {
   IApplicationThread whoThread = (IApplicationThread) contextThread;
   ...
   try {
       intent.migrateExtraStreamToClipData();
       intent.prepareToLeaveProcess();
       int result = ActivityManagerNative.getDefault()
           .startActivity(whoThread, who.getBasePackageName(), intent,
                 intent.resolveTypeIfNeeded(who.getContentResolver()),
                   token, target != null ? target.mEmbeddedID : null,
                   requestCode, 0, null, options);
       checkStartActivityResult(result, intent);
   } catch (RemoteException e) {
       throw new RuntimeException("Failure from system", e);
   }
   return null;
}

这里我省略了中间一段,就看核心的ActivityManagerNative.getDefault().startActivity这个函数,先看看getDefault获取了一个什么对象

  1. 下面是getDefault的实现:
/*** Retrieve the system's default/global activity manager.
*/
static public IActivityManager getDefault() {
   return gDefault.get();
}
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
    protected IActivityManager create() {
        //通过ServiceManager获取对应Service
        IBinder b = ServiceManager.getService("activity");
        if (false) {
            Log.v("ActivityManager", "default service binder = " + b);
        }
        IActivityManager am = asInterface(b);
        if (false) {
            Log.v("ActivityManager", "default service = " + am);
        }
        return am;
    }
};

上述代码我们看到一段熟悉的Binder机制代码, 就是ServiceManager.getService("activity"), 大概理解Binder机制就会知道,Binder是C/S架构,而Client客户端就是通过ServiceManager.getService的方式获取服务端代理对象(所以说是代理对象,因为真正的服务端在另外一个进程中)。

  1. 再回到刚刚ActivityManagerNative.getDefault().startActivity,getDefault是IActivityManager接口, 实例对象是ActivityManagerProxy,下面看看这个ActivityManagerProxy代码:
    这里就是经典的Binder的模式, 这里的mRemote就是上面第3步代码中获取的Service对象

  2. 第4步通过Binder机制(后面会再详细看看Binder机制, 简单说就是客户端方法映射到服务端的方法),所以这里就进入了服务端(另外一个进程)ActivityManagerService的startActivity函数:

这里主要是调用了ActivityStackSupervisor类的startActivityMayWait方法, 下面会重点看一下ActivityStackSupervisor这个类的处理:

  1. startActivityMayWait(), 里面主要是对Intent做了解析,将要启动的Activity的信息保存在ActivityInfo(变量对应的是aInfo)中, 然后调用startActivityLocked方法;

  2. startActivityLocked: 这里又解析了一些信息,例如调用者callApp等,然后生成一个ActivityRecord对象

ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
                intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
                requestCode, componentSpecified, voiceSession != null, this, container, options);
err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,
                startFlags, true, options, inTask);
  1. startActivityUncheckedLocked: 这个函数大约有六百多行代码,这个函数主要处理了Task相关的逻辑, 在AndroidManifest或者代码中, 我们可以定义Activity的4中启动模式: standard, singleTop, singleTask, singleInstance。这里就是判断了具体的启动模式,并根据当前Activity栈的情况,作出不同的处理。
    最终,走到一个基本的启动模式函数:targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options)
  2. startActivityLocked在ActivityStack文件中,这里继续对Task相关的逻辑做处理,不做深入的分析了, 直接看接下来的处理: resumeTopActivitiesLocked
  3. resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options); 它的其中一个参数prev是在stack中的上一个activity, 那么这个函数要做的是对上一个activity做一些事情了,下面看具体的代码:
// We need to start pausing the current activity so the top one
        // can be resumed...
        boolean dontWaitForPause = (next.info.flags&ActivityInfo.FLAG_RESUME_WHILE_PAUSING) != 0;
        boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, true, dontWaitForPause);
        if (mResumedActivity != null) {
            if (DEBUG_STATES) Slog.d(TAG_STATES,
                    "resumeTopActivityLocked: Pausing " + mResumedActivity);
            pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause);
        }

其中的注释说的很明白: 要启动top activity, 我们必须将目前正在运行的activity置于pause的状态。

  1. 下面又来到一个比较关键的节点:“将当前activity置于pause状态”, 代码如下:
if (prev.app != null && prev.app.thread != null) {
            if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending pause: " + prev);
            try {
                EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
                        prev.userId, System.identityHashCode(prev),
                        prev.shortComponentName);
                mService.updateUsageStats(prev, false);
                prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
                        userLeaving, prev.configChangeFlags, dontWait);
            } 

可以看到,最核心的是调用了prev.app.thread.schedulePauseActivity, 其中app是ProcessRecord对象,是当前正在前台运行的应用相关信息; thread是IApplicationThread对象,文中一开始的时候提到的ApplicationThread实现了这个接口,是应用进程和ActivityManagerService服务进程间通信的桥梁。
下面要执行的就是进程间的通信了,这里是第二次执行Binder进程间通信了(第一次是第5步的时候, 应用进程作为客户端client,通知服务端AMS调用startActivity),这一次,则正好相反,是AMS进程通知应用进程执行pause activity操作。
------------一条分割线-------------
这里再详细看看为什么thread.schedulePauseActivity可以完成一次Binder跨进程的调用,在一开始接触Binder的时候,都是client调用service的方法, 而service由ServiceManager对象管理,所以,client要调用service的时候,可以通过ServiceManager.getService("activity")这样的方法获取,现在是service调用client,那么service又是怎么知道我要调用哪个client呢?
那要看看thread这个对象是怎么生成的? 通过一层层函数调用发现thread对象传递的流程如下:
最开始, 当application启动的时候,ActivityThread的main函数作为应用程序的入口, 有如下这段代码:

thread.attach(false);
private void attach(boolean system) {
...
        final IActivityManager mgr = ActivityManagerNative.getDefault();
        try {
            mgr.attachApplication(mAppThread);
            }
...
}

这里就通过Binder机制,将mAppThread对象,也就是我们一直提到ApplicationThread传递给ActivityManagerService, 而在service中的处理:

public void handleMessage(Message msg) {
    switch (msg.what) {
        case ATTACH_APPLICATION_TRANSACTION: {
            data.enforceInterface(IActivityManager.descriptor);
            IApplicationThread app = ApplicationThreadNative.asInterface(
                    data.readStrongBinder());
            if (app != null) {
                attachApplication(app);
            }
            reply.writeNoException();
            return true;
        }
    }
}
Override
public final void attachApplication(IApplicationThread thread) {
    synchronized (this) {
        int callingPid = Binder.getCallingPid();
        final long origId = Binder.clearCallingIdentity();
        attachApplicationLocked(thread, callingPid);
        Binder.restoreCallingIdentity(origId);
    }
}
private final boolean attachApplicationLocked(IApplicationThread thread, int pid) {
    app.makeActive(thread, mProcessStats);
}
public void makeActive(IApplicationThread _thread, ProcessStatsService tracker) {
    thread = _thread;
}

上面这段代码, 很好的解释了, 我们上面看到的prev.app.thread对象, 就是当应用启动的时候从ActivityThread传递过来的ApplicationThread对象。所以调了thread.schedulePauseActivity, 就可以实现service与当前应用进程的通信;
------------又是一条分割线-------------

  1. 这里,我们又回到了应用进程, 执行的是ApplicationThread对象的schedulePauseActivity方法:
public final void schedulePauseActivity(IBinder token, boolean finished,
                boolean userLeaving, int configChanges, boolean dontReport) {
            sendMessage(
                    finished ? H.PAUSE_ACTIVITY_FINISHING : H.PAUSE_ACTIVITY,
                    token,
                    (userLeaving ? 1 : 0) | (dontReport ? 2 : 0),
                    configChanges);
        }

因为ApplicationThread是ActivityThread的内部类,sendMessage函数是ActivityThread的实现, 如下:

private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {
        if (DEBUG_MESSAGES) Slog.v(
            TAG, "SCHEDULE " + what + " " + mH.codeToString(what)
            + ": " + arg1 + " / " + obj);
        Message msg = Message.obtain();
        msg.what = what;
        msg.obj = obj;
        msg.arg1 = arg1;
        msg.arg2 = arg2;
        if (async) {
            msg.setAsynchronous(true);
        }
        mH.sendMessage(msg);
    }

可以看到,这里是一个Handler发送消息的机制,ActivityThread的成员变量mH处理了来自ApplicationThread的PAUSEACTIVITY消息。至于这里为什么要用Handler机制呢?因为ApplicationThread作为和服务端交互的桥梁,它是单独挂起一个线程在接收服务端的消息的, 而下面我们要操作的是在主线程(UI线程)做PAUSEACTIVITY的处理, 所以这里就需要一个Handler把消息传递给主线程去执行相应操作。看下面的代码:

//handler处理pause消息
case PAUSE_ACTIVITY:
                    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityPause");
                    handlePauseActivity((IBinder)msg.obj, false, (msg.arg1&1) != 0, msg.arg2,
                            (msg.arg1&2) != 0);
                    maybeSnapshot();
                    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                    break;
//ActivityThread处理pauseActivity
private void handlePauseActivity(IBinder token, boolean finished,
            boolean userLeaving, int configChanges, boolean dontReport) {
        ActivityClientRecord r = mActivities.get(token);
        if (r != null) {
            //Slog.v(TAG, "userLeaving=" + userLeaving + " handling pause of " + r);
            if (userLeaving) {
                performUserLeavingActivity(r);
            }

            r.activity.mConfigChangeFlags |= configChanges;
            performPauseActivity(token, finished, r.isPreHoneycomb());

            // Make sure any pending writes are now committed.
            if (r.isPreHoneycomb()) {
                QueuedWork.waitToFinish();
            }

            // Tell the activity manager we have paused.
            if (!dontReport) {
                try {
                 //通知服务端
                    ActivityManagerNative.getDefault().activityPaused(token);
                } catch (RemoteException ex) {
                }
            }
            mSomeActivitiesChanged = true;
        }
    }
//由activity管理者来执行pause操作
final Bundle performPauseActivity(ActivityClientRecord r, boolean finished,
            boolean saveState) {
            mInstrumentation.callActivityOnPause(r.activity);
            }
//Activity 文件中的pause处理
final void performPause() {
        mDoReportFullyDrawn = false;
        mFragments.dispatchPause();
        mCalled = false;
        onPause();
        mResumed = false;
        if (!mCalled && getApplicationInfo().targetSdkVersion
                >= android.os.Build.VERSION_CODES.GINGERBREAD) {
            throw new SuperNotCalledException(
                    "Activity " + mComponent.toShortString() +
                    " did not call through to super.onPause()");
        }
        mResumed = false;
    }

可以看到,在最后Activity中的performPause() 函数中,调用了我们熟悉的生命周期函数onPause(), 到这里,就完成了服务端的PAUSEACTIVITY操作, 然后再ActivityThread中,又通知了服务端完成pauseActivity操作: ActivityManagerNative.getDefault().activityPaused(token);

  1. 下面又通过Binder机制回到Service端的代码, ActivityManagerService的activityPaused():
Override
    public final void activityPaused(IBinder token) {
        final long origId = Binder.clearCallingIdentity();
        synchronized(this) {
            ActivityStack stack = ActivityRecord.getStackLocked(token);
            if (stack != null) {
                stack.activityPausedLocked(token, false);
            }
        }
        Binder.restoreCallingIdentity(origId);
    }
//ActivityStack.java
final void activityPausedLocked(IBinder token, boolean timeout) {
    final ActivityRecord r = isInStackLocked(token);
    if (r != null) {
        mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
        if (mPausingActivity == r) {
            completePauseLocked(true);
        } 
    }
}

接下来继续执行resumeActivity的操作, 这里我省略了一些ActivityStack文件中的函数的跳转,直接看下面关键的节点函数:

void startSpecificActivityLocked(ActivityRecord r,
            boolean andResume, boolean checkConfig) {
        // Is this activity's application already running?
    ProcessRecord app = mService.getProcessRecordLocked(r.processName,
            r.info.applicationInfo.uid, true);

    r.task.stack.setLaunchTime(r);

    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.
    }

    mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
            "activity", r.intent.getComponent(), false, false, true);
}

这里的判断if (app != null && app.thread != null)中的两个变量在前面已经介绍过, 如果应用程序已经启动,在内部进行跳转的时候,这两个变量都是不为空的, 那么,我们就进入了realStartActivityLocked这个函数, 这个函数则会执行如下代码:

app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
    System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration),
    new Configuration(stack.mOverrideConfig), r.compat, r.launchedFromPackage,
    task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results,
    newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);

这段代码和上面app.thread.schedulePauseActivity非常相似, 这里也是通过Binder机制,又从服务端通知客户端ApplicationThread去执行scheduleLaunchActivity:

private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    Activity a = performLaunchActivity(r, customIntent);
}
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
        // System.out.println("##### [" + System.currentTimeMillis() + "] ActivityThread.performLaunchActivity(" + r + ")");

        ActivityInfo aInfo = r.activityInfo;
        if (r.packageInfo == null) {
            r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
                    Context.CONTEXT_INCLUDE_CODE);
        }

        ComponentName component = r.intent.getComponent();
        if (component == null) {
            component = r.intent.resolveActivity(
                mInitialApplication.getPackageManager());
            r.intent.setComponent(component);
        }

        if (r.activityInfo.targetActivity != null) {
            component = new ComponentName(r.activityInfo.packageName,
                    r.activityInfo.targetActivity);
        }

        Activity activity = null;
        try {
            java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
            activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
            StrictMode.incrementExpectedActivityCount(activity.getClass());
            r.intent.setExtrasClassLoader(cl);
            r.intent.prepareToEnterProcess();
            if (r.state != null) {
                r.state.setClassLoader(cl);
            }
        } catch (Exception e) {
            if (!mInstrumentation.onException(activity, e)) {
                throw new RuntimeException(
                    "Unable to instantiate activity " + component
                    + ": " + e.toString(), e);
            }
        }

        try {
            Application app = r.packageInfo.makeApplication(false, mInstrumentation);

            if (localLOGV) Slog.v(TAG, "Performing launch of " + r);
            if (localLOGV) Slog.v(
                    TAG, r + ": app=" + app
                    + ", appName=" + app.getPackageName()
                    + ", pkg=" + r.packageInfo.getPackageName()
                    + ", comp=" + r.intent.getComponent().toShortString()
                    + ", dir=" + r.packageInfo.getAppDir());

            if (activity != null) {
                Context appContext = createBaseContextForActivity(r, activity);
                CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
                Configuration config = new Configuration(mCompatConfiguration);
                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Launching activity "
                        + r.activityInfo.name + " with config " + config);
                activity.attach(appContext, this, getInstrumentation(), r.token,
                        r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config,
                        r.referrer, r.voiceInteractor);

                if (customIntent != null) {
                    activity.mIntent = customIntent;
                }
                r.lastNonConfigurationInstances = null;
                activity.mStartedActivity = false;
                int theme = r.activityInfo.getThemeResource();
                if (theme != 0) {
                    activity.setTheme(theme);
                }

                activity.mCalled = false;
                if (r.isPersistable()) {
                    mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
                } else {
                    mInstrumentation.callActivityOnCreate(activity, r.state);
                }
                if (!activity.mCalled) {
                    throw new SuperNotCalledException(
                        "Activity " + r.intent.getComponent().toShortString() +
                        " did not call through to super.onCreate()");
                }
                r.activity = activity;
                r.stopped = true;
                if (!r.activity.mFinished) {
                    activity.performStart();
                    r.stopped = false;
                }
                if (!r.activity.mFinished) {
                    if (r.isPersistable()) {
                        if (r.state != null || r.persistentState != null) {
                            mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,
                                    r.persistentState);
                        }
                    } else if (r.state != null) {
                        mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);
                    }
                }
                if (!r.activity.mFinished) {
                    activity.mCalled = false;
                    if (r.isPersistable()) {
                        mInstrumentation.callActivityOnPostCreate(activity, r.state,
                                r.persistentState);
                    } else {
                        mInstrumentation.callActivityOnPostCreate(activity, r.state);
                    }
                    if (!activity.mCalled) {
                        throw new SuperNotCalledException(
                            "Activity " + r.intent.getComponent().toShortString() +
                            " did not call through to super.onPostCreate()");
                    }
                }
            }
            r.paused = true;

            mActivities.put(r.token, r);

        } 
    }
}

performLaunchActivity通过ClassLoader类加载机制生成Activity对象,然后通过Instrumentation去执行生命周期的函数, 同时还设置了主题等其他初始化操作。

到这里, 就基本将Activity启动流程走了一遍, 其中重点描述了几次Client与Service交互的操作,对于一些函数内部的实现没有深入分析,仅仅是走了一遍流程,在此做一些记录。

推荐阅读更多精彩内容