Android App启动过程

4,315 阅读8分钟

概述

当你点击桌面App的图标到底发生了什么,上篇文章我们大概简述了流程

  • App发起进程:如果从桌面启动应用,则发起进程便是Launcher所在的进程,当从某App启动远程进程,则发起进程是App所在的进程,发起进程首先需要通过Binder发送信息给system_server进程
  • system_server进程:调用Process.start方法,通过SocketZygote进程发送新建进程的请求
  • zygote进程:在执行ZygoteInit.main()后进入runSelectLoop()循环体,当有客户端连接时,便会执行ZygoteConnection.runOnce()方法,再经过层层调用后fork出新的应用进程
  • 新进程:执行handleChildProc方法,设置进程名,打开binder驱动,启动新的binder线程,设置art虚拟机参数,反射目标类的main方法,即调用ActivityThread.main()方法

这次我们来详细的分析一下源码,基于API 27

1.Launcher

当你点击桌面上的App图标,Launcher捕获点击事件,其过程为Launcher#onClick-> Launcher#onClickAppShortcut->Launcher#startAppShortcutOrInfoActivity->Launcher#startActivitySafely -> Activity#startActivity最终调用了 startActivity(intent, optsBundle);方法

下面我们从startActivity(intent, optsBundle);方法开始分析调用流程

2.Activity.startActivity

上方我们说到了Activity.startActivity,点进源码发现调用的是Activity#startActivityForResult,其中还调用到了Instrumentation#execStartActivity这个方法,源码如下

  @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) {
        startActivityForResult(intent, requestCode, null);
    }
    
     public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
            @Nullable Bundle options) {
    ...
            Instrumentation.ActivityResult ar =
                mInstrumentation.execStartActivity(
                    this, mMainThread.getApplicationThread(), mToken, this,
                    intent, requestCode, options);
    ...
    }

3.Instrumentation.execStartActivity

Instrumentation.execStartActivity中,我们发现他调用了ActivityManager#getService()#startActivity,其中ActivityManager#getService()返回的是IActivityManager类型的Binder对象,他的具体实现在ActivityManagerService

  public ActivityResult execStartActivity(
        Context who, IBinder contextThread, IBinder token, String target,
        Intent intent, int requestCode, Bundle options) {
        ...
        try {
            intent.migrateExtraStreamToClipData();
            intent.prepareToLeaveProcess(who);
            int result = ActivityManager.getService()
                .startActivity(whoThread, who.getBasePackageName(), intent,
                        intent.resolveTypeIfNeeded(who.getContentResolver()),
                        token, target, requestCode, 0, null, options);
            checkStartActivityResult(result, intent);
        } catch (RemoteException e) {
            throw new RuntimeException("Failure from system", e);
        }
        return null;
    }
    
    ActivityManager源码
      public static IActivityManager getService() {
        return IActivityManagerSingleton.get();
    }
    
      private static final Singleton<IActivityManager> IActivityManagerSingleton =
            new Singleton<IActivityManager>() {
                @Override
                protected IActivityManager create() {
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                    final IActivityManager am = IActivityManager.Stub.asInterface(b);
                    return am;
                }
            };

4.ActivityManagerService.startActivity

我们查看ActivityManagerService.startActivity源码,发现他调用了ActivityManagerService#startActivityAsUser,该方法又调用了ActivityStarter#startActivityMayWait源码如下

 public final int startActivity(IApplicationThread caller, String callingPackage,
            Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
            int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
        return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
                resultWho, requestCode, startFlags, profilerInfo, bOptions,
                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 bOptions, int userId) {
        enforceNotIsolatedCaller("startActivity");
        userId = mUserController.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, "startActivityAsUser");
    }
    

5.ActivityStarter.startActivityMayWait

我们查看ActivityStarter.startActivityMayWait源码发现他调用了ActivityStarter#startActivityLocked,接着是ActivityStarter#startActivity,然后是ActivityStarter#startActivityUnchecked,其中调用了ActivityStackSupervisor#resumeFocusedStackTopActivityLocked

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 globalConfig, Bundle bOptions, boolean ignoreTargetSecurity, int userId,
        TaskRecord inTask, String reason) {
    ...
    int res = startActivityLocked(caller, intent, ephemeralIntent, resolvedType,
            aInfo, rInfo, voiceSession, voiceInteractor,
            resultTo, resultWho, requestCode, callingPid,
            callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
            options, ignoreTargetSecurity, componentSpecified, outRecord, inTask,
            reason);
    ...
}

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, TaskRecord inTask, String reason) {
    ...
    mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType,
            aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,
            callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
            options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,
            inTask);
}

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, TaskRecord inTask) {
    ...
    return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true,
            options, inTask, outActivity);
}

