Android源码分析之App启动流程(一)

Framework代码虽然没有读过,但是相关的文章看过很多,各方大牛阅读的姿势也了解了不少,可到自己开始学习时还是有无从下手的感觉。

Binder应该是看过的博客中提到最多次的概念了,然而现在我除了知道它是用来搞进程间通讯的之外,其它的就一无所知了,也不知道它对开发一个App有什么样的作用,想从它下手是不可能了。想来想去,还是对App最为熟悉,所以就先搞清楚一个APP从启动到运行的整个流程吧。

Android系统开机解锁后,就会进入桌面,不过这个桌面也是一个APP,它的名字叫Launcher,我们的应用就是通过点击这里的一个图标打开的。它的源码位于/packages/apps/目录,这里存放的是一些系统应用,像电话短信等。以下是这个目录的截图:

Android源码分析之App启动流程(一)_第1张图片
系统APP

可以看到其中Launcher程序有两个:Launcher2Launcher3,前者是从Android2.2开始使用的,直到Android4.4之后换成了后者。Launcher的具体实现并不是关注的重点,我们只是想知道从这里是如何启动其他APP的。通过其AndroidManifest.xml可以找到它的主页面是com.android.launcher3.Launcher,这是一个Activity,我在这里找到了点击应用图标打开APP的入口代码:

/packages/apps/Launcher3/src/com/android/launcher3/Launcher.java

/**
* Launches the intent referred by the clicked shortcut.
*
* @param v The view representing the clicked shortcut.
*/
public void onClick(View v) {
    // Make sure that rogue clicks don't get through while allapps is launching, or after the
    // view has detached (it's possible for this to happen if the view is removed mid touch).
    if (v.getWindowToken() == null) {
        return;
    }

    ...

    Object tag = v.getTag();
    if (tag instanceof ShortcutInfo) {
        onClickAppShortcut(v);
    } else if (tag instanceof FolderInfo) {
        ...
    } else if (v == mAllAppsButton) {
        ...
    } else if (tag instanceof AppInfo) {
        startAppShortcutOrInfoActivity(v);
    } else if (tag instanceof LauncherAppWidgetInfo) {
        ...
    }
}

这里Launcher#startAppShortcutOrInfoActivity(View)就是我们要找的代码,它的主要实现如下:

void startAppShortcutOrInfoActivity(View v) {
    Object tag = v.getTag();
    final ShortcutInfo shortcut;
    final Intent intent;
    if (tag instanceof ShortcutInfo) {
        shortcut = (ShortcutInfo) tag;
        intent = shortcut.intent;
        ...

    } else if (tag instanceof AppInfo) {
        shortcut = null;
        intent = ((AppInfo) tag).intent;
    } else {
        throw new IllegalArgumentException("Input must be a Shortcut or AppInfo");
    }

    boolean success = startActivitySafely(v, intent, tag);
    mStats.recordLaunch(v, intent, shortcut);

    ...
}

首先通过Tag获取到了Intent,然后调用了Launcher#startActivitySafely(View, Intent, Object)方法,如下所示:

public boolean startActivitySafely(View v, Intent intent, Object tag) {
    boolean success = false;

    ...

    try {
        success = startActivity(v, intent, tag);
    } catch (ActivityNotFoundException e) {
       ...
    }
    return success;
}

继续跳转到Launcher#startActivity(View, Intent, Object),它主要处理了一下启动的动画,以及对用户的管理,代码如下:

private boolean startActivity(View v, Intent intent, Object tag) {
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    try {
        ...
        LauncherAppsCompat launcherApps = LauncherAppsCompat.getInstance(this);
        UserManagerCompat userManager = UserManagerCompat.getInstance(this);

        UserHandleCompat user = null;
        if (intent.hasExtra(AppInfo.EXTRA_PROFILE)) {
            long serialNumber = intent.getLongExtra(AppInfo.EXTRA_PROFILE, -1);
            user = userManager.getUserForSerialNumber(serialNumber);
        }

        ...

        // 如果user为空,或者user是Launcher所在的用户
        if (user == null || user.equals(UserHandleCompat.myUserHandle())) {
            // Could be launching some bookkeeping activity
            startActivity(intent, optsBundle);
        } else {
            // TODO Component can be null when shortcuts are supported for secondary user
            launcherApps.startActivityForProfile(intent.getComponent(), user,
                    intent.getSourceBounds(), optsBundle);
        }
        return true;
    } catch (SecurityException e) {
        ...
    }
    return false;
}

