1. 程式人生 > >App啟動流程分析(下)

App啟動流程分析(下)

我們知道Java中一個能夠獨立執行的java程式的方法入口是main方法,它是被Jvm識別呼叫的。而在Android中一個應用的開始也可說是從ActivityThread的main方法開始的,然而不同的是他不是由Jvm呼叫的。

上一節我們講到在ZygoteInit中通過丟擲MethodAndArgsCaller異常,然後在main方法中,通過捕獲異常,然後呼叫run方法,然後在run方法中通過invoke來反射呼叫到ActivityThread中的main方法。詳見App啟動流程分析(上)

public static void main(String[] args) {
        SamplingProfilerIntegration.start();

        CloseGuard.setEnabled(false
); //設定程序引數 Process.setArgV0("<pre-initialized>"); //建立主執行緒Looper Looper.prepareMainLooper(); if (sMainThreadHandler == null) { //建立主執行緒Handler sMainThreadHandler = new Handler(); } //建立ActivityThread物件 ActivityThread thread = new
ActivityThread(); //關鍵的一步,詳見1.1小節。false表示建立的是普通應用的程序。true表示建立的是系統應用程式的程序。 thread.attach(false); if (false) { Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG, "ActivityThread")); } //開起主執行緒Looper迴圈。 Looper.loop(); //執行到這裡說明退出了主執行緒Looper迴圈。丟擲異常。
throw new RuntimeException("Main thread loop unexpectedly exited"); }

LAUNCH_ACTIVITY

1.1 ActivityThread.attach

private void attach(boolean system) {
 //將ActivityThread物件放入ThreadLocal中儲存。ThreadLocal可以保證每個執行緒中資料獨立。
    sThreadLocal.set(this);
    mSystemThread = system;
  //普通app進入這個if中。
    if (!system) {
        ViewRootImpl.addFirstDrawHandler(new Runnable() {
            public void run() {
                ensureJitEnabled();
            }
        });
        android.ddm.DdmHandleAppName.setAppName("<pre-initialized>");
      //將ApplicationThread物件傳遞給RuntimeInit儲存,setApplicationObject是一個靜態方法,且RuntimeInit中方法多為靜態方法。見1.1.1與1.1.2小節
        RuntimeInit.setApplicationObject(mAppThread.asBinder());
      //獲得了ActivityManagerService的本地代理物件ActivityManagerProxy,見1.1.3小節
        IActivityManager mgr = ActivityManagerNative.getDefault();
        try {
            //實際上呼叫了ActivityManagerProxy的attachApplication方法,見1.2小節
            mgr.attachApplication(mAppThread);
        } catch (RemoteException ex) {
            // Ignore
        }
    } else {
      //系統app會進入else
        android.ddm.DdmHandleAppName.setAppName("system_process");
        try {
            mInstrumentation = new Instrumentation();
            ContextImpl context = new ContextImpl();
            context.init(getSystemContext().mPackageInfo, null, this);
            Application app = Instrumentation.newApplication(Application.class, context);
            mAllApplications.add(app);
            mInitialApplication = app;
            app.onCreate();
        } catch (Exception e) {
            throw new RuntimeException(
                    "Unable to instantiate Application():" + e.toString(), e);
        }
    }
    ...
}

對於Binder瞭解較深的就會發現,這裡的ApplicationThread有點類似於ActivityMangerServiceActivityMangerService繼承自ActivityManagerNativeActivityManagerNative繼承自BinderActivityManagerNativeActivityMangerProxy均實現了IApplicationThread這個介面。而ActivityMangerProxy就是AMS在客戶端的代理物件。

這裡的ApplicationThread繼承自ApplicationThreadNativeApplicationThreadNative繼承了Binder

ApplicationThreadNativeApplicationThreadProxy均實現了IApplicationThread介面,典型的是Binder的客戶端代理。

可以推測出,AMS作為系統的服務,執行在SystemServer程序。當app呼叫AMS中的方法時,需要獲得AMS的本地代理物件ActivityManagerProxy,AMS與AMP均繼承自同一個介面。客戶端呼叫AMP中的方法,通過Binder驅動即可傳遞資料,跨程序呼叫到AMS中的方法。

那麼當AMS要呼叫app中的方法時呢? ApplicationThreadApplicationThreadProxy均實現了IApplicationThread介面,在這裡通過mgr.attachApplication()方法(mgr就是AMS在本地的代理物件ActivityManagerProxy),將ApplicationThread傳遞給了AMS儲存。

1.1.1 RuntimeInit.setApplicationObject
    public static final void setApplicationObject(IBinder app) {
        mApplicationObject = app;
    }
