去电界面启动分析---之一

2019-04-13 13:35发布

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进行跨进程调用。例如,挂断电话/接听电话等操作。