Version:1.0 StartHTML:0000000174 EndHTML:0000527746 StartFragment:0000129196 EndFragment:0000527706 SourceURL:file:///Y:\Desktop\Dialer\Android去电流程%203.18.docx
Android去电流程
6.Frameworks Telephony层流程.... 8
此文档详细的介绍了android中的去电流程,一直从上层(dialer)到底层(RIL)层的详细流程,可以让相关的同事在解决去电问题的时候快速的定位问题点,方便了bug的fix。
此问题使用了android P平台,高通和MTK均适用。
- 层流程
- 模块简介
- 概述
- 模块简介
手机最基本的功能包括两个大的方面,一个是打电话功能,一个是短信功能,我们这里的Dialer模块指的就是打电话功能的一部分,他是手机与用户交互的桥梁,提供图形界面来给用户操作,使用户能够通过一系列的操作拨打电话等等。
从源码的包的命名,可以将Dialer分为四个大的部分,包含:contact、incallui、dialer、voicemial。Contact主要是联系人相关的逻辑,与Contact模块有着很大的联系;incallui主要是通话过程中的incall界面的东西,在通话过程中,设计到很多的与底层交与的逻辑,需要调用底层的接口来获取电话状态并显示在incall界面上,需要调用底层接口来对call进行操作;dialer主要是点击app图标进入之后的界面的显示、界面相关操作的逻辑以及一部分dialer的设置;voicemial是voicemail相关的代码,调用的是底层的接口。
-
- 关键代码及log
这一个部分代码逻辑较为简单,且代码中没有打印关键log,所以这一部分就不贴关键代码以及关键log,只要关注上一个部分的流程就可以。
- 层流程
- 模块简介
- 概述
- 模块简介
这里的Telecom层指的是位于packages/services/Telecomm的模块,是android 5.0之后从phone进程中提出来的位于incallui(也就是dialer进程)和phone进程(telephony)之间的模块,运行于系统进程之中。基本上所有的incallui界面上的显示相关的信息都是从这个模块中调用接口获取而来的,而这个模块实质上是没有和底层打交道的,他上面链接dialer,下面链接的是framework/base/telecom,所以可以把他看做是一个中间层的接口,涉及到底层的东西是没有放在这里处理的。
实际上,在这个模块中,我认为最最重要的需要我们来关注的类,就是TelecomServiceImpl.java,基本上所有的call相关的重要方法,都是放在这个类中来实现的。
-
- 流程分析
- 流程图
- 流程分析
-
-
- 分析
-
- 检查一些权限相关的东西,然后创建一个UserCallIntentProcessor,调用它的processIntent方法。
- 从intent中取出action,判断action是否等于ACTION_CALL||ACTION_CALL_PRIVILEGED||ACTION_CALL_EMERGENCY。如果相等,调用processOutgoingCallIntent方法
- 对号码的uri做了以下处理,判断传入的正在拨号的dialer是不是默认dialer,存入intent中(CallIntentProcessor.KEY_IS_PRIVILEGED_DIALER)。然后调用sendIntentToDestination方法
- 在这个方法中会判断isLocalInvocation,这个参数是从TelecomServiceImpl中的placeCall方法传过来的,默认是true。如果是false,就会发送广播到PrimaryCallReceiver,然后调用CallIntentProcessor的processIntent方法。如果是true,则会直接调用CallIntentProcessor的processIntent方法,这样就省去了中间的广播接受时间,性能更加优异。
- 在processIntent方法中,从intent中判断KEY_IS_UNKNOWN_CALL是否是true,如果是,则调用processUnknownCallIntent方法,如果不是,调用processOutgoingCallIntent方法。
- 对号码的uri进行处理,判断是sip号码还是普通号码,添加上scheme,将call相关的信息封装到Bundle中,然后调用callsmanager的startOutgoingCall方法。
- 在startOutgoingCall方法中,创建了一个call对象,并调用call.setTargetPhoneAccount方法设置了call的phone账户,并判断是否需要选择账户,如果需要,设置call的State为CallState.SELECT_PHONE_ACCOUNT,如果不需要,就将call的状态设置为CallState.CONNECTING,并在这个方法中判断传入的Bundle中是否含有TelecomManager.EXTRA_START_CALL_WITH_RTT,如果是true,则表示用户拨出的是rtt call,会调用call.setRequestedToStartWithRtt()方法去启动rtt。然后调用addCall方法,在这个方法中,会遍历call状态变化的观察者并逐个回调通知,这里的观察者比较多,在callsManager创建的时候注册监听的,call状态的改变会通知到这些观察者(里面包含了一个重要的观察者:incallcontroller,它内部封装了与incallui服务的相关操作,实际上就是一个远程服务代理类,当callsmanager添加一路call时, 回调InCallController的onCallAdded方法,最后调用inCallService的addCall方法告诉incallui当前添加了一路通话,incallui收到后会拉起界面)。初始化完毕call,返回给processOutgoingCallIntent方法,接着调用sendNewOutgoingCallIntent。
- 创建一个NewOutgoingCallIntentBroadcaster对象,调用他的processIntent方法。这个方法是有返回值的,如果返回值不等于DisconnectCause.NOT_DISCONNECTED,那么就会在这里挂断电话并弹出提示框提示。
- 在processIntent方法中,会判断号码是不是voicemail,如果是,会调用placeOutgoingCallImmediately方法去拨打电话。如果不是,会先调用rewriteCallIntentAction方法去修改action,因为传入的action有三种:
普通call Intent.ACTION_CALL
系统call Intent.ACTION_CALL_PRIVILEGED
紧急呼叫call Intent.ACTION_CALL_EMERGENCY
普通call任何应用都可以发起,第三方应用拨号都是使用该intent;系统call只有系统应用才能使用;紧急呼叫call 同样只有系统应用才能使用,并且可以在无卡状态下呼出。对于一个Intent.ACTION_CALL_PRIVILEGED的拨号请求,会根据当前号码是否为紧急号码来转化该intent,如果是紧急号码则转化为Intent.ACTION_CALL_EMERGENCY如果不是紧急号码则转化为Intent.ACTION_CALL,所以实际上处理call只有两种情况Intent.ACTION_CALL和Intent.ACTION_CALL_EMERGENCY。
对于Intent.ACTION_CALL的处理:
如果当前是紧急号码,会校验调用者是否为系统默认拨号盘,如果是则置变量callImmediately为true,后续直接呼出该电话。如果不是则拉起系统默认拨号盘,当前方法调用返回DisconnectCause.OUTGOING_CANCELED
对于Intent.ACTION_CALL_EMERGENCY的处理:
直接设置变量callImmediately为true,直接呼出该电话。
所以如果callImmediately参数为true,会直接调用placeOutgoingCallImmediately方法来拨打电话,不会去发送广播。而如果这个参数为false,会调用broadcastIntent方法来拨打电话。
- 在broadcastIntent方法中,调用sendOrderedBroadcastAsUser方法发送了广播。
- NewOutgoingCallIntentBroadcast的onReceive方法接收到这个广播,最后还是调用placeOutgoingCallImmediately方法来拨打电话。
- 在placeOutgoingCallImmediately方法中,将call的mIsNewOutgoingCallIntentBroadcastDone参数设置为了true,表示NewOutgoingCallIntentBroadcast完毕,接着调用callsmanager的placeOutgoingCall方法。
- 在callsmanager的placeOutgoingCall方法中,会检查是否需要打开扬声器,如果需要会打开扬声器。然后调用call的startCreateConnection方法去创建Connection。
- startCreateConnection方法中创建了一个CreateConnectionProcessor对象,然后调用它的process方法。
- 向mAttemptRecords中加入当前电话的CallAttemptRecord对象,实质上就是两个PhoneAccountHandle对象。然后调用attemptNextPhoneAccount方法。
- 在attemptNextPhoneAccount方法中,首先会判断mAttemptRecords列表中的PhoneAccountHandle是否具有BIND_TELECOM_CONNECTION_SERVICE权限,判断是否能够绑定链接,然后调用ConnectionServiceRepository的getService()方法得到mService,而mService是一个ConnectionServiceWrapper类的实例对象,我们可以把ConnectionServiceWrapper看做是一个代理类,因为其父类ServiceBinder是一个抽象类,且绑定了一个远程服务,然后调用ConnectionServiceWrapper.java的createConnection方法。
- 在createConnection方法中,会创建一个BindCallback对象,实现它的onSuccess和onFailure方法,创建完毕之后,会调用mBinder.bind(callback, call)方法去绑定,如果绑定成功,就会回调BindCallback的onSuccess方法 。
-
- 关键代码及log
- 关键代码
- 关键代码及log
- TelecomServiceImpl.java
public void placeCall(Uri handle, Bundle extras, String callingPackage) { ....................... //创建一个UserCallIntentProcessor对象,调用它的processIntent方法
|