1.1.2 mAppThread.asBinder
//mAppThread是ApplicationThread的例項物件。ApplicationThread繼承自ApplicationThreadNative。而ApplicationThreadNative是一個Binder。
public final class ActivityThread {
    ...
    final ApplicationThread mAppThread = new ApplicationThread();
    ...
}
public abstract class ApplicationThreadNative extends Binder implements IApplicationThread {
    ...
    public IBinder asBinder(){
         return this;
    }
    ...
}
1.1.3 ActivityManagerNative.getDefault
 //熟悉AIDL的就會發現,這裡的ActivityManagerNative就相當於常規下,我們AIDL建立後自動生成的Stub類,而ActivityManagerProxy類就相當於AIDL建立之後的Proxy內部代理類,當客戶端和服務端在同一程序時,呼叫時直接呼叫服務端的方法,不需要走Proxy中的方法。而當客戶端和服務端不在同一程序時,客戶端呼叫方法時,先呼叫了Proxy中的方法,再走transact過程呼叫服務端的方法。
static public IActivityManager getDefault() {
        return gDefault.get();
    }
//gDefault是一個泛型為IActivityManager的Singleton型別變數。實際上是一種單例模式的快速實現。
public abstract class Singleton<T> {
    private T mInstance;

    protected abstract T create();
    //呼叫了這個get方法,當T不存在,也就是IActivityManager不存在時,呼叫create方法來建立這個變數。
    public final T get() {
        synchronized (this) {
            if (mInstance == null) {
                mInstance = create();
            }
            return mInstance;
        }
    }
}

 private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
        protected IActivityManager create() {
          //通過serviceManger獲得了AMS的Binder,獲得的是BinderProxy這個例項,其中儲存了AMS在Native層BpBinder的Handle。(關於BpBinder和BBinder可以去看binder方面原始碼分析),而ActivityManagerService繼承自ActivityMangerNative。,具體可以看1.1.4小節
            IBinder b = ServiceManager.getService("activity");
            if (false) {
                Log.v("ActivityManager", "default service binder = " + b);
            }
          //呼叫ActivityManagerNative.asInterface,這個方法在客戶端和服務端在同一程序時,返回ActivityManagerNative物件,否則返回的是ActivityManagerProxy這個物件。
            IActivityManager am = asInterface(b);
            if (false) {
                Log.v("ActivityManager", "default service = " + am);
            }
            //返回了ActivityManagerProxy物件。ActivityManagerService的BinderProxy就儲存在了ActivityManagerProxy中的mRemote這個變數中。
            return am;
        }
    };

1.2 ActivityManagerProxy.attachApplication

ActivityManagerProxy是ActivityManagerNative的內部類

    public void attachApplication(IApplicationThread app) throws RemoteException
    {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        //這裡的app是ApplicationThread物件
        data.writeStrongBinder(app.asBinder());
        //呼叫了mRemote的transact方法,mRemote實際上是一個BinderProxy類,它在內部呼叫了一個native方法transact。見1.2.1小節
        mRemote.transact(ATTACH_APPLICATION_TRANSACTION, data, reply, 0);
        reply.readException();
        data.recycle();
        reply.recycle();
    }
1.2.1 BinderProxy.transact

final class BinderProxy implements IBinder {
    ...
    public native boolean pingBinder();
    public native boolean isBinderAlive();
    //native的transact方法,最終會通過Binder驅動呼叫到ActivityManagerService中繼承自ActivityManagerNative的onTransact方法。
    public native boolean transact(int code, Parcel data, Parcel reply, int flags) throws           RemoteException;
    public native void linkToDeath(DeathRecipient recipient, int flags) throws RemoteException;
    public native boolean unlinkToDeath(DeathRecipient recipient, int flags);
    ...
}
1.2.2 ActivityManagerNative.onTransact
 public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
            throws RemoteException {
     switch (code) {
          ...
          //省略了非常多的case分支
          case ATTACH_APPLICATION_TRANSACTION: {
              data.enforceInterface(IActivityManager.descriptor);
              //見下方說明
              IApplicationThread app = ApplicationThreadNative.asInterface(
                    data.readStrongBinder());
              if (app != null) {
                  //呼叫了AMS中的attachApplication方法,見1.2.3小節
                  attachApplication(app);
              }
              reply.writeNoException();
              return true;
           }
           ...
       }
     return super.onTransact(code, data, reply, flags);
}
  1. 這裡的app實際是一個ApplicationThreadProxy例項。
  2. readStrongBinder會返回一個IBinder物件,實際上是前面寫入的ApplicationThread經過Binder驅動後在native層轉為一個BpBinder,同過JNI轉為一個BinderProxy物件。
  3. ApplicationThreadNative.asInterface呼叫之後會返回一個ApplicationThreadProxy物件,就像在App程序獲得的AMS代理物件ActivityMangerProxy一樣,這個ApplicationThreadProxy就是App程序中ApplicationThread的代理。
  4. 當app程序呼叫AMS中方法時,app程序是客戶端,AMS所在的SystemServer是服務端。 此時,在AMS中儲存了app端的代理物件ApplicationThreadProxy,當AMS要呼叫ApplicationThread中方法時,AMS就是客戶端,而app程序就是服務端了。
