android startService流程梳理筆記


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方法。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM