Android Service的啟動流程源碼分析

一,寫在前面

Android Service的啟動流程源碼分析,在Android中服務有兩種狀態,一種是啟動服務,一種是綁定服務,它們有著不同的生命周期。啟動服務的生命周期:onCreate,onStart,onDestroy;綁定服務的生命周期:onCreate,onBind,onUnBind,onDestroy。至於服務具體如何使用,本篇將不做介紹。主要介紹從源碼角度,解析啟動服務過程。需要註意的是,閱讀本篇文章之前建議先瞭解Activity的啟動流程。

二,進入主題

通常需要在Activity組件中啟動一個服務,用於在後臺執行一些計算的操作。這時,會調用startService(Intent service)方法,其實這個方法的具體實現在Activity的父類ContextWrapper類中,類ContextWrapper是Context的子類。好瞭,查看源碼開始分析吧~

查看ContextWrapper$startService源碼:

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

第3行,字段mBase是Context類型,但Context是一個抽象類,事實上mBase變量是一個ContextImpl對象。給mBase變量設置值是在Activity$attach方法被調用時完成,具體分析見文章Android Activity的啟動流程源碼解析,這裡不再重復闡述。

 

查看ContextImpl$startService方法源碼:

    @Override
    public ComponentName startService(Intent service) {
        warnIfCallingFromSystemProcess();
        return startServiceCommon(service, false, mUser);
    }

//繼續查看

    private ComponentName startServiceCommon(Intent service, boolean requireForeground,
            UserHandle user) {
       //...code

	ComponentName cn = ActivityManager.getService().startService(
                mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
                            getContentResolver()), requireForeground,
                            getOpPackageName(), user.getIdentifier());
	
	//...code
    }

第13行,ActivityManager.getService()返回的是一個IActivityManager的一個代理對象,利用AIDL技術完成進程間通信,需要找到那個extendsIActivityManager.Stub的實現類,它就是ActivityManagerService。IActivityManager的代理對象調用startService方法,會向系統服務ActivityManagerService發送一個請求,基於Binder機制,會調用ActivityManagerService$startService方法。詳細的代碼流程分析見文章Android Activity的啟動流程源碼解析,這裡不再重復闡述。

 

查看ActivityManagerService$startService方法源碼:

@Override
    public ComponentName startService(IApplicationThread caller, Intent service,
            String resolvedType, boolean requireForeground, String callingPackage, int userId)
            throws TransactionTooLargeException {
	
	//...code

        synchronized(this) {
            final int callingPid = Binder.getCallingPid();
            final int callingUid = Binder.getCallingUid();
            final long origId = Binder.clearCallingIdentity();
            ComponentName res;
            try {
                res = mServices.startServiceLocked(caller, service,
                        resolvedType, callingPid, callingUid,
                        requireForeground, callingPackage, userId);
            } finally {
                Binder.restoreCallingIdentity(origId);
            }
            return res;
        }
    }

第14行,變量mServices是ActiveServices類型的對象。於是,啟動服務的工作交給瞭ActiveServices來處理。

 

查看ActiveServices源碼如下:

    ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
            int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId)
            throws TransactionTooLargeException {
	    
	    //...code

	    ServiceLookupResult res =
            retrieveServiceLocked(service, resolvedType, callingPackage,
                    callingPid, callingUid, userId, true, callerFg, false);

	    //...code

	    ServiceRecord r = res.record;

	    //...code

	    r.lastActivity = SystemClock.uptimeMillis();
            r.startRequested = true;
            r.delayedStop = false;
            r.fgRequired = fgRequired;
            r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
                service, neededGrants, callingUid));
	    
	    //...code

	    ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
	    return cmp;	    	    
    }

    //繼續查看

    ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
            boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
	    
	    //...

	    String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
	    
	    //...
    } 
    
    //繼續查看

    private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
            boolean whileRestarting, boolean permissionsReviewRequired)
            throws TransactionTooLargeException {
	    
	    //...

	    realStartServiceLocked(r, app, execInFg);
	    
	    //...
    }

    //繼續查看

    private final void realStartServiceLocked(ServiceRecord r,
            ProcessRecord app, boolean execInFg) throws RemoteException {
	    
	    //...

	    app.thread.scheduleCreateService(r, r.serviceInfo,
                    mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                    app.repProcState);

            //...

	    sendServiceArgsLocked(r, execInFg, true);
	    
    }

第13行,ServiceRecord封裝瞭要啟動的服務一些信息,r作為方法的參數進行傳遞。

