bindService过程

       有了前面一篇《Service启动过程》,bindService应该很好分析了。但不用看代码也能估计出来,AMS需要缓存BinderProxy并转发给Client,跟Provider一样。
       如果是进程内,ActivityThread中直接返回的是ContentProviderNative对象,即进程内直接调用ContentProvider函数而不是RPC。如果是进程外,那么ActiviyThread会找AMS要ContentProviderHolder,最终得到的ContentProviderProxy。
       对于进程内和进程外,bindService的过程也会一样吗?我们估计,进程内得到的是一个Binder,而进程外得到的是一个BInderProxy。

1747    @Override
1748    public boolean bindService(Intent service, ServiceConnection conn,
1749            int flags) {
1751        return bindServiceCommon(service, conn, flags, Process.myUserHandle());
1752    }复制代码

1761    private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,
1762            UserHandle user) {
1763        IServiceConnection sd;

1767        if (mPackageInfo != null) {
1768            sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(),
1769                    mMainThread.getHandler(), flags);
1770        } else {
1772        }
1774        try {
1775            IBinder token = getActivityToken();
1782            int res = ActivityManagerNative.getDefault().bindService(
1783                mMainThread.getApplicationThread(), getActivityToken(),
1784                service, service.resolveTypeIfNeeded(getContentResolver()),
1785                sd, flags, user.getIdentifier());
1790            return res != 0;
1791        } catch (RemoteException e) {
1792            return false;
1793        }
1794    }复制代码
关注一下参数有三个:第一个是Intent,第二个是连接监听,第三个是bindService的flags。
首先是构造了一个IServiceConnection,其次调用了AMS的startService。

957    public final IServiceConnection getServiceDispatcher(ServiceConnection c,
958            Context context, Handler handler, int flags) {
959        synchronized (mServices) {
960            LoadedApk.ServiceDispatcher sd = null;
961  ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map=mServices.get(context)
965            if (sd == null) {
966                sd = new ServiceDispatcher(c, context, handler, flags);
967                if (map == null) {
968                    map = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>();
969                    mServices.put(context, map);
970                }
971                map.put(c, sd);
972            } 
975            return sd.getIServiceConnection();
976        }
977    }复制代码
原来ServiceConnection就是一个纯粹的接口,要为其加一层皮用于跨进程通信,通信用的倒不是ServiceDispatcher而是其中的通信代表 IServiceConnection. Stub。ServiceDispatcher画个uml图记忆一下,服务连接和断开消息的发布者。
mServices的key是Context这说明一个Context只能bindService一次(同时)。返回值是ServiceDispatcher的内部类InnerConnection extends IServiceConnection.Stub。

还有个释放ServiceConnection的函数也看看:

979    public final IServiceConnection forgetServiceDispatcher(Context context,
980            ServiceConnection c) {
981        synchronized (mServices) {
982            ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map
983                    = mServices.get(context);
984            LoadedApk.ServiceDispatcher sd = null;
985            if (map != null) {
986                sd = map.get(c);
987                if (sd != null) {
988                    map.remove(c);
989                    sd.doForget();
990                    if (map.size() == 0) {
991                        mServices.remove(context);
992                    }
993                    if ((sd.getFlags()&Context.BIND_DEBUG_UNBIND) != 0) {
994                        ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> holder
995                                = mUnboundServices.get(context);
996                        if (holder == null) {
997                            holder = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>();
998                            mUnboundServices.put(context, holder);
999                        }
1002                        ex.fillInStackTrace();
1003                        sd.setUnbindLocation(ex);
1004                        holder.put(c, sd);
1005                    }
1006                    return sd.getIServiceConnection();
1007                }
1008            }
1009            ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> holder
1010                    = mUnboundServices.get(context);
1011            if (holder != null) {
1012                sd = holder.get(c);
1013                if (sd != null) {
1014                    RuntimeException ex = sd.getUnbindLocation();
1018                }
1019            }
1026        }
1027    }复制代码
------------------------------------------------------------------------------------------------
开始要执行AMS.bindService了

14907    public int bindService(IApplicationThread caller, IBinder token,
14908            Intent service, String resolvedType,
14909            IServiceConnection connection, int flags, int userId) {
14916
14917        synchronized(this) {
14918            return mServices.bindServiceLocked(caller, token, service, resolvedType,
14919                    connection, flags, userId);
14920        }
14921    }复制代码

