有了前面一篇《Service启动过程》,bindService应该很好分析了。但不用看代码也能估计出来,AMS需要缓存BinderProxy并转发给Client,跟Provider一样。
如果是进程内,ActivityThread中直接返回的是ContentProviderNative对象,即进程内直接调用ContentProvider函数而不是RPC。如果是进程外,那么ActiviyThread会找AMS要ContentProviderHolder,最终得到的ContentProviderProxy。
对于进程内和进程外,bindService的过程也会一样吗?我们估计,进程内得到的是一个Binder,而进程外得到的是一个BInderProxy。
1747 @Override1748 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 ArrayMapmap=mServices.get(context)965 if (sd == null) {966 sd = new ServiceDispatcher(c, context, handler, flags);967 if (map == null) {968 map = new ArrayMap ();969 mServices.put(context, map);970 }971 map.put(c, sd);972 } 975 return sd.getIServiceConnection();976 }977 }复制代码
原来ServiceConnection就是一个纯粹的接口,要为其加一层皮用于跨进程通信,通信用的倒不是ServiceDispatcher而是其中的通信代表 . 。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 ArrayMapmap983 = 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 holder995 = mUnboundServices.get(context);996 if (holder == null) {997 holder = new ArrayMap ();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 holder1010 = 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) {1491614917 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 }720721 final boolean callerFg = callerApp.setSchedGroup != Process.THREAD_GROUP_BG_NONINTERACTIVE;722723 ServiceLookupResult res =724 retrieveServiceLocked(service, resolvedType,725 Binder.getCallingPid(), Binder.getCallingUid(), userId, true, callerFg);732 ServiceRecord s = res.record;733734 final long origId = Binder.clearCallingIdentity();735736 try {754 AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);755 ConnectionRecord c = new ConnectionRecord(b, activity,756 connection, flags, clientLabel, clientIntent);757758 IBinder binder = connection.asBinder();759 ArrayListclist = s.connections.get(binder);760 if (clist == null) {761 clist = new ArrayList ();762 s.connections.put(binder, clist);763 }779 clist = mServiceConnections.get(binder);780 if (clist == null) {781 clist = new ArrayList ();782 mServiceConnections.put(binder, clist);783 }784 clist.add(c);785786 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 }818822 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 }828829 getServiceMap(s.userId).ensureNotStartingBackground(s);830831 } finally {833 }834835 return 1;836 }复制代码
取得IBinder放到了b.intent.binder中,即放到了AppBindRecord中,而AppBinderRecord绑定了Intent信息,且存放到了ServiceRecord.bindings中。从c.conn.connected来看最终调用了 .connected,这个是在Client应用层代码中的,所以基本可以断定bringUpServiceLocked这一步坑定准备好了AppBindRecord. .binder
------------------------------------------------------------------------------------------------
看看如何取到IBinder的
1430 private final void realStartServiceLocked(ServiceRecord r,1431 ProcessRecord app, boolean execInFg) throws RemoteException {14401446 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) {1493414935 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 filter845 = 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 ArrayListclist = r.connections.valueAt(conni);853 for (int i=0; i
------------------------------------------------------------------------------------------------
从代码来看,不管怎样bindService都会穿越到AMS中,AMS中记录了BindProxy。当在进程内bindService时,AMS将BindProxy传递到进程内部,会转化为Binder,最终就进程内直接调用了;如果是进程外bindService,那么从AMS中拿到的还是BinderProxy,依然是RPC。IBinder在创建进程中变为Binder,在其他进程变为BinderProxy,这得去读一下Binder机制源码,如果要彻底理解需要看看Binder驱动代码。