private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
        IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
        int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
        ActivityRecord[] outActivity) {
    ...
    result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
            startFlags, doResume, options, inTask, outActivity);
    ...
}

private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
        IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
        int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
        ActivityRecord[] outActivity) {
    ...
    mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
            mOptions);
    ...
}

6.ActivityStackSupervisor.resumeFocusedStackTopActivityLocked

我们查看ActivityStackSupervisor.resumeFocusedStackTopActivityLocked他调用了ActivityStack#resumeTopActivityUncheckedLocked,然后是ActivityStack#resumeTopActivityInnerLocked,接着又回到了ActivityStackSupervisor.java,调用了ActivityStackSupervisor#startSpecificActivityLocked,这个方法要判断启动的App进程是否存在,存在就直接启动Activity,如果不存在就把进程创建出来

void startSpecificActivityLocked(ActivityRecord r,
        boolean andResume, boolean checkConfig) {
    ...
    if (app != null && app.thread != null) {
        ...
        // 如果进程已存在,则通知进程启动组件
        realStartActivityLocked(r, app, andResume, checkConfig);
        return;
        ...
    }
    // 否则先将进程创建出来
    mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
            "activity", r.intent.getComponent(), false, false, true);
    ...
}

7.mService.startProcessLocked

我们这里分析进程不存在的情况,这里的mService指的是ActivityManagerService,我们查看ActivityManagerService#startProcessLocked源码如下

private final void startProcessLocked(ProcessRecord app, String hostingType,
        String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
    ...
    if (entryPoint == null) entryPoint = "android.app.ActivityThread";
    startResult = Process.start(entryPoint,
            app.processName, uid, uid, gids, debugFlags, mountExternal,
            app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
            app.info.dataDir, invokeWith, entryPointArgs);
    ...
}

最终调用Process.start来开启新进程,这个进程的入口就会在android.app.ActivityThread.javamain方法,我们下面继续分析ActivityThread#main

8.ActivityThread#main

ActivityThread#main方法其中调用了ActivityThread#attach方法,这个方法中的ActivityManager.getService()返回的是IActivityManager类型的Binder对象,其实现类是ActivityManagerService,源码如下

public static void main(String[] args) {
    ...
    Looper.prepareMainLooper();

    ActivityThread thread = new ActivityThread();
    thread.attach(false);
    ...
    Looper.loop();
    ...
}

private void attach(boolean system) {
    sCurrentActivityThread = this;
    mSystemThread = system;
    if (!system) {
        ...
        final IActivityManager mgr = ActivityManager.getService();
        try {
            mgr.attachApplication(mAppThread);
        } catch (RemoteException ex) {
            ...
        }
        ...
    }
    ...
}

现在我们又回到了ActivityManagerService中,查看其attachApplication方法,发现调用了thread#bindApplicationmStackSupervisor#attachApplicationLocked,我们一次讲解这俩个方法作用

public final void attachApplication(IApplicationThread thread) {
    ...
    attachApplicationLocked(thread, callingPid);
    ...
}

private final boolean attachApplicationLocked(IApplicationThread thread,
        int pid) {
    ....
    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);
    ...
    if (normalMode) {
        try {
            if (mStackSupervisor.attachApplicationLocked(app)) {
                didSomething = true;
            }
        } catch (Exception e) {
            ...
        }
    }
    ...
}

9.thread#bindApplication

上面说到的thread#bindApplication中的thread类型是ApplicationThread,是ActivityThread的一个内部类,继承自IApplicationThread.Stub,我们查看ApplicationThread#bindApplication方法,我发现调用了ActivityThread#sendMessage 方法,它内部调用mH.sendMessage来发送消息,其中mHActivityThread的一个内部类H的一个实例

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) {
    ...
    sendMessage(H.BIND_APPLICATION, data);
}

 void sendMessage(int what, Object obj) {
        sendMessage(what, obj, 0, 0, false);
    }
    
   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);
    }

10.H.handleMessage