这里给Intent增加了一个Intent.FLAG_ACTIVITY_NEW_TASKflag,然后调用了Activity#startActivity(Intent, Bundle)方法,这时我们就脱离了Launcher进入了Framework层面。代码如下:

/frameworks/base/core/java/android/app/Activity.java

@Override
public void startActivity(Intent intent, @Nullable Bundle options) {
    if (options != null) {
        startActivityForResult(intent, -1, options);
    } else {
        // Note we want to go through this call for compatibility with
        // applications that may have overridden the method.
        startActivityForResult(intent, -1);
    }
}

这里if-else最终都会调用Activity#startActivityForResult(Intent, int, Bundle),代码如下:

/**
* Launch an activity for which you would like a result when it finished.
* When this activity exits, your
* onActivityResult() method will be called with the given requestCode.
* Using a negative requestCode is the same as calling
* {@link #startActivity} (the activity is not launched as a sub-activity).
*
* 

Note that this method should only be used with Intent protocols * that are defined to return a result. In other protocols (such as * {@link Intent#ACTION_MAIN} or {@link Intent#ACTION_VIEW}), you may * not get the result when you expect. For example, if the activity you * are launching uses the singleTask launch mode, it will not run in your * task and thus you will immediately receive a cancel result. * *

As a special case, if you call startActivityForResult() with a requestCode * >= 0 during the initial onCreate(Bundle savedInstanceState)/onResume() of your * activity, then your window will not be displayed until a result is * returned back from the started activity. This is to avoid visible * flickering when redirecting to another activity. * * ... */ public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) { if (mParent == null) { Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity( this, mMainThread.getApplicationThread(), mToken, this, intent, requestCode, options); if (ar != null) { mMainThread.sendActivityResult( mToken, mEmbeddedID, requestCode, ar.getResultCode(), ar.getResultData()); } if (requestCode >= 0) { // If this start is requesting a result, we can avoid making // the activity visible until the result is received. Setting // this code during onCreate(Bundle savedInstanceState) or onResume() will keep the // activity hidden during this time, to avoid flickering. // This can only be done when a result is requested because // that guarantees we will get information back when the // activity is finished, no matter what happens to it. mStartedActivity = true; } cancelInputsAndStartExitTransition(options); // TODO Consider clearing/flushing other event sources and events for child windows. } else { ... } }

这里看到一个叫做mInstrumentation的成员变量,并调用了它的execStartActivity方法,还有一个mMainThread变量,这应该就是APP的主线程,这两个变量在哪里实例化的呢?我在Activity里找到了如下方法:

final void attach(Context context, ActivityThread aThread,
        Instrumentation instr, IBinder token, int ident,
        Application application, Intent intent, ActivityInfo info,
        CharSequence title, Activity parent, String id,
        NonConfigurationInstances lastNonConfigurationInstances,
        Configuration config, String referrer, IVoiceInteractor voiceInteractor) {
    attachBaseContext(context);

    ...
    mMainThread = aThread;
    mInstrumentation = instr;
    ...
}

可以看到,这几个变量是传进来的,但是在Activity中没有任何地方调用到这段代码,所以它的实例化一定是在别的类中完成的。这里就先留下一个悬念,我们还是应该先顺着代码去研究,跳来跳去不一会儿就糊涂了,我相信在后续一定会找到答案。

Activity#startActivityForResult(Intent, int, Bundle)返回了一个Instrumentation.ActivityResult实例,并调用了ActivityThread#sendActivityResult方法,不过这里没有要获取返回值,所以这句代码应该不会执行,我们以后再分析它。现在,我们先看这个Instrumentation#execStartActivity做了什么,在Instrumentation类中,这个函数有两个,其中一个在注释中说了是用来让Fragment调用的,这里不要跟错了。正确跳转的代码如下:

/frameworks/base/core/java/android/app/Instrumentation.java

public ActivityResult execStartActivity(
        Context who, IBinder contextThread, IBinder token, Activity target,
        Intent intent, int requestCode, Bundle options) {
    IApplicationThread whoThread = (IApplicationThread) contextThread;

    ...

    if (mActivityMonitors != null) {
        synchronized (mSync) {
            final int N = mActivityMonitors.size();
            for (int i=0; i= 0 ? am.getResult() : null;
                    }
                    break;
                }
            }
        }
    }
    try {
        ...
        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;
}

这里的mActivityMonitors变量是在Instrumentation中维护的一个列表,就是来记录的,如果之前请求过,就会被记录到这里,如果monitor阻塞了,也就是想打开的Activity无法启动,就会直接返回。真正的启动在下边的try-catch中,这里先看下这个ActivityManagerNative#getDefault()又是什么:

/frameworks/base/core/java/android/app/ActivityManagerNative.java

static public IActivityManager getDefault() {
    return gDefault.get();
}

private static final Singleton gDefault = new Singleton() {
    protected IActivityManager create() {
        IBinder b = ServiceManager.getService("activity");
        ...
        IActivityManager am = asInterface(b);
        ...
        return am;
    }
};

这里看到了IBinder,这么快就遇到了Binder,刚刚还说对它毫无所知呢。继续跟进:

/frameworks/base/core/java/android/os/ServiceManager.java

public static IBinder getService(String name) {
    try {
        IBinder service = sCache.get(name);
        if (service != null) {
            return service;
        } else {
            return getIServiceManager().getService(name);
        }
    } catch (RemoteException e) {
        Log.e(TAG, "error in getService", e);
    }
    return null;
}

private static IServiceManager getIServiceManager() {
    if (sServiceManager != null) {
        return sServiceManager;
    }

    // Find the service manager
    sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
    return sServiceManager;
}

可以看到这个ServiceManager和我们写xxxManager一样,就是方便调用和管理实例的,这个sServiceManager的实例化又是通过ServiceManagerNative完成,这里asInterface的参数通过BinderInternal.getContextObject()给出,它是一个native方法,代码如下:

/frameworks/base/core/java/com/android/internal/os/BinderInternal.java

/**
* Return the global "context object" of the system.  This is usually
* an implementation of IServiceManager, which you can use to find
* other services.
*/
public static final native IBinder getContextObject();

不过这里代码就走到Native了,我们还是先停下,Native的代码后续再研究,它的作用是用来获取Service的。看下这个ServiceManagerNative#asInterface(IBinder)方法:

/frameworks/base/core/java/android/os/ServiceManagerNative.java

static public IServiceManager asInterface(IBinder obj)
{
    ...
    IServiceManager in =
        (IServiceManager)obj.queryLocalInterface(descriptor);
    if (in != null) {
        return in;
    }
    
    return new ServiceManagerProxy(obj);
}

/**
* Attempt to retrieve a local implementation of an interface
* for this Binder object.  If null is returned, you will need
* to instantiate a proxy class to marshall calls through
* the transact() method.
*/
public IInterface queryLocalInterface(String descriptor);

也就是说,这里获取到的对象是ServiceManagerProxy,然后调用了它的ServiceManagerProxy#getService方法,代码如下:

public IBinder getService(String name) throws RemoteException {
    Parcel data = Parcel.obtain();
    Parcel reply = Parcel.obtain();
    data.writeInterfaceToken(IServiceManager.descriptor);
    data.writeString(name);
    mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
    IBinder binder = reply.readStrongBinder();
    reply.recycle();
    data.recycle();
    return binder;
}

这里mRemoteNative传过来的,我们暂时不跟踪,经调试后发现这里获取到的IBinder实例是BinderProxy。也就是说通过ServiceManager.getService("activity")得到的就是BinderProxy,然后回到ActivityManagerNative#gDetault继续向下看,看到调用了ActivityManagerNative#asInterface方法,实现如下:

/frameworks/base/core/java/android/app/ActivityManagerNative.java

static public IActivityManager asInterface(IBinder obj) {
    if (obj == null) {
        return null;
    }
    IActivityManager in =
        (IActivityManager)obj.queryLocalInterface(descriptor);
    if (in != null) {
        return in;
    }

    return new ActivityManagerProxy(obj);
}

和在ServiceManagerNative里的方法类似,这里返回了一个ServiceManagerProxy实例,也就是说通过ActivityManagerNative#getDefault()获取到的实例就是ActivityManagerProxy,而它的mRemoteBinderProxy

由此可见,作为客户端的我们,要与作为服务端的ActivityManagerService通信,都是通过Proxy代理完成的,真正的数据处理在Native层。接下来看它的ActivityManagerProxy#startActivity方法:

public int startActivity(IApplicationThread caller, String callingPackage, Intent intent,
        String resolvedType, IBinder resultTo, String resultWho, int requestCode,
        int startFlags, ProfilerInfo profilerInfo, Bundle options) throws RemoteException {
    Parcel data = Parcel.obtain();
    Parcel reply = Parcel.obtain();
    data.writeInterfaceToken(IActivityManager.descriptor);
    data.writeStrongBinder(caller != null ? caller.asBinder() : null);
    data.writeString(callingPackage);
    intent.writeToParcel(data, 0);
    data.writeString(resolvedType);
    data.writeStrongBinder(resultTo);
    data.writeString(resultWho);
    data.writeInt(requestCode);
    data.writeInt(startFlags);
    if (profilerInfo != null) {
        data.writeInt(1);
        profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
    } else {
        data.writeInt(0);
    }
    if (options != null) {
        data.writeInt(1);
        options.writeToParcel(data, 0);
    } else {
        data.writeInt(0);
    }
    mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0);
    reply.readException();
    int result = reply.readInt();
    reply.recycle();
    data.recycle();
    return result;
}

首先通过Parcel封装了一些数据,然后通过mRemote.transact(START_ACTIVITY_TRANSACTION, data, reply, 0)方法将数据发送出去,这个mRemote就是BinderProxy了,代码如下:

/frameworks/base/core/java/android/os/Binder.java

public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
    Binder.checkParcel(this, code, data, "Unreasonably large binder buffer");
    if (Binder.isTracingEnabled()) { Binder.getTransactionTracker().addTrace(); }
    return transactNative(code, data, reply, flags);
}