1.2.3 ActivityManagerService.attachApplication
public final void attachApplication(IApplicationThread thread) {
        synchronized (this) {
            //獲得遠遠端呼叫程序的程序id
            int callingPid = Binder.getCallingPid();
            final long origId = Binder.clearCallingIdentity();
            //見1.2.4小節
            attachApplicationLocked(thread, callingPid);
            Binder.restoreCallingIdentity(origId);
        }
}
1.2.4 ActivityManagerService.attachApplicationLocked

這段程式碼很長,其中部分if判斷提高程式健壯性的程式碼,log日誌程式碼,以及 thread.bindApplication後的一大段程式碼等等已被略去

//在AMS物件被建立時,這個集合就被例項化了
final SparseArray<ProcessRecord> mPidsSelfLocked = new SparseArray<ProcessRecord>();
private final boolean attachApplicationLocked(IApplicationThread thread, int pid) {
        //在上篇中的4.3小節中,我們成功啟動一個新的程序之後,以程序的pid作為鍵,ProcessRecord物件作為值儲存在了mPidsSelfLocked這個SparseArray集合中。
        ProcessRecord app;
        if (pid != MY_PID && pid >= 0) {
            synchronized (mPidsSelfLocked) {
                app = mPidsSelfLocked.get(pid);
            }
        } else {
            app = null;
        }

        if (app == null) {
            EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
            if (pid > 0 && pid != MY_PID) {
                Process.killProcessQuiet(pid);
            } else {
                try {
                    thread.scheduleExit();
                } catch (Exception e) {
                    // Ignore exceptions.
                }
            }
            return false;
        }


        //app.thread不為null,說明這個ProcessRecord依然繫結的有另一個程序,需要清理乾淨。這裡的thread指的是IApplicationThread物件。實際上是ApplicationThreadProxy例項物件。
        if (app.thread != null) {
            handleAppDiedLocked(app, true, true);
        }
        //獲得程序名稱
        String processName = app.processName;
        try {
            //設定當app程序死亡,Binder的死亡代理
            AppDeathRecipient adr = new AppDeathRecipient(
                    app, pid, thread);
            thread.asBinder().linkToDeath(adr, 0);
            app.deathRecipient = adr;
        } catch (RemoteException e) {
            app.resetPackageList();
            startProcessLocked(app, "link fail", processName);
            return false;
        }

        EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.pid, app.processName);
        //將ProcessRecord中的thread這個成員變數指向傳遞進來的IApplicationThread例項,即ApplicationThreadProxy。
        app.thread = thread;
        app.curAdj = app.setAdj = -100;
        app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
        app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
        app.forcingToForeground = null;
        app.foregroundServices = false;
        app.hasShownUi = false;
        app.debugging = false;

        mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);

        boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
        List providers = normalMode ? generateApplicationProvidersLocked(app) : null;
        try {
            int testMode = IApplicationThread.DEBUG_OFF;
            ...
            String profileFile = app.instrumentationProfileFile;
            ParcelFileDescriptor profileFd = null;
            boolean profileAutoStop = false;
            if (mProfileApp != null && mProfileApp.equals(processName)) {
                mProfileProc = app;
                profileFile = mProfileFile;
                profileFd = mProfileFd;
                profileAutoStop = mAutoStopProfiler;
            }

            boolean isRestrictedBackupMode = false;

            ApplicationInfo appInfo = app.instrumentationInfo != null
                    ? app.instrumentationInfo : app.info;
            //通過thread,即ApplicationThreadProxy跨程序呼叫了ApplicationThread中的bindApplication方法。從這裡,這裡又到了app程序
            thread.bindApplication(processName, appInfo, providers,
                    app.instrumentationClass, profileFile, profileFd, profileAutoStop,
                    app.instrumentationArguments, app.instrumentationWatcher, testMode, 
                    isRestrictedBackupMode || !normalMode, app.persistent,
                    new Configuration(mConfiguration), app.compat, getCommonServicesLocked(),
                    mCoreSettingsObserver.getCoreSettingsLocked());
            updateLruProcessLocked(app, false, true);
            app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
        } catch (Exception e) {
            app.resetPackageList();
            app.unlinkDeathRecipient();
            startProcessLocked(app, "bind fail", processName);
            return false;
        }
    // See if the top visible activity is waiting to run in this process
    //啟動即將要被啟動的Activity
        ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
        if (hr != null && normalMode) {
            if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
                    && processName.equals(hr.processName)) {
                try {
                    //realStartActivityLocked才是真正啟動Activity的方法。見2.1小節
                    if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
                        didSomething = true;
                    }
                } catch (Exception e) {
                    Slog.w(TAG, "Exception in new application when starting activity "
                          + hr.intent.getComponent().flattenToShortString(), e);
                    badApp = true;
                }
            } else {
                mMainStack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
            }
        }

        // Find any services that should be running in this process...
    //啟動程序中應該被啟動的Services
        if (!badApp && mPendingServices.size() > 0) {
            ServiceRecord sr = null;
            try {
                for (int i=0; i<mPendingServices.size(); i++) {
                    sr = mPendingServices.get(i);
                    if (app.info.uid != sr.appInfo.uid
                            || !processName.equals(sr.processName)) {
                        continue;
                    }

                    mPendingServices.remove(i);
                    i--;
                    realStartServiceLocked(sr, app);
                    didSomething = true;
                }
            } catch (Exception e) {
                Slog.w(TAG, "Exception in new application when starting service "
                      + sr.shortName, e);
                badApp = true;
            }
        }

        // Check if the next broadcast receiver is in this process...
    //啟動程序中應該被啟動的Broadcast
        BroadcastRecord br = mPendingBroadcast;
        if (!badApp && br != null && br.curApp == app) {
            try {
                mPendingBroadcast = null;
                processCurBroadcastLocked(br, app);
                didSomething = true;
            } catch (Exception e) {
                Slog.w(TAG, "Exception in new application when starting receiver "
                      + br.curComponent.flattenToShortString(), e);
                badApp = true;
                logBroadcastReceiverDiscardLocked(br);
                finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
                        br.resultExtras, br.resultAbort, true);
                scheduleBroadcastsLocked();
                // We need to reset the state if we fails to start the receiver.
                br.state = BroadcastRecord.IDLE;
            }
        }
        ...
        return true;
    }

