第三章:通话连接的作用以及建立过程之二Binder机制绑定framework层TelephonyConnectionService服务

二.Binder机制绑定framework层TelephonyConnectionService服务

1).上面我们说过connection有可能通过binder机制绑定framework层的service服务,但是这个service还是packages层的吗,我认为并不是像直接在packages/services/telecomm层去创建这么简单,通话连接到最后要创建以及使用涉及到的是底层的一些服务,所以我认为这种服务应该是放在framework层去维护的,这样,使用binder机制自然就合乎情理了,不过,这只是个假设,按照这个思路我们看下面怎么发展,在这里有必要打个log,这样我们就知道流程了,我们先继续看后面的调用:

Intent serviceIntent = newIntent(mServiceAction).setComponent(mComponentName);

               ServiceConnection connection = new ServiceBinderConnection();

               Log.d(ServiceBinder.this, "Binding to service with intent:%s", serviceIntent);

               final boolean binding;

               if (mUserHandle != null) {

                   binding = mContext.bindServiceAsUser(serviceIntent,connection,

Context.BIND_AUTO_CREATE);

根据上面我们打的log显示serviceIntent是com.android.services.telephony.TelephonyConnectionService,这个显然就是我们要绑定的类了,可想而知,ConnectionServiceWrapper最后的创建连接的实际调用的很大部分可能就是依赖此类去完成了,我们先看 connection实例,其实是ServiceBinderConnection 类型的,我们可以直接看其onServiceConnected方法,在调用bindServiceAsUser方法之后就会去调用这个onServiceConnected方法实现binder连接了:

public voidonServiceConnected(ComponentName componentName, IBinder binder) {

           ThreadUtil.checkOnMainThread();

           Log.i(this, "Service bound %s", componentName);

           // Unbind request was queued so unbind immediately.

           if (mIsBindingAborted) {

               clearAbort();

               logServiceDisconnected("onServiceConnected");

               mContext.unbindService(this);

               handleFailedConnection();

               return; }

           mServiceConnection = this;

           setBinder(binder);

           handleSuccessfulConnection();

}

我们看到先去调用了 setBinder方法,然后再调用了handleSuccessfulConnection,回调机制,在setBinder拿到binder实例后再去回调此方法:

or (BindCallback callback : mCallbacks) {

           callback.onSuccess();

        }

       mCallbacks.clear();

这个onSuccess 到底做了什么呢?这里先放一下,我们先继续看 setBinder方法:

        if (mBinder !=binder) {

           mBinder = binder;

           setServiceInterface(binder);

           if (binder == null) {

               for (Listener l : mListeners) {

                   l.onUnbind(this);

               }

           }}

调用了 setServiceInterface方法,实际上是ConnectionServiceWrapper中的setServiceInterface,这很好理解,事实上上面的所有调用过程其实都是在ConnectionServiceWrapper进行的,继承之后调用相当于自己的方法了,继续看setServiceInterface方法:

if (binder == null) {

           // We have lost our service connection. Notify the world that this service isdone.

           // We must notify the adapter before CallsManager. The adapter will force anypending

           // outgoing calls to try the next service. This needs to happen beforeCallsManager

           // tries to clean up any calls still associated with this service.

           handleConnectionServiceDeath();

           CallsManager.getInstance().handleConnectionServiceDeath(this);

           mServiceInterface = null;

        } else {

           mServiceInterface = IConnectionService.Stub.asInterface(binder);

           addConnectionServiceAdapter(mAdapter);}

看到关键的地方了:

mServiceInterface =IConnectionService.Stub.asInterface(binder);

           addConnectionServiceAdapter(mAdapter);

似乎有点晕了,没关系,我们先理一下逻辑,首先是在ConnectionServiceWrapper的createConnection方法,这里定义了callback并作为参数去调用继承过来的内部类Binder的bind()方法,最终bind去绑定了TelephonyConnectionService .java类(packages/services/Telephony)并且返回了前者的类中定义的  IBinder实例(暂时先猜测),之后就去调用了setServiceInterface并且将使用bind技术绑定拿过来的TelephonyConnectionService中的IBinder实例作为形参,而且这个binder是IConnectionService 类型的,最后得到了mServiceInterface实例,这样,一切就顺理成章了,不过好像还是缺失一点,就是这个TelephonyConnectionService类仍然是个谜,这个类有什么作用呢,是不是定义了IBinder实例呢,我们先看其定义:

public class TelephonyConnectionServiceextends ConnectionService

此类继承自ConnectionService类,既然前面猜测是使用了Binder技术,那么这个被绑定的类必然存在一个返回IBinder实例的方法,很简单,搜索一下,不好意思没找到,那就只有去父类ConnectionService搜索了:

    @Override

    public final IBinderonBind(Intent intent) {

        returnmBinder;

    }

果然找到,哈哈,果然是使用binder技术进行了进程间通信,看mBinder定义:

private final IBinder mBinder = newIConnectionService.Stub() {

IConnectionService类型,与上面的分析正好吻合,这个IBinder中实现了很多方法,我们先看关键的方法:

@Override

        public voidcreateConnection(

               PhoneAccountHandle connectionManagerPhoneAccount,

               String id,

               ConnectionRequest request,

               boolean isIncoming,

               boolean isUnknown) {

           SomeArgs args = SomeArgs.obtain();

           args.arg1 = connectionManagerPhoneAccount;

           args.arg2 = id;

           args.arg3 = request;

           args.argi1 = isIncoming ? 1 : 0;

           args.argi2 = isUnknown ? 1 : 0;

           mHandler.obtainMessage(MSG_CREATE_CONNECTION, args).sendToTarget();

        }

我们看mHnadler的MSG_CREATE_CONNECTION:

   case MSG_CREATE_CONNECTION: {

                   SomeArgs args = (SomeArgs) msg.obj;

                   try {

                       final PhoneAccountHandleconnectionManagerPhoneAccount = (PhoneAccountHandle) args.arg1;

                       final String id = (String) args.arg2;

                       final ConnectionRequest request =(ConnectionRequest) args.arg3;

                       final boolean isIncoming = args.argi1== 1;

                       final boolean isUnknown = args.argi2== 1;

                       if (!mAreAccountsInitialized) {

                           Log.d(this,"Enqueueing pre-init request %s", id);

                          mPreInitializationConnectionRequests.add(newRunnable() {

                               @Override

                               publicvoid run() {

                                  createConnection(

                                          connectionManagerPhoneAccount,

                                          id,

                                          request,

                                          isIncoming,

                                          isUnknown);

                               }

                           });

                       } else {

                           createConnection(

                                  connectionManagerPhoneAccount,

                                  id,

                                  request,

                                  isIncoming,

                                  isUnknown);

                       }

                   } finally {

                       args.recycle();

                   }break;

               }

最后会调用 createConnection方法,直接定位createConnection方法:

Connection connection = isUnknown ?onCreateUnknownConnection(callManagerAccount, request)

               : isIncoming ? onCreateIncomingConnection(callManagerAccount,request)

               : onCreateOutgoingConnection(callManagerAccount, request);

        Log.d(this,"createConnection, connection: %s", connection);

        if (connection== null) {

           connection = Connection.createFailedConnection(

                   new DisconnectCause(DisconnectCause.ERROR));

        }

        if(connection.getState() != Connection.STATE_DISCONNECTED) {

           addConnection(callId, connection);

        }

        Uri address =connection.getAddress();

        String number= address == null ? "null" : address.getSchemeSpecificPart();

        Log.v(this,"createConnection, number: %s, state: %s, capabilities: %s",

               Connection.toLogSafePhoneNumber(number),

               Connection.stateToString(connection.getState()),

              Connection.capabilitiesToString(connection.getConnectionCapabilities()));

        Log.d(this,"createConnection, calling handleCreateConnectionSuccessful %s",callId);

       mAdapter.handleCreateConnectionComplete(

               callId,

               request,

               new ParcelableConnection(

                       request.getAccountHandle(),

                       connection.getState(),

                       connection.getConnectionCapabilities(),

                       connection.getAddress(),

                       connection.getAddressPresentation(),

                       connection.getCallerDisplayName(),

                      connection.getCallerDisplayNamePresentation(),

                       connection.getVideoProvider() == null?

                               null :connection.getVideoProvider().getInterface(),

                       connection.getVideoState(),

                       connection.isRingbackRequested(),

                       connection.getAudioModeIsVoip(),

                       connection.getStatusHints(),

                       connection.getDisconnectCause(),

                      createIdList(connection.getConferenceables())));

显然connection得到的实例是 onCreateOutgoingConnection方法返回的值,具体的方法暂时不做分析,我们只看最后一行:

placeOutgoingConnection(connection, phone,request);

这里实现了真正的拨号动作,分析到这里,已经明白了TelephonyConnectionService和ConnectionService类的作用,即定义了IBinder并且实现了真正拨号的动作,一切都是那么顺理成章,但是我们还是忽略了一点,想一想这个mBinder中的createConnection是如何被调用到的,我们先回到ConnectionServiceWrapper.java的createConnection中,这个createConnection中的BindCallback实例callback中实现了onSuccess方法,这个方法中最终会有一行:

mServiceInterface.createConnection(

                              call.getConnectionManagerPhoneAccount(),

                               callId,

                               newConnectionRequest(

                                      call.getTargetPhoneAccount(),

                                      call.getHandle(),

                                      extras,

                                      call.getVideoState()),

                                      call.isIncoming(),

                                      call.isUnknown());

这个mServiceInterface即是在调用mBinder.bind(callback)实现远程Binder绑定TelephonyConnectionService后去调用父类ServiceBinder.java中的ServiceBinderConnection内部类的onServiceConnected方法创建Binder连接时得到远程IBinder后调用setBinder方法继而调用setServiceInterface方法:

mServiceInterface =IConnectionService.Stub.asInterface(binder);

做了上面一个动作后mServiceInterface就是和TelephonyConnectionService绑定的纽带了,随即在调用完setBinder后回调handleSuccessfulConnection方法中的:

callback.onSuccess();

而callback已经在ConnectionServiceWrapper类中的 createConnection中实现了,可以参看上面已经分析过的流程,最终回去调用mServiceInterface的createConnection方法,也就是TelephonyConnectionService的createConnection方法,一切明朗,这样大家也就明白了这个创建通话连接的过程,即复杂又简单,只要框架明了,多处复杂的地方也酒化简了,这里还有一个小点就是setServiceInterface方法除了拿到IBinder还做了一个动作就是:

addConnectionServiceAdapter(mAdapter);

这个mAdapter是内部类Adapter的实例,实现了handleCreateConnectionComplete方法,这个方法就是最后底层创建连接成功后ConnectionServic的createConnection 方法中回调的mAdapter.handleCreateConnectionComplete去通知Call调用handleCreateConnectionSuccess完成状态通知。

总结:

以上便是通话连接的具体创建过程以及如何使用binder方法去进行的进程间通信,最后回调方法去更新状态更新界面的显示,但是,通话连接如何和底层进行交互呢,接下来我们将对connection如何关联到底层、调用底层的方法进行详细的分析。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值