《Android中级工程师》Service启动流程

来源:互联网 发布:android c语言开发 编辑:程序博客网 时间:2024/05/05 22:33

前言

前几天深入研究了Activity的启动流程之后,尝到了研究源码的甜头,趁热打铁,准备把四大组件都研究一遍,今天来研究研究Service的启动流程,由于Service可以通过start和bind方式来启动,所以两部分分开研究。

一、Start方式时序图

这里写图片描述

二、Start方式追踪

1. ContextWrapper.startService()

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

这里的mBase是ContextImpl类型,在上一篇分析Activity的时候我们看到过,ContextImpl完成了Context的大部分逻辑,主要是Activity通过attach方法来建立关联,这里是使用了桥接模式,让ContextWrapper的操作交给ContextImpl去完成。

2. ContextImpl.startService()

    @Override    public ComponentName startService(Intent service) {        //当system进程调用此方法时,打印warn信息        warnIfCallingFromSystemProcess();        return startServiceCommon(service, mUser);    }

3. ContextImpl.startServiceCommon()

    private ComponentName startServiceCommon(Intent service, UserHandle user) {        try {            //检查Intent是否符合要求            validateServiceIntent(service);            //Intent可能跨进程传输,检验安全性            service.prepareToLeaveProcess(this);            //通过AMS的接口拉起服务            ComponentName cn = ActivityManagerNative.getDefault().startService(                mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(                            getContentResolver()), getOpPackageName(), user.getIdentifier());            //权限检查,省略部分代码            return cn;        } catch (RemoteException e) {            throw e.rethrowFromSystemServer();        }    }

这里我们先看一下validateServiceIntent()方法:

private void validateServiceIntent(Intent service) {        //Intent中既没有指定Component,也没有指定Package,即以隐式启动的方式拉起服务        if (service.getComponent() == null && service.getPackage() == null) {            //当版本大于Android L,即Android 5.0时,会抛出异常            if (getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.LOLLIPOP) {                IllegalArgumentException ex = new IllegalArgumentException(                        "Service Intent must be explicit: " + service);                throw ex;            } else {                Log.w(TAG, "Implicit intents with startService are not safe: " + service                        + " " + Debug.getCallers(2, 3));            }        }    }

需要注意的是,在Android5.0之后,已经不建议隐式启动service了,在Android5.0以下采用隐式启动时会提示warning,而在Android5.0以上,则直接报异常。
回到上面的startServiceCommon()方法往下看,我们看到了熟悉的ActivityManagerNative.getDefault(),我们已经知道这个就是ActivityManagerService(AMS)了,那么这里显然又通过了跨进程的方式把启动service的任务交给了AMS。

4. ActivityManagerService.startService()

public ComponentName startService(//省略参数)            throws TransactionTooLargeException {        //当调用者是孤立进程,则抛出异常。        enforceNotIsolatedCaller("startService");        //省略部分代码        synchronized(this) {            final int callingPid = Binder.getCallingPid();//调用者pid            final int callingUid = Binder.getCallingUid();//调用者uid            final long origId = Binder.clearCallingIdentity();            ComponentName res = mServices.startServiceLocked(caller, service,                    resolvedType, callingPid, callingUid, callingPackage, userId);            Binder.restoreCallingIdentity(origId);            return res;        }    }

这里的mServices类型为ActiveServices,在AMS初始化时得到。在早期的安卓版本中并没有这个类,后来重构时抽出这个类专门用来管理Service。

5. ActiveServices.startServiceLocked()

    ComponentName startServiceLocked(//省略参数) throws TransactionTooLargeException {        final boolean callerFg;        if (caller != null) {            //通过AMS得到调用方的进程信息            final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);            //省略部分代码            //判断调用方是否属于前台进程            callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND;        } else {            callerFg = true;        }        //检索待启动的Service        ServiceLookupResult res =            retrieveServiceLocked(service, resolvedType, callingPackage,                    callingPid, callingUid, userId, true, callerFg, false);        //省略部分代码        //如果这个服务在重启列表中,清空对应的信息        if (unscheduleServiceRestartLocked(r, callingUid, false)) {            if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "START SERVICE WHILE RESTART PENDING: " + r);        }        //如果启动的是非前台进程,且同时服务对应的ServiceRecord中没有记录对应进程的信息(即初次使用),        if (!callerFg && r.app == null                //且user已经启动过其它进程                && mAm.mUserController.hasStartedUserState(r.userId)) {            //通过AMS查询Service对应的进程信息            ProcessRecord proc = mAm.getProcessRecordLocked(r.processName, r.appInfo.uid, false);            //若Service对应的进程未启动,或优先级过低,则有可能需要延迟启动服务            if (proc == null || proc.curProcState > ActivityManager.PROCESS_STATE_RECEIVER) {                if (smap.mStartingBackground.size() >= mMaxStartingBackground) {                    //当超出 同一时间允许后续启动的最大服务数,则将该服务加入延迟启动的队列                    Slog.i(TAG_SERVICE, "Delaying start of: " + r);                    smap.mDelayedStartList.add(r);                    r.delayed = true;                    return r.name;                }                if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "Not delaying: " + r);                addToStarting = true;            } else if (proc.curProcState >= ActivityManager.PROCESS_STATE_SERVICE) {                //将新的服务加入到后台启动队列,该队列也包含当前正在运行其他services或者receivers的进程                addToStarting = true;                //省略部分代码        return startServiceInnerLocked(smap, service, r, callerFg, addToStarting);    }

这个方法主要是判断当前Service是否需要延迟启动,如果需要延迟启动,则将ServiceRecord保存到smap中的mDelayedStartList中,并结束本启动流程;否则,调用startServiceInnerLocked函数,进入启动Service的下一个阶段。

6. ActiveServices.startServiceInnerLocked()

ComponentName startServiceInnerLocked(//省略参数) throws TransactionTooLargeException {        ServiceState stracker = r.getTracker();        if (stracker != null) {            //更新ServiceRecord的ServiceState            stracker.setStarted(true, mAm.mProcessStats.getMemFactorLocked(), r.lastActivity);        }        r.callStart = false;        synchronized (r.stats.getBatteryStats()) {            //用于耗电统计,开启运行的状态            r.stats.startRunningLocked();        }        String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);        //上文提到的,后台进程启动的service才有可能将addToStarting置为true        if (r.startRequested && addToStarting) {            boolean first = smap.mStartingBackground.size() == 0;            //将ServiceRecord加入到smap中的mStartingBackground中            smap.mStartingBackground.add(r);            //设置启动Service的超时时间            r.startingBgTimeout = SystemClock.uptimeMillis() + BG_START_TIMEOUT;            if (first) {                //first为true,说明之前mStartingBackground中的Service处理完毕                //调用smap的rescheduleDelayedStarts函数                smap.rescheduleDelayedStarts();            }        } else if (callerFg) {            //若当前Service被后台进程启动过,现在重新被前台进程启动            //则将其从mStartingBackground中移除,并调用rescheduleDelayedStarts函数(后台服务少了一个,故可能可以继续处理等待的延迟服务)            //若mDelayedStartList存在该服务的记录,移除对应的信息            smap.ensureNotStartingBackground(r);        }        return r.name;    }

7. ActiveServices.bringUpServiceLocked()

    private String bringUpServiceLocked(//省略参数) throws TransactionTooLargeException {        //Service已经启动        if (r.app != null && r.app.thread != null) {            sendServiceArgsLocked(r, execInFg, false);            return null;        }        //等待延迟重启的过程,则直接返回        if (!whileRestarting && r.restartDelay > 0) {            return null;        }        //启动service前,把service从重启服务队列中移除        if (mRestartingServices.remove(r)) {            r.resetRestartCounter();            clearRestartingIfNeededLocked(r);        }        //service正在启动,将delayed设置为false        if (r.delayed) {            getServiceMap(r.userId).mDelayedStartList.remove(r);            r.delayed = false;        }        //确保拥有该服务的user已经启动,否则停止;        if (!mAm.mUserController.hasStartedUserState(r.userId)) {            String msg = "";            Slog.w(TAG, msg);            bringDownServiceLocked(r);            return msg;        }        //Service正在启动,package不能被停止.        try {            AppGlobals.getPackageManager().setPackageStoppedState(                    r.packageName, false, r.userId);        } catch (RemoteException e) {        } catch (IllegalArgumentException e) {        }        if (!isolated) {            //取出ServiceRecord对应的进程信息            app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);            //如果对应进程已经启动            if (app != null && app.thread != null) {                try {                    app.addPackage(r.appInfo.packageName, r.appInfo.versionCode, mAm.mProcessStats);                    //真正启动服务                    realStartServiceLocked(r, app, execInFg);                    return null;            }        } else {        //对于“孤立”的Service而言,其ServiceRecord中记录着它将运行的进程        //此处,若isolatedProc为null,则表明需要启动新的进程; 不为null,说明正在等待进程的启动            app = r.isolatedProc;        }        //对于进程没有启动的情况        if (app == null && !permissionsReviewRequired) {        //启动服务对应的进程            if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,                    "service", r.name, false, isolated, false)) == null) {                String msg = "";                Slog.w(TAG, msg);                //进程启动失败,将停止服务                bringDownServiceLocked(r);                return msg;            }        }        //mPendingServices保存待启动服务,当进程启动后,会重新启动该服务        if (!mPendingServices.contains(r)) {            mPendingServices.add(r);        }        //服务还未完成启动,就收到结束请求时,会直接停止该服务        if (r.delayedStop) {            // Oh and hey we've already been asked to stop!            r.delayedStop = false;            if (r.startRequested) {                if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE,                        "Applying delayed stop (in bring up): " + r);                stopServiceLocked(r);            }        }        return null;    }

整个方法看似比较复杂,但是逻辑还是比较清晰的,主要是处理三种情况:
1、service已经启动过,则调用sendServiceArgsLocked函数,将新的待处理信息发送给service;
2、service未启动过,但对应的进程已启动,那么调用realStartServiceLocked函数,启动服务即可;
3、service对应的进程并没有启动,那么先启动进程
对于第1种,当第2种场景中的服务启动后,仍将利用sendServiceArgsLocked函数中的流程,将Intent消息发往Service处理;
对于第2种,需要我们跟进;
对于第3种,当进程启动后,经过层层调用,最终会调用AMS的attachApplicationLocked(),将启动等待的service。

8. ActiveServices.realStartServiceLocked()

private final void realStartServiceLocked(//省略参数) throws RemoteException {        //省略部分代码        //对服务的状态进行记录        bumpServiceExecutingLocked(r, execInFg, "create");        //更新进程对应的优先级信息        mAm.updateLruProcessLocked(app, false, null);        mAm.updateOomAdjLocked();        boolean created = false;        try {            //省略部分代码            //更改进程状态为PROCESS_STATE_SERVICE            app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);            app.thread.scheduleCreateService(r, r.serviceInfo,                    mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),                    app.repProcState);            r.postNotification();            created = true;        } catch (DeadObjectException e) {            Slog.w(TAG, "Application dead when creating service " + r);            //失败则kill进程            mAm.appDiedLocked(app);            throw e;        } finally {            //服务创建失败            if (!created) {                //更新相关的统计信息                final boolean inDestroying = mDestroyingServices.contains(r);                serviceDoneExecutingLocked(r, inDestroying, inDestroying);                // Cleanup.                if (newService) {                    app.services.remove(r);                    r.app = null;                }                //将根据服务的重启次数,决定是否继续重启,以及重启的时间间隔                if (!inDestroying) {                    scheduleServiceRestartLocked(r, false);                }            }        }        //Service被绑定过,才会调用onBind函数        requestServiceBindingsLocked(r, execInFg);        //如果客户端Bind Service成功,按需更新服务端进程优先级        updateServiceClientActivitiesLocked(app, null, true);        //调用到sendServiceArgsLocked发送参数        sendServiceArgsLocked(r, execInFg, true);        //如果Service是延迟启动的,那么此时可以将其从mDelayedStartList移除        if (r.delayed) {            if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "REM FR DELAY LIST (new proc): " + r);            getServiceMap(r.userId).mDelayedStartList.remove(r);            r.delayed = false;        }        //若Service被要求停止,那么结束服务        if (r.delayedStop) {            //省略部分代码        }    }

realStartServiceLocked函数最主要的工作是:
1、利用bumpServiceExecutingLocked函数,记录ServiceRecord的执行状态,主要用于将进程的ProcessRecord信息,与ServiceRecord关联起来。同时,更新ServiceRecord中的一些信息,并设置命令超时的时间。;
2、利用scheduleCreateService函数,进程间调用,通过ApplicationThread创建出Service对象;
3、利用sendServiceArgsLocked函数,将Intent中的信息递交给Service处理。

9. ApplicationThread.scheduleCreateService()

public final void scheduleCreateService(//省略参数) {            updateProcessState(processState, false);            CreateServiceData s = new CreateServiceData();            s.token = token;            s.info = info;            s.compatInfo = compatInfo;            sendMessage(H.CREATE_SERVICE, s);        }

果然也是通过发送消息给H,来让handleCreateService()来完成。

10. ActivityThread.handleCreateService()

private void handleCreateService(CreateServiceData data) {        //当应用处于后台即将进行GC,而此时被调回到活动状态,则跳过本次gc        unscheduleGcIdler();        //得到Service对应的LoadedApk信息        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 {            //创建ContextImpl对象            ContextImpl context = ContextImpl.createAppContext(this, packageInfo);            context.setOuterContext(service);            //创建Application对象               Application app = packageInfo.makeApplication(false, mInstrumentation);            //建立ContextImpl和Service的联系            service.attach(context, this, data.info.name, data.token, app,                    ActivityManagerNative.getDefault());            //调用Service的onCreate函数            service.onCreate();            //将service对象存储到ActivityThread的一个列表中            mServices.put(data.token, service);            try {                //通知AMS service启动成功,进行取消超时消息等操作                ActivityManagerNative.getDefault().serviceDoneExecuting(                        data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);                //省略部分代码    }

走到这里service算是终于创建出来了,我们再回到8中的第3步看看,onCreate之后执行的方法。

11. ActiveServices.sendServiceArgsLocked()

private final void sendServiceArgsLocked(//省略参数) throws TransactionTooLargeException {        //省略部分代码        r.app.thread.scheduleServiceArgs(r, si.taskRemoved, si.id, flags, si.intent);        //省略部分代码    }

12. ActiveServices.scheduleServiceArgs()

public final void scheduleServiceArgs(//省略参数) {            ServiceArgsData s = new ServiceArgsData();            s.token = token;            s.taskRemoved = taskRemoved;            s.startId = startId;            s.flags = flags;            s.args = args;            sendMessage(H.SERVICE_ARGS, s);        }

13. ActiveServices.handleServiceArgs()

private void handleServiceArgs(ServiceArgsData data) {        Service s = mServices.get(data.token);        if (s != null) {            try {                int res;                if (!data.taskRemoved) {                    //调用Service的onStartCommand函数,处理Intent携带的内容                    res = s.onStartCommand(data.args, data.flags, data.startId);                } else {                    s.onTaskRemoved(data.args);                    res = Service.START_TASK_REMOVED_COMPLETE;                }                QueuedWork.waitToFinish();                try {                     //再次调用AMS的serviceDoneExecuting函数,通知AMS消息处理完毕                     ActivityManagerNative.getDefault().serviceDoneExecuting(                            data.token, SERVICE_DONE_EXECUTING_START, data.startId, res);                }                //省略部分代码        }    }

走到这里我们看到,service的onStartCommand方法也被调用了,service就已经start了。而我们知道onStartCommand()是有返回值的,它的返回值就在AMS的serviceDoneExecuting()方法中被处理。

14. ActivityManagerService.serviceDoneExecuting()

void serviceDoneExecutingLocked(ServiceRecord r, int type, int startId, int res) {        boolean inDestroying = mDestroyingServices.contains(r);        if (r != null) {            if (type == ActivityThread.SERVICE_DONE_EXECUTING_START) {                r.callStart = true;                switch (res) {                    case Service.START_STICKY_COMPATIBILITY:                    case Service.START_STICKY: {                        r.findDeliveredStart(startId, true);                        r.stopIfKilled = false;                        break;                    }                    case Service.START_NOT_STICKY: {                        r.findDeliveredStart(startId, true);                        if (r.getLastStartId() == startId) {                            r.stopIfKilled = true;                        }                        break;                    }                    case Service.START_REDELIVER_INTENT: {                        ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);                        if (si != null) {                            si.deliveryCount = 0;                            si.doneExecutingCount++;                            r.stopIfKilled = true;                        }                        break;                    }                    case Service.START_TASK_REMOVED_COMPLETE: {                        r.findDeliveredStart(startId, true);                        break;                    }                    default:                        throw new IllegalArgumentException(                                "Unknown service start result: " + res);                }                if (res == Service.START_STICKY_COMPATIBILITY) {                    r.callStart = false;                }            } else if (type == ActivityThread.SERVICE_DONE_EXECUTING_STOP) {                if (!inDestroying) {                    if (r.app != null) {                    }                } else if (r.executeNesting != 1) {                    r.executeNesting = 1;                }            }            final long origId = Binder.clearCallingIdentity();            serviceDoneExecutingLocked(r, inDestroying, inDestroying);            Binder.restoreCallingIdentity(origId);        } else {        }    }

基本上,startService的流程到此我们就走完了。

三、Start方式总结

还是借用一下http://gityuan.com/2016/03/06/start-service/这位仁兄的。
这里写图片描述
启动流程:

  1. Process A进程采用Binder IPC向system_server进程发起startService请求;
  2. system_server进程接收到请求后,向zygote进程发送创建进程的请求;
  3. zygote进程fork出新的子进程Remote Service进程;
  4. Remote Service进程,通过Binder IPC向sytem_server进程发起attachApplication请求;
  5. system_server进程在收到请求后,进行一系列准备工作后,再通过binder IPC向remote Service进程发送scheduleCreateService请求;
  6. Remote Service进程的binder线程在收到请求后,通过handler向主线程发送CREATE_SERVICE消息;
  7. 主线程在收到Message后,通过发射机制创建目标Service,并回调Service.onCreate()方法。

四、Bind方式时序图

这里写图片描述

五、Bind方式追踪

1. ContextWrapper.bindService()

    public boolean bindService(Intent service, ServiceConnection conn,            int flags) {        return mBase.bindService(service, conn, flags);    }

Bind方式仍然是从ContextWrapper开始的,这里面很多和Start方式相似的就不多提了。

2. ContextImpl.bindService()

    public boolean bindService(Intent service, ServiceConnection conn,            int flags) {        warnIfCallingFromSystemProcess();        return bindServiceCommon(service, conn, flags, mMainThread.getHandler(),                Process.myUserHandle());    }

3. ContextImpl.bindServiceCommon()

private boolean bindServiceCommon(//省略参数) {        IServiceConnection sd;        if (mPackageInfo != null) {            //得到ServiceConnetion的Binder通信端,内部静态类InnerConnection            sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);        } else {            throw new RuntimeException("Not supported in system context");        }        //检查Intent是否符合要求        validateServiceIntent(service);        try {            //省略部分代码            service.prepareToLeaveProcess(this);            //ServiceConnection对应的Binder通信服务端将注册到AMS            int res = ActivityManagerNative.getDefault().bindService(                mMainThread.getApplicationThread(), getActivityToken(), service,                service.resolveTypeIfNeeded(getContentResolver()),                sd, flags, getOpPackageName(), user.getIdentifier());        }    }

这里需要注意这个getServiceDispatcher()方法,它会将客户端的ServiceConnection对象转化为ServiceDispatcher.InnerConnection对象,原因是InnerConnection对象在跨进程调用中充当Binder,供AMS回调。我们来看看getServiceDispatcher()方法:

public final IServiceConnection getServiceDispatcher(ServiceConnection c,            Context context, Handler handler, int flags) {        synchronized (mServices) {            LoadedApk.ServiceDispatcher sd = null;            ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);            if (map != null) {                sd = map.get(c);            }            if (sd == null) {                //初始时,需要创建ServiceConnection对应的ServiceDispatcher                sd = new ServiceDispatcher(c, context, handler, flags);                if (map == null) {                    map = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>();                    mServices.put(context, map);                }                //然后将ServiceDispatcher加入到mServices中                map.put(c, sd);            } else {                sd.validate(context, handler);            }            //返回的内部类的对象InnerConnection            return sd.getIServiceConnection();        }    }

4. ActivityManagerService.bindService()

    public int bindService(//省略参数) throws TransactionTooLargeException {        enforceNotIsolatedCaller("bindService");    //参数有效性检查        synchronized(this) {            return mServices.bindServiceLocked(caller, token, service,                    resolvedType, connection, flags, callingPackage, userId);        }    }

5. ActiveServices.bindServiceLocked()

int bindServiceLocked(//参数检查) throws TransactionTooLargeException {        //得到客户端进程信息        final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);        //如果是一个Activity绑定Service, 那么该Activity必须是有效的        ActivityRecord activity = null;        if (token != null) {            //判断Activity是否存在于Task中            activity = ActivityRecord.isInStackLocked(token);            if (activity == null) {                return 0;            }        }        //一些特殊标志位的处理        //判断调用方是否来自前台        final boolean callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND;        final boolean isBindExternal = (flags & Context.BIND_EXTERNAL_SERVICE) != 0;        //检索待启动的服务        ServiceLookupResult res =            retrieveServiceLocked(service, resolvedType, callingPackage, Binder.getCallingPid(),                    Binder.getCallingUid(), userId, true, callerFg, isBindExternal);        //权限检查        try {            //从待重启服务中,移除当前的Service            if (unscheduleServiceRestartLocked(s, callerApp.info.uid, false)) {                if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "BIND SERVICE WHILE RESTART PENDING: "                        + s);            }            if ((flags&Context.BIND_AUTO_CREATE) != 0) {                s.lastActivity = SystemClock.uptimeMillis();                //Service初次被绑定时,更改其状态信息                if (!s.hasAutoCreateConnections()) {                //省略部分代码                }            }            //将绑定的发起方和接收方关联起来,同时保存在AMS定义的数据结构中            mAm.startAssociationLocked(callerApp.uid, callerApp.processName, callerApp.curProcState,                    s.appInfo.uid, s.name, s.processName);            //根据Intent信息,检索出对应的IntentBindRecord(记录Intent,能启动哪个Service)            //进一步从IntentBindRecord中检索出AppBindRecord (记录进程,与哪个Service绑定)            //初次绑定时,将分别创建出IntentBindRecord和AppBindRecord            AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);            //构造注册connection对应的ConnectionRecord            ConnectionRecord c = new ConnectionRecord(b, activity,                    connection, flags, clientLabel, clientIntent);            //以下都是更新ServiceRecord中的数据结构            IBinder binder = connection.asBinder();            //省略部分代码            //如果Service所在进程之前已经启动过            if (s.app != null) {                //更新Service对应进程的优先级                updateServiceClientActivitiesLocked(s.app, c, true);            }            //ActiveServices也将按照ServiceConnection的Binder保存ConnectionRecord            clist = mServiceConnections.get(binder);            //注意到同一个Binder可以对应多个ConnectionRecord            //这是因为,客户端可以用同一个ServiceConnection绑定多个Service            //每次绑定时,都会生成对应的ConnectionRecord,但这些ConnectionRecord共用相同的Binder            if (clist == null) {                clist = new ArrayList<ConnectionRecord>();                mServiceConnections.put(binder, clist);            }            clist.add(c);            if ((flags&Context.BIND_AUTO_CREATE) != 0) {                s.lastActivity = SystemClock.uptimeMillis();                //如同Unbounded Service,仍然调用bringUpServiceLocked函数启动Service                if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,                        permissionsReviewRequired) != null) {                    return 0;                }            }            //省略部分代码    }

这个方法主要完成的工作是:

  1. 通过retrieveServiceLocked(),根据用户传递进来Intent来检索相对应的服务;
  2. 通过retrieveAppBindingLocked().创建AppBindRecord对象记录着当前ServiceRecord, intent以及发起方的进程信息;
  3. 通过bringUpServiceLocked()拉起目标服务。

6. ActiveServices.bringUpServiceLocked()

private String bringUpServiceLocked(//省略参数) throws TransactionTooLargeException {        app.addPackage(r.appInfo.packageName, r.appInfo.versionCode, mAm.mProcessStats);        //这个流程就和Start方式一样,就不分析了        realStartServiceLocked(r, app, execInFg);}

7. ActiveServices.realStartServiceLocked()

    private final void realStartServiceLocked(//省略参数) throws RemoteException {        //省略部分代码        mAm.notifyPackageUse(r.serviceInfo.packageName,                             PackageManager.NOTIFY_PACKAGE_USE_SERVICE);        app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);        //服务进入onCreate(),这里下去的流程和Start方式一样,就不分析了        app.thread.scheduleCreateService(r, r.serviceInfo,                mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),                app.repProcState);        r.postNotification();        created = true;    //和Start方式不同之处        requestServiceBindingsLocked(r, execInFg);        //省略部分代码    }

8. ActiveServices.requestServiceBindingsLocked()

private final boolean requestServiceBindingLocked(//省略参数) throws TransactionTooLargeException {        //IntentBindRecord被处理过后,requested将被置为true        //因此只有第一次处理的请求,和重新绑定时,才会处理    //这就是,客户端第一次绑定Service时,onBind函数才会被回调的原因        if ((!i.requested || rebind) && i.apps.size() > 0) {            try {                bumpServiceExecutingLocked(r, execInFg, "bind");                r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);                //服务进入onBind()                r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,                        r.app.repProcState);        }        return true;    }

9. ActivityThread.scheduleBindService()

public final void scheduleBindService(IBinder token, Intent intent,        boolean rebind, int processState) {    sendMessage(H.BIND_SERVICE, s);}

10. ActivityThread.handleBindService()

private void handleBindService(BindServiceData data) {        Service s = mServices.get(data.token);        if (DEBUG_SERVICE)            Slog.v(TAG, "handleBindService s=" + s + " rebind=" + data.rebind);        if (s != null) {            try {                data.intent.setExtrasClassLoader(s.getClassLoader());                data.intent.prepareToEnterProcess();                try {                    if (!data.rebind) {                        //调用Service的onBind函数                        IBinder binder = s.onBind(data.intent);                        //调用AMS的publishService函数,发布服务                        ActivityManagerNative.getDefault().publishService(                                data.token, data.intent, binder);                    } else {                        s.onRebind(data.intent);                        ActivityManagerNative.getDefault().serviceDoneExecuting(                                data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);                    }                    ensureJitEnabled();                } catch (RemoteException ex) {                    throw ex.rethrowFromSystemServer();                }            } catch (Exception e) {            }        }    }

onBind()方法调用之后,会返回一个Binder对象给客户端使用,此时Service就处于绑定状态了,但是onBind方法是Service的方法,这个时候客户端并不知道已经成功连接了Service了,所以还必须调用客户端的ServiceConnection中的onServiceConnected(),这个过程由ActivityManagerNative.getDefault().publishService()来完成。

11. ActivityManagerService.publishService()

    public void publishService(IBinder token, Intent intent, IBinder service) {        synchronized(this) {            if (!(token instanceof ServiceRecord)) {                throw new IllegalArgumentException("Invalid service token");            }            mServices.publishServiceLocked((ServiceRecord)token, intent, service);        }    }

12. ActiveServices.publishServiceLocked()

void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {     try {            c.conn.connected(r.name, service);        } catch (Exception e) {            Slog.w(TAG, "Failure sending service " + r.name +                  " to connection " + c.conn.asBinder() +                  " (in " + c.binding.client.processName + ")", e);        }    }

这里c的类型是ConnectionRecord,c.conn的类型是ServiceDispatcher.InnerConnection,接下来就看看InnerConnection的connected()方法。

13. InnerConnection.connected()

public void connected(ComponentName name, IBinder service) throws RemoteException {                LoadedApk.ServiceDispatcher sd = mDispatcher.get();                if (sd != null) {                    sd.connected(name, service);                }            }

14. ServiceDispatcher.connected()

public void connected(ComponentName name, IBinder service) {    if (mActivityThread != null) {        mActivityThread.post(new RunConnection(name, service, 0));    } else {        doConnected(name, service);    }}

15 RunConnection

private final class RunConnection implements Runnable {    RunConnection(ComponentName name, IBinder service, int command) {        mName = name;        mService = service;        mCommand = command;    }    public void run() {        if (mCommand == 0) {            doConnected(mName, mService);        } else if (mCommand == 1) {            doDeath(mName, mService);        }    }    final ComponentName mName;    final IBinder mService;    final int mCommand;}

16. ServiceDispatcher.doConnected()

public void doConnected(ComponentName name, IBinder service) {    //省略部分代码    //如果存在旧的连接,回调ServiceConnection的onServiceDisconnected方法    if (old != null) {        mConnection.onServiceDisconnected(name);    }    //如果是新的连接,就回调ServiceConnection的onServiceConnected方法    if (service != null) {        mConnection.onServiceConnected(name, service);    }}

六、Bind方式总结

  1. 首先Client进程通过getServiceDispatcher获取匿名Binder服务端,即LoadedApk.ServiceDispatcher.InnerConnection;
  2. 通过bindService方法跨进程调用进入system_server进程;
  3. 通过scheduleCreateService和scheduleBindService方法, 远程调用到target进程;
  4. target进程:依次执行onCreate()和onBind()方法,将onBind()方法的返回值IBinder(作为target进程的binder服务端)通过publishService传递回system_server进程;
  5. system_server进程利用IServiceConnection代理对象向Client进程发起connected()调用, 并把target进程的onBind返回Binder对象的代理端传递到Client进程;
  6. Client进程回调到onServiceConnection()方法, 该方法的第二个参数便是target进程的binder代理端. 到此便成功地拿到了target进程的代理, 可以畅通无阻地进行交互。
原创粉丝点击