源码环境下跟进MO通话流程(涉及到其中每一个方法的跳转)

对Tele这一块的MO流程在源码环境下做一个跟进,通过观察每一个方法的跳转加深对MO流程的印象,如有错误,欢迎在评论区指出,篇幅较长,请耐心阅读。

packages/apps/Dialer/java/com/android/dialer/dialpadview/DialpadFragment.java

handleDialButtonPressed();

private void handleDialButtonPressed() {
...
PreCall.start(getContext(), new CallIntentBuilder(number, CallInitiationType.Type.DIALPAD));
...
}

packages/apps/Dialer/java/com/android/dialer/callintent/CallIntentBuilder.java

new CallIntentBuilder构造方法

CallIntentBuilder.java中的build方法,返回intent请求对象,Action为ACTION_CALL,还有些附加信息

public Intent build() {
Intent intent = new Intent(Intent.ACTION_CALL, uri);
206 intent.putExtra(
207 TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE,
208 isVideoCall ? VideoProfile.STATE_BIDIRECTIONAL : VideoProfile.STATE_AUDIO_ONLY);

vendor/codeaurora/commonsys/packages/apps/Dialer/java/com/android/dialer/precall/PreCall.java

接着调用外层的PreCall.start();

static void start(Context context, CallIntentBuilder builder) {
43 DialerUtils.startActivityWithErrorToast(context, getIntent(context, builder));
44 }

packages/apps/Dialer/java/com/android/dialer/util/DialerUtils.java

转到 DialerUtils.startActivityWithErrorToast();

 public static void startActivityWithErrorToast(
...//首先判断是不是CallIntentBuilder.build里面的Intent,再对intent的附加信息做出一些处理,执行placeCallOrMakeToast()
if ((Intent.ACTION_CALL.equals(intent.getAction()))) {
...
placeCallOrMakeToast(context , intent);
}else {
context.startActivity(intent);
}

转到 placeCallOrMakeToast(context , intent);

118  private static void placeCallOrMakeToast(Context context, Intent intent) {
final boolean hasCallPermission = TelecomUtil.placeCall(context, intent);
//接着再判断是否有拨打电话的权限

packages/apps/Dialer/java/com/android/dialer/telecom/TelecomUtil.java

转到TelecomUtil.placeCall(context, intent);

258  public static boolean placeCall(Context context, Intent intent) {
259 if (hasCallPhonePermission(context)) {//再次判断是否有拨打权限
260 getTelecomManager(context).placeCall(intent.getData(), intent.getExtras());//去创建TelecomManager对象
261 return true;
262 }
263 return false;
264 }

转到getTelecomManager(context);

301  private static TelecomManager getTelecomManager(Context context) {
302 return (TelecomManager) context.getSystemService(Context.TELECOM_SERVICE);
303 }//返回一个TelecomManager对象,调用其placeCall方法,服务名是TELECOM_SERVICE

frameworks/base/telecomm/java/android/telecom/TelecomManager.java

转到TelecomManager.placeCall(Uri address, Bundle extras);

1857    public void placeCall(Uri address, Bundle extras) {//携带了intent的地址(应该是电话)以及其上的附加信息
1858 ITelecomService service = getTelecomService();//获取ITelecomService服务
//如果服务开启,地址不为空就会执行,此处还对附加信息进行判空处理,如果为空就new Bundle(),如果不为空就用传进来的extras
1864 service.placeCall(address, extras == null ? new Bundle() : extras,//第一次跨进程的服务调用
1865 mContext.getOpPackageName());

转到getTelecomService();

2092    private ITelecomService getTelecomService() {
2093 if (mTelecomServiceOverride != null) {//判断是否已经存在服务
2094 return mTelecomServiceOverride;
2095 }
2096 return ITelecomService.Stub.asInterface(ServiceManager.getService(Context.TELECOM_SERVICE));
2097 }//由此可知ITelecomService这个服务的服务名为TELECOM_SERVICE

frameworks/base/telecomm/java/com/android/internal/telecom/ITelecomService.aidl

转到void placeCall(in Uri handle, in Bundle extras, String callingPackage); 但毕竟这是接口,还是得去它的实现中去看这个方法的实现,ITelecomService的实现在TelecomServiceImpl这个类中

packages/services/Telecomm/src/com/android/server/telecom/TelecomServiceImpl.java

转到private final ITelecomService.Stub mBinderImpl = new ITelecomService.Stub()

108    private final ITelecomService.Stub mBinderImpl = new ITelecomService.Stub() {
...//继续调用placeCall()
1230 public void placeCall()(Uri handle, Bundle extras, String callingPackage) {
...
synchronized (mLock) {
1277 try {//创建一个新的intent,并根据传过来的intent的信息做出更新
1288 final Intent intent = new Intent(hasCallPrivilegedPermission ?
1289 Intent.ACTION_CALL_PRIVILEGED : Intent.ACTION_CALL, handle);
...//接着又处理了附加信息,创建用户CallIntent的处理器
1294 mUserCallIntentProcessorFactory.create(mContext, userHandle)
1295 .processIntent(
1296 intent, callingPackage, isSelfManaged ||
1297 (hasCallAppOp && hasCallPermission),
1298 true /* isLocalInvocation */);

packages/services/Telecomm/src/com/android/server/telecom/components/UserCallIntentProcessor.java

转到UserCallIntentProcessor.processIntent

82    public void processIntent(Intent intent, String callingPackageName,
83 boolean canCallNonEmergency, boolean isLocalInvocation) {
85 if (!isVoiceCapable()) {
86 return;
87 }
88
89 String action = intent.getAction();
90 //对三种拨号请求的类型做了或运算,表示都能进入到下面的processOutgoingCallIntent方法
91 if (Intent.ACTION_CALL.equals(action) ||
92 Intent.ACTION_CALL_PRIVILEGED.equals(action) ||
93 Intent.ACTION_CALL_EMERGENCY.equals(action)) {
94 processOutgoingCallIntent(intent, callingPackageName, canCallNonEmergency,
95 isLocalInvocation);
96 }

转到processOutgoingCallIntent()

99    private void processOutgoingCallIntent(Intent intent, String callingPackageName,
100 boolean canCallNonEmergency, boolean isLocalInvocation) {
...
sendIntentToDestination(intent, isLocalInvocation, callingPackageName);

转到sendIntentToDestination();

196    private boolean sendIntentToDestination(Intent intent, boolean isLocalInvocation,
197 String callingPackage) {
...
200 if (isLocalInvocation) {//从TelecomServiceImpl中调用的就执行如下方法
201 // We are invoking this from TelecomServiceImpl中调用的就执行如下方法, so TelecomSystem is available. Don't
202 // bother trampolining the intent, just sent it directly to the call intent processor.
203 // TODO: We should not be using an intent here; this whole flows needs cleanup.
204 Log.i(this, "sendIntentToDestination: send intent to Telecom directly.");
205 synchronized (TelecomSystem.getInstance().getLock()) {
206 TelecomSystem.getInstance().getCallIntentProcessor().processIntent(intent,
207 callingPackage);//最终会调用到CallIntentProcessor的processIntent方法
208 }

packages/services/Telecomm/src/com/android/server/telecom/CallIntentProcessor.java

调用到CallIntentProcessor.processIntent();

84    public void processIntent(Intent intent, String callingPackage) {//判断是不是未知来电
85 final boolean isUnknownCall = intent.getBooleanExtra(KEY_IS_UNKNOWN_CALL, false);//如果不是未知来电
else { //执行processOutgoingCallIntent
92 processOutgoingCallIntent(mContext, mCallsManager, intent, callingPackage);
93 }

调用到processOutgoingCallIntent()方法

104    static void processOutgoingCallIntent(
...
201 // Send to CallsManager to ensure the InCallUI gets kicked off before the broadcast returns
// 发送到CallsManager以确保在广播返回之前启动Incallui
// 1.调用callsManager.startOutgoingCall()方法
202 CompletableFuture<Call> callFuture = callsManager
203 .startOutgoingCall(handle, phoneAccountHandle, clientExtras, initiatingUser,
204 intent, callingPackage);
...// 2.调用sendNewOutgoingCallIntent()
211 sendNewOutgoingCallIntent(context, call, callsManager, intent);
...

调用到sendNewOutgoingCallIntent()方法

219    static void sendNewOutgoingCallIntent(Context context, Call call, CallsManager callsManager,
220 Intent intent) {
...//调用到 broadcaster.processCall() 发起主动呼叫通知的广播 NewOutgoingCallIntentBroadcaster broadcaster;
240 broadcaster.processCall(disposition);

调用到broadcaster.processCall()方法 在packages/services/Telecomm/src/com/android/server/telecom/NewOutgoingCallIntentBroadcaster.java

public void processCall(CallDisposition disposition) {
...//调用placeOutgoingCallImmediately()
354 placeOutgoingCallImmediately(mCall, disposition.callingAddress, null,
355 speakerphoneOn, videoState);

调用到placeOutgoingCallImmediately()方法

504    private void placeOutgoingCallImmediately(Call call, Uri handle, GatewayInfo gatewayInfo,
505 boolean speakerphoneOn, int videoState) {
...//调用callsManager.placeOutgoingCall()方法
511 mCallsManager.placeOutgoingCall(call, handle, gatewayInfo, speakerphoneOn, videoState);

综上:调用CallIntentProcessor.processOutgoingCallIntent()方法时,最终会一起调用如下两个方法

callsManager.startOutgoingCall(); 开始拨号前的准备工作,创建Call对象,将其添加到通话列表,发出新增Call的通知
callsManager.placeOutgoingCall(); 继续传递拨号请求

packages/services/Telecomm/src/com/android/server/telecom/CallsManager.java

调用到callsManager.startOutgoingCall();

1304    CompletableFuture<Call> startOutgoingCall(Uri handle,
1305 PhoneAccountHandle requestedAccountHandle,
1306 Bundle extras, UserHandle initiatingUser, Intent originalIntent,
1307 String callingPackage) {
...//依靠传进来的Uri创建Call对象,当Call对象连接上服务时,Uri可能会产生变化,但大多数情况下它是不变的
1317 if (call == null) {
1318 call = new Call(getNextCallId(), mContext,
1319 this,
1320 mLock,
1321 mConnectionServiceRepository,
1322 mPhoneNumberUtilsAdapter,
1323 handle,
...
}
...//处理其它类型的Call对象
1634 if (isPotentialMMICode(handle) && !isSelfManaged) {
1635 // 如果是Potential MMI Code就不添加Call对象
1636 callToUse.addListener(this);
1637 } else if (!mCalls.contains(callToUse) && mPendingMOEmerCall == null) {
1638 // 有可能会重复使用以前保存在mCalls里的Call对象,所以要先判断列表里是否包含了新增的Call对象
//(See {@link #reuseOutgoingCall}).
1641 addCall(callToUse);//保存并触发新增Call的通知
1642 }

调用到callsManager.addCall();

3072    public void addCall(Call call) {
3073 Trace.beginSection("addCall");
3074 Log.v(this, "addCall(%s)", call);
3075 call.addListener(this);// 将Call对象的Listener设置为CallsManager
3076 mCalls.add(call);

...//更新Call对象的mInentExtras属性,此属性在telecom包下的Call对象中,如下所示
566 private final Bundle mIntentExtras;

3084 updateCanAddCall();//更新addCall的状态
//遍历已经注册的CallsManagerListener,调用其onCallAdded方法,目的是为了快速设置Call对象为第一路通话
3086 for (CallsManagerListener listener : mListeners) {
// 回调,通知增加了Call对象
3090 listener.onCallAdded(call);

Call对象设置监听为CallsManager,CallsManager对象将Call对象添加到mCalls中,通过mListeners进行回调,他们之间相互引用

探究mListeners

		// mListeners是一个类型为CallsManagerListener的Set集合,初始大小为16,在CallsManager的构造方法中添加了13个监听器
303 private final Set<CallsManagerListener> mListeners是一个类型为 = Collections.newSetFromMap(
304 new ConcurrentHashMap<CallsManagerListener, Boolean>(16, 0.9f, 1));

public CallsManager {
527 mListeners.add(mInCallWakeLockController);
528 mListeners.add(statusBarNotifier);
529 mListeners.add(mCallLogManager);
530 mListeners.add(mPhoneStateBroadcaster);
531 mListeners.add(mInCallController);//拨号流程主要关注此监听器
532 mListeners.add(mCallAudioManager);
533 mListeners.add(mCallRecordingTonePlayer);
534 mListeners.add(missedCallNotifier);
535 mListeners.add(mHeadsetMediaButton);
536 mListeners.add(mProximitySensorManager);
}

packages/services/Telecomm/src/com/android/server/telecom/InCallController.java

调用到InCallController.onCallAdded()

763    public void onCallAdded(Call call) {
764 if (!isBoundAndConnectedToServices()) {
765 Log.i(this, "onCallAdded: %s; not bound or connected.", call);
766 // 如果没有绑定或连接服务就执行bindToServices,此处是第一次绑定,Dialer和Telecom的绑定
767 bindToServices(call);
} else {
769 ...// 如果有绑定或连接服务

调用到InCallController.bindToServices();

1103    public void bindToServices(Call call) {
...//重点关注InCallServiceBindingConnection创建的对象,即carModeInCall
1125 carModeInCall = new InCallServiceBindingConnection(carModeComponentInfo);
1128 mInCallServiceConnection = //用carModeInCall作为构造方法的参数,创建mInCallServiceConnection
1129 new CarSwappingInCallServiceConnection(systemInCall, carModeInCall);
//判断是不是显示的car的UI
1132 mInCallServiceConnection.setCarMode(shouldUseCarModeUI());
//真正的开始和InCallServie连接
1135 if (mInCallServiceConnection.connect(call) ==
1136 InCallServiceConnection.CONNECTION_SUCCEEDED) {
1137 // 只有成功连接到通话界面的服务,才能执行连接无界面InCallService服务
1139 connectToNonUiInCallServices(call);

InCallServiceConnection是InCallController的内部共有类,InCallServiceBindingConnection、EmergencyInCallServiceConnection和CarSwappingInCallServiceConnection是InCallController的内部私有类,全部继承于InCallServiceConnection

调用到mInCallServiceConnection.connect(call); 此时是CarSwappingInCallServiceConnection的connect方法

471        public int connect(Call call) {
472 if (mIsConnected) {
473 // 当前未连接
474 return CONNECTION_SUCCEEDED;
475 } else {
476 int result = mCurrentConnection.connect(call);

调用到mCurrentConnection.connect(call);

 			 private InCallServiceConnection mCurrentConnection;
//在CarSwappingInCallServiceConnection构造方法中
446 public CarSwappingInCallServiceConnection(
...
451 mCurrentConnection = getCurrentConnection();

调用到getCurrentConnection();

531        private InCallServiceConnection getCurrentConnection() {
532 if (mIsCarMode && mCarModeConnection != null) {
//不走这一步
533 return mCarModeConnection;
534 } else {
//走这一步,所以是mDialerConnection.connect(Call);
535 return mDialerConnection;
536 }
537 }

调用到InCallServiceBindingConnection的connect()方法

210        public int connect(Call call) {
211 if (mIsConnected) {//先判断是不是已经连接成功了,连接成功就忽略本次请求,很明显这里没成功,往下走
212 Log.addEvent(call, LogUtils.Events.INFO, "Already connected, ignoring request.");
213 return CONNECTION_SUCCEEDED;
214 }
...// 新new一个intent,指明绑定的service为InCallService.SERVICE_INTERFACE
224 Intent intent = new Intent(InCallService.SERVICE_INTERFACE);
225 intent.setComponent(mInCallServiceInfo.getComponentName());// 设置intent的action为InCallService服务的包名
//如果Call对象不为空、确认是拨号操作、不是外部的Call对象
226 if (call != null && !call.isIncoming() && !call.isExternalCall()){
...//添加一系列的附加信息TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS,TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE
231 }
//真正的开始连接了
233 Log.i(this, "Attempting to bind to InCall %s, with %s", mInCallServiceInfo, intent);
234 mIsConnected = true;
235 if (!mContext.bindServiceAsUser(intent, mServiceConnection,//同步创建mServiceConnection匿名对象
236 Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE |
237 Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS |
238 Context.BIND_ABOVE_CLIENT,
239 UserHandle.CURRENT)) {

//注:创建InCallServiceBindingConnection对象的时候会同步创建ServiceConnection的匿名对象mServiceConnection
166 private class InCallServiceBindingConnection extends InCallServiceConnection {
167
168 private final ServiceConnection mServiceConnection = new ServiceConnection() {

调用到mServiceConnection的匿名内部类ServiceConnection重写的方法

170            public void onServiceConnected(ComponentName name, IBinder service) {
177 // Only proceed if we are supposed to be connected.
178 onConnected(service);
184 }
185
186 @Override
187 public void onServiceDisconnected(ComponentName name) {
...
199 };

调用到InCallServiceBindingConnection的onConnected()方法

280        protected void onConnected(IBinder service) {
281 boolean shouldRemainConnected =
282 InCallController.this.onConnected(mInCallServiceInfo, service);
283 if (!shouldRemainConnected) {
288 disconnect();
289 }
290 }

调用到InCallController的onConnected()方法

1358    private boolean onConnected(InCallServiceInfo info, IBinder service) {
...//获取IInCallService服务并保存
1362 IInCallService inCallService = IInCallService.Stub.asInterface(service);
1363 mInCallServices.put(info, inCallService);
// 添加Adapter
1365 try {
1366 inCallService.setInCallAdapter(
1367 new InCallAdapter(
1368 mCallsManager,
1369 mCallIdMapper,
1370 mLock,
1371 info.getComponentName().getPackageName()));
}
...//把之前添加进来的Call对象,通过IInCallService发送出去,通过addCall方法
1383 for (Call call : calls) { //第二次跨进程服务调用
...//有Call对象的转换,将com.android.server.telecom.Call转换成可跨进程传递的对象android.telecom.ParcelabelCall
1396 inCallService.addCall(ParcelableCallUtils.toParcelableCall(
1397 call,
1398 true /* includeVideoProvider */,
1399 mCallsManager.getPhoneAccountRegistrar(),
1400 info.isExternalCallsSupported(),
1401 includeRttCall,
1402 info.getType() == IN_CALL_SERVICE_TYPE_SYSTEM_UI));
...//通过inCallService传递Call的更新状态
1406 try {
1407 inCallService.onCallAudioStateChanged(mCallsManager.getAudioState());
1408 inCallService.onCanAddCallChanged(mCallsManager.canAddCall());

由于绑定了IncallService服务,所以下一步应该走到IncallService的方法,由于IncallService是一个位于frameworks/base/telecomm/java/android/telecom/InCallService.java的抽象类,所以需要转到其实现类InCallServiceImpl.java中

packages/apps/Dialer/java/com/android/incallui/InCallServiceImpl.java

调用到InCallServiceImpl的onBind()去响应绑定服务这个过程

95  public IBinder onBind(Intent intent) {
...//启动指定的IncallActivity
113 InCallPresenter.getInstance().maybeStartRevealAnimation(intent);
...//调用到父类的onBind方法
120 IBinder iBinder = super.onBind(intent);

调用到InCallService的onBind()方法

421    public IBinder onBind(Intent intent) {
422 return new InCallServiceBinder();
423 }

调用到内部类InCallServiceBinder

private final class InCallServiceBinder extends IInCallService.Stub {
293 @Override//最终在这里调用到setInCallAdapter以及addCall
294 public void setInCallAdapter(IInCallAdapter inCallAdapter) {
295 mHandler.obtainMessage(MSG_SET_IN_CALL_ADAPTER, inCallAdapter).sendToTarget();
296 }
297
298 @Override
299 public void addCall(ParcelableCall call) {
300 mHandler.obtainMessage(MSG_ADD_CALL, call).sendToTarget();
301 }
302
303 @Override
304 public void updateCall(ParcelableCall call) {
305 mHandler.obtainMessage(MSG_UPDATE_CALL, call).sendToTarget();
306 }
// mHandler发送Handler消息将IInCallService的同步调用转换为异步处理
//---------------------------------------------------------------------------------------------------------------------
//同步调用在匿名内部类 ServiceConnection (InCallController的私有内部类InCallServiceBindingConnection) 中
166 private class InCallServiceBindingConnection extends InCallServiceConnection {
167
168 private final ServiceConnection mServiceConnection = new ServiceConnection() {
169 @Override
170 public void onServiceConnected(ComponentName name, IBinder service) {
171 Log.startSession("ICSBC.oSC");
172 synchronized (mLock) {
...
178 onConnected(service);

onBind()只是获取到了intent对象,对于Call对象的信息一无所知,相当于对InCallActivity的预加载过程,具体的Call对象信息状态的更新在addCall和updateCall中完成

调用到setInCallAdapter

294        public void setInCallAdapter(IInCallAdapter inCallAdapter) {
// 发初异步处理消息 MSG_SET_IN_CALL_ADAPTER
295 mHandler.obtainMessage(MSG_SET_IN_CALL_ADAPTER, inCallAdapter).sendToTarget();
296 }

调用到handleMessage();

206    private final Handler mHandler = new Handler(Looper.getMainLooper()) {
207 @Override
208 public void handleMessage(Message msg) {
209 if (mPhone == null && msg.what != MSG_SET_IN_CALL_ADAPTER) {
210 return;
211 }
212
213 switch (msg.what) {
214 case MSG_SET_IN_CALL_ADAPTER:
215 String callingPackage = getApplicationContext().getOpPackageName();
// 创建Phone对象,给Phone对象的Listener属性赋值,这个Phone对象和InCallService在同一个包下面
// 此处还new InCallAdapter,可以跨进程调用Telecom应用
216 mPhone = new Phone(new InCallAdapter((IInCallAdapter) msg.obj), callingPackage,
217 getApplicationContext().getApplicationInfo().targetSdkVersion);
// 此处是拨号流程Dialer应用中第一个Listener
218 mPhone.addListener(mPhoneListener);
219 onPhoneCreated(mPhone);
220 break;

此时setInCallAdapter()已调用完毕,回过头来调用addCall();

221                case MSG_ADD_CALL:
222 mPhone.internalAddCall((ParcelableCall) msg.obj);
223 break;

frameworks/base/telecomm/java/android/telecom/Phone.java

调用到Phone.internalAddCall();

145    final void internalAddCall(ParcelableCall parcelableCall) {//根据parcelableCall的信息创建Call对象
146 Call call = new Call(this, parcelableCall.getId(), mInCallAdapter,
147 parcelableCall.getState(), mCallingPackage, mTargetSdkVersion);
148 mCallByTelecomCallId.put(parcelableCall.getId(), call);
149 mCalls.add(call);
150 checkCallTree(parcelableCall);
151 call.internalUpdate(parcelableCall, mCallByTelecomCallId);通过parcelableCall更新当前的Call对象
152 fireCallAdded(call);//发出新增Call的通知
153 }

这里就很疑惑了,好像在CallsManager.addCall方法中有同样的创建Call对象和发出新增Call对象通知的操作,那么这两个Call对象是否是同一个?
答案是否定的,CallsManager中创建的Call对象是在packages/services/Telecomm/src/com/android/server/telecom中的定义,而Phone.internalAddCall中的Call对象是在frameworks/base/telecomm/java/android/telecom/中的定义,前者是在Telecom应用中,后者是在Dialer应用中。Telecom应用中创建Call对象后,会通过此Call对象创建跨进程传递的parcelableCall对象,在Dialer应用中通过parcelableCall的信息继续创建Dialer中的Call对象

调用到Phone.fireCallAdded();

380    private void fireCallAdded(Call call) {
// private final List<Listener> mListeners = new CopyOnWriteArrayList<>(); 线程安全
// 这里的mListeners通过赋值已经是mPhoneListener
381 for (Listener listener : mListeners) {
382 listener.onCallAdded(this, call);//传递Call对象,
383 }
384 }

响应到frameworks/base/telecomm/java/android/telecom/InCallService.java——InCallService.mPhoneListener.onCallAdded();

372    private Phone.Listener mPhoneListener = new Phone.Listener() {
...
391 public void onCallAdded(Phone phone, Call call) {
392 InCallService.this.onCallAdded(call);
393 }

调用到InCallService.onCallAdded();

606    public void onCallAdded(Call call) {
607 }
//是一个空方法,说明子类重写了此方法

packages/apps/Dialer/java/com/android/incallui/InCallServiceImpl.java

调用到[InCallServiceImpl.onCallAdded();

66  public void onCallAdded(Call call) {
67 Trace.beginSection("InCallServiceImpl.onCallAdded");
68 InCallPresenter.getInstance().onCallAdded(call);
69 Trace.endSection();
70 }
//接着会进入类InCallPresenter调用其onCallAdded()方法,最终的调用结果是
628 callList.onCallAdded(context, call, latencyReport);

packages/apps/Dialer/java/com/android/incallui/call/CallList.java

调用到CallList.onCallAdded();

122  public void onCallAdded(
123 final Context context, final android.telecom.Call telecomCall, LatencyReport latencyReport) {
...
148 call.addListener(new DialerCallListenerImpl(call));//添加监听跟踪信息
...
798 private class DialerCallListenerImpl implements DialerCallListener {

816 public void onDialerCallUpdate() {
817 Trace.beginSection("CallList.onDialerCallUpdate");
818 onUpdateCall(call);
819 notifyGenericListeners();
820 Trace.endSection();
821 }

//拨号流程Dialer应用中第二个Listener
615 private void notifyGenericListeners() {
616 Trace.beginSection("CallList.notifyGenericListeners");
617 for (Listener listener : listeners) {
618 listener.onCallListChange(this);
619 }
620 Trace.endSection();
621 }

//接着会进入类InCallPresenter调用onCallListChange,拨号流程Dialer应用中第三个Listener
882 for (InCallStateListener listener : listeners) {
883 LogUtil.d(
884 "InCallPresenter.onCallListChange",
885 "Notify " + listener + " of state " + inCallState.toString());
886 listener.onStateChange(oldState, inCallState, callList);
887 }

至此,通过调用onStateChange方法后结束了一开始在CallsManager中调用startOutgoingCall的调用,之后会显示出通话界面InCallActivity

下面开始跟进CallsManager.placeOutgoingCall

packages/services/Telecomm/src/com/android/server/telecom/CallsManager.java

调用到CallsManager.placeOutgoingCall();

1947    public void placeOutgoingCall(Call call, Uri handle, GatewayInfo gatewayInfo,
1948 boolean speakerphoneOn, int videoState) {
...//如果获取到目标用户或者是紧急电话
1996 if (call.getTargetPhoneAccount() != null || call.isEmergencyCall()) {
1999 if (call.isSelfManaged() && !isOutgoingCallPermitted) {
2000 notifyCreateConnectionFailed(call.getTargetPhoneAccount(), call);
2001 } else {
2002 if (call.isEmergencyCall()) {//如果是紧急电话
2004 disconnectSelfManagedCalls("place emerg call" /* reason */);
2005 }
2007 if (mPendingMOEmerCall == null) {//开始创建Connection对象
2011 call.startCreateConnection(mPhoneAccountRegistrar);
2012 }
...

packages/services/Telecomm/src/com/android/server/telecom/Call.java

调用到Call.startCreateConnection();

1720    void startCreateConnection(PhoneAccountRegistrar phoneAccountRegistrar) {
...//先判断是否已经拥有createProssesor处理器,如果有则返回
1728 mCreateConnectionProcessor = new CreateConnectionProcessor(this, mRepository, this,
1729 phoneAccountRegistrar, mContext);
1730 mCreateConnectionProcessor.process();//通过mCreateConnectionProcessor来创建Connection对象

packages/services/Telecomm/src/com/android/server/telecom/CreateConnectionProcessor.java

调用到CreateConnectionProcessor.process();

158    public void process() {
...
171 attemptNextPhoneAccount();
}

调用到CreateConnectionProcessor.attemptNextPhoneAccount();

205    private void attemptNextPhoneAccount() {
...
233 if (mCallResponse != null && attempt != null) {// 又创建了一个新的服务
236 mService = mRepository.getService(phoneAccount.getComponentName(),
237 phoneAccount.getUserHandle());
238 if (mService == null) {// 如果这个服务没有连接,则递归调用attemptNextPhoneAccount
239 Log.i(this, "Found no connection service for attempt %s", attempt);
240 attemptNextPhoneAccount();
241 } else {
242 mConnectionAttempt++;
243 mCall.setConnectionManagerPhoneAccount(attempt.connectionManagerPhoneAccount);
244 mCall.setTargetPhoneAccount(attempt.targetPhoneAccount);
245 mCall.setConnectionService(mService);
246 setTimeoutIfNeeded(mService, attempt);
if {
...
249 } else {// 服务连接好后,通过服务创建Connection对象
258 mService.createConnection(mCall,CreateConnectionProcessor.this);

-----------------------------------------------------------------------------------------------------------------------
//在本类中,mService的定义如下,说明它是ConnectionServiceWrapper类型的服务
124 private ConnectionServiceWrapper mService;

packages/services/Telecomm/src/com/android/server/telecom/ConnectionServiceWrapper.java

调用到ConnectionServiceWrapper.createConnection();

1107    public void createConnection(final Call call, final CreateConnectionResponse response) {
1111 public void onSuccess() {
...
1178 }
1181 public void onFailure() {
...
1184 }
1187 mBinder.bind(callback, call);

-----------------------------------------------------------------------------------------------------------------------
68public class ConnectionServiceWrapper extends ServiceBinder implements
69 ConnectionServiceFocusManager.ConnectionServiceFocus {
1043 private Binder2 mBinder = new Binder2();
}

42public abstract class ServiceBinder {
62 final class Binder2 {
...
}
}
// 所以,从上面可以看出mBinder是ConnectionServiceWrapper的父类

packages/services/Telecomm/src/com/android/server/telecom/ServiceBinder.java

调用到Binder2.bind();

70        void bind(BindCallback callback, Call call) {
...
85 if (mServiceConnection == null) {// 通过mServiceAction指定将要绑定什么服务
86 Intent serviceIntent = new Intent(mServiceAction).setComponent(mComponentName);
87 ServiceConnection connection = new ServiceBinderConnection(call);
...
96 } else {///开始绑定服务,第二次绑定Telecom和Telephony的绑定
97 isBound = mContext.bindService(serviceIntent, connection, bindingFlags);

----------------------------------------------------------------------------------------------------------------------- //在ConnectionServiceWrapper的构造方法中调用了父类的构造方法,即
1062 ConnectionServiceWrapper(
1063 ComponentName componentName,
1064 ConnectionServiceRepository connectionServiceRepository,
1065 PhoneAccountRegistrar phoneAccountRegistrar,
1066 CallsManager callsManager,
1067 Context context,
1068 TelecomSystem.SyncRoot lock,
1069 UserHandle userHandle) {
1070 super(ConnectionService.SERVICE_INTERFACE, componentName, context, lock, userHandle);
...// 将父类中构造方法的第一个参数serviceAction赋值为ConnectionService.SERVICE_INTERFACE
}

255    protected ServiceBinder(String serviceAction, ComponentName componentName, Context context,
256 TelecomSystem.SyncRoot lock, UserHandle userHandle) {
...// 即bind方法里面intent要绑定的服务为ConnectionService.SERVICE_INTERFACE
262 mServiceAction = serviceAction;
...
265 }

研究ServiceConnection connection = new ServiceBinderConnection(call),调用到ServiceConnection.onServiceConnected();

//bindService中传入了ServiceConnection的对象,响应到ServiceConnection的onServiceConnected();
145 public void onServiceConnected(ComponentName componentName, IBinder binder) {
...
162 if (binder != null) {
163 mServiceDeathRecipient = new ServiceDeathRecipient(componentName);
164 try {
165 binder.linkToDeath(mServiceDeathRecipient, 0);
166 mServiceConnection = this;
167 setBinder(binder); //保存绑定服务成功后的Binder对象
168 handleSuccessfulConnection();//bindService成功之后的处理逻辑

调用到ServiceBinder.setBinder();

418    private void setBinder(IBinder binder) {
419 if (mBinder != binder) {
420 if (binder == null) {
...//binder != null 走下面
425 }
426 } else {
427 mBinder = binder;
428 setServiceInterface(binder);
429 }
430 }
431 }

调用到ServiceBinder.setServiceInterface();

438    protected abstract void setServiceInterface(IBinder binder);// 抽象方法,在子类ConnectionServiceWrapper中实现

调用到ConnectionServiceWrapper的setServiceInterface方法

1622    protected void setServiceInterface(IBinder binder) {
1623 mServiceInterface = IConnectionService.Stub.asInterface(binder);//保存BInder对象
1624 Log.v(this, "Adding Connection Service Adapter.");
1625 addConnectionServiceAdapter(mAdapter);// 增加Adapter对象
1626 }

调用到ConnectionServiceWrapper.addConnectionServiceAdapter();

1082    private void addConnectionServiceAdapter(IConnectionServiceAdapter adapter) {
...// 最终是通过ConnectionService服务增加Adapter对象
1086 mServiceInterface.addConnectionServiceAdapter(adapter, Log.getExternalSession());
...
1090 }
// 此处添加的是IConnectionServiceAdapter,进入其aidl文件查看

frameworks/base/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl

47    void setActive(String callId, in Session.Info sessionInfo);
48
49 void setRinging(String callId, in Session.Info sessionInfo);
50
51 void setDialing(String callId, in Session.Info sessionInfo);
52
53 void setPulling(String callId, in Session.Info sessionInfo);
...
// 全是和通话状态相关的接口方法,当前绑定的服务为ConnectionService,通过调用Adapter中的方法来更新Telec om通话状态

回过头来看handleSuccessfulConnection(); 这个方法在ServiceBinder类里面

356    private void handleSuccessfulConnection() {
357 // Make a copy so that we don't have a deadlock inside one of the callbacks. 防止死锁
358 Set<BindCallback> callbacksCopy = new ArraySet<>();
359 synchronized (mCallbacks) {// 进来后每回处理的都是新的数组
360 callbacksCopy.addAll(mCallbacks);
361 mCallbacks.clear();
362 }
363
364 for (BindCallback callback : callbacksCopy) {
365 callback.onSuccess();
366 }
367 }

callback.onSuccess()在子类ConnectionServiceWrapper.createConnection中实现

1107    public void createConnection(final Call call, final CreateConnectionResponse response) {
1108 Log.d(this, "createConnection(%s) via %s.", call, getComponentName());
1109 BindCallback callback = new BindCallback() {
1110 @Override
1111 public void onSuccess() {
...// 根据通话的相关信息创建connectionRequest
1149 ConnectionRequest connectionRequest = new ConnectionRequest.Builder()
1150 .setAccountHandle(call.getTargetPhoneAccount())
1151 .setAddress(call.getHandle())
1152 .setExtras(extras)
1153 .setVideoState(call.getVideoState())
1154 .setTelecomCallId(callId)//
1155 // For self-managed incoming calls, if there is another ongoing call Telecom
1156 // is responsible for showing a UI to ask the user if they'd like to answer
1157 // this new incoming call.
1158 .setShouldShowIncomingCallUi(
1159 !mCallsManager.shouldShowSystemIncomingCallUi(call))
1160 .setRttPipeFromInCall(call.getInCallToCsRttPipeForCs())
1161 .setRttPipeToInCall(call.getCsToInCallRttPipeForCs())
1162 .build();
1164 try {
1165 mServiceInterface.createConnection( // 第二次跨进程访问,绑定的对象依然为ConnectionService
1166 call.getConnectionManagerPhoneAccount(),
1167 callId,
1168 connectionRequest,
1169 call.shouldAttachToExistingConnection(),
1170 call.isUnknown(),
1171 Log.getExternalSession());

拨号流程中,telecom应用第二次跨进程访问,将call对象传给了Dialer应用,使通话界面得到更新,第三次跨进程访问,将Call拨号请求的相关信息封装成ConnectionRequest对象并传给了TeleService应用

根据AndroidManifest.xml中的定义,android.telecom.ConnectionService服务所服务的Java类为TelephonyConnectionService,TelephonyConnectionService继承自ConnectionService抽象类,分别从onBind,addConnectionServiceAdapter和createConnection加以分析

调用到ConnectionService.onBinder()

1542    public final IBinder onBind(Intent intent) {
1543 return mBinder;// 返回IConnectionService.Stub的对象
1544 }

调用到ConnectionService.mBinder.addConnectionServiceAdapter()

207        public void addConnectionServiceAdapter(IConnectionServiceAdapter adapter,
208 Session.Info sessionInfo) {
...
214 mHandler.obtainMessage(MSG_ADD_CONNECTION_SERVICE_ADAPTER, args).sendToTarget();
...
}

680 private final Handler mHandler = new Handler(Looper.getMainLooper()) {
681 @Override
682 public void handleMessage(Message msg) {
683 switch (msg.what) {
684 case MSG_ADD_CONNECTION_SERVICE_ADAPTER: {
685 SomeArgs args = (SomeArgs) msg.obj;
686 try {
687 IConnectionServiceAdapter adapter = (IConnectionServiceAdapter) args.arg1;
688 Log.continueSession((Session) args.arg2,
689 SESSION_HANDLER + SESSION_ADD_CS_ADAPTER);
690 mAdapter.addAdapter(adapter);
691 onAdapterAttached();
692 } finally {
693 args.recycle();
694 Log.endSession();
695 }
696 break;

调用到ConnectionService.createConnection() 继续发送拨号请求

1558    private void createConnection(
1559 final PhoneAccountHandle callManagerAccount,
1560 final String callId,
1561 final ConnectionRequest request,
1562 boolean isIncoming,
1563 boolean isUnknown) {
...// 分别去创建不同的connection对象
1583 } else {
1584 connection = isUnknown ? onCreateUnknownConnection(callManagerAccount, request)
1585 : isIncoming ? onCreateIncomingConnection(callManagerAccount, request)
1586 : onCreateOutgoingConnection(callManagerAccount, request);
...
1617 mAdapter.handleCreateConnectionComplete(
...//通过mAdapter传过来的binder对象进行接口回调

首先看onCreateOutgoingConnection,子类TelephonyService重写了此方法

packages/services/Telephony/src/com/android/services/telephony/TelephonyConnectionService.java

调用到[TelephonyConnectionService.onCreateOutgoingConnection

497    public Connection onCreateOutgoingConnection(
498 PhoneAccountHandle connectionManagerPhoneAccount,
499 final ConnectionRequest request) {
...//首先判断是不时紧急电话
674 final Phone phone = getPhoneForAccount(request.getAccountHandle(), isEmergencyNumber, 675 /* Note: when not an emergency, handle can be null for unknown callers */
676 handle == null ? null : handle.getSchemeSpecificPart());
...
691 placeOutgoingConnection(request, resultConnection, phone);

调用到placeOutgoingConnection();

1399    private void placeOutgoingConnection(
...
1410 if (phone != null) {// 这里的Phone对象为GsmCdmaPhone
1411 if (isAddParticipant) {
1412 phone.addParticipant(number);
1413 return;
1414 } else {
1415 originalConnection = phone.dial(number, new ImsPhone.ImsDialArgs.Builder()
1416 .setVideoState(videoState)
1417 .setIntentExtras(extras)
1418 .setRttTextStream(connection.getRttTextStream())
1419 .build());
1420 }
1421 }

如果是普通呼叫,则此处的Phone对象为GsmCdmaPhone,调用到GsmCdmaPhone.dial()

1158    public Connection dial(String dialString, @NonNull DialArgs dialArgs)
1159 throws CallStateException {
...
1267 if (isPhoneTypeGsm()) {
1268 return dialInternal(dialString, new DialArgs.Builder<>()
1269 .setIntentExtras(dialArgs.intentExtras)
1270 .build());
1271 } else {
1272 return dialInternal(dialString, dialArgs);

调用到GsmCdmaPhone.dialInternal(),两个参数的

1318    protected Connection dialInternal(String dialString, DialArgs dialArgs,
1319 ResultReceiver wrappedCallback)
1320 throws CallStateException {
...
1348 } else {
1349 return mCT.dial(newDialString, dialArgs.intentExtras);

mCT即GsmCdmaCallTracker

frameworks/opt/telephony/src/java/com/android/internal/telephony/GsmCdmaCallTracker.java

调用到[GsmCdmaCallTracker.dialGsm

282    public synchronized Connection dialGsm(String dialString, int clirMode, UUSInfo uusInfo,
283 Bundle intentExtras)
284 throws CallStateException {
...
326 mPendingMO = new GsmCdmaConnection(mPhone, checkForTestEmergencyNumber(dialString),
327 this, mForegroundCall, isEmergencyCall);kan
...
338 if ( mPendingMO.getAddress() == null || mPendingMO.getAddress().length() == 0
339 || mPendingMO.getAddress().indexOf(PhoneNumberUtils.WILD) >= 0) {//如果号码非法
...
346 } else {
347 // Always unmute when initiating a new call
348 setMute(false);
349 boolean isPhoneInEcmMode = EcbmHandler.getInstance().isInEcm();
350 // In Ecm mode, if another emergency call is dialed, Ecm mode will not exit.
351 if(!isPhoneInEcmMode || (isPhoneInEcmMode && isEmergencyCall)) {// 调用到mCi.dial()
352 mCi.dial(mPendingMO.getAddress(), mPendingMO.isEmergencyCall(),
353 mPendingMO.getEmergencyNumberInfo(),
354 mPendingMO.hasKnownUserIntentEmergency(), clirMode, uusInfo,
355 obtainCompleteMessage());

调用到mCi.dial时,将通话请求转交到Modem中

packages/services/Telecomm/src/com/android/server/telecom/ConnectionServiceWrapper.java

回过头来看mAdapter.handleCreateConnectionComplete()接口回调

1689    private void handleCreateConnectionComplete(
1690 String callId,
1691 ConnectionRequest request,
1692 ParcelableConnection connection) {
...
1708 } else {
1709 // Successful connection
1710 if (mPendingResponses.containsKey(callId)) {
1711 mPendingResponses.remove(callId)
1712 .handleCreateConnectionSuccess(mCallIdMapper, connection);

最终调用到Call.handleCreateConnectionSuccess();

1734    public void handleCreateConnectionSuccess(
1735 CallIdMapper idMapper,
1736 ParcelableConnection connection) {
...
1758 switch (mCallDirection) {
1759 case CALL_DIRECTION_INCOMING:
1760 // Listeners (just CallsManager for now) will be responsible for checking whether
1761 // the call should be blocked.
1762 for (Listener l : mListeners) {
1763 l.onSuccessfulIncomingCall(this);
1764 }
1765 break;
1766 case CALL_DIRECTION_OUTGOING:
1767 for (Listener l : mListeners) {
1768 l.onSuccessfulOutgoingCall(this,
1769 getStateFromConnectionState(connection.getState()));
1770 }
1771 break;
//Call类中有ListenerBase抽象类,它实现了Listener接口,实现了Listener所有方法,并且都是空方法,在ListenerBase的三个子类CallsManager,InCallController的匿名内部类对象mCallListener,InComingCallNotifier的匿名内部类对象mCallListener,在这三个类中只有CallsManger重写了onSuccessfulOutgoingCall方法,继续跟进

调用到CallsManager.onSuccessfulOutgoingCall()

581    public void onSuccessfulOutgoingCall(Call call, int callState) {
...
584 setCallState(call, callState, "successful outgoing call");// 改变Call的状态
...
596 markCallAsDialing(call);

调用到CallsManager.markCallAsDialing();

2528    void markCallAsDialing(Call call) {
2529 setCallState(call, CallState.DIALING, "dialing set explicitly");

调用到CallsManager.setCallState();

3137    private void setCallState(Call call, int newState, String tag) {
3168 for (CallsManagerListener listener : mListeners) {
3169 if (LogUtils.SYSTRACE_DEBUG) {
...// 这里的Listener为InCallController
3173 listener.onCallStateChanged(call, oldState, newState);

调用到InCallController.onCallStateChanged();

912    public void onCallStateChanged(Call call, int oldState, int newState) {
913 updateCall(call);
914 }

调用到InCallController.updateCall();

1446    private void updateCall(Call call, boolean videoProviderChanged, boolean rttInfoChanged) {
...// 通过已经修改状态的Call对象构造跨进程传递的ParcelableCall对象
1460 ParcelableCall parcelableCall = ParcelableCallUtils.toParcelableCall(
1461 call,
1462 videoProviderChanged /* includeVideoProvider */,
1463 mCallsManager.getPhoneAccountRegistrar(),
1464 info.isExternalCallsSupported(),
1465 rttInfoChanged && info.equals(mInCallServiceConnection.getInfo()),
1466 info.getType() == IN_CALL_SERVICE_TYPE_SYSTEM_UI);
...
1471 try {// 通过inCallService调用updateCall来更新当前通话界面的通话状态为Dialing
1472 inCallService.updateCall(parcelableCall);

至此,打电话流程完毕

原创:https://www.panoramacn.com
源码网提供WordPress源码,帝国CMS源码discuz源码,微信小程序,小说源码,杰奇源码,thinkphp源码,ecshop模板源码,微擎模板源码,dede源码,织梦源码等。

专业搭建小说网站,小说程序,杰奇系列,微信小说系列,app系列小说

源码环境下跟进MO通话流程(涉及到其中每一个方法的跳转)

免责声明,若由于商用引起版权纠纷,一切责任均由使用者承担。

您必须遵守我们的协议,如果您下载了该资源行为将被视为对《免责声明》全部内容的认可-> 联系客服 投诉资源
www.panoramacn.com资源全部来自互联网收集,仅供用于学习和交流,请勿用于商业用途。如有侵权、不妥之处,请联系站长并出示版权证明以便删除。 敬请谅解! 侵权删帖/违法举报/投稿等事物联系邮箱:2640602276@qq.com
未经允许不得转载:书荒源码源码网每日更新网站源码模板! » 源码环境下跟进MO通话流程(涉及到其中每一个方法的跳转)
关注我们小说电影免费看
关注我们,获取更多的全网素材资源,有趣有料!
120000+人已关注
分享到:
赞(0) 打赏

评论抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

您的打赏就是我分享的动力!

支付宝扫一扫打赏

微信扫一扫打赏