這裡主要是通過pid獲得了app程序儲存在AMS中的ProcessRecord物件。設定了ApplicationThread這個Binder的死亡代理,通過ProcessRecord獲得了許多呼叫bindApplication的必要引數。然後通過Binder跨程序呼叫了ApplicationThread中的bindApplication方法。

1.3 ApplicationThread.bindApplication

public final void bindApplication(String processName,
                ApplicationInfo appInfo, List<ProviderInfo> providers,
                ComponentName instrumentationName, String profileFile,
                ParcelFileDescriptor profileFd, boolean autoStopProfiler,
                Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher,
                int debugMode, boolean isRestrictedBackupMode, boolean persistent,
                Configuration config, CompatibilityInfo compatInfo,
                Map<String, IBinder> services, Bundle coreSettings) {
            //這個services是一個HashMap,其中儲存了WindowManagerService,PackageManagersService,AlarmMangerService的Ibinder,見1.3.1小節
            if (services != null) {
                // Setup the service cache in the ServiceManager
                ServiceManager.initServiceCache(services);
            }
            //一些設定引數,coreSettings是一個Bundle物件,最終通過H Handler傳送訊息,呼叫了ActivityThread.handleSetCoreSettings。 見1.3.2小節
            setCoreSettings(coreSettings);
            //建立一個dataBean,將資料打包成一個Bean
            AppBindData data = new AppBindData();
            data.processName = processName;
            data.appInfo = appInfo;
            data.providers = providers;
            data.instrumentationName = instrumentationName;
            data.instrumentationArgs = instrumentationArgs;
            data.instrumentationWatcher = instrumentationWatcher;
            data.debugMode = debugMode;
            data.restrictedBackupMode = isRestrictedBackupMode;
            data.persistent = persistent;
            data.config = config;
            data.compatInfo = compatInfo;
            data.initProfileFile = profileFile;
            data.initProfileFd = profileFd;
            data.initAutoStopProfiler = false;
            //見1.3.3小節
            queueOrSendMessage(H.BIND_APPLICATION, data);
        }
1.3.1 ActivityMangaerService.getCommonServicesLocked

services是在AMS中作為引數傳入的,檢視AMS中原方法,實際上直接呼叫了getCommonServicesLocked方法,將返回值作為引數傳入,所以我們直接看getCommonServicesLocked這個方法。

    private HashMap<String, IBinder> getCommonServicesLocked() {
        //mAppBindArgs是一個HashMap,作為AMS中的一個成員變數
        if (mAppBindArgs == null) {
            mAppBindArgs = new HashMap<String, IBinder>();
            //獲得並儲存PackageManagerService的IBInder
            mAppBindArgs.put("package", ServiceManager.getService("package"));
            //獲得並儲存WindowMangerService的IBInder
            mAppBindArgs.put("window", ServiceManager.getService("window"));
            //獲得並儲存AlarmMangerService的IBInder
            mAppBindArgs.put(Context.ALARM_SERVICE,
                    ServiceManager.getService(Context.ALARM_SERVICE));
        }
        return mAppBindArgs;
    }
1.3.2 ActivityThread.handleSetCoreSettings
    private void handleSetCoreSettings(Bundle coreSettings) {synchronized (mPackages) {
        //即,最後將其儲存在了ActivityThread中的mCoreSettings。
            mCoreSettings = coreSettings;
        }
    }