我们来看一下H这个内部类的handleMessage,最终走到了ActivityThread#handleBindApplication方法

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

11.ActivityThread#handleBindApplication

从源码中我们发现,他首先创建了mInstrumentation对象,调用data#info#makeApplication来创建Application对象,其中data#info代表的是LoadedApk的一个实例,查看LoadedApk#makeApplication方法可以看到,内部调用了Instrumentation#newApplication方法,这个方法内部调用Class#newInstance()来完成对Application的实例化,然后调用Application#attach(context)来绑定Context

上面创建完Application后,就调用Instrumentation#callApplicationOnCreateApplicationonCreate生命周期,源码如下


private void handleBindApplication(AppBindData data) {
    ...
    final InstrumentationInfo ii;
    ...
    // 创建 mInstrumentation 实例
    if (ii != null) {
        final ApplicationInfo instrApp = new ApplicationInfo();
        ii.copyTo(instrApp);
        instrApp.initForUser(UserHandle.myUserId());
        final LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
                appContext.getClassLoader(), false, true, false);
        final ContextImpl instrContext = ContextImpl.createAppContext(this, pi);

        try {
            final ClassLoader cl = instrContext.getClassLoader();
            mInstrumentation = (Instrumentation)
                cl.loadClass(data.instrumentationName.getClassName()).newInstance();
        } catch (Exception e) {
            ...
        }
        ...
    } else {
        mInstrumentation = new Instrumentation();
    }
    ...
    Application app;
    ...
    // 创建 Application 实例
    try {
        ...
        app = data.info.makeApplication(data.restrictedBackupMode, null);
        mInitialApplication = app;
        ...
        try {
            mInstrumentation.callApplicationOnCreate(app);
        } catch (Exception e) {
            ...
        }
    } finally {
        ...
    }
    ...
}



// http://androidxref.com/8.1.0_r33/xref/frameworks/base/core/java/android/app/LoadedApk.java#959
public Application makeApplication(boolean forceDefaultAppClass,
        Instrumentation instrumentation) {
    Application app = null;

    String appClass = mApplicationInfo.className;
    if (forceDefaultAppClass || (appClass == null)) {
        appClass = "android.app.Application";
    }

    try {
        java.lang.ClassLoader cl = getClassLoader();
        ...
        ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
        app = mActivityThread.mInstrumentation.newApplication(
                cl, appClass, appContext);
        appContext.setOuterContext(app);
    } catch (Exception e) {
        ...
    }
    mActivityThread.mAllApplications.add(app);
    mApplication = app;

    if (instrumentation != null) {// 传入为 null 所以不走
        try {
            instrumentation.callApplicationOnCreate(app);
        } catch (Exception e) {
            ...
        }
    }
    ...
    return app;
}

// http://androidxref.com/8.1.0_r33/xref/frameworks/base/core/java/android/app/Instrumentation.java#1084
  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 {
        Application app = (Application)clazz.newInstance();
        app.attach(context);
        return app;
    }

12.mStackSupervisor#attachApplicationLocked

上面说完了thread#bindApplication这个方法,下面我们继续说mStackSupervisor#attachApplicationLocked这个方法,其mStackSupervisorActivityStackSupervisor的一个实例,我们查看ActivityStackSupervisor#attachApplicationLocked方法发现其中调用了ActivityStackSupervisor#realStartActivityLocked,这个方法调用了app#thread#scheduleLaunchActivity,源码如下

// http://androidxref.com/8.1.0_r33/xref/frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java#956
boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
    final String processName = app.processName;
    ...
    if (realStartActivityLocked(activity, app,
            top == activity /* andResume */, true /* checkConfig */)) {
        ...
    }
    ...
}


// http://androidxref.com/8.1.0_r33/xref/frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java#1313
final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
        boolean andResume, boolean checkConfig) throws RemoteException {
    ...
    app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
            System.identityHashCode(r), r.info,
            // TODO: Have this take the merged configuration instead of separate global
            // and override configs.
            mergedConfiguration.getGlobalConfiguration(),
            mergedConfiguration.getOverrideConfiguration(), r.compat,
            r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
            r.persistentState, results, newIntents, !andResume,
            mService.isNextTransitionForward(), profilerInfo);
    ...
}

12.app#thread#scheduleLaunchActivity

