源码分析:Service的绑定过程(bindService)

ContextWrapper#bindService(除特殊说明外,以下代码都基于API25)

和Service的启动过程一样,Service的绑定过程也是从ContextWrapper开始的,mBase同样是ContextImpl类型的对象,所以真正调用的是ContextImpl的bindService方法。

    @Override
    public boolean bindService(Intent service, ServiceConnection conn,
            int flags) {
        return mBase.bindService(service, conn, flags);
    }

ContextImpl#bindService

    @Override
    public boolean bindService(Intent service, ServiceConnection conn,
            int flags) {
        warnIfCallingFromSystemProcess();
        return bindServiceCommon(service, conn, flags, mMainThread.getHandler(),
                Process.myUserHandle());
    }

继续调用自己的bindServiceCommon方法。

ContextImpl#bindServiceCommon

    private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler
            handler, UserHandle user) {
        IServiceConnection sd;	//IServiceConnection是一个aidl文件
        if (conn == null) {
            throw new IllegalArgumentException("connection is null");
        }
        if (mPackageInfo != null) {
			//mPackageInfo是一个LoadedApk类型的对象
			//最终sd的类型是LoadedApk.ServiceDispatcher.InnerConnection
            sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
        } else {
            throw new RuntimeException("Not supported in system context");
        }
		
		//验证Service的有效性,Android 5.0版本以后不允许使用隐式调用
        validateServiceIntent(service);
		
        try {
            //...
            
			// 准备离开应用程序进程,进人ActivityManagerService进程
            service.prepareToLeaveProcess(this);
            
			//调用AMS的bindService方法来完成具体的绑定过程
            int res = ActivityManagerNative.getDefault().bindService(
                mMainThread.getApplicationThread(), getActivityToken(), service,
                service.resolveTypeIfNeeded(getContentResolver()),
                sd, flags, getOpPackageName(), user.getIdentifier());
            if (res < 0) {
                throw new SecurityException(
                        "Not allowed to bind to service " + service);
            }
            return res != 0;
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

bindServiceCommon方法主要完成了如下两件事情:

  1. 首先将客户端的ServiceConnection对象转化为LoadedApk.ServiceDispatcher.InnerConnection对象。这是通过LoadedApk的getServiceDispatcher方法来实现。

为什么不能直接使用ServiceConnection对象?

因为服务的绑定可能是跨进程的,因此ServiceConnection必须借助Binder才能让远程服务端回调自己的方法。InnerConnection就充当了Binder这个角色。而ServiceDispatcher起着连接ServiceConnection和InnerConnection的作用。

  1. 调用AMS的bindService方法来完成具体的绑定过程。

LoadedApk#getServiceDispatcher

    public final IServiceConnection getServiceDispatcher(ServiceConnection c,
            Context context, Handler handler, int flags) {
		/*
		 * mServices是一个ArrayMap对象,它的key是Context类型,value是ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>类型
		 * 所以存储的是当前活动的ServiceConnection和ServiceDispatcher的映射关系
		 */
        synchronized (mServices) {	
            LoadedApk.ServiceDispatcher sd = null;
            ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);
            if (map != null) {
                sd = map.get(c);	//查找当前ServiceConnection对应的ServiceDispatcher
            }
            if (sd == null) {	//若没有找到ServiceDispatcher
                sd = new ServiceDispatcher(c, context, handler, flags);	//初始化ServiceDispatcher
				//若当前活动还没有ServiceConnection和ServiceDispatcher的映射关系,先创建该映射关系
                if (map == null) {
                    map = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>();
                    mServices.put(context, map);
                }
				//在本活动新增映射关系
                map.put(c, sd);
            } else {
                sd.validate(context, handler);	//验证ServiceDispatcher
            }
			//返回IServiceConnection对象,该对象的真正类型是ServiceDispatcher.InnerConnection
            return sd.getIServiceConnection();	
        }
    }

该方法先是得到与当前ServiceConnection对应的LoadedApk.ServiceDispatcher对象,并最终返回ServiceDispatcher中保存的InnerConnection对象。

LoadedApk.ServiceDispatcher.InnerConnection

InnerConnection是ServiceDispatcher的静态内部类

    private static class InnerConnection extends IServiceConnection.Stub {
        final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;

        InnerConnection(LoadedApk.ServiceDispatcher sd) {
            mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
        }

        public void connected(ComponentName name, IBinder service) throws RemoteException {
            LoadedApk.ServiceDispatcher sd = mDispatcher.get();
            if (sd != null) {
                sd.connected(name, service);
            }
        }
    }

系统会通过InnerConnection来调用ServiceConnection的onServiceConnected方法,这个过程有可能是跨进程的。

ContextImpl#bindServiceCommon(API26)

在API26中,bindServiceCommon方法有一处小改变

    private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler
            handler, UserHandle user) {
        //...
        
        try {

            int res = ActivityManager.getService().bindService(
                mMainThread.getApplicationThread(), getActivityToken(), service,
                service.resolveTypeIfNeeded(getContentResolver()),
                sd, flags, getOpPackageName(), user.getIdentifier());

            //...
            return res != 0;
        } //...
    }