1.3.3 ApplicationThread.queueOrSendMessage(H.BIND_APPLICATION, data);
    private void queueOrSendMessage(int what, Object obj) {
        queueOrSendMessage(what, obj, 0, 0);
    }
    //最終,將其包裝為一個message。傳送給了mH這個Handler。跳到了1.3.4小節
    private void queueOrSendMessage(int what, Object obj, int arg1, int arg2) {
        synchronized (this) {
            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;
            mH.sendMessage(msg);
        }
    }

mH這個Handler在AcitivityThread被例項話時,直接作為成員變數被例項化了。

1.3.4 H Handler
private class H extends Handler {
        public static final int LAUNCH_ACTIVITY         = 100;
        public static final int PAUSE_ACTIVITY          = 101;
        public static final int PAUSE_ACTIVITY_FINISHING= 102;
        public static final int STOP_ACTIVITY_SHOW      = 103;
        public static final int STOP_ACTIVITY_HIDE      = 104;
        public static final int SHOW_WINDOW             = 105;
        public static final int HIDE_WINDOW             = 106;
        public static final int RESUME_ACTIVITY         = 107;
        public static final int SEND_RESULT             = 108;
        public static final int DESTROY_ACTIVITY        = 109;
        public static final int BIND_APPLICATION        = 110;
        public static final int EXIT_APPLICATION        = 111;
        public static final int NEW_INTENT              = 112;
        public static final int RECEIVER                = 113;
        public static final int CREATE_SERVICE          = 114;
        public static final int SERVICE_ARGS            = 115;
        public static final int STOP_SERVICE            = 116;
        public static final int REQUEST_THUMBNAIL       = 117;
        public static final int CONFIGURATION_CHANGED   = 118;
        public static final int CLEAN_UP_CONTEXT        = 119;
        public static final int GC_WHEN_IDLE            = 120;
        public static final int BIND_SERVICE            = 121;
        public static final int UNBIND_SERVICE          = 122;
        public static final int DUMP_SERVICE            = 123;
        public static final int LOW_MEMORY              = 124;
        public static final int ACTIVITY_CONFIGURATION_CHANGED = 125;
        public static final int RELAUNCH_ACTIVITY       = 126;
        public static final int PROFILER_CONTROL        = 127;
        public static final int CREATE_BACKUP_AGENT     = 128;
        public static final int DESTROY_BACKUP_AGENT    = 129;
        public static final int SUICIDE                 = 130;
        public static final int REMOVE_PROVIDER         = 131;
        public static final int ENABLE_JIT              = 132;
        public static final int DISPATCH_PACKAGE_BROADCAST = 133;
        public static final int SCHEDULE_CRASH          = 134;
        public static final int DUMP_HEAP               = 135;
        public static final int DUMP_ACTIVITY           = 136;
        public static final int SLEEPING                = 137;
        public static final int SET_CORE_SETTINGS       = 138;
        public static final int UPDATE_PACKAGE_COMPATIBILITY_INFO = 139;
        public static final int TRIM_MEMORY             = 140;
        public void handleMessage(Message msg) {
            if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + msg.what);
            switch (msg.what) {
                    ...
                    //1.3.3傳送的訊息會進入這個case
                    case BIND_APPLICATION:
                    AppBindData data = (AppBindData)msg.obj;
                    //呼叫了ActivityThread的handleBindApplication方法。見1.3.5小節
                    handleBindApplication(data);
                    break;
                    ...
            }
        }
        ...
}

H Handler是ActivityThread的一個內部類,其中我們可以看到定義了非常多的狀態量,常見的SHOW_WINDOW,CREATE_SERVICE,NEW_INTENT,LAUNCH_ACTIVITY,PAUSE_ACTIVITY,RECEIVER,BIND_SERVICE等等都是android中非常常見的一些操作。 由此可見H Handler是非常重要的一個類,在Window,Activity,Service,Intent,Receiver等等的許多操作中都會用到它來發送訊息。

1.3.5 ActivityThread.handleBindApplication

