--- Service 的绑定原理 --- 1. 知道 bindService 的用法 2. 了解 bindService 的大致流程 3. bindService 涉及哪些参与者,通信过程是怎样的? ```java IRemoteCaller mCaller; ServiceConnection mServiceConnection = new ServiceConnection(){ @Override public void onServiceConnected(ComponentName name, IBinder service) { mCaller = IRemoteCaller.Stub.asInterface(service); mCaller.call(); } } Intent service = new Intent(this, MyService.class); bindService(service, mServiceConnection, BIND_AUTO_CREATE); ``` Bind Service 总体流程: ![](https://i.loli.net/2020/03/24/F4HYsiel7phDGBw.png) ```java @Override boolean bindService(Intent service, ServiceConnection conn, int flags) { return bindServiceCommon(service, conn, flags, ...); } boolean bindServiceCommon(Intent service, ServiceConnection conn, ...) { IServiceConnection sd; // 为 ServiceConnection 接口生成一个 binder 对象,可用于跨进程传递给 AMS sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), mMainThread.getHandler(), flags); ActivityManagerNative.getDefult().bindService(mMainThread.getApplicationThread(), service, sd, ...); } IServiceConnection getServiceDispatcher(ServiceConnection c, ...) { ServiceDispatcher sd = null; Map map = mServices.get(context); if(map != null){ sd = map.get(c); } if(sd == null){ sd = new ServiceDispatcher(c, context, handler,flags); if(map == null){ map = new ArrayMap(); mService.put(context, map); } map.put(c, sd); } return sd.getIServiceConnection(); } ServiceDispatcher(ServiceConnection conn, ...){ mIServiceConnection = new InnerConnection(this); mConnection = conn; } static class InnerConnection extends IServiceConnection.Stub { final WeakReference mDispatcher; public void connected(ComponentName name, IBinder service) { LoadedApk.ServiceDispatcher sd = mDispatcher.get(); if(sd != null){ sd.connected(name, service); } } } void connected(){ mActivityThread.post(new RunConnection(name, service, 0)); } public void doConnected(ComponentName name, IBinder service) { old = mActiveConnections.get(name); if(old!=null && old.binder == service){ return; } if(service != null){ info = new ConnectionInfo(service); mActiveConnections.put(name, info); }else{ mActiveConnections.remove(name); } if(old != null){ mConnection.onServiceDisconnected(name); } if(service != null){ mConnection.onServiceConnected(name, service); } } ``` ```java // AMS#bindServiceLocked bindServiceLocked(IApplicationThread caller, ...){ //... if((flag&Context.BIND_AUTO_CREATE)!=0){ bringUpServiceLocked(s, ); } if(s.app != null && b.intent.received){ c.conn.connected(s.name, b.intent.binder); }else if(!b.intent.requested){ requestServiceBindingLocked(s, b.intent, false); } } ``` ```java final String bringUpServiceLocked(ServiceRecord r, ...) { if(r.app != null && r.app.thread != null){ // 如果 Service 已经启动,就执行 Service#onStartCommand // 在 bind service 中没啥用 sendServiceArgsLocked(r, ...); return null; } ProcessRecord app = mAm.getProcessRecordLocked(procName, ...); if(app != null && app.thread != null) { realStartServiceLocked(r, app, execlnFg); return null; } if(app == null){ app = mAm.startProcessLocked(procName, ...); } if(!mPendingService.contains(r)){ mPendingService.add(r); } return null; } ``` ```java void realStartServiceLocked(ServiceRecord r, ProcessRecord app, ...) { r.app = app; // scheduleCreateService: 向应用端发起 IPC 调用 // 应用端收到之后就会去创建 Service,并执行 onCreate 回调 // r: class ServiceRecord extends Binder{} app.thread.scheduleCreateService(r, r.serviceInfo, ...); // 请求 Service 发布它的 binder 句柄给 AMS requestServiceBindingLocked(r, ...); // 触发 Service 的 onStartCommand 回调 sendServiceArgsLocked(r, ...); } boolean requestServiceBindingLocked(ServiceRecord r, ...) { if(r.app == null || r.app.thread == null){ return false; } if((!i.requested||rebind)&&i.apps.size()>0){ r.app.thread.scheduleBindService(r, rebind, ...); if(!rebind){ i.requested = true; } i.doRebind = false; } return true; } // scheduleBindService 的处理过程 private void handleBindService(BindServiceData data) { Service s = mService.get(data.token); if(!data.rebind){ IBinder binder = s.onBind(data.intent); ActivityManagerNative.getDefault().publishService(data.token, data.intent, binder); }else { s.onRebind(data.intent); } } ``` ```java // AMS#publishServiceLocked void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) { Intent.FilterComparison filter = new Intent.FilterComparison(intent); IntentBindRecord b = r.bindings.get(filter); if(b!=null && !b.received){ b.binder = service; b.requested = true; b.received = true; for(int conni=r.connections.size()-1;conni>=0;conni--) { ArrayList clist = r.connections.valueAt(conni); for(int i=0;i clist = mServiceConnections.get(binder); while(clist.size()>0){ ConnectionRecord r = clist.get(0); removeConnectionLocked(r, null, null); if(clist.size()>0&&clist.get(0)==r){ clist.remove(0); } } return true; } void removeConnectionLocked(ConnectionRecord c, ...){ if(s.app!=null&&s.app.thread!=null&&b.intent.apps.size()==0&&b.intent.hasBound){ b.intent.hasBound = false; b.intent.doRebind = false; s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent()); } } private void handleUnbindService(BindServiceData data) { Service s = mService.get(data.token); boolean doRebind = s.onUnbind(data.intent); if(doRebind){ ActivityManagerNative.getDefault().unbindFinished(doRebind); } } // AMS#unbindFinishedLocked void unbindFinishedLocked(ServiceRecord r, Intent intent, boolean doRebind) { Intent.FilterComparison filter = new Intent.FilterComparison(intent); IntentBindRecord b = r.bindings.get(filter); if(b.apps.size()>0&&!inDestorying) { }else { b.doRebind = true; } } ```