理解 startService過程

前言

本文假設(shè)你已經(jīng)了解了android中Binder相關(guān)的機制,如果你還未了解相關(guān)知識,就沒必要閱讀本文了。

正文

我們直接看ContextImp相關(guān)代碼

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

    private ComponentName startServiceCommon(Intent service, UserHandle user) {
        try {
            ...
            ComponentName cn = ActivityManagerNative.getDefault().startService(
                mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
                            getContentResolver()), getOpPackageName(), user.getIdentifier());
            ...
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

看線ActivityManagerNative相關(guān)代碼

    static public IActivityManager getDefault() {
        return gDefault.get();
    }
    ...
    private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
        protected IActivityManager create() {
            IBinder b = ServiceManager.getService("activity");
            if (false) {
                Log.v("ActivityManager", "default service binder = " + b);
            }
            IActivityManager am = asInterface(b);
            if (false) {
                Log.v("ActivityManager", "default service = " + am);
            }
            return am;
        }
    };
    ...
    static public IActivityManager asInterface(IBinder obj) {
        if (obj == null) {
            return null;
        }
        IActivityManager in =
            (IActivityManager)obj.queryLocalInterface(descriptor);
        if (in != null) {
            return in;
        }

        return new ActivityManagerProxy(obj);
    }

綜上我們可以知道,ActivityManagerNative.getDefault().startServices實際上是調(diào)用了ActivityMangerProxy對象的startService方法,看下這個方法

    public ComponentName startService(IApplicationThread caller, Intent service,
            String resolvedType, String callingPackage, int userId) throws RemoteException
    {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IActivityManager.descriptor);
        data.writeStrongBinder(caller != null ? caller.asBinder() : null);
        service.writeToParcel(data, 0);
        data.writeString(resolvedType);
        data.writeString(callingPackage);
        data.writeInt(userId);
        mRemote.transact(START_SERVICE_TRANSACTION, data, reply, 0);
        reply.readException();
        ComponentName res = ComponentName.readFromParcel(reply);
        data.recycle();
        reply.recycle();
        return res;
    }

mRemote實際上是

IBinder b = ServiceManager.getService("activity");

的返回值,也就一個IBinder對象,它實際上是ActivityMangerService的一個引用,或者叫句柄。
我們看下AMS對應的這個指令的處理方式,搜了一下發(fā)現(xiàn)AMS中沒有相關(guān)代碼,我們?nèi)MS的父類AMN中看下,我們看到

case START_SERVICE_TRANSACTION: {
            data.enforceInterface(IActivityManager.descriptor);
            IBinder b = data.readStrongBinder();
            IApplicationThread app = ApplicationThreadNative.asInterface(b);
            Intent service = Intent.CREATOR.createFromParcel(data);
            String resolvedType = data.readString();
            String callingPackage = data.readString();
            int userId = data.readInt();
            ComponentName cn = startService(app, service, resolvedType, callingPackage, userId);
            reply.writeNoException();
            ComponentName.writeToParcel(cn, reply);
            return true;
        }

AMN中取出了參數(shù)后,交給startService方法去處理,我們看下AMS的startService方法

    @Override
    public ComponentName startService(IApplicationThread caller, Intent service,
            String resolvedType, String callingPackage, int userId)
            throws TransactionTooLargeException {
        ...
        synchronized(this) {
            final int callingPid = Binder.getCallingPid();
            final int callingUid = Binder.getCallingUid();
            final long origId = Binder.clearCallingIdentity();
            ComponentName res = mServices.startServiceLocked(caller, service,
                    resolvedType, callingPid, callingUid, callingPackage, userId);
            Binder.restoreCallingIdentity(origId);
            return res;
        }
    }

我們看下關(guān)鍵代碼startServiceLocked,mServices是ActiveService的一個實例
這個方法創(chuàng)建了一個ServiceRecord對象,又做了一些其他事情,但是有一行非常關(guān)鍵的代碼

    ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
            int callingPid, int callingUid, String callingPackage, final int userId)
            throws TransactionTooLargeException {
       ....
            return startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
    }

    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 {
        ...
        ProcessRecord app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
        if (app != null && app.thread != null) {//要啟動的service的進程已經(jīng)存在
            realStartServiceLocked(r, app, execInFg);

        }
        ...
       //如果進程不存在,那么先創(chuàng)建目標進程,并把要啟動的service加入到mPendingServices中
       if (app == null && !permissionsReviewRequired) {
            if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
                    "service", r.name, false, isolated, false)) == null) {
                String msg = "Unable to launch app "
                        + r.appInfo.packageName + "/"
                        + r.appInfo.uid + " for service "
                        + r.intent.getIntent() + ": process is bad";
                Slog.w(TAG, msg);
                bringDownServiceLocked(r);
                return msg;
            }
            if (isolated) {
                r.isolatedProc = app;
            }
        }

        if (!mPendingServices.contains(r)) {
            mPendingServices.add(r);
        }

    }