這又是一個長到爆炸的方法,我們依然是省略部分程式碼,只留下整體中最重要的呼叫程式碼

    private void handleBindApplication(AppBindData data) {
        //現將打包的data儲存起來,接下來一大段都是獲得data中對應的資料,將其賦值給對應的一些變數。
        mBoundApplication = data;
        mConfiguration = new Configuration(data.config);
        mCompatConfiguration = new Configuration(data.config);

        mProfiler = new Profiler();
        mProfiler.profileFile = data.initProfileFile;
        mProfiler.profileFd = data.initProfileFd;
        mProfiler.autoStopProfiler = data.initAutoStopProfiler;

        Process.setArgV0(data.processName);
        android.ddm.DdmHandleAppName.setAppName(data.processName);

        if (data.persistent) {
            Display display = WindowManagerImpl.getDefault().getDefaultDisplay();
            if (!ActivityManager.isHighEndGfx(display)) {
                HardwareRenderer.disable(false);
            }
        }

        if (mProfiler.profileFd != null) {
            mProfiler.startProfiling();
        }

        //當app版本小於等於12時,設定AsyncTask的預設執行緒池
        if (data.appInfo.targetSdkVersion <= 12) {
            AsyncTask.setDefaultExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
        }
        //預設時區設定
        TimeZone.setDefault(null);

        Locale.setDefault(data.config.locale);

        ...
        if (data.instrumentationName != null) {
            //建立ContextImpl,我們知道,在android中,Context是一個抽象類,它的具體實現類就是ContextImpl。而像Application,Service類均繼承自COntextWapper。而ContextWapper雖然也繼承自Context,但它只是ContextImpl的一個包裝類,它裡面很多具體的處理都是直接丟給了ContextImpl。
            ContextImpl appContext = new ContextImpl();
            appContext.init(data.info, null, this);
            InstrumentationInfo ii = null;

            try {
                ii = appContext.getPackageManager().
                    getInstrumentationInfo(data.instrumentationName, 0);
            } catch (PackageManager.NameNotFoundException e) {
            }
            if (ii == null) {
                throw new RuntimeException(
                    "Unable to find instrumentation info for: "
                    + data.instrumentationName);
            }

            mInstrumentationAppDir = ii.sourceDir;
            mInstrumentationAppPackage = ii.packageName;
            mInstrumentedAppDir = data.info.getAppDir();

            ApplicationInfo instrApp = new ApplicationInfo();
            instrApp.packageName = ii.packageName;
            instrApp.sourceDir = ii.sourceDir;
            instrApp.publicSourceDir = ii.publicSourceDir;
            instrApp.dataDir = ii.dataDir;

            instrApp.nativeLibraryDir = ii.nativeLibraryDir;
            LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
                    appContext.getClassLoader(), false, true);

            ContextImpl instrContext = new ContextImpl();
            instrContext.init(pi, null, this);
            //建立ClassLoader,建立Instrumentation例項
            try {
                java.lang.ClassLoader cl = instrContext.getClassLoader();
                mInstrumentation = (Instrumentation)
                    cl.loadClass(data.instrumentationName.getClassName()).newInstance();
            } catch (Exception e) {
                throw new RuntimeException(
                    "Unable to instantiate instrumentation "
                    + data.instrumentationName + ": " + e.toString(), e);
            }

            mInstrumentation.init(this, instrContext, appContext,
                    new ComponentName(ii.packageName, ii.name), data.instrumentationWatcher);

            if (mProfiler.profileFile != null && !ii.handleProfiling
                    && mProfiler.profileFd == null) {
                mProfiler.handlingProfiling = true;
                File file = new File(mProfiler.profileFile);
                file.getParentFile().mkdirs();
                Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
            }

            try {
                mInstrumentation.onCreate(data.instrumentationArgs);
            }
            catch (Exception e) {
                throw new RuntimeException(
                    "Exception thrown in onCreate() of "
                    + data.instrumentationName + ": " + e.toString(), e);
            }

        } else {
            mInstrumentation = new Instrumentation();
        }

        if ((data.appInfo.flags&ApplicationInfo.FLAG_LARGE_HEAP) != 0) {
            dalvik.system.VMRuntime.getRuntime().clearGrowthLimit();
        }

        //建立Application例項,見1.3.6小節
        Application app = data.info.makeApplication(data.restrictedBackupMode, null);
        mInitialApplication = app;

        if (!data.restrictedBackupMode){ 
            List<ProviderInfo> providers = data.providers;
            if (providers != null) {
                //建立本程序的ContentProvider,並啟動ContentProvider,見1.3.7小節
                installContentProviders(app, 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);
            }
        }
        //呼叫了application的oncreate方法
        try {
            mInstrumentation.callApplicationOnCreate(app);
        } catch (Exception e) {
            if (!mInstrumentation.onException(app, e)) {
                throw new RuntimeException(
                    "Unable to create application " + app.getClass().getName()
                    + ": " + e.toString(), e);
            }
        }
    }

主要做了一下幾件事:

  1. 解包AMS傳過來的資料。
  2. 建立Instrumentation例項物件。
  3. 建立Application例項物件。
  4. 建立所在程序的ContentProvider例項物件,並呼叫它的onCreate方法
  5. 呼叫了Application的onCreate方法。
