首先了解Phone 与 system是什么 ,我在网上找了一张图片先了解一下
设计图:
- Dialer (dialer进程 )拨打电话的入口,来电不会经过Dialer。但是拨打电话的出口不光是Dialer,在联系人和短信里也有拨打电话的出口。
- InCallUI (dialer进程) 负责显示通话界面的信息,来电信息。
- Telecomm(system_process和telecomm:ui进程) 处理Intent,发送广播,设置call的状态,audio状态。
- Telephony ( phone进程) 向下层传递拨号,注册了很多广播,申请很多权限,service data sms wap network等。
- telecomm(phone_process) 提供placeCall的接口,创建outgoingCall的connection,通知上层成功建立connection
- telephony (phone_process) 拨号也就是dial命令的下发,但是如果是Ims网络就会有下面一步
- Vendor/ims(phone_process) 创建ImsConnection,ImsCall,拨号.
连接入口在system_process进程中的ConnectionServiceWrapper.java
system进程与phone进程之间连接流程图
流程图:
第一步
ConnectionServiceWrapper.java
system进入ConnectionServiceWrapper.java中的createConnection方法
步骤一
public void createConnection(final Call call, final CreateConnectionResponse response) {//创建链接就是一个绑定服务的过程
Log.d(this, "createConnection(%s) via %s.", call, getComponentName());
BindCallback callback = new BindCallback() {// 链接创建成功后 onSuccess 会被调用
@Override
public void onSuccess() {
String callId = mCallIdMapper.getCallId(call);
mPendingResponses.put(callId, response);
GatewayInfo gatewayInfo = call.getGatewayInfo();
Bundle extras = call.getIntentExtras();
if (gatewayInfo != null && gatewayInfo.getGatewayProviderPackageName() != null &&
gatewayInfo.getOriginalAddress() != null) {
extras = (Bundle) extras.clone();
extras.putString(
TelecomManager.GATEWAY_PROVIDER_PACKAGE,
gatewayInfo.getGatewayProviderPackageName());
extras.putParcelable(
TelecomManager.GATEWAY_ORIGINAL_ADDRESS,
gatewayInfo.getOriginalAddress());
}
if (call.isIncoming() && mCallsManager.getEmergencyCallHelper()
.getLastEmergencyCallTimeMillis() > 0) {
// Add the last emergency call time to the connection request for incoming calls
if (extras == call.getIntentExtras()) {
extras = (Bundle) extras.clone();
}
extras.putLong(android.telecom.Call.EXTRA_LAST_EMERGENCY_CALLBACK_TIME_MILLIS,
mCallsManager.getEmergencyCallHelper().getLastEmergencyCallTimeMillis());
}
// Call is incoming and added because we're handing over from another; tell CS
// that its expected to handover.
if (call.isIncoming() && call.getHandoverSourceCall() != null) {
extras.putBoolean(TelecomManager.EXTRA_IS_HANDOVER, true);
extras.putParcelable(TelecomManager.EXTRA_HANDOVER_FROM_PHONE_ACCOUNT,
call.getHandoverSourceCall().getTargetPhoneAccount());
}
Log.addEvent(call, LogUtils.Events.START_CONNECTION,
Log.piiHandle(call.getHandle()));
ConnectionRequest connectionRequest = new ConnectionRequest.Builder()
.setAccountHandle(call.getTargetPhoneAccount())
.setAddress(call.getHandle())
.setExtras(extras)
.setVideoState(call.getVideoState())
.setTelecomCallId(callId)
// For self-managed incoming calls, if there is another ongoing call Telecom
// is responsible for showing a UI to ask the user if they'd like to answer
// this new incoming call.
.setShouldShowIncomingCallUi(
!mCallsManager.shouldShowSystemIncomingCallUi(call))
.setRttPipeFromInCall(call.getInCallToCsRttPipeForCs())
.setRttPipeToInCall(call.getCsToInCallRttPipeForCs())
.build();
try {
mServiceInterface.createConnection( // 通过远程接口创建链接 利用远程接口创建一个通话链接
call.getConnectionManagerPhoneAccount(),
callId,
connectionRequest,
call.shouldAttachToExistingConnection(),
call.isUnknown(),
Log.getExternalSession());
} catch (RemoteException e) {
Log.e(this, e, "Failure to createConnection -- %s", getComponentName());
mPendingResponses.remove(callId).handleCreateConnectionFailure(
new DisconnectCause(DisconnectCause.ERROR, e.toString()));
}
}
@Override
public void onFailure() {
Log.e(this, new Exception(), "Failure to call %s", getComponentName());
response.handleCreateConnectionFailure(new DisconnectCause(DisconnectCause.ERROR));
}
};
//绑定
mBinder.bind(callback, call);
ServiceBinder.java
进入mBinder.bind中 ConnectionServiceWrapper是ServiceBinder的子类,而mBinder.bind方法是ServiceBinder里面的内部类Binder2 中
步骤二
void bind(BindCallback callback, Call call) {
Log.d(ServiceBinder.this, "bind()");
// Reset any abort request if we're asked to bind again.
clearAbort();
if (!mCallbacks.isEmpty()) {
// Binding already in progress, append to the list of callbacks and bail out.
mCallbacks.add(callback);
return;
}
//在类里面绑定成功后mBinder.bind(callback, call);在父类ServiceBinder类里面mCallbacks.add(callback);吧回调用集合给装载起来,然后进行便利数据
//成功获取到aidl接口后将其赋值mServiceInterface,
mCallbacks.add(callback);
if (mServiceConnection == null) {
Intent serviceIntent = new Intent(mServiceAction).setComponent(mComponentName);
ServiceConnection connection = new ServiceBinderConnection(call);
Log.addEvent(call, LogUtils.Events.BIND_CS, mComponentName);
final int bindingFlags = Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE;
final boolean isBound;
if (mUserHandle != null) {// 进行绑定
isBound = mContext.bindServiceAsUser(serviceIntent, connection, bindingFlags, //如果绑定成功调用connection方法 这里绑定是绑定了framework/base/telepony
mUserHandle);
} else {
isBound = mContext.bindService(serviceIntent, connection, bindingFlags);
}
if (!isBound) {
handleFailedConnection();
return;
}
} else {
Log.d(ServiceBinder.this, "Service is already bound.");
Preconditions.checkNotNull(mBinder);
handleSuccessfulConnection();
}
}
}
步骤三
mContext.bindServiceAsUser()传入了一个connection对象代表,如果连接成功回调到connection对象中,connection继承ServiceConnection,我们来看一下connection对象吧,
回调onServiceConnected()方法,返回一个bind
步骤四
private final class ServiceBinderConnection implements ServiceConnection {
/**
* 绑定服务的初始调用。
*/
private Call mCall;
ServiceBinderConnection(Call call) {
mCall = call;
}
@Override
public void onServiceConnected(ComponentName componentName, IBinder binder) {
try {
Log.startSession("SBC.oSC");
synchronized (mLock) {
Log.i(this, "Service bound %s", componentName);
Log.addEvent(mCall, LogUtils.Events.CS_BOUND, componentName);
mCall = null;
//取消绑定请求被排队,因此立即取消绑定。
if (mIsBindingAborted) {
clearAbort();
logServiceDisconnected("onServiceConnected");
mContext.unbindService(this);
handleFailedConnection();
return;
}
if (binder != null) {
mServiceDeathRecipient = new ServiceDeathRecipient(componentName);
try {
binder.linkToDeath(mServiceDeathRecipient, 0);
mServiceConnection = this;
// 设置 mServiceInterface
// 会触发 ConnectionServiceWrapper.setServiceInterface ==> ConnectionServiceWrapper.addConnectionServiceAdapter
// 通过mServiceInterface,给绑定的服务,提供一个访问自己的接口
setBinder(binder);// 触发bind(BindCallback callback, Call call) 中 callback 的 onSuccess
handleSuccessfulConnection(); //回调进入子类
//整个绑定过程,只做2件事,一是给远程服务提供访问自己的接口,二是利用远程接口创建一个通话链接。
// 这2件事都是跨进程进行的。远程服务访问自己的接口是
} catch (RemoteException e) {
Log.w(this, "onServiceConnected: %s died.");
if (mServiceDeathRecipient != null) {
mServiceDeathRecipient.binderDied();
}
}
}
}
} finally {
Log.endSession();
}
}
@Override
public void onServiceDisconnected(ComponentName componentName) {
失败处理...
}
}
入口步骤五
setBinder() 回调到ServiceConnectionWrapper.java中setServiceInterface() 远程服务提供访问自己的接口
private void setBinder(IBinder binder) {
if (mBinder != binder) {
if (binder == null) {
removeServiceInterface();
mBinder = null;
for (Listener l : mListeners) {
l.onUnbind(this);
}
} else {
mBinder = binder;
setServiceInterface(binder);
}
}
}
步骤六
setServiceInterace() 调用的是子类实现方法 ,他的子类是ConnectionServiceWrapper.java
ConnectionServiceWrapper.java
@Override
protected void setServiceInterface(IBinder binder) {
mServiceInterface = IConnectionService.Stub.asInterface(binder);
Log.v(this, "Adding Connection Service Adapter.");
addConnectionServiceAdapter(mAdapter);//这个mAdapter 给远程服务提供访问自己的接口
}
步骤七
/** See {@link IConnectionService#addConnectionServiceAdapter}. */
private void addConnectionServiceAdapter(IConnectionServiceAdapter adapter) {
if (isServiceValid("addConnectionServiceAdapter")) {
try {
//在类里面绑定成功后mBinder.bind(callback, call);在父类ServiceBinder类里面mCallbacks.add(callback);吧回调用集合给装载起来,然后进行便利数据
//成功获取到aidl接口后将其赋值mServiceInterface,
logOutgoing("addConnectionServiceAdapter %s", adapter);
mServiceInterface.addConnectionServiceAdapter(adapter, Log.getExternalSession());
} catch (RemoteException e) {
}
}
}
完成远程服务提供访问自己的接口
步骤八
回到ServiceBinder中子类对象中的connection对象里面的onServiceConnected()方法
然后调用 handleSuccessfulConnection()
private void handleSuccessfulConnection() {
for (BindCallback callback : mCallbacks) {
callback.onSuccess();
}
mCallbacks.clear();
}
步骤九
回调到ConnectionServiceWrapper中Bindcallback中的onSuccess()方法中
@Override
public void onSuccess() {
String callId = mCallIdMapper.getCallId(call);
mPendingResponses.put(callId, response);
GatewayInfo gatewayInfo = call.getGatewayInfo();
Bundle extras = call.getIntentExtras();
if (gatewayInfo != null && gatewayInfo.getGatewayProviderPackageName() != null &&
gatewayInfo.getOriginalAddress() != null) {
extras = (Bundle) extras.clone();
extras.putString(
TelecomManager.GATEWAY_PROVIDER_PACKAGE,
gatewayInfo.getGatewayProviderPackageName());
extras.putParcelable(
TelecomManager.GATEWAY_ORIGINAL_ADDRESS,
gatewayInfo.getOriginalAddress());
}
if (call.isIncoming() && mCallsManager.getEmergencyCallHelper()
.getLastEmergencyCallTimeMillis() > 0) {
// Add the last emergency call time to the connection request for incoming calls
if (extras == call.getIntentExtras()) {
extras = (Bundle) extras.clone();
}
extras.putLong(android.telecom.Call.EXTRA_LAST_EMERGENCY_CALLBACK_TIME_MILLIS,
mCallsManager.getEmergencyCallHelper().getLastEmergencyCallTimeMillis());
}
// Call is incoming and added because we're handing over from another; tell CS
// that its expected to handover.
if (call.isIncoming() && call.getHandoverSourceCall() != null) {
extras.putBoolean(TelecomManager.EXTRA_IS_HANDOVER, true);
extras.putParcelable(TelecomManager.EXTRA_HANDOVER_FROM_PHONE_ACCOUNT,
call.getHandoverSourceCall().getTargetPhoneAccount());
}
Log.addEvent(call, LogUtils.Events.START_CONNECTION,
Log.piiHandle(call.getHandle()));
ConnectionRequest connectionRequest = new ConnectionRequest.Builder()
.setAccountHandle(call.getTargetPhoneAccount())
.setAddress(call.getHandle())
.setExtras(extras)
.setVideoState(call.getVideoState())
.setTelecomCallId(callId)
// For self-managed incoming calls, if there is another ongoing call Telecom
// is responsible for showing a UI to ask the user if they'd like to answer
// this new incoming call.
.setShouldShowIncomingCallUi(
!mCallsManager.shouldShowSystemIncomingCallUi(call))
.setRttPipeFromInCall(call.getInCallToCsRttPipeForCs())
.setRttPipeToInCall(call.getCsToInCallRttPipeForCs())
.build();
try {
mServiceInterface.createConnection( // 通过远程接口创建链接 利用远程接口创建一个通话链接
call.getConnectionManagerPhoneAccount(),
callId,
connectionRequest,
call.shouldAttachToExistingConnection(),
call.isUnknown(),
Log.getExternalSession());
} catch (RemoteException e) {
Log.e(this, e, "Failure to createConnection -- %s", getComponentName());
mPendingResponses.remove(callId).handleCreateConnectionFailure(
new DisconnectCause(DisconnectCause.ERROR, e.toString()));
}
}
这个方法内部
步骤十
phone进程
ConnectionService.java
@Override
public void createConnection(
PhoneAccountHandle connectionManagerPhoneAccount,
String id,
ConnectionRequest request,
boolean isIncoming,
boolean isUnknown,
Session.Info sessionInfo) {
Log.startSession(sessionInfo, SESSION_CREATE_CONN);
try {
SomeArgs args = SomeArgs.obtain();
args.arg1 = connectionManagerPhoneAccount;
args.arg2 = id;
args.arg3 = request;
args.arg4 = Log.createSubsession();
args.argi1 = isIncoming ? 1 : 0;
args.argi2 = isUnknown ? 1 : 0;
mHandler.obtainMessage(MSG_CREATE_CONNECTION, args).sendToTarget();
} finally {
Log.endSession();
}
}
步骤十一
创建连接MSG_CREATE_CONNECTION
private final Handler mHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_ADD_CONNECTION_SERVICE_ADAPTER: {
SomeArgs args = (SomeArgs) msg.obj;
try { // 添加 来自于 system 进程的接口
IConnectionServiceAdapter adapter = (IConnectionServiceAdapter) args.arg1;
Log.continueSession((Session) args.arg2,
SESSION_HANDLER + SESSION_ADD_CS_ADAPTER);
mAdapter.addAdapter(adapter);
onAdapterAttached();
} finally {
args.recycle();
Log.endSession();
}
break;
}
case MSG_REMOVE_CONNECTION_SERVICE_ADAPTER: {
SomeArgs args = (SomeArgs) msg.obj;
try {
Log.continueSession((Session) args.arg2,
SESSION_HANDLER + SESSION_REMOVE_CS_ADAPTER);
mAdapter.removeAdapter((IConnectionServiceAdapter) args.arg1); // 移除
} finally {
args.recycle();
Log.endSession();
}
break;
}
case MSG_CREATE_CONNECTION: { // 创建链接
SomeArgs args = (SomeArgs) msg.obj;
Log.continueSession((Session) args.arg4, SESSION_HANDLER + SESSION_CREATE_CONN);
try {
final PhoneAccountHandle connectionManagerPhoneAccount =
(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(
new android.telecom.Logging.Runnable(
SESSION_HANDLER + SESSION_CREATE_CONN + ".pICR",
null /*lock*/) {
@Override
public void loggedRun() {
createConnection(
connectionManagerPhoneAccount,
id,
request,
isIncoming,
isUnknown);
}
}.prepare());
} else {
createConnection(
connectionManagerPhoneAccount,
id,
request,
isIncoming,
isUnknown);
}
} finally {
args.recycle();
Log.endSession();
}
break;
}
}
}
}
步骤十二
通过远程接口创建链接 ,利用远程接口创建一个通话链接,等待12步骤完成,完成后会返回一连接对象connection对象传入handlerCreateConnectionComplete()方法
/**
* This can be used by telecom to either create a new outgoing call or attach to an existing
* incoming call. In either case, telecom will cycle through a set of services and call
* createConnection util a connection service cancels the process or completes it successfully.
*/
private void createConnection(
final PhoneAccountHandle callManagerAccount,
final String callId,
final ConnectionRequest request,
boolean isIncoming,
boolean isUnknown) {
boolean isLegacyHandover = request.getExtras() != null &&
request.getExtras().getBoolean(TelecomManager.EXTRA_IS_HANDOVER, false);
boolean isHandover = request.getExtras() != null && request.getExtras().getBoolean(
TelecomManager.EXTRA_IS_HANDOVER_CONNECTION, false);
Log.d(this, "createConnection, callManagerAccount: %s, callId: %s, request: %s, " +
"isIncoming: %b, isUnknown: %b, isLegacyHandover: %b, isHandover: %b",
callManagerAccount, callId, request, isIncoming, isUnknown, isLegacyHandover,
isHandover);
Connection connection = null;
if (isHandover) {
PhoneAccountHandle fromPhoneAccountHandle = request.getExtras() != null
? (PhoneAccountHandle) request.getExtras().getParcelable(
TelecomManager.EXTRA_HANDOVER_FROM_PHONE_ACCOUNT) : null;
if (!isIncoming) {
connection = onCreateOutgoingHandoverConnection(fromPhoneAccountHandle, request);
} else {
connection = onCreateIncomingHandoverConnection(fromPhoneAccountHandle, request);
}
} else {
connection = isUnknown ? onCreateUnknownConnection(callManagerAccount, request)
: isIncoming ? onCreateIncomingConnection(callManagerAccount, request)
: onCreateOutgoingConnection(callManagerAccount, request);
}
Log.d(this, "createConnection, connection: %s", connection);
if (connection == null) {
Log.i(this, "createConnection, implementation returned null connection.");
connection = Connection.createFailedConnection(
new DisconnectCause(DisconnectCause.ERROR, "IMPL_RETURNED_NULL_CONNECTION"));
}
connection.setTelecomCallId(callId);
if (connection.getState() != Connection.STATE_DISCONNECTED) {
// 监听 Connection 的状态变化,通知 system 进程(CallsManager)更新
// 通过 system 进程提供的 adapter 实现
addConnection(request.getAccountHandle(), callId, connection);
}
Uri address = connection.getAddress();
String number = address == null ? "null" : address.getSchemeSpecificPart();
Log.v(this, "createConnection, number: %s, state: %s, capabilities: %s, properties: %s",
Connection.toLogSafePhoneNumber(number),
Connection.stateToString(connection.getState()),
Connection.capabilitiesToString(connection.getConnectionCapabilities()),
Connection.propertiesToString(connection.getConnectionProperties()));
Log.d(this, "createConnection, calling handleCreateConnectionSuccessful %s", callId);
//mAdapter.handleCreateConnectionComplete 调用回到 ConnectionServiceWrapper 的 handleCreateConnectionComplete,
// 然后回到 Call 的 handleCreateConnectionSuccess
mAdapter.handleCreateConnectionComplete(// 通知 system 进程(即CallsManager) 电话链接已经创建完成
callId,
request,
new ParcelableConnection(
request.getAccountHandle(),
connection.getState(),
connection.getConnectionCapabilities(),
connection.getConnectionProperties(),
connection.getSupportedAudioRoutes(),
connection.getAddress(),
connection.getAddressPresentation(),
connection.getCallerDisplayName(),
connection.getCallerDisplayNamePresentation(),
connection.getVideoProvider() == null ?
null : connection.getVideoProvider().getInterface(),
connection.getVideoState(),
connection.isRingbackRequested(),
connection.getAudioModeIsVoip(),
connection.getConnectTimeMillis(),
connection.getConnectElapsedTimeMillis(),
connection.getStatusHints(),
connection.getDisconnectCause(),
createIdList(connection.getConferenceables()),
connection.getExtras()));
if (isIncoming && request.shouldShowIncomingCallUi() &&
(connection.getConnectionProperties() & Connection.PROPERTY_SELF_MANAGED) ==
Connection.PROPERTY_SELF_MANAGED) {
// Tell ConnectionService to show its incoming call UX.
connection.onShowIncomingCallUi();
}
if (isUnknown) {
triggerConferenceRecalculate();
}
}
通过Adapter.handleCreateConnectionComplete()回调进入ConnectionServiceWrapper.java里面的Adapter内部类中
@Override
public void handleCreateConnectionComplete(String callId, ConnectionRequest request, //连接建立完成
ParcelableConnection connection, Session.Info sessionInfo) {
Log.startSession(sessionInfo, LogUtils.Sessions.CSW_HANDLE_CREATE_CONNECTION_COMPLETE);
long token = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
logIncoming("handleCreateConnectionComplete %s", callId);
ConnectionServiceWrapper.this
.handleCreateConnectionComplete(callId, request, connection); //framework/base/telecom回调后调用 更新UI
if (mServiceInterface != null) {
logOutgoing("createConnectionComplete %s", callId);
try {
mServiceInterface.createConnectionComplete(callId,
Log.getExternalSession());//调用到
} catch (RemoteException e) {
}
}
}
} catch (Throwable t) {
Log.e(ConnectionServiceWrapper.this, t, "");
throw t;
} finally {
Binder.restoreCallingIdentity(token);
Log.endSession();
}
}
private void handleCreateConnectionComplete(
String callId,
ConnectionRequest request,
ParcelableConnection connection) {
// TODO: Note we are not using parameter "request", which is a side effect of our tacit
// assumption that we have at most one outgoing connection attempt per ConnectionService.
// This may not continue to be the case. 判断是否连接成功连接只需要进行一次
if (connection.getState() == Connection.STATE_DISCONNECTED) {
// A connection that begins in the DISCONNECTED state is an indication of
// failure to connect; we handle all failures uniformly
removeCall(callId, connection.getDisconnectCause());
} else {
// Successful connection 连接成功
if (mPendingResponses.containsKey(callId)) {
mPendingResponses.remove(callId)
.handleCreateConnectionSuccess(mCallIdMapper, connection);
}
}
连接建立完毕