第62行,app.thread是一個IApplicationThread的代理對象,最終會調用ApplicationThread$scheduleCreateService方法啟動服務,具體分析可以參考文章Android Activity的啟動流程源碼解析。內部會調用Service$onCreate方法啟動服務,後面會有所分析。

第68行,內部會調用onStartCommand方法,這裡不做過多介紹,代碼流程與onCreate類似。

三,啟動服務的操作,交給ActivityThread來處理

繼續app.thread.scheduleCreateService進行分析,值得一提的是,ApplicationThread是ActivityThread的內部類。

查看ApplicationThread$scheduleCreateService源碼:

public final void scheduleCreateService(IBinder token,
	ServiceInfo info, CompatibilityInfo compatInfo, int processState) {
    updateProcessState(processState, false);
    CreateServiceData s = new CreateServiceData();
    s.token = token;
    s.info = info;
    s.compatInfo = compatInfo;

    sendMessage(H.CREATE_SERVICE, s);
}

 

查看ActivityThread$sendMessage源碼如下:

private 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);
}

第19行,Handler發送瞭一個消息,於是啟動服務的操作在消息的處理中瞭。

查看ActivityThread$handleMessage方法源碼:

public void handleMessage(Message msg) {
        if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
        switch (msg.what) {
		
	    //...code

	    case CREATE_SERVICE:
                Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, ("serviceCreate: " + String.valueOf(msg.obj)));
                handleCreateService((CreateServiceData)msg.obj);
                Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                break;

	    //...code
	}			    	   	    
}

第9行,調用handleCreateService方法啟動服務。可以發現,啟動服務的過程與啟動Activity的過程有相同地方,剛開始將啟動組件的操作交給系統服務ActivityManagerService來出來,然後,將啟動組件的操作交給ApplicationThread來處理。值得一提是,這兩步都涉及到進程間的通信,且是基於Binder機制,可以看到Binder機制在framework層的利用無處不在。最後,處理組件的操作都是通過發送一次消息來完成,啟動服務與啟動Activity具體做的操作比較相同,這也是為何文章開頭建議先瞭解Activity的啟動流程。

 

繼續查看ActivityThread$handleCreateService方法源碼:

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;
        Application app = null;
        try {
            app = packageInfo.makeApplication(false, mInstrumentation);
            java.lang.ClassLoader cl = packageInfo.getClassLoader();
            service = instantiate(cl, data.info.name, data.intent, app,
                    Application::instantiateService);
        } catch (Exception e) {
            if (!mInstrumentation.onException(service, e)) {
                throw new RuntimeException(
                    "Unable to instantiate service " + data.info.name
                    + ": " + e.toString(), e);
            }
        }

        try {
            if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);

            ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
            context.setOuterContext(service);

            service.attach(context, this, data.info.name, data.token, app,
                    ActivityManager.getService());
            service.onCreate();
            mServices.put(data.token, service);
            try {
                ActivityManager.getService().serviceDoneExecuting(
                        data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
            } catch (RemoteException e) {
                throw e.rethrowFromSystemServer();
            }
        } catch (Exception e) {
            if (!mInstrumentation.onException(service, e)) {
                throw new RuntimeException(
                    "Unable to create service " + data.info.name
                    + ": " + e.toString(), e);
            }
        }
    }

仔細分析代碼可以發現,啟動服務最終調用瞭Activity$handleCreateService方法,與啟動Activity最終調用瞭ActivityThread$performLaunchActivity方法做的事情有些類似,詳情參考文章Android Activity的啟動流程源碼解析。

handleCreateService啟動服務大致有操作:

第11行,創建Application對象,若應用程序已經存在該對象,則不再創建。

第13行,通過類加載器ClassLoader創建Service的實例。

第26行,創建Service的上下文環境,也就是創建ContextImpl對象,會作為Service$attach方法的參數傳入。

第29行,調用Service$attach方法,做初始化一些變量的操作。

第31行,調用Service$onCreate方法啟動服務。

第32行,將Service的實例對象存入Map集合中,執行Service生命周期的其他方法時,可以在該集合中取出Service實例。

上述操作,與啟動Activity的流程大體類似,每一步操作不再作細致分析,詳細分析可以參考文章Android Activity的啟動流程源碼解析。

四,最後

可以發現,啟動服務與啟動Activity的流程有很多類似之處,瞭解Activity的啟動流程,對於本篇的理解很有意義~ ^_^

You May Also Like