1.3.6 Loaded.makeApplication
public Application makeApplication(boolean forceDefaultAppClass,
            Instrumentation instrumentation) {
    //存在Application就直接返回
        if (mApplication != null) {
            return mApplication;
        }

        Application app = null;
        //Application的包名,如果不存在就使用預設包名路徑
        String appClass = mApplicationInfo.className;
        if (forceDefaultAppClass || (appClass == null)) {
            appClass = "android.app.Application";
        }

        try {
            java.lang.ClassLoader cl = getClassLoader();
            //建立ApplicationContext中的ContextImpl物件
            ContextImpl appContext = new ContextImpl();
            appContext.init(this, null, mActivityThread);
            //建立了Application物件。最終通過包名路徑,clazz.newInstance()的方式獲得Application物件,並將appContext繫結到Application中。(Application繼承自ContextWapper)
            app = mActivityThread.mInstrumentation.newApplication(
                    cl, appClass, appContext);
            appContext.setOuterContext(app);
        } catch (Exception e) {
            if (!mActivityThread.mInstrumentation.onException(app, e)) {
                throw new RuntimeException(
                    "Unable to instantiate application " + appClass
                    + ": " + e.toString(), e);
            }
        }
        mActivityThread.mAllApplications.add(app);
        mApplication = app;

    //instrumentation不為null的情況下,呼叫Application的onCreate方法,但在前面傳入時,傳的值就是null,所以這裡不會呼叫onCreate
        if (instrumentation != null) {
            try {
                instrumentation.callApplicationOnCreate(app);
            } catch (Exception e) {
                if (!instrumentation.onException(app, e)) {
                    throw new RuntimeException(
                        "Unable to create application " + app.getClass().getName()
                        + ": " + e.toString(), e);
                }
            }
        }

        return app;
    }
1.3.7 ActivityThread.installContentProviders
private void installContentProviders(Context context, List<ProviderInfo> providers) {
        final ArrayList<IActivityManager.ContentProviderHolder> results =
            new ArrayList<IActivityManager.ContentProviderHolder>();

        Iterator<ProviderInfo> i = providers.iterator();
        while (i.hasNext()) {
            ProviderInfo cpi = i.next();
            StringBuilder buf = new StringBuilder(128);
            buf.append("Pub ");
            buf.append(cpi.authority);
            buf.append(": ");
            buf.append(cpi.name);
            Log.i(TAG, buf.toString());
            //通過ClassLoder建立ContentProvider物件並呼叫了ContentProvider的onCreate方法
            IContentProvider cp = installProvider(context, null, cpi,
                    false /*noisy*/, true /*noReleaseNeeded*/);
            if (cp != null) {
                IActivityManager.ContentProviderHolder cph =
                        new IActivityManager.ContentProviderHolder(cpi);
                cph.provider = cp;
                cph.noReleaseNeeded = true;
                results.add(cph);
            }
        }
        //將ContentProvider的Binder 儲存到AMS中,方便其他程序呼叫。
        try {
            ActivityManagerNative.getDefault().publishContentProviders(
                getApplicationThread(), results);
        } catch (RemoteException ex) {
        }
    }

