二.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如何关联到底层、调用底层的方法进行详细的分析。