天天看點

源碼角度淺析App啟動流程

     寫這篇部落格,其實我自己還有很多地方原理沒有看懂(像Binder機制達到目前程序跟AMS進行通信),但并不是很影響看懂App啟動主要做了一些什麼事。

   看源碼我是帶着1個問題

    問題:Application具體在什麼時候建立以及執行的onCreate

   衆所周知App應用是從ActivityThread的main方法開始(以友善閱讀我删掉了一些次要代碼)

public static void main(String[] args) {
        //從這裡我們可以知道 App以消息來驅動App的各種事件(Handler機制嘛,有機會我會寫一遍關于Handler機制源碼分析的部落格)
        Looper.prepareMainLooper();
        ActivityThread thread = new ActivityThread();
        //接下來,看看ActivityThread的attach的實作
        thread.attach(false);
        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }
        Looper.loop();

        throw new RuntimeException("Main thread loop unexpectedly exited");
    }
           
private void attach(boolean system) {
        sCurrentActivityThread = this;
        mSystemThread = system;
        if (!system) {
            // ...省略
            RuntimeInit.setApplicationObject(mAppThread.asBinder());
            //這裡拿到的IActivityManager,這裡先打住忘下看。我搞清楚mgr它真正是什麼,在哪裡執行個體,搞清這個情況接下來看看ActivityManager的getService()
            final IActivityManager mgr = ActivityManager.getService();
            try {
                //這裡等一等,先搞清楚mgr
                mgr.attachApplication(mAppThread);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
            // Watch for getting close to heap limit.
            BinderInternal.addGcWatcher(new Runnable() {
                @Override public void run() {
                    ....
            });
        } else {
           //...省略
        }
        // ...省略
    }
           
/**
     * @hide
     */
    public static IActivityManager getService() {
        //赫赫...點選IActivityManagerSingleton就到了下面
        return IActivityManagerSingleton.get();
    }
    //這裡... 
    private static final Singleton<IActivityManager> IActivityManagerSingleton =
            new Singleton<IActivityManager>() {
                @Override
                protected IActivityManager create() {
//這裡先記住這個Context.ACTIVITY_SERVICE,
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                    final IActivityManager am = IActivityManager.Stub.asInterface(b);
                    return am;
//看完這裡,是不是有點什麼感覺,這塊Binder機制來實作擷取到遠端的一個代理類 am
//到此還是沒搞懂這個am真正的執行個體在哪裡,它的實作類是什麼鬼
//要弄清這個問題,我要飙車了,直接去看一下ActivityManagerService的一個方法,請往下看
                }
            };
           
//這快的代碼我是在ActivityManagerService拷貝過來的
public void setSystemProcess() {
        try {
            //這裡,看Context.ACTIVITY_SERVICE 注冊的AMS,看到這裡我們應該知道上面的哪個am
            //真正實作就是ActivityManagerService
            //别問我怎麼知道的,我也是看了《深入了解android核心設計》AMS專題才知道的,
            //要不然鬼知道AMS在這裡注冊的哈
            ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
            ServiceManager.addService(ProcessStats.SERVICE_NAME, mProcessStats);
            ServiceManager.addService("meminfo", new MemBinder(this));
            ServiceManager.addService("gfxinfo", new GraphicsBinder(this));
            ServiceManager.addService("dbinfo", new DbBinder(this));
            if (MONITOR_CPU_USAGE) {
                ServiceManager.addService("cpuinfo", new CpuBinder(this));
            }
            ServiceManager.addService("permission", new PermissionController(this));
            ServiceManager.addService("processinfo", new ProcessInfoService(this));
           //...省略
        }
    }
           

OK,回到剛開始的ActivityThread的attach那裡

final IActivityManager mgr = ActivityManager.getService();
            try {
                mgr.attachApplication(mAppThread);
            } catch (RemoteException ex) {
                throw ex.rethrowFromSystemServer();
            }
           

到此已經知道了mgr他的真正實作是ActivityManagerService(我直接說AMS了),我們直接去去看看attachApplication(...)的實作(哦對了,先留意一下mAppThread它是目前程序跟遠端AMS通信的接口)

下面是AMS相關實作

@Override
    public final void attachApplication(IApplicationThread thread) {
        synchronized (this) {
            int callingPid = Binder.getCallingPid();
            final long origId = Binder.clearCallingIdentity();
            //繼續跟,往下看
            attachApplicationLocked(thread, callingPid);
            Binder.restoreCallingIdentity(origId);
        }
    }
           
private final boolean attachApplicationLocked(IApplicationThread thread,
            int pid) {
            //...此處省略一堆代碼
            checkTime(startTime, "attachApplicationLocked: immediately before bindApplication");
            mStackSupervisor.mActivityMetricsLogger.notifyBindApplication(app);
            //這裡AMS通過收集資訊,然後通過程序通信把資訊回傳App程序。OK,下面我們再往會看看ActivityThread的一個内部類實作的IApplicationThread的bindApplication的方法
            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);
            } else {
                thread.bindApplication(processName, appInfo, providers, null, profilerInfo,
                        null, null, null, 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...
        if (normalMode) {
            try {//這裡會有驚喜,這次暫時不做分析這塊流程
                if (mStackSupervisor.attachApplicationLocked(app)) {
                    didSomething = true;
                }
            } catch (Exception e) {
                Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
                badApp = true;
            }
        }
        //...省略一路代碼
        return true;
    }
           

回到ActivityThread的ApplicationThread(這裡是App程序哦,不是AMS所在程序)

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;
            //這裡,sendMessage,然後跟進去其實就是ActivityThread一個内部Handler執行個體,繼續
            sendMessage(H.BIND_APPLICATION, data);
        }
           

根據sendMessage的H.BIND_APPLICATION,我跟到了這裡

public void handleMessage(Message msg) {
//...省略其它case
    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;
//...省略其它case
}
           

接下來看看handleBindApplication(data)實作

Application app;
        try {
            //看到這裡,Application在此處執行個體化(次于怎麼建立的感興趣的同學跟進去看看哈)
            app = data.info.makeApplication(data.restrictedBackupMode, null);
            mInitialApplication = app;

            // don't bring up providers in restricted mode; they may depend on the
            // app's custom Application class
            if (!data.restrictedBackupMode) {
                if (!ArrayUtils.isEmpty(data.providers)) {
                    installContentProviders(app, data.providers);
                    // For process that contains content providers, we want to
                    // ensure that the JIT is enabled "at some point".
                    mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
                }
            }

            //...省略
            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 {
            
            if (data.appInfo.targetSdkVersion <= Build.VERSION_CODES.O
                    || StrictMode.getThreadPolicy().equals(writesAllowedPolicy)) {
                StrictMode.setThreadPolicy(savedPolicy);
            }
        }
           

到此Application的啟動流程夢遊了一遍,看源碼需謹慎帶着問題去源碼裡面走可以不容易迷失在源碼裡面

其實看看這些東西,有些問題可能會不言自明,比如App啟動優化為什麼在Application的onCreate進行優化...

最近一個多月公司大部分精力放在了小程式開發這塊,時間充足,接下來要是有空我會寫幾遍關于App換皮膚,插件化的幹貨部落格附帶Demo