public native boolean transactNative(int code, Parcel data, Parcel reply,
        int flags) throws RemoteException;

这里又到了Native层,在Java层已经无法继续调试了,不过最终会调用到ActivityManagerService#onTransact,代码如下:

/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
        throws RemoteException {
    if (code == SYSPROPS_TRANSACTION) {
        ...
    }
    try {
        return super.onTransact(code, data, reply, flags);
    } catch (RuntimeException e) {
        // The activity manager only throws security exceptions, so let's
        // log all others.
        if (!(e instanceof SecurityException)) {
            Slog.wtf(TAG, "Activity Manager Crash", e);
        }
        throw e;
    }
}

发现这里处理的code值和之前传入的START_ACTIVITY_TRANSACTION并不一致,这一过程交给了父类ActivityManagerNative完成,代码如下:

public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
        throws RemoteException {
    switch (code) {
    case START_ACTIVITY_TRANSACTION:
    {
        data.enforceInterface(IActivityManager.descriptor);
        IBinder b = data.readStrongBinder();
        IApplicationThread app = ApplicationThreadNative.asInterface(b);
        String callingPackage = data.readString();
        Intent intent = Intent.CREATOR.createFromParcel(data);
        String resolvedType = data.readString();
        IBinder resultTo = data.readStrongBinder();
        String resultWho = data.readString();
        int requestCode = data.readInt();
        int startFlags = data.readInt();
        ProfilerInfo profilerInfo = data.readInt() != 0
                ? ProfilerInfo.CREATOR.createFromParcel(data) : null;
        Bundle options = data.readInt() != 0
                ? Bundle.CREATOR.createFromParcel(data) : null;
        int result = startActivity(app, callingPackage, intent, resolvedType,
                resultTo, resultWho, requestCode, startFlags, profilerInfo, options);
        reply.writeNoException();
        reply.writeInt(result);
        return true;
    }

    ...
    }

    return super.onTransact(code, data, reply, flags);
}

ActivityManagerNative的这个方法非常长,有接近3000行代码,全部是case XXX。稍微吐槽一下哈,写这么多case不累吗?接下来调用了ActivityManagerService#startActivity方法,代码如下:

/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

public final int startActivity(IApplicationThread caller, String callingPackage,
        Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
        int startFlags, ProfilerInfo profilerInfo, Bundle options) {
    return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
        resultWho, requestCode, startFlags, profilerInfo, options,
        UserHandle.getCallingUserId());
}

public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
        Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
        int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) {
    // 确保用户没有被隔离
    enforceNotIsolatedCaller("startActivity");
    // 拿到用户的userId
    userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
            false, ALLOW_FULL_ONLY, "startActivity", null);
    // TODO: Switch to user app stacks here.
    return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
            resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
            profilerInfo, null, null, bOptions, false, userId, null, null);
}

mActivityStarter是在ActivityManagerService实例化时就被初始化了,这里调用了它的startActivityMayWait方法,代码如下:

/frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java

final int startActivityMayWait(IApplicationThread caller, int callingUid,
        String callingPackage, Intent intent, String resolvedType,
        IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
        IBinder resultTo, String resultWho, int requestCode, int startFlags,
        ProfilerInfo profilerInfo, WaitResult outResult, Configuration config,
        Bundle options, boolean ignoreTargetSecurity, int userId,
        IActivityContainer iContainer, TaskRecord inTask) {
    ...
    
    synchronized (mService) {
        ...

        int res = startActivityLocked(caller, intent, resolvedType, aInfo,
                voiceSession, voiceInteractor, resultTo, resultWho,
                requestCode, callingPid, callingUid, callingPackage,
                realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity,
                componentSpecified, null, container, inTask);

        ...

        return res;
    }
}