可以看出,主要是获取AMS的方法变了,但是最终都是获取到AMS,然后调用AMS的bindService方法。

ActivityManagerService#bindService

    public int bindService(IApplicationThread caller, IBinder token, Intent service,
            String resolvedType, IServiceConnection connection, int flags, String callingPackage,
            int userId) throws TransactionTooLargeException {
        //...

        synchronized(this) {
            //mServices是一个ActiveServices对象
            return mServices.bindServiceLocked(caller, token, service,
                    resolvedType, connection, flags, callingPackage, userId);
        }
    }

然后调用ActiveServices的bindServiceLocked方法

ActiveServices#bindServiceLocked

    int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
            String resolvedType, final IServiceConnection connection, int flags,
            String callingPackage, final int userId) throws TransactionTooLargeException {
        //...

        //retrieveServiceLocked方法解析Service,解析结果保存在res.record中
        ServiceLookupResult res =
            retrieveServiceLocked(service, resolvedType, callingPackage, Binder.getCallingPid(),
                    Binder.getCallingUid(), userId, true, callerFg, isBindExternal);
        if (res == null) {
            return 0;
        }
        if (res.record == null) {
            return -1;
        }
        ServiceRecord s = res.record;   //res.record是一个ServiceRecord对象

        //...

        try {
            //...

            if ((flags&Context.BIND_AUTO_CREATE) != 0) {
                s.lastActivity = SystemClock.uptimeMillis();
                
                //当标志位为BIND_AUTO_CREATE时,正常启动服务
                if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
                        permissionsReviewRequired) != null) {
                    return 0;
                }
            }
            
            //...

        } 

        return 1;
    }

继续调用bringUpServiceLocked,到这里开始和Service的启动过程类似,最终都是通过ApplicationThread来完成Service实例的创建并执行其onCreate方法。

ActiveServices#bringUpServiceLocked

    private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
            boolean whileRestarting, boolean permissionsReviewRequired)
            throws TransactionTooLargeException {
        //...

        final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;

        if (!isolated) {
            if (app != null && app.thread != null) {    //如果服务所在进程已经启动
                try {
                    realStartServiceLocked(r, app, execInFg);
                    return null;
                } 
            }
        }
        //...

        return null;
    }

继续调用realStartServiceLocked,同样和Service的启动过程类似

ActiveServices#realStartServiceLocked

    private final void realStartServiceLocked(ServiceRecord r,
            ProcessRecord app, boolean execInFg) throws RemoteException {
        //...
        
        try {
            //...
            
            app.thread.scheduleCreateService(r, r.serviceInfo,
                    mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
                    app.repProcState);

            //...
        } 

        requestServiceBindingsLocked(r, execInFg);  
    
        //...

        sendServiceArgsLocked(r, execInFg, true);

        //...
    }

同样和Service的启动过程类似,这里说一下不同的,首先看requestServiceBindingsLocked方法

ActiveServices#requestServiceBindingsLocked

    private final void requestServiceBindingsLocked(ServiceRecord r, boolean execInFg)
            throws TransactionTooLargeException {
        for (int i=r.bindings.size()-1; i>=0; i--) {
            IntentBindRecord ibr = r.bindings.valueAt(i);
            if (!requestServiceBindingLocked(r, ibr, execInFg, false)) {
                break;
            }
        }
    }

其中调用了requestServiceBindingLocked方法

ActiveServices#requestServiceBindingLocked

    private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
            boolean execInFg, boolean rebind) throws TransactionTooLargeException {
        if (r.app == null || r.app.thread == null) {
            // If service is not currently running, can't yet bind.
            return false;
        }
        if ((!i.requested || rebind) && i.apps.size() > 0) {
            try {
                //...
                
                r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
                        r.app.repProcState);
                
                //...
            } //...
        }
        return true;
    }

r.app.thread的实现类是ActivityThread.ApplicationThread,调用其scheduleBindService方法进行Service的绑定

