从Android 8.0源码的角度剖析APP的启动过程

从Android 8.0源码的角度剖析Android系统启动过程(2)一文中,我们了解到当ActivitiyManagerService服务被启动后,就会通过Intent以隐士匹配的方式启动一个匹配属性Action值为Intent.ACTION_MAIN和Category值为Intent.CATEGORY_HOME的Activity,而这个Activity就是Launcher应用中一个名为Launcher的Activity,这个Activity是Launcher应用的入口Activity,通常这类Activity我们称之为应用程序的Home Activity,当这个Home Activity被启动后,Launcher应用也就被启动了。也就是说,一个Android应用程序(APP)的启动就是启动它的Home Activity,而在Home Activity的启动过程中,又经历了该应用程进程的创建和Home Activity的启动两个过程。

1. 应用进程启动过程

 应用程序进程的创建分为两个步骤:一是SystemServer进程中的AMS服务通过Socket通信的方式向Zygote进程发起连接请求;二是Zygote进程接收到Sokect请求后与SystemServer进程建立Socket链接,然后以fork形式创建一个子进程,该子进程就是要创建的进程。

1.1 AMS向Zygote进程发起请求

 应用进程启动时序图如下:
在这里插入图片描述
 一个APP的启动通常是通过从点击"手机桌面"的应用程序图标(快捷方式)开始的,而这个"手机桌面"就是剖析Android系统启动过程(2)这篇文章中介绍到的Launcher应用,该进程被AMS(位于SystemServer进程中)启动后就会为被安装在Android系统中的应用程序生成对应的快捷方式图标,并显示在"桌面"上。当我们点击“手机桌面”上某个应用程序图标后,就会触发Launcher应用的Home Activity(根Activity),即Launcher的点击事件回调方法onClick。该源码如下:

// \Android8.0\packages\apps\Launcher3\src\com\android\launcher2
// Launcher.java
public void onClick(View v) {
    Object tag = v.getTag();
    // 判断是否为快捷方式图标
    // 如果是获取对应intent,并调用startActivitySafely进入下一步处理
    if (tag instanceof ShortcutInfo) {
        // Open shortcut
        final Intent intent = ((ShortcutInfo) tag).intent;
        int[] pos = new int[2];
        v.getLocationOnScreen(pos);
        intent.setSourceBounds(new Rect(pos[0], pos[1],
                                        pos[0] + v.getWidth(), pos[1] + 
                                        v.getHeight()));
        boolean success = startActivitySafely(v, intent, tag);

        if (success && v instanceof BubbleTextView) {
            mWaitingForResume = (BubbleTextView) v;
            mWaitingForResume.setStayPressed(true);
        }
    }
    // 判断是否为文件夹
    else if (tag instanceof FolderInfo) {
        if (v instanceof FolderIcon) {
            FolderIcon fi = (FolderIcon) v;
            handleFolderClick(fi);
        }
    } else if (v == mAllAppsButton) {
        if (isAllAppsVisible()) {
            showWorkspace(true);
        } else {
            onClickAllAppsButton(v);
        }
    }
}

 OnClick方法首先会获取目标View的tag信息,然后根据tag信息判断是否为ShortcutInfo的一个实例,如果是就说明当前点击事件为点击了某个应用程序图标,或称应用快捷方式,这时onClick方法就会获取存储在tag中intent,这个intent存储了要启动的APP信息,然后调用Launcher的startActivitySafely方法进入下一步处理。startActivitySafely方法实现非常简单,就是去调用Launcher的startActivity方法。该方法源码如下:

// \Android8.0\packages\apps\Launcher3\src\com\android\launcher2
// Launcher.java
boolean startActivity(View v, Intent intent, Object tag) {
    // 为Intent添加一个FLAG_ACTIVITY_NEW_TASK标记
    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

    try {
        // 是否显示启动APP的动画
        boolean useLaunchAnimation = (v != null) &&
                    !intent.hasExtra(INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION);
        // 用户句柄
        UserHandle user = (UserHandle) 
                intent.getParcelableExtra(ApplicationInfo.EXTRA_PROFILE);
        // 用于在多用户情境下启动App的系统服务
        LauncherApps launcherApps = (LauncherApps)
                    this.getSystemService(Context.LAUNCHER_APPS_SERVICE);
        if (useLaunchAnimation) {
            if (user == null || user.equals(android.os.Process.myUserHandle())) {
				// 调用Activity的startActivity
                startActivity(intent, opts.toBundle());
            } else {
                launcherApps.startMainActivity(intent.getComponent(), user,
                                               intent.getSourceBounds(),
                                               opts.toBundle());
            }
        } else {
            if (user == null || user.equals(android.os.Process.myUserHandle())) {
                // 调用Activity的startActivity
                startActivity(intent);
            } else {
                launcherApps.startMainActivity(intent.getComponent(), user,
                                               intent.getSourceBounds(), null);
            }
        }
        return true;
    } catch (SecurityException e) {
        Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
    }
    return false;
}

 从上述源码可知,它首先将Intent的flag属性设为Intent.FLAG_ACTIVITY_NEW_TASK,其目的是创建一个新的Activity任务栈来放置即将被打开的Activity;然后获取Intent中是否传输了Parcelable格式的用户句柄,该用户句柄与Android的多用户安全机制有关。由于我们接触的大多是单用户情景,所以直接考虑user==null情况,且无论是否显示启动APP动画,都会调用Activity的startActivity方法。该方法实现很简单,只是调用了startActivityForResult方法。相关源码如下:


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

