Android去电流程

Version:1.0 StartHTML:0000000174 EndHTML:0000527746 StartFragment:0000129196 EndFragment:0000527706 SourceURL:file:///Y:\Desktop\Dialer\Android去电流程%203.18.docx

 

Android去电流程

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

目录

目录.... 2

1. 简介.... 3

1.1.      概述... 3

1.2.      适用范围... 3

1.3.      详细流程图... 3

2.Dialer层流程.... 4

2.1.      模块简介... 4

2.2.      流程分析... 4

2.3.      关键代码及log. 4

3.Telecom层流程.... 5

3.1.      模块简介... 5

3.2.      流程分析... 5

3.3.      关键代码及log. 5

4.Frameworks telecom层流程.... 6

4.1.      模块简介... 6

4.2.      流程分析... 6

4.3.      关键代码及log. 6

5.Telephony层流程.... 7

5.1.      模块简介... 7

5.2.      流程分析... 7

5.3.      关键代码及log. 7

6.Frameworks Telephony层流程.... 8

6.1.      模块简介... 8

6.2.      流程分析... 8

6.3.      关键代码及log. 8

 

 

  1. 简介
    1. 概述

此文档详细的介绍了android中的去电流程,一直从上层(dialer)到底层(RIL)层的详细流程,可以让相关的同事在解决去电问题的时候快速的定位问题点,方便了bug的fix。

 

    1. 适用范围

此问题使用了android P平台,高通和MTK均适用。

 

    1. 详细流程图

 

  1. 层流程
    1. 模块简介
      1. 概述

手机最基本的功能包括两个大的方面,一个是打电话功能,一个是短信功能,我们这里的Dialer模块指的就是打电话功能的一部分,他是手机与用户交互的桥梁,提供图形界面来给用户操作,使用户能够通过一系列的操作拨打电话等等。

从源码的包的命名,可以将Dialer分为四个大的部分,包含:contact、incallui、dialer、voicemial。Contact主要是联系人相关的逻辑,与Contact模块有着很大的联系;incallui主要是通话过程中的incall界面的东西,在通话过程中,设计到很多的与底层交与的逻辑,需要调用底层的接口来获取电话状态并显示在incall界面上,需要调用底层接口来对call进行操作;dialer主要是点击app图标进入之后的界面的显示、界面相关操作的逻辑以及一部分dialer的设置;voicemial是voicemail相关的代码,调用的是底层的接口。

 

    1. 流程分析

 

 

    1. 关键代码及log

这一个部分代码逻辑较为简单,且代码中没有打印关键log,所以这一部分就不贴关键代码以及关键log,只要关注上一个部分的流程就可以。

  1. 层流程
    1. 模块简介
      1. 概述

这里的Telecom层指的是位于packages/services/Telecomm的模块,是android 5.0之后从phone进程中提出来的位于incallui(也就是dialer进程)和phone进程(telephony)之间的模块,运行于系统进程之中。基本上所有的incallui界面上的显示相关的信息都是从这个模块中调用接口获取而来的,而这个模块实质上是没有和底层打交道的,他上面链接dialer,下面链接的是framework/base/telecom,所以可以把他看做是一个中间层的接口,涉及到底层的东西是没有放在这里处理的。

实际上,在这个模块中,我认为最最重要的需要我们来关注的类,就是TelecomServiceImpl.java,基本上所有的call相关的重要方法,都是放在这个类中来实现的。

 

    1. 流程分析
      1. 流程图

 

      1. 分析
  1. 检查一些权限相关的东西,然后创建一个UserCallIntentProcessor,调用它的processIntent方法。

 

  1. 从intent中取出action,判断action是否等于ACTION_CALL||ACTION_CALL_PRIVILEGED||ACTION_CALL_EMERGENCY。如果相等,调用processOutgoingCallIntent方法

 

  1. 对号码的uri做了以下处理,判断传入的正在拨号的dialer是不是默认dialer,存入intent中(CallIntentProcessor.KEY_IS_PRIVILEGED_DIALER)。然后调用sendIntentToDestination方法

 

  1. 在这个方法中会判断isLocalInvocation,这个参数是从TelecomServiceImpl中的placeCall方法传过来的,默认是true。如果是false,就会发送广播到PrimaryCallReceiver,然后调用CallIntentProcessor的processIntent方法。如果是true,则会直接调用CallIntentProcessor的processIntent方法,这样就省去了中间的广播接受时间,性能更加优异。

 

  1. 在processIntent方法中,从intent中判断KEY_IS_UNKNOWN_CALL是否是true,如果是,则调用processUnknownCallIntent方法,如果不是,调用processOutgoingCallIntent方法。

 

  1. 对号码的uri进行处理,判断是sip号码还是普通号码,添加上scheme,将call相关的信息封装到Bundle中,然后调用callsmanager的startOutgoingCall方法。

 

  1. 在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。

 

  1. 创建一个NewOutgoingCallIntentBroadcaster对象,调用他的processIntent方法。这个方法是有返回值的,如果返回值不等于DisconnectCause.NOT_DISCONNECTED,那么就会在这里挂断电话并弹出提示框提示。

 

  1. 在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方法来拨打电话。

 

  1. 在broadcastIntent方法中,调用sendOrderedBroadcastAsUser方法发送了广播。

 

  1. NewOutgoingCallIntentBroadcast的onReceive方法接收到这个广播,最后还是调用placeOutgoingCallImmediately方法来拨打电话。

 

  1. 在placeOutgoingCallImmediately方法中,将call的mIsNewOutgoingCallIntentBroadcastDone参数设置为了true,表示NewOutgoingCallIntentBroadcast完毕,接着调用callsmanager的placeOutgoingCall方法。

 

  1. 在callsmanager的placeOutgoingCall方法中,会检查是否需要打开扬声器,如果需要会打开扬声器。然后调用call的startCreateConnection方法去创建Connection。
  2. startCreateConnection方法中创建了一个CreateConnectionProcessor对象,然后调用它的process方法。

 

  1. 向mAttemptRecords中加入当前电话的CallAttemptRecord对象,实质上就是两个PhoneAccountHandle对象。然后调用attemptNextPhoneAccount方法。

 

  1. 在attemptNextPhoneAccount方法中,首先会判断mAttemptRecords列表中的PhoneAccountHandle是否具有BIND_TELECOM_CONNECTION_SERVICE权限,判断是否能够绑定链接,然后调用ConnectionServiceRepository的getService()方法得到mService,而mService是一个ConnectionServiceWrapper类的实例对象,我们可以把ConnectionServiceWrapper看做是一个代理类,因为其父类ServiceBinder是一个抽象类,且绑定了一个远程服务,然后调用ConnectionServiceWrapper.java的createConnection方法。

 

  1. 在createConnection方法中,会创建一个BindCallback对象,实现它的onSuccess和onFailure方法,创建完毕之后,会调用mBinder.bind(callback, call)方法去绑定,如果绑定成功,就会回调BindCallback的onSuccess方法 。

 

    1. 关键代码及log
      1. 关键代码
  1. TelecomServiceImpl.java

public void placeCall(Uri handle, Bundle extras, String callingPackage) {

.......................

//创建一个UserCallIntentProcessor对象,调用它的processIntent方法

      

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值