2.1 ActivityStack.realStartActivityLocked

    final boolean realStartActivityLocked(ActivityRecord r,
            ProcessRecord app, boolean andResume, boolean checkConfig)
            throws RemoteException {
        ...

        try {
           ...
            //啟動Activity。這裡的thread從1.2.4小節可以知道是ApplicationThreadProxy例項,它實際上是一個IBinder物件,最終通過Bind而跨程序呼叫了ApplicationThread中的對應方法,見2.2.1小節
            app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                    System.identityHashCode(r), r.info,
                    new Configuration(mService.mConfiguration),
                    r.compat, r.icicle, results, newIntents, !andResume,
                    mService.isNextTransitionForward(), profileFile, profileFd,
                    profileAutoStop);
          ...
            }

        } catch (RemoteException e) {
            
            
           

相關推薦

App啟動流程分析()

我們知道Java中一個能夠獨立執行的java程式的方法入口是main方法,它是被Jvm識別呼叫的。而在Android中一個應用的開始也可說是從ActivityThread的main方法開始的,然而不同的是他不是由Jvm呼叫的。 上一節我們講到在ZygoteIn

iOS作業系統-- App啟動流程分析與優化

背景知識: mach-o檔案為基於Mach核心的作業系統的可執行檔案、目的碼或動態庫,是.out的代替,其提供了更強的擴充套件性並提升了符號表中資訊的訪問速度, 符號表,用於標記原始碼中包括識別符號、宣告資訊、行號、函式名稱等元素的具體資訊,比如說資料型別、作用域以及記憶體地址,iOS符號表在dS

深入淺出Android中的App啟動流程分析

App啟動是指使用者點選手機桌面的app對應的icon開始,所以我們需要明白幾點基礎知識: 1.桌面也是一個Activity叫Launcher.java 2.在桌面點選icon啟動app跟在app內部啟動另一個Activity是一樣的都是呼叫startAct

App啟動流程分析(上)

App啟動流程分析 一.概述流程 在LAUNCH介面,點選一個app的圖示之後,會呼叫startActivity來啟動對應的Activity。 通過Binder遠端通知AMS啟動新的Activity。 AMS進行一系列的許可權判斷,建立Activity

Android5 Zygote 與 SystemServer 啟動流程分析

進一步 null 正常的 rtb 這樣的 ket constant vml resp Android5 Zygote 與 SystemServer 啟動流程分析 Android5 Zygote 與 SystemServer 啟動流程分析 前言 zy

開機啟動流程分析

boot 啟動流程 本節索引 在對系統啟動流程進行分析的時候,我想你一定是對系統有了一定的了解。系統的啟動目前來講大都為串行接力的方式來啟動。而所謂的並行方式的啟動方式也是某一個階段的並行。所以我按照系統啟動的順序來把文章連綴起來。 * BIOS階段 * BootLoader階段

kexec 內核快速啟動流程分析

-- 令行 並且 內存 tab 執行過程 family use -a 一、命令行 1. kexec -l $kpwd --append="$arg" 其中$kpwd =目標內核的路徑   $arg =傳給內核的參數,與/proc/cmdline一致時表示重啟現有內核

從0移植uboot (二) _啟動流程分析

title tco ret 沒有 返回 ips css location config 來源:Linux社區 作者:xiaojiang1025 : http://www.linuxidc.com/Linux/2017-02/141019.htm 經過

u-boot.2012.10——mini2440(二、啟動流程分析)

我們 分享 默認 從數據 中斷 改變 處理 mini2440 https 參考資料:https://blog.csdn.net/suiyuan19840208/article/details/7239949 1、第一階段功能   * 硬件設備初始化   * 加載u-boot

GEF入門實例_總結_04_Eclipse插件啟動流程分析

理解 viso inf targe get ica order workbench 註意 一、前言 本文承接上一節:GEF入門實例_總結_03_顯示菜單和工具欄 註意到app目錄下的6個類文件。 這6個文件對RCP應用程序而言非常重要,可能我們現在對這幾個文件的理

[Abp 源碼分析] 一、Abp 框架啟動流程分析

arch rep man job dsi 法則 依賴 gconf dep Abp 不一定僅用於 Asp.Net Core 項目,他也可以在 Console 與 WinFrom 項目當中進行使用,所以關於啟動流程可以分為兩種,一種是 Asp.Net Core 項目的啟動流程

linux-2.6.22.6內核啟動流程分析之配置

linux 分享圖片 src image 比較 文件包含 子目錄 2.6 config 配置過程最終結果是生成.config文件,我們想要對配置的目的有很清楚的了解,必須先對.config文件進行分析。通過cd命令切換到linux-2.6.22.6內核目錄,輸入vi .co

Flink on Yarn模式啟動流程分析

cin XML images ont list action -i 多個 信息 此文已由作者嶽猛授權網易雲社區發布。歡迎訪問網易雲社區,了解更多網易技術產品運營經驗。Flink On Yarn 架構Paste_Image.png前提條件首先需要配置YARN_CONF_DIR

App啟動流程

目錄介紹 1.什麼是Zygote程序 1.1 簡單介紹 1.2 各個程序的先後順序 1.3 程序作用說明 2.Zygote程序的啟動流程 2.1 原始碼位置 2.2 ZygoteInit類的main方法 2.3 regist

Spark2.2.2原始碼解析: 3.啟動worker節點啟動流程分析

本文啟動worker節點啟動流程分析   啟動命令: ${SPARK_HOME}/sbin/start-slave.sh spark://sysadmindeMacBook-Pro.local:7077   檢視start-slave.sh  

Android9.0 Activity啟動流程分析(二)

文章目錄 1、ActivityThread的main函式 2. AMS的attachApplication函式 2.1 Part-I 2.2 Part-II 2.2.1 ApplicationThread的bindApp

Android9.0 Activity啟動流程分析(一)

1、ActivityRecord、TaskRecord、ActivityStack和ActivityDisplay介紹   本篇文章是基於Android refs/tags/android-9.0.0_r8分支的程式碼進行分析的   在分析Activity啟動的原始碼之前先介紹一下Act

s5pv210 -uboot(三)SD卡啟動流程分析

https://blog.csdn.net/wangweijundeqq/article/details/78886155 --------------------- 本文來自 MrT_WANG 的CSDN 部落格 ,全文地址請點選:https://blog.csdn.net

Android 虛擬機器簡單介紹——ART、Dalvik、啟動流程分析

Android 虛擬機器方面的知識,我是通過《深入理解 Android 核心設計思想》來學習的,內容特別多(只有一章,但有 160 頁),但感覺和 Android 開發有些偏了,因此很多內容都沒有認真去看,比如 EFL 格式等,這裡只是選取了一些感覺比較重要的做

Linux核心啟動流程分析(一)

1. 依據arch/arm/kernel/vmlinux.lds 生成linux核心原始碼根目錄下的vmlinux,這個vmlinux屬於未壓縮,帶除錯資訊、符號表的最初的核心,大小約23MB;  命令:arm-linux-gnu-ld -o vmlinux -T a