重點看下bringUpServiceLocked函數(shù),如果service所在進程已經(jīng)存在了,那么直接調(diào)用realStartServiceLocked,否則的話,先拉起目標進程,并把目標service存進Pending隊列中。我們看下realStartServiceLocked這個函數(shù)

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

其中app是ProcessRecord對象,成員變量thread是IApplicationThread對象,那根據(jù)Binder原理,我們知道,thread實際上是一個ApplicationThreadProxy的一個實例。我們看下對應的方法

    public final void scheduleCreateService(IBinder token, ServiceInfo info,
            CompatibilityInfo compatInfo, int processState) throws RemoteException {
        Parcel data = Parcel.obtain();
        data.writeInterfaceToken(IApplicationThread.descriptor);
        data.writeStrongBinder(token);
        info.writeToParcel(data, 0);
        compatInfo.writeToParcel(data, 0);
        data.writeInt(processState);
        try {
            mRemote.transact(SCHEDULE_CREATE_SERVICE_TRANSACTION, data, null,
                    IBinder.FLAG_ONEWAY);
        } catch (TransactionTooLargeException e) {
            Log.e("CREATE_SERVICE", "Binder failure starting service; service=" + info);
            throw e;
        }
        data.recycle();
    }

我們看到這個方法實際上通過RPC發(fā)送指令SCHEDULE_CREATE_SERVICE_TRANSACTION,接收者應該是ApplicationThread,由于ApplicationThread的父類是ATN,我們?nèi)ダ锩婵聪孪鄳拇a

 case SCHEDULE_CREATE_SERVICE_TRANSACTION: {
            data.enforceInterface(IApplicationThread.descriptor);
            IBinder token = data.readStrongBinder();
            ServiceInfo info = ServiceInfo.CREATOR.createFromParcel(data);
            CompatibilityInfo compatInfo = CompatibilityInfo.CREATOR.createFromParcel(data);
            int processState = data.readInt();
            scheduleCreateService(token, info, compatInfo, processState);
            return true;
        }

我們看到它調(diào)用了函數(shù) scheduleCreateService,我們看下這個函數(shù)

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

我們看到,ApplicationThread組織了一些參數(shù),交給了ActivityThread去處理了,我們再看下ActivityThread是如何處理的。

 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;

我們把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;
        try {
            java.lang.ClassLoader cl = packageInfo.getClassLoader();
            service = (Service) cl.loadClass(data.info.name).newInstance();
        } 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);

            Application app = packageInfo.makeApplication(false, mInstrumentation);
            service.attach(context, this, data.info.name, data.token, app,
                    ActivityManagerNative.getDefault());
            service.onCreate();
            mServices.put(data.token, service);
            try {
                ActivityManagerNative.getDefault().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);
            }
        }
    }

通過newInstance創(chuàng)建了一個Service對象,有一句代碼比較重要,是

ActivityManagerNative.getDefault().serviceDoneExecuting(
                        data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);

我們知道getDefault返回的是一個AMP對象,它的serviceDoneExecuting方法發(fā)出這樣一條指令

mRemote.transact(SERVICE_DONE_EXECUTING_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY);

對應的AMN中接收到指令后處理方式為

serviceDoneExecuting(token, type, startId, res);

在AMS中我們看下這個方法

 public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
        synchronized(this) {
            if (!(token instanceof ServiceRecord)) {
                Slog.e(TAG, "serviceDoneExecuting: Invalid service token=" + token);
                throw new IllegalArgumentException("Invalid service token");
            }
            mServices.serviceDoneExecutingLocked((ServiceRecord)token, type, startId, res);
        }
    }

實際上就是把這個service加到了相應的隊列里。
以上就是startService的時候,如果service所在進程存在,切是service第一次create的情況。
如果啟動這個service的時候,該service所在進程不存在,那么AMS先創(chuàng)建進程然后創(chuàng)建Application,并且把該service對應的ServiceRecord存到Pending隊列里,application創(chuàng)建后會attach到AMS,此時AMS找到對應的Service后,再走realStartServiceLocked流程。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

  • 啟動Service分為兩種方式,分別是start方式和bind方式。 start方式對應的是Service由Con...
    sososeen09閱讀 2,076評論 0 0
  • 2.1 Activity 2.1.1 Activity的生命周期全面分析 典型情況下的生命周期:在用戶參與的情況下...
    AndroidMaster閱讀 3,273評論 0 8
  • 今天偶然在網(wǎng)上看到一篇新聞,原文如下:8月2日,吉林長春一公交司機因孩子是否應購票與一對帶孩夫婦發(fā)生爭執(zhí),司機持刀...
    夏蟬秋雨閱讀 950評論 0 0
  • 本文理論部份基于Andew Ng的公開課,工程實踐來自 Spark ML。我是個愚鈍的人,純理論學不動。 Line...
    董澤潤閱讀 1,716評論 2 5
  • 最近諸多事情壓在一起,對于反思有些遲鈍了,內(nèi)心里有諸多小煩躁,始終靜不下來,這是對未來的擔憂和恐懼。人啊,有時候走...
    流年般若閱讀 164評論 0 0

友情鏈接更多精彩內(nèi)容