从AILD与bindService谈Binder进程间通信原理(下)

从AILD与bindService谈Binder进程间通信原理(下)


上文回顾

从AILD与bindService谈Binder进程间通信原理(上)

上一篇文章主要讲述了,在Client进程向AMS所在进程发起bindService操作的服务请求的过程中,Binder是如何跨进程通信的。实际上,Java层的Binder进程间通信都是同样的流程。主要有以下2点:
1,A进程持有B进程的IBinder对象(BinderProxy对象,对应原生层的BpBinder对象),通过这个Binder代理A进程即可与B进程进程间通信。
2,Binder代理的获取有两种方式,一种是通过查询ServiceManager获取,一种是通过一个中间进程(例如AMS进程)互相交换各自binder代理(实质上ServiceManager也是一个中间进程,不过他把服务进程的binder代理给保存下来)。

正文

接下来,我们将分析剩余的bindService所涉及的操作步骤:

这里写图片描述

上篇文章讲述到在第22-27步中, 在AMS的Binder对象ActivityManagerNative中解包Parcel,获取Client进程传递过来的参数,主要包括Client进程的2个BinderProxy,Client创建的用于bindeService操作的ServiceConnection对象的BinderProxy,以及Intent对象。最后调用ActivityManagerService类中的bindeService方法。

28,AMS会执行自身的成员变量mServices的bindServiceLocked方法。mServices是一个ActiveServices对象。ActiveServices才是AMS中真正管理Service的实现类。

  int bindServiceLocked(IApplicationThread caller, IBinder token,
            Intent service, String resolvedType,
            IServiceConnection connection, int flags, int userId) {

        …………………………………………………………………………………………………………

        ServiceLookupResult res =
            retrieveServiceLocked(service, resolvedType,
                    Binder.getCallingPid(), Binder.getCallingUid(), userId, true, callerFg);


        ServiceRecord s = res.record;

        …………………………………………………………………………………………………………

        try {

            …………………………………………………………………………………………………………

            AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
            ConnectionRecord c = new ConnectionRecord(b, activity,
                    connection, flags, clientLabel, clientIntent);//yyt

            IBinder binder = connection.asBinder();
            ArrayList<ConnectionRecord> clist = s.connections.get(binder);
            if (clist == null) {
                clist = new ArrayList<ConnectionRecord>();
                s.connections.put(binder, clist);
            }
            clist.add(c);//yyt
            b.connections.add(c);
            if (activity != null) {
                if (activity.connections == null) {
                    activity.connections = new HashSet<ConnectionRecord>();
                }
                activity.connections.add(c);
            }
            b.client.connections.add(c);
            if ((c.flags&Context.BIND_ABOVE_CLIENT) != 0) {
                b.client.hasAboveClient = true;
            }
            if (s.app != null) {
                updateServiceClientActivitiesLocked(s.app, c, true);
            }
            clist = mServiceConnections.get(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();
                if (bringUpServiceLocked(s, service.getFlags(), callerFg, false) != null) {
                    return 0;
                }
            }
            ………………………………………………………………………………………………………………………………………………………………

        } finally {
            Binder.restoreCallingIdentity(origId);
        }

        return 1;
    }

在bindServiceLocked方法中,首先调用retrieveServiceLocked方法检索将要启动的Service所在,是否是在本应用中的Service,通过Service的name和filter来进行检索,找到目标Service后,查看权限(permission是否满足),如果该Service是第一次被检索,则会创建一个新的ServiceRecord对象保存这个Service的信息,这个ServiceRecord会在bringUpServiceLocked方法中被保存到一个mPendingServices数组集合中。

然后会把刚才的ServiceConnection对象封装成一个ConnectionRecord对象,并存入ServiceRecord的相关成员列表中。接着再调用bringUpServiceLocked方法

29,在bringUpServiceLocked方法中,判断目标Service所在的app进程是否已经启动,如果已经启动则直接调用realStartServiceLocked方法启动Service;如果app进程没启动,即为null,则调用startProcessLocked启动目标Service所在的目标app进程。


    private final String bringUpServiceLocked(ServiceRecord r,
            int intentFlags, boolean execInFg, boolean whileRestarting) {

    …………………………………………………………………………………………

        final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
        final String procName = r.processName;
        ProcessRecord app;

        if (!isolated) {
            app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
            if (DEBUG_MU) Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid
                        + " app=" + app);
            if (app != null && app.thread != null) {
                try {
                    app.addPackage(r.appInfo.packageName, r.appInfo.versionCode, mAm.mProcessStats);
                    realStartServiceLocked(r, app, execInFg);
                    return null;
                } catch (RemoteException e) {
                    Slog.w(TAG, "Exception when starting service " + r.shortName, e);
                }

                // If a dead object exception was thrown -- fall through to
                
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值