public void startActivityForResult(@RequiresPermission Intent intent,
                                   int requestCode,
                                   @Nullable Bundle options) {
    // 判断mParent是否为空
    // 当前Activity的父类
    if (mParent == null) {
        options = transferSpringboardActivityOptions(options);
        Instrumentation.ActivityResult ar =
            mInstrumentation.execStartActivity(
            this, mMainThread.getApplicationThread(), mToken, this,
            intent, requestCode, options);
		...
    }
    ...
}

 在startActivityForResult方法中,由于是新启动的Activity,当前Activity无父类,因此我们只需要考虑mParent=null情况,接着就回去调用Instrumentation的execStartActivity方法,Instrumentation主要用来监控应用程序和系统的交互。execStartActivity方法需传入多个参数,其中who表示启动这个Activity应用进程的上下文信息,contextThread表示启动这个Activity应用进程的线程信息,很明显这里的应用进程指的就是Launcher进程。execStartActivity方法源码如下:

// Android8.0\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) {
    // 表示谁启动Activity
    IApplicationThread whoThread = (IApplicationThread) contextThread;
    ...
        try {
            intent.prepareToLeaveProcess(who);
            // 调用AMS的startActivity
            int result = ActivityManager.getService()
                .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;
}

// Android8.0\frameworks\base\core\java\android\app\ActivityManager.java
public static IActivityManager getService() {
    // 单例模式返回AMS代理对象
    return IActivityManagerSingleton.get();
}

private static final Singleton<IActivityManager> IActivityManagerSingleton =
    new Singleton<IActivityManager>() {
    @Override
    protected IActivityManager create() {
        // am为AMS Binder实体代理对象
        final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
        final IActivityManager am = IActivityManager.Stub.asInterface(b);
        return am;
    }
};

 在execStartActivity方法中,它会去调用ActivityManager的getService方法来获取AMS的Binder实体代理对象IActivityManager,并接着调用它的startActivity方法,由于整个过程是一次基于Binder机制的跨进程通信,因此本次启动Activity的请求将传递到远程的AMS(位于系统进程SystemServer)中,并执行Binder实体中真实的startActivity方法,这也就意味着执行流程从Launcher进程切换到SystemServer进程。需要注意的是,这里获取AMS的代码对象与Android 8.0之前的源码不同,Android 8.0之前的代码是通过ActivityManagerNative的getDefault来获取的,它采用类似AIDL的形式,用AMS得代理对象ActivityManagerProxy来与AMS进行进程间通信。Android8.0摒弃了这种方式,直接采用AIDL的形式实现AMS的Binder通信框架,其中IActivityManager就是AMS的代理对象,用于替代ActivityManagerNative的内部类ActivityManagerProxy。接下来,我们来看AMS的startActivity方法。该方法源码如下:

// \Android8.0\frameworks\base\services\core\java\com\android\server\am
// ActivityManagerService.java
@Override
public final int startActivity(IApplicationThread caller, String callingPackage,
                               Intent intent, String resolvedType, IBinder resultTo, 
                               String resultWho, int requestCode,
                               int startFlags, ProfilerInfo profilerInfo, Bundle 
                               bOptions) {
    // 启动Activity
    return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
                               resultWho, requestCode, startFlags, profilerInfo, 
                               bOptions,
                               UserHandle.getCallingUserId());
}

@Override
public final int startActivityAsUser(IApplicationThread caller, String 
    		callingPackage,Intent intent, String resolvedType, IBinder resultTo, 
            String resultWho, intrequestCode,int startFlags, ProfilerInfo profilerInfo, 
                                     Bundle bOptions, int userId) {
     enforceNotIsolatedCaller("startActivity");
     // 获取调用者的userId
     userId = mUserController.handleIncomingUser(Binder.getCallingPid(), 
                                                    Binder.getCallingUid(),
                userId, false, ALLOW_FULL_ONLY, "startActivity", null);
    
     // 调用ActivityStarter的startActivityMayWait
     return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
                resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
                profilerInfo, null, null, bOptions, false, userId, null, null,
                "startActivityAsUser");
}

 AMS的startActivity实现很简单,它继续调用了startActivityAsUser方法,在该方法中首先获取调用者的userID,因为AMS后续用这个userID来确定调用者的权限;然后调用ActivityStarter的startActivityMayWait方法,该方法继续调用ActivityStarter的startActivityLocked方法,而这个方法实现更简单,直接调用了ActivityStarter的startActivity方法。需要注意的是,ActivityStarter是Android7.0中新加入的类,它是加载Activity的控制类,会收集所有的逻辑来决定如何将Intent和Flags属性值转换为Activity,并将Activity和task相关联。接下来,我们就来看下ActivityStarter的startActivity方法做了什么。

// Android8.0\frameworks\base\services\core\java\com\android\server\am
// ActivityStarter.java
private int startActivity(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) {
    // 注释1: 用于描述调用者进程
    ProcessRecord callerApp = null;
    // 注释2: 指向调用者进程的ApplicationThread
    if (caller != null) {
        callerApp = mService.getRecordForAppLocked(caller);
        if (callerApp != null) {
            callingPid = callerApp.pid;
            callingUid = callerApp.info.uid;
        } else {
            Slog.w(TAG, "Unable to find app for caller " + caller
                   + " (pid=" + callingPid + ") when starting: "
                   + intent.toString());
            err = ActivityManager.START_PERMISSION_DENIED;
        }
    }
    ...
    // 注释3
    ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
                callingPackage, intent, resolvedType, aInfo, 
                mService.getGlobalConfiguration(),resultRecord, resultWho, 
                requestCode, componentSpecified,voiceSession != null,
                mSupervisor, container, options, sourceRecord);
    if (outActivity != null) {
        outActivity[0] = r;
    }
    ...
	// 注释4
    return startActivity(r, sourceRecord, voiceSession, voiceInteractor, 
                         startFlags, true,
                         options, inTask, outActivity);
}

 注释1中定义了一个ProcessRecord对象,该对象描述了一个应用进程信息,这里指的是Launcher进程;注释2会判断IApplicationThread类型的caller是否为空,这个caller对象指向的是Launcher所在的应用进程的ApplicationThread对象,很明显caller不为空;注释3创建了 一个ActivityRecord对象,该对象用来记录一个Activity的所有信息,这里要记录的就是我们要启动的根Activity信息;注释4调用ActivityStarter的startActivity的重载方法,在该方法中又会继续调用ActivityStarter的startActivityUnchecked。由于后续的调用较为复杂,我们需要关注的东西不是很多,下面就只给出调用时序图,具体如下:

ActivityStarterActivityStaActivityStackstartActivityUncheckedresumeFocusedStackTopActivityLockedresumeFocusedStackTopActivityLockedresumeTopActivityUncheckedLockedresumeTopActivityInnerLockedstartSpecificActivityLockedActivityStarterActivityStaActivityStack

 接下来,我们就直接分析ActivityStackSupervisor的startSpecificActivityLocked方法,因为在这个方法中会去判断要启动的Activity所属进程是否启动,如果启动了则说明当前启动的是一个普通的Activity,如果没有启动,则需要先去创建这个应用进程,而将要启动的这个Activity就是这个应用的根Activity。该方法源码如下:

// Android8.0\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?
    // 获取进程名为processName的ProcessRecord对象
    ProcessRecord app = mService.getProcessRecordLocked(r.processName,
                                                        r.info.applicationInfo.uid, true);

    r.getStack().setLaunchTime(r);
    // 获取app进程记录
    // 判断app是否已经启动过,如果启动过
    // 调用realStartActivityLocked执行普通的。Activity启动
    // 说明:app.thread指的是IApplicationThread,它的实现是ActivityThread的内部类
    //      ApplicationThread,ApplicationThread继承了IApplicationThread.Stub,它是
    //      AMS所在进程(SystemServer进程)与应用程序进程Binder通信的桥梁。
    if (app != null && app.thread != null) {
        try {
            if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
                || !"android".equals(r.info.packageName)) {
                app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
                               mService.mProcessStats);
            }
            // 启动一个普通的Activity
            realStartActivityLocked(r, app, andResume, checkConfig);
            return;
        } catch (RemoteException e) {
            Slog.w(TAG, "Exception when starting activity "
                   + r.intent.getComponent().flattenToShortString(), e);
        }
    }
    // 如果进程没有被启动,调用AMS的startProcessLocked
    // 去请求Zygote创建新的应用程序进程
    mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
                                "activity", r.intent.getComponent(), false, false, true);
}

 在startSpecificActivityLocked方法中,它首先会根据processName获得一个ProcessRecord对象app,该对象描述了一个应用进程信息,可以这么说app对象指的就是要启动的Activity所在的应用程序进程;然后判断appapp.thread是否为空,如果不为空,说明被启动的Activity所在的应用程序进程已经被启动了,说明当前启动的Activity是一个普通的Activity,将调用ActivityStackSupervisor的realStartActivityLocked方法执行具体的Activity启动工作。如果为空,说明被启动的Activity所在的应用进程没有被启动,此时就会去调用AMS的startProcessLocked方法执行应用程序进程创建工作,进而启动应用程序的根Activity。由于这里我们分析的是APP的启动过程,说明此时应用进程是没有被启动的,接下来我们就分析AMS的startProcessLocked方法,该方法又调用了它的两个重载方法,我们看最后一个。源码如下:

// \Android8.0\frameworks\base\services\core\java\com\android\server\am
// ActivityManagerService.java
private final void startProcessLocked(ProcessRecord app, String hostingType,
                                      String hostingNameStr, String abiOverride, 
                                      String entryPoint, String[] entryPointArgs) {
    ...
    // 获取要创建的应用程序的用户ID
    int uid = app.uid;
    int[] gids = 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");
    ProcessStartResult startResult;
    if (hostingType.equals("webview_service")) {
        startResult = startWebView(entryPoint,
                                   app.processName, uid, uid, gids, 
                                   debugFlags, mountExternal,
                                   app.info.targetSdkVersion, seInfo, 
                                   requiredAbi, instructionSet,
                                   app.info.dataDir, null, entryPointArgs);
    } else {
        // 创建新的应用进程
        // 传入entryPoint,后面会用到
        startResult = Process.start(entryPoint,
                                    app.processName, uid, uid, gids, 
                                    debugFlags, mountExternal,
                                    app.info.targetSdkVersion, seInfo,
                                    requiredAbi, instructionSet,
                                    app.info.dataDir, invokeWith, entryPointArgs);
    }
    checkTime(startTime, "startProcess: returned from zygote!");
    ...
}

 该方法首先获取要创建的应用程序的用户ID,它被存储在进程描述类ProcessRecord的app对象中;然后将entrypoint变量值设置为"android.app.ActivityThread",这个变量存储的是应用程序进程被创建后启动的入口,这个ActivityThread代表主线程的实例,它管理着当前应用程序进程的主线程;最后调用Process的start方法真正进入新进程的创建工作,该方法源码如下:

// Android8.0\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 invokeWith,
                                             String[] zygoteArgs) {
    return zygoteProcess.start(processClass, niceName, uid, gid, gids,
                               debugFlags, mountExternal, targetSdkVersion, seInfo,
                               abi, instructionSet, appDataDir, invokeWith, 
                               zygoteArgs);
}

 从Process的start方法可知,它继续调用了ZygoteProcess的start方法,这个ZygoteProcess类主要用于维持与Zygote进程的通信状态,即向Zygote进程的Server Socket端(Zygote进程在启动时,会在Zygoyte的main方法中创建name为"zygote"的Server端Socket。)发起连接请求和进行Socket通信。接下来,我们来看一下ZygoteProcess的start方法:

