android startService流程梳理筆記

來源:互聯網
上載者:User

1、ContextWrapper.startService

  startService是Context的方法,Activity、Service都繼承自ContextWrapper,而ContextWrapper又繼承自Context,BroadcastReceiver的onReceive方法中有個參數是Context類型的,所以我們在Activity、Service、BroadcastReceiver中都可以調用startService方法,當在Activity等中調用startService時,首先會調用到ContextWrapper的startService方法:

public ComponentName startService(Intent service) {    return mBase.startService(service);}

2、ContextImpl.startService

  mBase是ContextImpl的執行個體,從名字也可以看到ContextImpl也是Context的子類,從ContextWrapper的名字也可以看到,它只是Context的封裝類,其函數內部的實現都是通過調用內部ContextImpl類的執行個體mBase來完成實際請求,這被稱為裝飾者模式。

  ContextImpl的startService直接調用startServiceAsUser,在startServiceAsUser中調用ActivityManagerNative.getDefault().startService,ActivityManagerNative.getDefault()返回一個IActivityManager對象,典型的Binder通訊。所以接下來會通過ActivityManagerProxy的startService經由Binder調用到ActivityManagerService(繼承自ActivityManagerNative)的startService方法。

public ComponentName startServiceAsUser(Intent service, UserHandle user) {    try {        service.setAllowFds(false);        ComponentName cn = ActivityManagerNative.getDefault().startService(            mMainThread.getApplicationThread(), service,            service.resolveTypeIfNeeded(getContentResolver()), user.getIdentifier());    ...        return cn;    } catch (RemoteException e) {        return null;    }}

3、ActivityManagerService.startService與ActiveServices

  在ActivityManagerService的startService中,首先檢查Caller的合法性(PID、UID),然後調用ActiveServices的startServiceLocked方法(在舊版本中這個方法在ActivityManagerService中),在startServiceLocked中,首先通過retrieveServiceLocked檢索我們調用startService時傳入的Intent資訊,將結果存入ServiceLookupResult.record中(ServiceRecord),緊接著調用ActiveServices的bringUpServiceLocked方法。

  在bringUpServiceLocked中調用ActivityManagerService的startProcessLocked獲得一個ProcessRecord對象並將其加入到mPendingServices隊列中。startServiceLocked、bringUpServiceLocked都是從ActivityManagerService中調用過來的,所以是一直運行在ActivityaManagerService進程中,再調用ActivityManagerService的方法就是直接調用,而不用通過IPC。

  ActivityManagerService中有兩個重載形式的startProcessLocked,首先進入參數多的那一個,通過newProcessRecordLocked獲得一個ProcessRecord對象,然後把這個對象作為參數調用另一個形式的startProcessLocked,在這個startProcessLocked中,調用Process.start建立一個新的進程,將返回的Process.ProcessStartResult對象、新進程的PID及獲得的ProcessRecord對象放入mPidSelfLocked列表中。

