1,去电界面启动分析
在去电流程中论述过,会调用CallsManager的startOutgoingCall启动拨号界面,在该方法中会调用addCall方法,
此时还处于services telecom进程中。
addCall(call);
addCall方法如下,
for (CallsManagerListener listener : mListeners) {
if (Log.SYSTRACE_DEBUG) {
Trace.beginSection(listener.getClass().toString() + " addCall");
}
listener.onCallAdded(call);
if (Log.SYSTRACE_DEBUG) {
Trace.endSection();
}
}
mListeners定义如下,
private final Set mListeners = Collections.newSetFromMap(
new ConcurrentHashMap(16, 0.9f, 1));
该哈希表是线程安全的。
并且在CallsManager的构造方法中就会添加监听器,
mListeners.add(mInCallController);
mListeners.add(mRinger);
当然,还可以调用addListener方法添加监听器,
void addListener(CallsManagerListener listener) {
mListeners.add(listener);
}
InCallController的onCallAdded方法主要逻辑如下,
1, 绑定InCallService服务
if (!isBoundToServices()) {//如果还没有绑定
bindToServices(call);
}
2,添加具体的call
for (Map.Entry entry : mInCallServices.entrySet()) {
ComponentName componentName = entry.getKey();
IInCallService inCallService = entry.getValue();
ParcelableCall parcelableCall = toParcelableCall(call, true /* includeVideoProvider */);
try {
inCallService.addCall(parcelableCall);
} catch (RemoteException ignored) {
}
}
3,电话状态的变化,
onCallAudioStateChanged(null, mCallsManager.getAudioState());
1.1绑定InCallService服务
InCallController的bindToServices方法中会调用bindToInCallService方法,该方法如下,
Intent intent = new Intent(InCallService.SERVICE_INTERFACE);
intent.setComponent(componentName);
if (call != null && !call.isIncoming()){
intent.putExtra(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS,
call.getIntentExtras());
intent.putExtra(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE,
call.getTargetPhoneAccount());
}
Log.i(this, "Attempting to bind to [%s] InCall %s, with %s", tag, componentName, intent);
InCallServiceConnection inCallServiceConnection = new InCallServiceConnection();
if (mContext.bindServiceAsUser(intent, inCallServiceConnection,
Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE,
UserHandle.CURRENT)) {
mServiceConnections.put(componentName, inCallServiceConnection);
return true;
}
InCallService的SERVICE_INTERFACE变量如下,
public static final String SERVICE_INTERFACE = "android.telecom.InCallService";
InCallService只是一个抽象类,具体的实现在IncallUI 的InCallServiceImpl中, IncallUI 整个运行于dialer进程中。
InCallServiceImpl继承于InCallService,
public class InCallServiceImpl extends InCallService {
Dialer的AndroidManifest.xml 中有关InCallServiceImpl如下,
由此可见,确认是启动InCallServiceImpl无疑。
InCallServiceImpl的onBind方法会调用父类InCallService的onBind方法,
public IBinder onBind(Intent intent) {
return new InCallServiceBinder();
}
返回的是InCallServiceBinder对象, InCallServiceBinder是InCallService的内部类,定义如下,
private final class InCallServiceBinder extends IInCallService.Stub {
因此,绑定的是dialer进程中的是InCallService的内部类InCallServiceBinder。
InCallServiceConnection是 InCallController的内部类,绑定成功之后,就会回调InCallServiceConnection的
onServiceConnected方法,
public void onServiceConnected(ComponentName name, IBinder service) {
Log.d(this, "onServiceConnected: %s", name);
onConnected(name, service);
}
onConnected方法如下,
1,首先保存绑定的远程对象,
IInCallService inCallService = IInCallService.Stub.asInterface(service);
mInCallServices.put(componentName, inCallService);
2,调用绑定对象的setInCallAdapter方法,
inCallService.setInCallAdapter(new InCallAdapter(mCallsManager, mCallIdMapper, mLock));
dialer进程中的是InCallService的内部类InCallServiceBinder的setInCallAdapter方法下个小节详细论述。
1.2设置InCallAdapter
InCallService的内部类InCallServiceBinder的setInCallAdapter方法如下,
public void setInCallAdapter(IInCallAdapter inCallAdapter) {
mHandler.obtainMessage(MSG_SET_IN_CALL_ADAPTER, inCallAdapter).sendToTarget();
}
mHandler的handleMessage对MSG_SET_IN_CALL_ADAPTER消息处理如下,
case MSG_SET_IN_CALL_ADAPTER:
mPhone = new Phone(new InCallAdapter((IInCallAdapter) msg.obj));
mPhone.addListener(mPhoneListener);
onPhoneCreated(mPhone);
break;
在构造Phone对象之前会构造InCallAdapter对象, InCallAdapter构造方法如下,
public InCallAdapter(IInCallAdapter adapter) {
mAdapter = adapter;
}
mAdapter就是指向services Telephony的InCallAdapter对象。
这样services telecom就可以通过binder进行跨进程调用。例如,挂断电话/接听电话等操作。