// Android8.0\frameworks\base\core\java\android\os
// ZygoteProcess.java
public final Process.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 invokeWith,
                                              String[] zygoteArgs) {
    try {
        // 创建进程
        return startViaZygote(processClass, niceName, uid, gid, gids,
                              debugFlags, mountExternal, targetSdkVersion, seInfo,
                              abi, instructionSet, appDataDir, invokeWith, zygoteArgs);
    } catch (ZygoteStartFailedEx ex) {
        Log.e(LOG_TAG,
              "Starting VM process through Zygote failed");
        throw new RuntimeException(
            "Starting VM process through Zygote failed", ex);
    }
}

 该方法继续调用ZygoteProcess的startViaZygote方法:

// Android8.0\frameworks\base\core\java\android\os
// ZygoteProcess.java
private Process.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 invokeWith,
                                                  String[] extraArgs)
    throws ZygoteStartFailedEx {
    // 保存应用程序进程启动参数
    ArrayList<String> argsForZygote = new ArrayList<String>();
    ...
    argsForZygote.add(processClass);

    if (extraArgs != null) {
        for (String arg : extraArgs) {
            argsForZygote.add(arg);
        }
    }
    // 启动进程
    synchronized(mLock) {
        return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), 
                                          argsForZygote);
    }    
}

 该方法首先会创建一个列表argsForZygote用于保存应用程序进程启动参数,比如processClass,这个字符串就是之前传进来的应用进程入口类"android.app.ActivityThread";然后调用zygoteSendArgsAndGetResult方法向Zygote进程的Server Socket端发起连接请求,并将应用进程的启动参数传递过去。首先我们来看下,发起Socket连接请求的流程,通过调用openZygoteSocketIfNeeded方法实现。该方法源码如下:

// Android8.0\frameworks\base\core\java\android\os
// ZygoteProcess.java
@GuardedBy("mLock")
private ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
    Preconditions.checkState(Thread.holdsLock(mLock), "ZygoteProcess lock not held");
	
    if (primaryZygoteState == null || primaryZygoteState.isClosed()) {
        try {
            // 向主Zygote进程发起scoket连接请求
            // mSocket=ZYGOTE_SOCKET="zygote"(由Process传入)
            primaryZygoteState = ZygoteState.connect(mSocket);
        } 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 {
            // 向辅Zygote进程发起scoket连接请求
            // mSecondarySocket=SECONDARY_ZYGOTE_SOCKET = "zygote_secondary";
            secondaryZygoteState = ZygoteState.connect(mSecondarySocket);
        } 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);
}

 在openZygoteSocketIfNeeded方法中,它首先会调用ZygoteState的connect方法与名称为"zygote“的Socket建立连接并返回一个ZygoteState对象primaryZygoteState,其中这个名为”zygote"的Scoket就是Zygote进程在启动时创建的Server端Socket。需要注意的是,如果primaryZygoteState与启动的应用程序进程所需的ABI不匹配,就会去连接辅Zygote进程中名为"zygote_secondary"的Server端Socket,并返回ZygoteState对象secondaryZygoteState。如果两种模式都不匹配,就会抛出ZygoteStartFailedEx异常。对于主Zygote进程和辅Zygote进程,在剖析Android系统启动过程(1)一文(末)中,我们曾谈到Zygote进程在启动时根据不同的脚本启动不同类型的Zygote进程,通常包含主Zygote进程和辅Zygote进程。接下来,我们再分析建立Socket连接后,将应用进程启动参数传递给Zygote进程的过程,请看ZygoteProcess的zygoteSendArgsAndGetResult方法。

// Android8.0\frameworks\base\core\java\android\os
// ZygoteProcess.java
private static Process.ProcessStartResult zygoteSendArgsAndGetResult(
    ZygoteState zygoteState, ArrayList<String> args)
    throws ZygoteStartFailedEx {
    try {
        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");
            }
        }

        final BufferedWriter writer = zygoteState.writer;
        final DataInputStream inputStream = zygoteState.inputStream;
		// 将应用进程启动参数args写入到zygoteState中
        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();

        Process.ProcessStartResult result = new Process.ProcessStartResult();

        result.pid = inputStream.readInt();
        result.usingWrapper = inputStream.readBoolean();

        if (result.pid < 0) {
            throw new ZygoteStartFailedEx("fork() failed");
        }
        // 返回创建的应用程序进程pid
        return result;
    } catch (IOException ex) {
        zygoteState.close();
        throw new ZygoteStartFailedEx(ex);
    }
}

  该方法的目的就是将传入的应用程序进程启动参数写入到之前openZygoteSocketIfNeeded方法返回的ZygoteState对象中,这个对象表示的与Zygote进程通信(Socket方式)的状态。当Zygote进程读取完这些参数,并fork子进程成功后会将该子进程的pid(进程号)返回。下一小节,我们将分析Zygote进程接收到AMS发起的Socket请求后,是如何fork出子进程,即新的应用程序进程。

1.2 Zygote进程接受请求

 Zygote进程fork子进程时序图:
在这里插入图片描述
 在剖析Android系统启动过程(1)一文中,我们曾谈到当Zygote进程启动后就会去创建一个名为"zygote"的Server端Socket,该Socket的作用就是等待SystemServer进程中的AMS服务请求Zygote进程创建一个新的应用程序进程,其中这个等待的过程通过调用ZygoteServer的runSelectLoop方法实现。源码如下:

// Android8.0\frameworks\base\core\java\com\android\internal\os\ZygoteServer.java
void runSelectLoop(String abiList) throws Zygote.MethodAndArgsCaller {
    ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
    ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
    // 获取Server Socket的fd字段的值
    // 添加到fds列表中
    fds.add(mServerSocket.getFileDescriptor());
    peers.add(null);
    // 无限等待AMS的请求
    while (true) {
        StructPollfd[] pollFds = new StructPollfd[fds.size()];
        for (int i = 0; i < pollFds.length; ++i) {
            pollFds[i] = new StructPollfd();
            pollFds[i].fd = fds.get(i);
            pollFds[i].events = (short) POLLIN;
        }
        try {
            Os.poll(pollFds, -1);
        } catch (ErrnoException ex) {
            throw new RuntimeException("poll failed", ex);
        }

        for (int i = pollFds.length - 1; i >= 0; --i) {
            if ((pollFds[i].revents & POLLIN) == 0) {
                continue;
            }
            // AMS与Zygote进程建立连接
            if (i == 0) {
                ZygoteConnection newPeer = acceptCommandPeer(abiList);
                peers.add(newPeer);
                fds.add(newPeer.getFileDesciptor());
            } else {
                // 收到AMS发送的请求
                // 调用runOnce创建一个新的应用程序进程
                boolean done = peers.get(i).runOnce(this);
                if (done) {
                    peers.remove(i);
                    fds.remove(i);
                }
            }
        }
    }
}

 从runSelectLoop方法源码可知,当Zygote进程接收到AMS发送过来的请求后,就会调用ZygoteConnection的runOnce方法进入新应用程序进程的创建工作。ZygoteConnection$runOnce方法源码如下:

// Android8.0\frameworks\base\core\java\com\android\internal\os\ZygoteConnection.java
boolean runOnce(ZygoteServer zygoteServer) throws Zygote.MethodAndArgsCaller {
    ...
        FileDescriptor fd = mSocket.getFileDescriptor();

    if (fd != null) {
        fdsToClose[0] = fd.getInt$();
    }

    fd = zygoteServer.getServerSocketFileDescriptor();

    if (fd != null) {
        fdsToClose[1] = fd.getInt$();
    }

    fd = null;
    // Zygote进程fork自身创建新的应用程序进程
    pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
                                   parsedArgs.debugFlags, rlimits, 
                                   parsedArgs.mountExternal, parsedArgs.seInfo,
                                   parsedArgs.niceName, fdsToClose, fdsToIgnore, 
                                   parsedArgs.instructionSet,
                                   parsedArgs.appDataDir);
	...
	// pid=0
    // 当前代码逻辑运行在子进程中
    try {
        if (pid == 0) {
            // in child
            zygoteServer.closeServerSocket();
            IoUtils.closeQuietly(serverPipeFd);
            serverPipeFd = null;
            // 处理子进程启动逻辑
            handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);

            // should never get here, the child is expected to either
            // throw Zygote.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 {
        IoUtils.closeQuietly(childPipeFd);
        IoUtils.closeQuietly(serverPipeFd);
    }
}

 runOnce方法主要完成两个任务,一是调用Zygote的forkAndSpecialize方法创建一个子进程,该方法最终会调用Zygote的nativeForkAndSpecialize方法,这个方法是一个native方法,它将在native层调用fork函数实现子进程的创建;二是当pid=0时,说明子进程被创建成功且当前代码运行在子进程中,接着就会去调用ZygoteConnection的handleChildProc方法进入子进程(新的应用程序进程)的启动过程。接下来,我们分析新创建的子进程(或称应用程序进程)是如何启动的。继续看ZygoteConnection$handleChildProc方法,源码如下:

private void handleChildProc(Arguments parsedArgs,
                             FileDescriptor[] descriptors, FileDescriptor pipeFd, 
                             PrintStream newStderr)
    throws Zygote.MethodAndArgsCaller {

    // 关闭Sokcet
    closeSocket();
    ...
    ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion,
                              parsedArgs.remainingArgs, null /* classLoader */);
    ...
}

 该方法实现很简单,首先是关闭Socket,因为随着子进程在native层被fork出来,Socket连接实际上在native层已断开,这里只是收尾工作;然后继续调用ZygoteInit的zygoteInit,这个方法我们在剖析Android系统启动过程(2)文中分析SystemServer进程启动有接触过,它首先会启动一个Binder线程池,便于当前新创建的进程(注:这里就不是SystemServer进程了哈)能与其他进程进行Binder通信;然后调用RuntimeInit的applicationInit方法,该方法最终会通过反射的形式调用之前传进来的"android.app.ActivityThread"类的main方法。ZygoteInit$zygoteInit源码如下:

public static final void zygoteInit(int targetSdkVersion, String[] argv,
                                    ClassLoader classLoader) throws 
    								Zygote.MethodAndArgsCaller {
    if (RuntimeInit.DEBUG) {
        Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
    }

    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
    RuntimeInit.redirectLogStreams();

    RuntimeInit.commonInit();
    // 启动Binder线程池
    ZygoteInit.nativeZygoteInit();
    // 最终调用ActivityThread的main方法
    RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
}

 虽然上述两个过程剖析Android系统启动过程(2)文中都分析过程,但是为了引出下一小节,这里再“撸”下ActivityThread的main方法调用过程。RuntimeInit$applicationInit方法源码如下:

// Android8.0\frameworks\base\core\java\com\android\internal\os\RuntimeInit.java
protected static void applicationInit(int targetSdkVersion, String[] argv, 
                                      ClassLoader classLoader)
    throws Zygote.MethodAndArgsCaller {
    ...
    // 将应用程序进程启动参数
    //  String args[] = {
    //      processClass = "android.app.ActivityThread"
    //    	pid
    //        ...
    //   };
    // 存储到Arguments中
    final Arguments args;
    try {
        args = new Arguments(argv);
    } catch (IllegalArgumentException ex) {
        Slog.e(TAG, ex.getMessage());
        // let the process exit
        return;
    }
    
    // Remaining arguments are passed to the start class's static main
    // 调用startClass的main方法,该方法是一个静态方法
    // 这个startClass就是AMS传递过来的processClass
    // 即"android.app.ActivityThread"
    invokeStaticMain(args.startClass, args.startArgs, classLoader);
}