ActivityThread.ApplicationThread#scheduleBindService

    public final void scheduleBindService(IBinder token, Intent intent,
            boolean rebind, int processState) {
        updateProcessState(processState, false);
        BindServiceData s = new BindServiceData();
        s.token = token;
        s.intent = intent;
        s.rebind = rebind;

        //发送消息给H
        sendMessage(H.BIND_SERVICE, s);
    }

H对这个消息的处理是

    case BIND_SERVICE:
        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "serviceBind");
        handleBindService((BindServiceData)msg.obj);
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        break;

接着调用handleBindService方法

ActivityThread.ApplicationThread#handleBindService

    private void handleBindService(BindServiceData data) {
		//mServices是一个ArrayMap<IBinder, Service>对象,这里根据token取出相应的service
		//这里的service是在前面执行handleCreateService方法时存进去的
        Service s = mServices.get(data.token);		

        //...
        if (s != null) {
            try {
                //...
                
                try {
                    if (!data.rebind) {
                        IBinder binder = s.onBind(data.intent);		//回调service的onBind方法
                        ActivityManagerNative.getDefault().publishService(	
                                data.token, data.intent, binder);	//调用AMS的publishService方法
                    } else {
                        s.onRebind(data.intent);    //如果多次绑定同一个service,回调onRebind方法
                        ActivityManagerNative.getDefault().serviceDoneExecuting(
                                data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
                    }
                    
                //...
                }   //...
            }   //...
        }
    }

可以看到在该方法中回调了Service的onBind方法。原则上来说,这时service已经处于绑定状态,但是客户端还不知道已经成功连接service,所以继续看AMS的publishService方法

ActivityManagerService#publishService

    public void publishService(IBinder token, Intent intent, IBinder service) {
        //...

        synchronized(this) {
            //...
            
			//mServices是一个ActiveServices对象
            mServices.publishServiceLocked((ServiceRecord)token, intent, service);
        }
    }

调用ActiveServices的publishServiceLocked方法

ActiveServices#publishServiceLocked

    void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {

        try {
            //...
            
            if (r != null) {
                Intent.FilterComparison filter
                        = new Intent.FilterComparison(intent);
                IntentBindRecord b = r.bindings.get(filter);
                if (b != null && !b.received) {
                    //...
                    
                    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);
                           
                            //...
                            
                            try {
								//执行连接成功的回调,其中c.conn是IServiceConnection对象,
								//其实现类是LoadedApk.ServiceDispatcher.InnerConnection
                                c.conn.connected(r.name, service);
                                
                            }//...
                        }
                    }
                }
                
                //...
            }
        }//...
    }

又跳转到了LoadedApk.ServiceDispatcher.InnerConnection的connected方法

LoadedApk.ServiceDispatcher.InnerConnection#connected

    public void connected(ComponentName name, IBinder service) throws RemoteException {
        LoadedApk.ServiceDispatcher sd = mDispatcher.get();
        if (sd != null) {
            sd.connected(name, service);    //调用LoadedApk.ServiceDispatcher的connected方法
        }
    }

InnerConnection的connected方法又调用LoadedApk.ServiceDispatcher的connected方法

LoadedApk.ServiceDispatcher#connected

    public void connected(ComponentName name, IBinder service) {
        if (mActivityThread != null) {
			//mActivityThread是一个Handler对象,其实它就是ActivityThread中的H
			//RunConnection就可以通过H的post方法运行在主线程
            mActivityThread.post(new RunConnection(name, service, 0));
        } else {
            doConnected(name, service);
        }
    }

接着看下RunConnection的定义

LoadedApk.ServiceDispatcher.RunConnection

RunConnection是ServiceDispatcher的内部类

    private final class RunConnection implements Runnable {
        RunConnection(ComponentName name, IBinder service, int command) {
            mName = name;
            mService = service;
            mCommand = command;
        }

        public void run() {
            if (mCommand == 0) {
                doConnected(mName, mService);
            } else if (mCommand == 1) {
                doDeath(mName, mService);
            }
        }

        final ComponentName mName;
        final IBinder mService;
        final int mCommand;
    }

其run方法在传入的command为0时调用了doConnected方法

LoadedApk.ServiceDispatcher#doConnected

    public void doConnected(ComponentName name, IBinder service) {
        //...

        // If there is a new service, it is now connected.
        if (service != null) {
            //mConnection是一个ServiceConnection对象,其保存了客户端的ServiceConnection
            mConnection.onServiceConnected(name, service);
        }
    }

可以看到,最终是在ServiceDispatcher的doConnected方法中回调了ServiceConnection的onServiceConnected方法。至此,service的绑定过程分析完毕。

参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值