You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

7.2 KiB

Service 的绑定原理
  1. 知道 bindService 的用法
  2. 了解 bindService 的大致流程
  3. bindService 涉及哪些参与者,通信过程是怎样的?
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 总体流程:

@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<ServiceConnection, ServiceDispatcher> 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<ServiceConnection, ServiceDispatcher>();
            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<ServiceDispatcher> 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);
    }
}
// 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);
    }
}
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;
}
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);
    }
}
// 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<ConnectionRecord> clist = r.connections.valueAt(conni);
            for(int i=0;i<clist.size();i++){
                ConnectionRecord c = clist.get(i);
                if(!filter.equals(c.binding.intent.intent)){
                    continue;
                }
                c.conn.connected(r.name, service);
            }
        }
    }
}

onRebind 什么时候调用?

int bindServiceLocked(IApplicationThread caller, IBinder token, ) {
    if(s.app!=null&&b.intent.received){
        if(b.intent.apps.size()==1&&b.intent.doRebind){
            requestServiceBindingLocked(s, b.intent, callerFg, true);
        }
    }
}
boolean unbindServiceLocked(IServiceConnection connection) {
    IBinder binder = connection.asBinder();
    ArrayList<ConnectionRecord> 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;
    }
}