RuntimeInit$applicationInit方法首先会将AMS传递过来的应用程序进程启动参数存储到Arguments中,然后调用RuntimeInit$invokeStaticMain方法,该方法将通过反射的形式调用args.startClass表示类的main方法,而这个arg.startClass表示的类就是"android.app.ActivityThread"。RuntimeInit$invokeStaticMain方法源码如下:

// Android8.0\frameworks\base\core\java\com\android\internal\os\RuntimeInit.java
private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
    throws Zygote.MethodAndArgsCaller {
    Class<?> cl;

    try {
        // 通过类名全限定路径获取对应的Class对象
        cl = Class.forName(className, true, classLoader);
    } catch (ClassNotFoundException ex) {
        throw new RuntimeException(
            "Missing class when invoking static main " + className,
            ex);
    }

    Method m;
    try {
        // 通过Class对象获取className类的main方法
        m = cl.getMethod("main", new Class[] { String[].class });
    } catch (NoSuchMethodException ex) {
        throw new RuntimeException(
            "Missing static main on " + className, ex);
    } catch (SecurityException ex) {
        throw new RuntimeException(
            "Problem getting static main on " + className, ex);
    }

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

    // 抛出MethodAndArgsCaller异常
    // 并将m作为参数传出去,将被ZygoteInit.main函数捕获
    throw new Zygote.MethodAndArgsCaller(m, argv);
}

 在invokeStaticMain方法中,对"android.app.ActivityThread"的main方法调用比较巧妙,它通过反射方式获取到ActivityThread类的main方法信息后并没有直接去调用它,而是在方法的最后抛出了一个Zygote.MethodAndArgsCaller异常,并将代表"main"函数的Method的对象和相关参数传递进去。那么问题来了,又在哪里捕获这个Zygote.MethodAndArgsCaller异常?首先我们来分析捕获这个异常的地方。通常一个异常的抛出,要么由方法本身捕获,要么由调用它的上一级方法,甚至更上多级。因此,我们采用向上回溯方式,从当前方法(invokeStaticMain)向上查找到底哪个方法catch了Zygote.MethodAndArgsCaller异常,最终我们找到ZygoteInit的main方法对这个异常进行了捕获,而该main方法就是之前我们分析得到的,即启动SystemServer进程的入口!回顾下ZygoteInit的main方法:

// \Android8.0\frameworks\base\core\java\com\android\internal\os\ZygoteInit.java
public static void main(String argv[]) {
    ...
    try{
		...
    } catch (Zygote.MethodAndArgsCaller caller) {
        // 捕获ygote.MethodAndArgsCaller异常
        caller.run();
    }
    ...
}

// Android8.0\frameworks\base\core\java\com\android\
//     internal\os\Zygote.java$MethodAndArgsCaller 
public static class MethodAndArgsCaller extends Exception
            implements Runnable {
        /** method to call */
        private final Method mMethod;

        /** argument array */
        private final String[] mArgs;

        public MethodAndArgsCaller(Method method, String[] args) {
            mMethod = method;
            mArgs = args;
        }

        public void run() {
            try {
				// 调用m方法,传入参数为mArgs
				// mArgs="android.app.ActivityThread"
                mMethod.invoke(null, new Object[] { mArgs });
            } catch (IllegalAccessException ex) {
                throw new RuntimeException(ex);
            } catch (InvocationTargetException ex) {
                Throwable cause = ex.getCause();
                if (cause instanceof RuntimeException) {
                    throw (RuntimeException) cause;
                } else if (cause instanceof Error) {
                    throw (Error) cause;
                }
                throw new RuntimeException(ex);
            }
        }
}

 从上述源码可知,ZygoteInit的main方法捕获到Zygote.MethodAndArgsCaller异常后,会直接调用Zygote.MethodAndArgsCaller的run方法,再调用反射类Method的invoke方法对"android.app.ActivityThread"类的main方法进行动态调用。ActivityThread$main方法源码如下:

// Android8.0\frameworks\base\core\java\android\app
// ActivityThread.java
public static void main(String[] args) {
    Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
	...
    // 创建主线程的Looper对象
    // 用于循环遍历消息队列
    Looper.prepareMainLooper();
    // 实例化一个ActivityThread对象
    // 该对象表示应用程序进程的主线程
    ActivityThread thread = new ActivityThread();
    thread.attach(false);	
    // 创建主线程的Handler
    // 用于发送、处理消息
    // final H mH = new H();
    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");
}

 ActivityThread的main方法主要做了以下几件事情:

  • 创建主线程的Looper对象,该对象将用于循环遍历消息队列;
  • 实例化一个ActivityThread对象,它管理着当前进程的主线程,即代表主线程;
  • 创建主线程的Handler对象mH,该对象用于发送消息和主线程处理消息;
  • 开启消息循环;

 至此,随着ActivityThread对象的创建和Handler消息处理机制的开启,新创建的应用程序进程就被启动了。下一小节,我们将继续分析如何在主线程中启动应该程序的Application和Home Activity(跟Activity)。

2. Activity启动过程

 Activity启动过程时序图:
在这里插入图片描述
 前面说到,当ActivityThread的实例被创建和Handler消息处理机制被开启后,应用程序进程也就被启动了,接着就会去启动应用程序的根Activity,通过调用ActivityThread的attach方法实现。attach方法源码如下:

// Android8.0\frameworks\base\core\java\android\app
// ActivityThread.java
final ApplicationThread mAppThread = new ApplicationThread();

private void attach(boolean system) {
    // 将ActivityThread缓存到sCurrentActivityThread
    // ActivityThread表示的是主线程
    sCurrentActivityThread = this;
    mSystemThread = system;
    if (!system) {
		...
        RuntimeInit.setApplicationObject(mAppThread.asBinder());
        // 获取AMS的代理对象
        final IActivityManager mgr = ActivityManager.getService();
        try {
            // 将ApplicationThread传递给AMS
            mgr.attachApplication(mAppThread);
        } catch (RemoteException ex) {
            throw ex.rethrowFromSystemServer();
        }
    }
    ...
}

// Android8.0\frameworks\base\core\java\android\app
// ActivityThread.java的内部类ApplicationThread
private class ApplicationThread extends IApplicationThread.Stub {
    @Override
    public final void scheduleLaunchActivity(){}
    ...
    public final void bindApplication(){}
    ...
}

 在attach方法中,它会根据system的值执行不同的流程,很明显上一个方法传递的值为false,因此我们只需要分析if(!system)情况。ActivityThread的attach方法实现很简单,就是获取AMS的代理,然后调用远程的attachApplication将ApplicationThread对象传送给AMS。ApplicationThread是ActivityThread的一个内部类,它继承于IApplicationThread.Stub,故其是一个Binder对象,运行在Binder线程池之中,AMS会使用它来和ActivityThread来进行进程间通信。换句话来说,就是每一个应用程序对应着一个ActivityThread对象,该对象代表的是应用程序进程的主线程,同时每一个应用进程也都对应着一个ApplicationThread对象,该对象是ActivityThread与AMS通信的桥梁。(注:AMS负责系统中四大组件的启动、切换、调度及应用进程的管理和调度等工作)接下来,继续看AMS的attachApplication方法。

// Android8.0\frameworks\base\services\core\java\com\android\server\am
// ActivityManagerService.java
@Override
public final void attachApplication(IApplicationThread thread) {
    synchronized (this) {
        // 获取调用者进程pid
        int callingPid = Binder.getCallingPid();
        final long origId = Binder.clearCallingIdentity();
        // IApplicationThread
        attachApplicationLocked(thread, callingPid);
        Binder.restoreCallingIdentity(origId);
    }
}

 在该方法中又继续调用了AMS的attachApplicationLocked方法,并向其传入ApplicationThread的代理对象IApplicationThread和应用进程的进程号pid。该方法源码如下:

// Android8.0\frameworks\base\services\core\java\com\android\server\am
// ActivityManagerService.java
private final boolean attachApplicationLocked(IApplicationThread thread,
                                              int pid) {
    // 获取应用程序进程的ProcessRecord
    // 该对象记录了进程的信息
    ProcessRecord app;
    long startTime = SystemClock.uptimeMillis();
    if (pid != MY_PID && pid >= 0) {
        synchronized (mPidsSelfLocked) {
            app = mPidsSelfLocked.get(pid);
        }
    } else {
        app = null;
    }
    ...
    // 获取进程名称
    final String processName = app.processName;
    try {
        // 绑定死亡监听
        // 监听ApplicationThread
        AppDeathRecipient adr = new AppDeathRecipient(
            app, pid, thread);
        thread.asBinder().linkToDeath(adr, 0);
        app.deathRecipient = adr;
    } catch (RemoteException e) {
        app.resetPackageList(mProcessStats);
        startProcessLocked(app, "link fail", processName);
        return false;
    }
    ...
    // 注释1 :进入应用程序的Application创建启动流程
    if (app.instr != null) {
         thread.bindApplication(processName, appInfo, providers,
                        app.instr.mClass,
                        profilerInfo, app.instr.mArguments,
                        app.instr.mWatcher,
                        app.instr.mUiAutomationConnection, testMode,
                        mBinderTransactionTrackingEnabled, enableTrackAllocation,
                        isRestrictedBackupMode || !normalMode, app.persistent,
                        new Configuration(getGlobalConfiguration()), app.compat,
                        getCommonServicesLocked(app.isolated),
                        mCoreSettingsObserver.getCoreSettingsLocked(),
                        buildSerial);
    }
    ...
    // See if the top visible activity is waiting to run in this process...
    // 注释2 :进入应用程序的根Activity的创建启动流程
    if (normalMode) {
        try {
            if (mStackSupervisor.attachApplicationLocked(app)) {
                didSomething = true;
            }
        } catch (Exception e) {
            Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
            badApp = true;
        }
    }
    ...
}

 attachApplicationLocked方法代码有点长,但我们重点关注两点:

  • 启动应用程序的Application;
  • 启动应用进程的根Activity;

 接下来,我们详细分析应用程序的Application和根Activity的启动过程。

2.1 应用程序的Appication启动过程

 应用程序的Application对象启动过程:
在这里插入图片描述
 前面说到,应用程序的Application的启动过程是从调用IApplicationThread的bindApplication方法开始的。由于IApplicationThread是ApplicationThread对象(Binder实体)在AMS的代理,因此,这里最终调用的是远程ApplicationThread对象(位于应用进程中,是ActivityThread的内部类)bindApplication方法。源码如下:

// Android8.0\frameworks\base\core\java\android\app
// ActivityThread.java
public final void bindApplication(String processName, ApplicationInfo appInfo,
                List<ProviderInfo> providers, ComponentName instrumentationName,
                ProfilerInfo profilerInfo, Bundle instrumentationArgs,
                IInstrumentationWatcher instrumentationWatcher,
                IUiAutomationConnection instrumentationUiConnection, int debugMode,
                boolean enableBinderTracking, boolean trackAllocation,
                boolean isRestrictedBackupMode, boolean persistent, Configuration 
                config,CompatibilityInfo compatInfo, Map services, Bundle coreSettings,
                String buildSerial) {

            if (services != null) {
                // Setup the service cache in the ServiceManager
                ServiceManager.initServiceCache(services);
            }

            setCoreSettings(coreSettings);

            AppBindData data = new AppBindData();
            data.processName = processName;
            data.appInfo = appInfo;
            data.providers = providers;
            data.instrumentationName = instrumentationName;
            data.instrumentationArgs = instrumentationArgs;
            data.instrumentationWatcher = instrumentationWatcher;
            data.instrumentationUiAutomationConnection = instrumentationUiConnection;
            data.debugMode = debugMode;
            data.enableBinderTracking = enableBinderTracking;
            data.trackAllocation = trackAllocation;
            data.restrictedBackupMode = isRestrictedBackupMode;
            data.persistent = persistent;
            data.config = config;
            data.compatInfo = compatInfo;
            data.initProfilerInfo = profilerInfo;
            data.buildSerial = buildSerial;
			// 发送BIND_APPLICATION消息
            sendMessage(H.BIND_APPLICATION, data);
}

final H mH = new H();
private class H extends Handler {
    public void handleMessage(Message msg) {
        switch (msg.what) {
            ...
            case BIND_APPLICATION:
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
                AppBindData data = (AppBindData)msg.obj;
                handleBindApplication(data);
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                break;
        }
}

 bindApplication方法实现很简单,就是调用mH对象的sendMessage方法发送一个BIND_APPLICATION消息。这个mH指的是H,它是ActivityThread的内部类并继承自Handler,是应用程序进程中主线程的消息管理类,因此这个消息将被传递到主线程并被H的handleMessage方法处理。这里为什么要这么做?因为ApplicationThread是一个Binder,它运行在Binder线程池,所以这里需要调用H将代码的逻辑切换到主线程中,因此应用程序的Applicaton对象是运行在主线程中的。ActivityThread$handleBindApplication方法源码如下:

// Android8.0\frameworks\base\core\java\android\app
// ActivityThread.java
private void handleBindApplication(AppBindData data) {
    ...
    try {
       // 调用LoadApk的makeApplication
       // 创建Application
       Application app = data.info.makeApplication(data.restrictedBackupMode, null);
       mInitialApplication = app;

        ...
            try {
                // 调用Application的onCreate方法
                mInstrumentation.callApplicationOnCreate(app);
            } catch (Exception e) {
                if (!mInstrumentation.onException(app, e)) {
                    throw new RuntimeException(
                        "Unable to create application " + app.getClass().getName()
                        + ": " + e.toString(), e);
                }
            }
    } finally {
        StrictMode.setThreadPolicy(savedPolicy);
    }
}

 当H收到BIND_APPLICATION消息后,就会调用ActivityThread的handleBindApplication方法进入下一步处理,该方法首先会调用LoadApk的makeApplication方法创建应用程序的Application实例,如果Application已经创建了就直接返回,这也说明了一个应用程序只存在一个Application对象;然后调用Instrumentation的callApplicationOnCreate方法进而调用Application的Oncreate方法。至此,应用程序的Application启动完毕。

  • 创建应用进程的Application对象
public Application makeApplication(boolean forceDefaultAppClass,
                                   Instrumentation instrumentation) {
    // 如果Application已经被创建
    // 则不再重复创建
    if (mApplication != null) {
        return mApplication;
    }
    ...
    Application app = null;
    // 获取当前应用程序Application类全限定路径
    String appClass = mApplicationInfo.className;
    
    try {
        // 获取当前类加载器
        java.lang.ClassLoader cl = getClassLoader();
        if (!mPackageName.equals("android")) {
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER,
                             "initializeJavaContextClassLoader");
            initializeJavaContextClassLoader();
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        }
        // 创建Application上下文
        ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
        // 创建Application实例
        app = mActivityThread.mInstrumentation.newApplication(
            cl, appClass, appContext);
        appContext.setOuterContext(app);
    } catch (Exception e) {
        if (!mActivityThread.mInstrumentation.onException(app, e)) {
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
            throw new RuntimeException(
                "Unable to instantiate application " + appClass
                + ": " + e.toString(), e);
        }
    }
    ...
}

public Application newApplication(ClassLoader cl, String className, Context context)
    throws InstantiationException, IllegalAccessException, 
					ClassNotFoundException {
    return newApplication(cl.loadClass(className), context);
}

static public Application newApplication(Class<?> clazz, Context context)
    throws InstantiationException, IllegalAccessException, 
			ClassNotFoundException {
    // 创建Applicaton对象
    // 通过调用Classs的newInstance创建实例
                
    Application app = (Application)clazz.newInstance();
    // 将Application与上下文绑定
    app.attach(context);
    return app;
}
  • 调用Application的onCreate方法
// Android8.0\frameworks\base\core\java\android\app
// Instrumentation.java
public void callApplicationOnCreate(Application app) {
    app.onCreate();
}

2.2 应用程序的根Activity启动过程

 根Activity启动过程时序图:
在这里插入图片描述
 由于关于Activity的创建、启动过程,我们在从Android 6.0源码的角度剖析Activity的启动过程一文中详细分析了,因此这里就不再重复阐述,这里只给出后续的调用时序图,总之,随着Activity的onCreate方法被调用,应用程序的根Activity就启动了。另外,还需要注意一点是,应用程序中除了一个根Activity,还有很多普通Activity,它们的启动过程与根Activity差不多,唯一区别是不需经历应用程序进程的创建过程,而是直接进入ActivityStackSupervisor的realStartActivityLocked具体执行流程。

发布了78 篇原创文章 · 获赞 288 · 访问量 26万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览