下面又走到了startActivityLocked,代码如下:

final int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
        String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
        IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
        IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
        String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
        ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
        ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
        TaskRecord inTask) {
    int err = ActivityManager.START_SUCCESS;

    ...

    ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
            intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
            requestCode, componentSpecified, voiceSession != null, mSupervisor, container,
            options, sourceRecord);
    ...

    try {
        mService.mWindowManager.deferSurfaceLayout();
        err = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
                true, options, inTask);
    } finally {
        mService.mWindowManager.continueSurfaceLayout();
    }
    postStartActivityUncheckedProcessing(r, err, stack.mStackId, mSourceRecord, mTargetStack);
    return err;
}

Activity一直传过来的IApplicationThread实例现在转换到了ActivityRecord实例里,接下来是startActivityUnchecked,代码如下:

private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
            int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask) {

        ...
        // 处理和ActivityStack相关的操作
        mTargetStack.startActivityLocked(mStartActivity, newTask, mKeepCurTransition, mOptions);
        if (mDoResume) {
            ...
            if (!mTargetStack.isFocusable()
                    || (topTaskActivity != null && topTaskActivity.mTaskOverlay
                    && mStartActivity != topTaskActivity)) {
                ...
            } else {
                mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
                        mOptions);
            }
        } else {
            mTargetStack.addRecentActivityLocked(mStartActivity);
        }
        ...

        return START_SUCCESS;
    }

mSupervisor是在ActivityStarter实例化时传入进来的,实例化是在ActivityManagerService中完成。继续跟踪代码:

/frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java

boolean resumeFocusedStackTopActivityLocked(
        ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
    if (targetStack != null && isFocusedStack(targetStack)) {
        return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
    }
    ...
    return false;
}

接下来终于是启动Activity了,代码如下:

/frameworks/base/services/core/java/com/android/server/am/ActivityStack.java

boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
    ...
    try {
        ...
        result = resumeTopActivityInnerLocked(prev, options);
    } finally {
        mStackSupervisor.inResumeTopActivity = false;
    }
    return result;
}

private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
    ...

    // We need to start pausing the current activity so the top one can be resumed...
    final boolean dontWaitForPause = (next.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0;
    // 在这里,把所有其他的Activity都Pause掉
    boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, true, dontWaitForPause);
    
    ...
    // 进程已经被创建会走这里
    if (next.app != null && next.app.thread != null) {
        ...
    } else {
        // Whoops, need to restart this activity!
        ...
        mStackSupervisor.startSpecificActivityLocked(next, true, true);
    }

    if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
    return true;
}

这里看到启动新Activity前,会先将原有的Activity pause掉,这样做可以释放很多资源。启动Activity的工作交给了mStackSupervisor来处理,如下所示:

/frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java

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);

    // 只有app已经创建好之后才会走这个if
    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);
            }
            //启动Activity,注意return,将不会执行最后一句
            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.
    }

    // APP还未创建才会走到这里,通过AMS开启进程
    mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
            "activity", r.intent.getComponent(), false, false, true);
}

这里如果APP已经创建好会直接走realStartActivityLocked方法,不过开启进程之后应该也会走这个方法,这里先看下是如何开启进程的:

/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

final ProcessRecord startProcessLocked(String processName,
        ApplicationInfo info, boolean knownToBeDead, int intentFlags,
        String hostingType, ComponentName hostingName, boolean allowWhileBooting,
        boolean isolated, boolean keepIfLarge) {
    return startProcessLocked(processName, info, knownToBeDead, intentFlags, hostingType,
            hostingName, allowWhileBooting, isolated, 0 /* isolatedUid */, keepIfLarge,
            null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */,
            null /* crashHandler */);
}

这里startProcessLocked调用了多次重载方法,最终会走到这里,如下所示:

private final void startProcessLocked(ProcessRecord app, String hostingType,
        String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
    ...
    boolean isActivityProcess = (entryPoint == null);
    ...
    // Start the process.  It will either succeed and return a result containing
    // the PID of the new process, or else throw a RuntimeException.
    boolean isActivityProcess = (entryPoint == null);
    if (entryPoint == null) entryPoint = "android.app.ActivityThread";
    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
                    app.processName);
    checkTime(startTime, "startProcess: asking zygote to start proc");
    Process.ProcessStartResult startResult = Process.start(entryPoint,
            app.processName, uid, uid, gids, debugFlags, mountExternal,
            app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
            app.info.dataDir, entryPointArgs);
    checkTime(startTime, "startProcess: returned from zygote!");
    ...
}

可以看到是通过Process#start方法创建了需要的进程,该方法如下所示:

/frameworks/base/core/java/android/os/Process.java

public static final ProcessStartResult start(final String processClass,
                                final String niceName,
                                int uid, int gid, int[] gids,
                                int debugFlags, int mountExternal,
                                int targetSdkVersion,
                                String seInfo,
                                String abi,
                                String instructionSet,
                                String appDataDir,
                                String[] zygoteArgs) {
    try {
        return startViaZygote(processClass, niceName, uid, gid, gids,
                debugFlags, mountExternal, targetSdkVersion, seInfo,
                abi, instructionSet, appDataDir, zygoteArgs);
    } catch (ZygoteStartFailedEx ex) {
        ...
    }
}

这里看到了Zygote的身影,这个单词的意思是受精卵,我们的APP进程都是通过它孵化而来的,接下来的代码如下:

private static ProcessStartResult startViaZygote(final String processClass,
                                final String niceName,
                                final int uid, final int gid,
                                final int[] gids,
                                int debugFlags, int mountExternal,
                                int targetSdkVersion,
                                String seInfo,
                                String abi,
                                String instructionSet,
                                String appDataDir,
                                String[] extraArgs)
                                throws ZygoteStartFailedEx {
    synchronized(Process.class) {
        ArrayList argsForZygote = new ArrayList();

        // --runtime-args, --setuid=, --setgid=,
        // and --setgroups= must go first
        argsForZygote.add("--runtime-args");
        argsForZygote.add("--setuid=" + uid);
        argsForZygote.add("--setgid=" + gid);
        ...

        return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
    }
}

传递了一堆参数,然后通过SocketZygote通信,代码如下:

private static ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
    if (primaryZygoteState == null || primaryZygoteState.isClosed()) {
        try {
            primaryZygoteState = ZygoteState.connect(ZYGOTE_SOCKET);
        } catch (IOException ioe) {
            throw new ZygoteStartFailedEx("Error connecting to primary zygote", ioe);
        }
    }

    if (primaryZygoteState.matches(abi)) {
        return primaryZygoteState;
    }

    // The primary zygote didn't match. Try the secondary.
    if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) {
        try {
        secondaryZygoteState = ZygoteState.connect(SECONDARY_ZYGOTE_SOCKET);
        } catch (IOException ioe) {
            throw new ZygoteStartFailedEx("Error connecting to secondary zygote", ioe);
        }
    }

    if (secondaryZygoteState.matches(abi)) {
        return secondaryZygoteState;
    }

    throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi);
}

private static ProcessStartResult zygoteSendArgsAndGetResult(
        ZygoteState zygoteState, ArrayList args)
        throws ZygoteStartFailedEx {
    try {
        // Throw early if any of the arguments are malformed. This means we can
        // avoid writing a partial response to the zygote.
        int sz = args.size();
        for (int i = 0; i < sz; i++) {
            if (args.get(i).indexOf('\n') >= 0) {
                throw new ZygoteStartFailedEx("embedded newlines not allowed");
            }
        }

        /**
            * See com.android.internal.os.ZygoteInit.readArgumentList()
            * Presently the wire format to the zygote process is:
            * a) a count of arguments (argc, in essence)
            * b) a number of newline-separated argument strings equal to count
            *
            * After the zygote process reads these it will write the pid of
            * the child or -1 on failure, followed by boolean to
            * indicate whether a wrapper process was used.
            */
        final BufferedWriter writer = zygoteState.writer;
        final DataInputStream inputStream = zygoteState.inputStream;

        writer.write(Integer.toString(args.size()));
        writer.newLine();

        for (int i = 0; i < sz; i++) {
            String arg = args.get(i);
            writer.write(arg);
            writer.newLine();
        }

        writer.flush();

        // Should there be a timeout on this?
        ProcessStartResult result = new ProcessStartResult();

        // Always read the entire result from the input stream to avoid leaving
        // bytes in the stream for future process starts to accidentally stumble
        // upon.
        result.pid = inputStream.readInt();
        result.usingWrapper = inputStream.readBoolean();

        if (result.pid < 0) {
            throw new ZygoteStartFailedEx("fork() failed");
        }
        return result;
    } catch (IOException ex) {
        zygoteState.close();
        throw new ZygoteStartFailedEx(ex);
    }
}