上面说到app#thread#scheduleLaunchActivity,这个里面的threadIApplicationThread,他的实现类是ActivityThread#ApplicationThread,我们查看ActivityThread#ApplicationThread#scheduleLaunchActivity方法中的代码,发现最终是发送了LAUNCH_ACTIVITY的消息,发送消息我们再9 ,10步骤中分析过,我们直接查看处理消息的代码,在 H#handleMessage方法中,我们可以看到他会接收并处理很多四大组件的相关操作,我们查看 LAUNCH_ACTIVITY的处理,发现其处理方法是调用了ActivityThread#handleLaunchActivity,这个方法再次涉及到了Instrumentation类,之前创建Application的时候用到了他,如今创建Activity也用到了他,其中Instrumentation#newActivity是通过 Class.newInstance()来实例化Activity,实例化完成后回到ActivityThread#performLaunchActivity中,让Activity依附到window中,然后callActivityOnCreate走ActivityonCreate的生命周期,涉及到的源码如下

// http://androidxref.com/8.1.0_r33/xref/frameworks/base/core/java/android/app/ActivityThread.java#756
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
        ActivityInfo info, Configuration curConfig, Configuration overrideConfig,
        CompatibilityInfo compatInfo, String referrer, IVoiceInteractor voiceInteractor,
        int procState, Bundle state, PersistableBundle persistentState,
        List<ResultInfo> pendingResults, List<ReferrerIntent> pendingNewIntents,
        boolean notResumed, boolean isForward, ProfilerInfo profilerInfo) {
    ...
    sendMessage(H.LAUNCH_ACTIVITY, r);
}

// http://androidxref.com/8.1.0_r33/xref/frameworks/base/core/java/android/app/ActivityThread.java#1580
public void handleMessage(Message msg) {
    ...
    switch (msg.what) {
        ...
        case LAUNCH_ACTIVITY: {
            Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
            final ActivityClientRecord r = (ActivityClientRecord) msg.obj;

            r.packageInfo = getPackageInfoNoCheck(
                    r.activityInfo.applicationInfo, r.compatInfo);
            handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        } break;
        ...
    }
}

// http://androidxref.com/8.1.0_r33/xref/frameworks/base/core/java/android/app/ActivityThread.java#2833
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent, String reason) {
    ...
    Activity a = performLaunchActivity(r, customIntent);
    ...
}

// http://androidxref.com/8.1.0_r33/xref/frameworks/base/core/java/android/app/ActivityThread.java#2644
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    ...
    Activity activity = null;
    try {
        java.lang.ClassLoader cl = appContext.getClassLoader();
        activity = mInstrumentation.newActivity(
                cl, component.getClassName(), r.intent);
        ...
    } catch (Exception e) {
        ...
    }

    try {
        // 返回之前创建过的 application 对象
        Application app = r.packageInfo.makeApplication(false, mInstrumentation);
        ...
        if (activity != null) {
            ...
            // attach 到 window 上
            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, window, r.configCallback);
            ...
            if (r.isPersistable()) {
                mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
            } else {
                mInstrumentation.callActivityOnCreate(activity, r.state);
            }
            ...
        }
    } catch (Exception e) {
        ...
    }
    return activity;
}

  public Activity newActivity(ClassLoader cl, String className,
            Intent intent)
            throws InstantiationException, IllegalAccessException,
            ClassNotFoundException {
        return (Activity)cl.loadClass(className).newInstance();
    }

总结

概述一下大致流程

  • 首先是点击App图标,此时是运行在Launcher进程,通过ActivityManagerServiceBinder IPC的形式向system_server进程发起startActivity的请求
  • system_server进程接收到请求后,通过Process.start方法向zygote进程发送创建进程的请求
  • zygote进程fork出新的子进程,即App进程
  • 然后进入ActivityThread.main方法中,这时运行在App进程中,通过ActivityManagerServiceBinder IPC的形式向system_server进程发起attachApplication请求
  • system_server接收到请求后,进行一些列准备工作后,再通过Binder IPC向App进程发送scheduleLaunchActivity请求
  • App进程binder线程(ApplicationThread)收到请求后,通过Handler向主线程发送LAUNCH_ACTIVITY消息
  • 主线程收到Message后,通过反射机制创建目标Activity,并回调ActivityonCreate

参考:gityuan.com/2016/03/12/…

blankj.com/2018/09/29/…

juejin.cn/post/684490…