final ProcessRecord startProcessLocked(String processName,        ApplicationInfo info, boolean knownToBeDead, int intentFlags,        String hostingType, ComponentName hostingName, boolean allowWhileBooting, boolean isolated) {    ...    app = newProcessRecordLocked(null, info, processName, isolated);    ...    startProcessLocked(app, hostingType, hostingNameStr);    return (app.pid != 0) ? app : null;}private final void startProcessLocked(ProcessRecord app,        String hostingType, String hostingNameStr) {    ...    Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",                    app.processName, uid, uid, gids, debugFlags, mountExternal,                    app.info.targetSdkVersion, null, null);    ...    synchronized (mPidsSelfLocked) {        this.mPidsSelfLocked.put(startResult.pid, app);        ...    }    ...}

4、ActivityThread.main

  在Process.start中建立了一個進程,然後調用了ActivityThread的main函數。

public static void main(String[] args) {    ...    Looper.prepareMainLooper();    ActivityThread thread = new ActivityThread();    thread.attach(false);    if (sMainThreadHandler == null) {        sMainThreadHandler = thread.getHandler();    }    ...    Looper.loop();    ...}

5、ActivityManagerService.attachApplication

  在main中建立一個ActivityThread對象,並調用其attach方法,參數表示是否是系統進程。這裡已經是在新進程裡了。在attach中,又調用了ActivityManagerNative.getDefault().attachApplication(mAppThread)。同樣,經由Binder由ActivityManagerProxy到了ActivityManagerService的attachApplication方法,在attachApplication中直接調用attachApplicationLocked。

  在attachApplicationLocked中,通過新進程的PID獲得在第3步中放入mPidSelfLocked列表中的ProcessRecord對象,然後調用ActiveyServices的attachApplicationLocked方法,在這個方法中通過進程PID與進程名找到在第3步中放入mPendingServices中的ServiceRecord對象,再以這個找到的ServiceRecord對象與傳入的ProcessRecord對象為參數調用realStartServiceLocked,這個函數也在ActiveServices中。

private final boolean attachApplicationLocked(IApplicationThread thread, nt pid) {    ProcessRecord app;    if (pid != MY_PID && pid >= 0) {        synchronized (mPidsSelfLocked) {            app = mPidsSelfLocked.get(pid);        }    } else {        app = null;    }    ...    mServices.attachApplicationLocked(app, processName);    ...}boolean attachApplicationLocked(ProcessRecord proc, String processName) throws Exception {    boolean didSomething = false;    // Collect any services that are waiting for this process to come up.    if (mPendingServices.size() > 0) {        ServiceRecord sr = null;        try {            for (int i=0; i<mPendingServices.size(); i++) {                sr = mPendingServices.get(i);                if (proc != sr.isolatedProc && (proc.uid != sr.appInfo.uid                        || !processName.equals(sr.processName))) {                    continue;                }                mPendingServices.remove(i);                i--;                realStartServiceLocked(sr, proc);                didSomething = true;            }        } catch (Exception e) {            Slog.w(TAG, "Exception in new application when starting service "                    + sr.shortName, e);            throw e;        }    }    ...}

6、ActiveServices.realStartServiceLocked

  在realStartServiceLocked中,取得傳入的ProcessRecord對象的IApplicationThread類型的成員變數thread,調用其scheduleCreateService方法,同ActivityManagerProxy一樣,調用的是ApplicationThreadProxy的scheduleCreateService,然後經由Binder到ApplicationThread的scheduleCreateService(ApplicationThread是ActivityThread的私人內部類)。

7、ApplicationThread.scheduleCreateService與ActivityThread.handleCreateService

  在ApplicationThread的scheduleCreateService中調用了外部類ActivityThread的queueOrSendMessage方法,向H中sendMessage(H繼承自Handler),接下來肯定到了H的handleMessage,在handleMessage中走CREATE_SERVICE的switch case,調用外部類ActivityThread的handleCreateService方法。

  在handleCreateService通過JAVA的ClassLoader load載入要啟動的Service的類,並通過newInstance建立一個Service的執行個體,new ContextImpl,makeApplication並跟建立的Service執行個體attach,然後調用我們熟悉的Service的onCreate方法,至此Service啟動成功。

private void handleCreateService(CreateServiceData data) {    // If we are getting ready to gc after going to the background, well    // we are back active so skip it.    unscheduleGcIdler();    LoadedApk packageInfo = getPackageInfoNoCheck(            data.info.applicationInfo, data.compatInfo);    Service service = null;    try {        java.lang.ClassLoader cl = packageInfo.getClassLoader();        service = (Service) cl.loadClass(data.info.name).newInstance();    } catch (Exception e) {        ...    }    try {        if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);        ContextImpl context = new ContextImpl();        context.init(packageInfo, null, this);        Application app = packageInfo.makeApplication(false, mInstrumentation);        context.setOuterContext(service);        service.attach(context, this, data.info.name, data.token, app,                    ActivityManagerNative.getDefault());        // 調用Service的onCreate,即要啟動的Service的onCreate        service.onCreate();        mServices.put(data.token, service);        try {            ActivityManagerNative.getDefault().serviceDoneExecuting(                    data.token, 0, 0, 0);        } catch (RemoteException e) {            // nothing to do.        }    } catch (Exception e) {        ...    }}

 

總結:

  1、調用ContextImpl的startService,通過Binder進入ActivityManagerService的進程執行ActivityManagerService的startService方法。

  2、在startService過程中建立一個進程,在建立的進程中建立Looper,調用ActivityThread的attach方法,然後就又進入了ActivityManagerService的進程。

  3、擷取要在新進程啟動的服務的相關資訊,在ActivityManagerService中通過ApplicationThreadProxy又進入Service進程,Service的進程啟起來,調用我們熟悉的Service的onCreate方法。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.