通过Socket,等待Zygote孵化完毕后,返回进程的pid,我们看看Zygote这边做了什么,发送的Socket连接请求会在ZygoteInit中接收,在上方代码的注释里有说明,以下是ZygoteInitmain方法:

/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

public static void main(String argv[]) {
    try {
        ...

        registerZygoteSocket(socketName);
        EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
            SystemClock.uptimeMillis());
        preload();
        ...
        runSelectLoop(abiList);

        closeServerSocket();
    } catch (MethodAndArgsCaller caller) {
        ...
    }
}

Socket连接就是在runSelectLoop中完成的,代码如下:

private static void runSelectLoop(String abiList) throws MethodAndArgsCaller {
    ArrayList fds = new ArrayList();
    ArrayList peers = new ArrayList();

    fds.add(sServerSocket.getFileDescriptor());
    peers.add(null);

    while (true) {
        ...
        for (int i = pollFds.length - 1; i >= 0; --i) {
            if ((pollFds[i].revents & POLLIN) == 0) {
                continue;
            }
            if (i == 0) {
                ZygoteConnection newPeer = acceptCommandPeer(abiList);
                peers.add(newPeer);
                fds.add(newPeer.getFileDesciptor());
            } else {
                boolean done = peers.get(i).runOnce();
                if (done) {
                    peers.remove(i);
                    fds.remove(i);
                }
            }
        }
    }
}

当有一个连接时,就会执行else语句,调用ZygoteConnection#runOnce()方法,代码如下:

/frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java

boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {

    ...
    int pid = -1;
    ...

    try {
        ...

        pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
                parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
                parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet,
                parsedArgs.appDataDir);
    } catch (ErrnoException ex) {
        ...
    }

    ...

    try {
        if (pid == 0) {
            // in child
            IoUtils.closeQuietly(serverPipeFd);
            serverPipeFd = null;
            handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);

            // should never get here, the child is expected to either
            // throw ZygoteInit.MethodAndArgsCaller or exec().
            return true;
        } else {
            // in parent...pid of < 0 means failure
            IoUtils.closeQuietly(childPipeFd);
            childPipeFd = null;
            return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);
        }
    } finally {
        ...
    }
}

这里当返回pid为0时,表示是在孵化出来的进程中,然后会执行handleChildProc,我们先看Zygote孵化相关的代码,如下所示:

/frameworks/base/core/java/com/android/internal/os/Zygote.java

public static int forkAndSpecialize(int uid, int gid, int[] gids, int debugFlags,
        int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
        String instructionSet, String appDataDir) {
    VM_HOOKS.preFork();
    int pid = nativeForkAndSpecialize(
                uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
                instructionSet, appDataDir);
    ...
    return pid;
}

这里nativeForkAndSpecialize就是在底层进行真正的孵化操作,因为暂时不追踪Native代码,这里到此先停止。接下来看这ZygoteConnection#handleChildProc做了什么,代码如下:

/frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java

private void handleChildProc(Arguments parsedArgs,
        FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)
        throws ZygoteInit.MethodAndArgsCaller {
    ...
    
    closeSocket();
    ZygoteInit.closeServerSocket();

    ...
    if (parsedArgs.invokeWith != null) {
        WrapperInit.execApplication(parsedArgs.invokeWith,
                parsedArgs.niceName, parsedArgs.targetSdkVersion,
                VMRuntime.getCurrentInstructionSet(),
                pipeFd, parsedArgs.remainingArgs);
    } else {
        RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,
                parsedArgs.remainingArgs, null /* classLoader */);
    }
}

接下来调用到了RuntimeInit#zygoteInit方法,代码如下:

/frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
        throws ZygoteInit.MethodAndArgsCaller {
    ...
    nativeZygoteInit(); // native
    applicationInit(targetSdkVersion, argv, classLoader);
}

private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
        throws ZygoteInit.MethodAndArgsCaller {
    ...
    final Arguments args;
    try {
        args = new Arguments(argv);
    } catch (IllegalArgumentException ex) {
        ...
    }
    ...
    // Remaining arguments are passed to the start class's static main
    invokeStaticMain(args.startClass, args.startArgs, classLoader);
}

下面就是调用main方法了,代码如下:

private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
        throws ZygoteInit.MethodAndArgsCaller {
    Class cl;

    try {
        cl = Class.forName(className, true, classLoader);
    } catch (ClassNotFoundException ex) {
        ...
    }

    Method m;
    try {
        m = cl.getMethod("main", new Class[] { String[].class });
    } catch (NoSuchMethodException ex) {
        ...
    }

    int modifiers = m.getModifiers();
    if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
        throw new RuntimeException(
                "Main method is not public and static on " + className);
    }

    /*
        * This throw gets caught in ZygoteInit.main(), which responds
        * by invoking the exception's run() method. This arrangement
        * clears up all the stack frames that were required in setting
        * up the process.
        */
    throw new ZygoteInit.MethodAndArgsCaller(m, argv);
}

这里注释说会在ZygoteInit#main()方法中捕获异常,代码如下:

/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

public static void main(String argv[]) {
    // Mark zygote start. This ensures that thread creation will throw
    // an error.
    ZygoteHooks.startZygoteNoThreadCreation();

    try {
        ...

        registerZygoteSocket(socketName);
        ...
        if (startSystemServer) {
            startSystemServer(abiList, socketName);
        }

        Log.i(TAG, "Accepting command socket connections");
        runSelectLoop(abiList);

        closeServerSocket();
    } catch (MethodAndArgsCaller caller) {
        caller.run();
    } catch (RuntimeException ex) {
        ...
    }
}

这个方法是在前面先调用的,所以如果抛出MethodAndArgsCaller异常,就会在这里被catch,然后执行它的run方法,代码如下:

public void run() {
    try {
        mMethod.invoke(null, new Object[] { mArgs });
    } catch (IllegalAccessException ex) {
        ...
    }
}

至此,要执行的main方法就被invoke成功了。那这个main方法是哪个类的呢?我们需要反向查看之前的代码,在RuntimeInit#invokeStaticMain方法中传入的第一个参数就是className,而这个参数是通过args.startClass获取的,相应的代码在RuntimeInit#applicationInit中。这个args是把传进来的String[] argv转成了Arguments变量,我们看下这个Arguments,它是RuntimeInit的内部类,代码如下:

Arguments(String args[]) throws IllegalArgumentException {
    parseArgs(args);
}

/**
    * Parses the commandline arguments intended for the Runtime.
    */
private void parseArgs(String args[])
        throws IllegalArgumentException {
    int curArg = 0;
    for (; curArg < args.length; curArg++) {
        String arg = args[curArg];

        if (arg.equals("--")) {
            curArg++;
            break;
        } else if (!arg.startsWith("--")) {
            break;
        }
    }

    if (curArg == args.length) {
        throw new IllegalArgumentException("Missing classname argument to RuntimeInit!");
    }

    startClass = args[curArg++];
    startArgs = new String[args.length - curArg];
    System.arraycopy(args, curArg, startArgs, 0, startArgs.length);
}

可以看到startClassargs里最后一个值。那么这个args又是从哪里来的呢?还记得在Process#startViaZygote方法里,创建了一堆参数吗?当时没有细细研究,现在回过头来看,在赋值了一些--xxx的字段之后,最后还添加了一个值,代码如下:

/frameworks/base/core/java/android/os/Process.java

argsForZygote.add(processClass);

这个processClass就是我们要找的值了,但是它也是从前面传过来的,调用的地方在Process#start方法里,这个值依然作为参数传递了过来。然后回到了Process#start的调用处,在ActivityManagerService#startProcessLocked方法里找到了下面关键一句话:

/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

if (entryPoint == null) entryPoint = "android.app.ActivityThread";

终于找到了根源,也就是说Zygote孵化完成之后,会invoke ActivityThread#main方法。接下来进程创建完毕,就该是我们APP的初始化了,下一篇文章再来分析。

上一篇:Android源码分析之准备:Android Studio调试AOSP代码

下一篇:Android源码分析之App启动流程(二)

你可能感兴趣的:(Android源码分析之App启动流程(一))