Android App啓動過程

概述

當你點擊桌面App的圖標到底發生了什麼,上篇文章咱們大概簡述了流程java

  • 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 27android

1.Launcher

當你點擊桌面上的App圖標,Launcher捕獲點擊事件,其過程爲Launcher#onClick-> Launcher#onClickAppShortcut->Launcher#startAppShortcutOrInfoActivity->Launcher#startActivitySafely -> Activity#startActivity最終調用了 startActivity(intent, optsBundle);方法git

下面咱們從startActivity(intent, optsBundle);方法開始分析調用流程bash

2.Activity.startActivity

上方咱們說到了Activity.startActivity,點進源碼發現調用的是Activity#startActivityForResult,其中還調用到了Instrumentation#execStartActivity這個方法,源碼以下app

@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對象,他的具體實如今ActivityManagerServiceasync

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源碼以下ide

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#resumeFocusedStackTopActivityLockedoop

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,若是不存在就把進程建立出來ui

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源碼以下this

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.im/entry/58610…

相關文章
相關標籤/搜索