671    int bindServiceLocked(IApplicationThread caller, IBinder token,
672            Intent service, String resolvedType,
673            IServiceConnection connection, int flags, int userId) {
677        final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
685        ActivityRecord activity = null;
686        if (token != null) {
687            activity = ActivityRecord.isInStackLocked(token);
688            if (activity == null) {
690                return 0;
691            }
692        }
720
721        final boolean callerFg = callerApp.setSchedGroup != Process.THREAD_GROUP_BG_NONINTERACTIVE;
722
723        ServiceLookupResult res =
724            retrieveServiceLocked(service, resolvedType,
725                    Binder.getCallingPid(), Binder.getCallingUid(), userId, true, callerFg);
732        ServiceRecord s = res.record;
733
734        final long origId = Binder.clearCallingIdentity();
735
736        try {
754            AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);
755            ConnectionRecord c = new ConnectionRecord(b, activity,
756                    connection, flags, clientLabel, clientIntent);
757
758            IBinder binder = connection.asBinder();
759            ArrayList<ConnectionRecord> clist = s.connections.get(binder);
760            if (clist == null) {
761                clist = new ArrayList<ConnectionRecord>();
762                s.connections.put(binder, clist);
763            }
779            clist = mServiceConnections.get(binder);
780            if (clist == null) {
781                clist = new ArrayList<ConnectionRecord>();
782                mServiceConnections.put(binder, clist);
783            }
784            clist.add(c);
785
786            if ((flags&Context.BIND_AUTO_CREATE) != 0) {
787                s.lastActivity = SystemClock.uptimeMillis();
788                if (bringUpServiceLocked(s, service.getFlags(), callerFg, false) != null) {
789                    return 0;
790                }
791            }
807            // 这里开始不会走的,因为IBinder还没有发布,即没有缓存到AMS中
808            if (s.app != null && b.intent.received) {
811                try {
812                    c.conn.connected(s.name, b.intent.binder);
813                } catch (Exception e) {
817                }
818
822                if (b.intent.apps.size() == 1 && b.intent.doRebind) {
823                    requestServiceBindingLocked(s, b.intent, callerFg, true);
824                }
825            } else if (!b.intent.requested) {
826                requestServiceBindingLocked(s, b.intent, callerFg, false);
827            }
828
829            getServiceMap(s.userId).ensureNotStartingBackground(s);
830
831        } finally {
833        }
834
835        return 1;
836    }复制代码
取得IBinder放到了b.intent.binder中,即放到了AppBindRecord中,而AppBinderRecord绑定了Intent信息,且存放到了ServiceRecord.bindings中。从c.conn.connected来看最终调用了 IServiceConnection.connected,这个是在Client应用层代码中的,所以基本可以断定bringUpServiceLocked这一步坑定准备好了AppBindRecord. IntentBindRecord.binder
------------------------------------------------------------------------------------------------
看看如何取到IBinder的

1430    private final void realStartServiceLocked(ServiceRecord r,
1431            ProcessRecord app, boolean execInFg) throws RemoteException {
1440
1446        boolean created = false;
1447        try {
1448            String nameTerm;
1449            int lastPeriod = r.shortName.lastIndexOf('.');
1460            app.thread.scheduleCreateService(r, r.serviceInfo,
1461                    mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
1462                    app.repProcState);
1463            r.postNotification();
1464            created = true;
1465        } catch (DeadObjectException e) {
1467            mAm.appDiedLocked(app);
1468        } finally {
1469            if (!created) {
1470                app.services.remove(r);
1471                r.app = null;
1472                scheduleServiceRestartLocked(r, false);
1473                return;
1474            }
1475        }
1477        requestServiceBindingsLocked(r, execInFg);
1489        sendServiceArgsLocked(r, execInFg, true);
1505    }复制代码


1121    private final boolean requestServiceBindingLocked(ServiceRecord r,
1122            IntentBindRecord i, boolean execInFg, boolean rebind) {
1127        if ((!i.requested || rebind) && i.apps.size() > 0) {
1128            try {
1130                r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
1131                r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
1132                        r.app.repProcState);
1138            } catch (RemoteException e) {
1140                return false;
1141            }
1142        }
1143        return true;
1144    }复制代码


2748    private void handleBindService(BindServiceData data) {
2749        Service s = mServices.get(data.token);
2752        if (s != null) {
2753            try {
2756                try {
2757                    if (!data.rebind) {
2758                        IBinder binder = s.onBind(data.intent);
2759                        ActivityManagerNative.getDefault().publishService(
2760                                data.token, data.intent, binder);
2761                    } else {
2762                        s.onRebind(data.intent);
2765                    }
2767                } catch (RemoteException ex) {
2768                }
2769            } catch (Exception e) {
2775            }
2776        }
2777    }复制代码

14929    public void publishService(IBinder token, Intent intent, IBinder service) {
14934
14935        synchronized(this) {
14939            mServices.publishServiceLocked((ServiceRecord)token, intent, service);
14940        }
14941    }复制代码

838    void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
839        final long origId = Binder.clearCallingIdentity();
840        try {
843            if (r != null) {
844                Intent.FilterComparison filter
845                        = new Intent.FilterComparison(intent);
846                IntentBindRecord b = r.bindings.get(filter);
847                if (b != null && !b.received) {
848                    b.binder = service;
849                    b.requested = true;849                     // 这里下次不需要再找Client要IBinder了
850                    b.received = true;
851                    for (int conni=r.connections.size()-1; conni>=0; conni--) {
852                        ArrayList<ConnectionRecord> clist = r.connections.valueAt(conni);
853                        for (int i=0; i<clist.size(); i++) {
854                            ConnectionRecord c = clist.get(i);
855                            if (!filter.equals(c.binding.intent.intent)) {
862                                continue;
863                            }
865                            try {
866                                c.conn.connected(r.name, service);
867                            } catch (Exception e) {
871                            }
872                        }
873                    }
874                }
877            }
878        } finally {
880        }
881    }复制代码
------------------------------------------------------------------------------------------------
从代码来看,不管怎样bindService都会穿越到AMS中,AMS中记录了BindProxy。当在进程内bindService时,AMS将BindProxy传递到进程内部,会转化为Binder,最终就进程内直接调用了;如果是进程外bindService,那么从AMS中拿到的还是BinderProxy,依然是RPC。IBinder在创建进程中变为Binder,在其他进程变为BinderProxy,这得去读一下Binder机制源码,如果要彻底理解需要看看Binder驱动代码。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值