呼叫分为主动呼叫和被动呼叫,主动呼叫也叫"去电",MO Call,表示用户通过UI上的拨号键盘拨出的电话。
被动呼叫叫做"来电",MT Call,表示其他打电话端打过来的电话,可以选择接听或者拒接或者missed。
有两种去电的方式(基于Android Q):
- 从UI(Dialer)使用TelecomManager中的placeCall将打电话的请求发给TelecomServer这边。
- 从其他App(比如VR,Nav提供的phone icon)直接调用Telecom提供的UserCallActivity来打电话。
这两种方式终会调用UserCallIntentProcessor的processIntent->processOutgoingCallIntent->sendIntentToDestination方法
该方法中会根据输入的参数isLocalInvocation来判断接下来是使用CallIntentProcessor.processIntent(第一种情况)还是TelecomManager的handleCallIntent(第二种情况)来处理后续拨打电话的流程。之后CallIntentProcessor.processOutgoingCallIntent来统一处理上面的两种情况,这里开始兵分两路:
1. CallsManager.startOutgoingCall--创建Call对象,然后起incall UI 2. sendNewOutgoingCallIntent,去创建connection
创建Connection的请求由ConnectionService的createConnection(同时对Connection添加监听,这样当底层上报的Call状态变化的时候,Connection就会监听到这边变化,然后将这个call状态变化上报给Telecom,这是后话)来发起,这里会根据当前通话的类型来区分创建Conneciton:
1. onCreateUnknownConnection -- 对应未知呼叫的Connection 2. onCreateIncomingConnection -- 对应来电的Connection 3. onCreateOutgoingConnection -- 对应去电的Connection
上述三个方法具体的实现由ConnectionService的子类来完成。
对于SIM-based 呼叫来说,ConnectionService的实现子类是TelephonyConnectionService, TelephonyConnectionService收到onCreateOutgoingCallConnetions后,在该Connectionservice中通过phone对象调用其dial方法(返回值就是一个connection),然后发给GsmCdmaCallTracker的dialGsm, 这个方法主要有两个作用:
- 将dial请求下发给RIL, 由RILJ发给RILC
- 创建创建Connection:new GsmCdmaConnection, 并将该connection返回,赋值给TelephonyConnectionService.placeOutgoingConnection中的变量:originalConnection,然后将该变量设置给TelephonyConnection。
也就是说Telephony拿到的Connetion,其实是从Telephoyframework中创建的GsmCdmaConnection。
之后调用CommandsInfterface.dial(RIL实现了该接口)的dial来向Modem发起拨打电话的请求。
KeyLogs
05-18 14:23:31.977 D/RILJ ( 2401): [0462]> DIAL [SUB0] 05-18 14:23:31.996 D/RILJ ( 2401): [0462]< DIAL [SUB0]
RILJ发送的请求会在RILC中接收,之后RILC上报DIAL给RILJ,然后将Call状态变化的消息主动上报给RILJ:UNSOL_RESPONSE_CALL_STATE_CHANGED,在RadioIndication中接收这种主动上报的消息,其作用就是通知注册的观察者CallTracker有call状态变化,以便CallTracker根据这个call消息进行下一步Action。
GsmCdmaCallTracker中注册该变化,当监听到该Call状态变化的时候,会继续下发getCurrentCalls请求给RIL来查询当前Call的详细的信息,RILC返回回来的Call信息包括:
DIALING — Call state
toa=129 — 表示当前是国内呼叫
norm — 表示是个Gsm 呼叫
mo – 表示是去电 等等
KeyLogs
05-18 14:23:32.002 D/RILJ ( 2401): [0465]> GET_CURRENT_CALLS [SUB0]
05-18 14:23:32.004 D/RILJ ( 2401): [0465]< GET_CURRENT_CALLS {[id=1,DIALING,toa=129,norm,mo,0,voc,noevp,,cli=1,,3,audioQuality=0] } [SUB0]
在下发getCurrentCalls的时候携带了一条消息:EVENT_POLL_CALLS_RESULT,当RILC上报回来该下发请求后,同时会将之前的message发送给对应的handler去处理,该消息的处理也在CallTracker.handlePollCalls->这里通过调用Phone.notifyPreciseCallStateChanged()将Call状态notify出去,在TelephonyConnection的setOriginalConnection中注册了观察者,去更新的时候会调用Telecomframework下的Connection的对应的Set方法(setDialing(),setRinging,setActive .etc)通知之前在ConnectionService.createConnection添加的listener去onStateChanged, 之后就将Call状态变化通知到TelecomServer(ConnectionServiceWrapper)中, Wrapper通知到CallsManager,然后CallsManager通知在其中的观察者,比如IncallController,让其将call变化信息通过InCallService通知给Dialer APP去更新InCallUI。
当然CallsManager中添加的listener不止IncallController, 还有其他:
1. PhoneStateBroadcaster --- Send a {@link TelephonyManager#ACTION_PHONE_STATE_CHANGED} broadcast when the call state changes.
2. CallLogManager --- Helper class that provides functionality to write information about calls and their associated caller details to the call log. All logging activity will be performed asynchronously in a background thread to avoid locking on the main thread.
3. MissedCallNotifier --- Creates a notification for calls that the user missed (neither answered nor rejected)
4. HeadsetMediaButton --- Static class to handle listening to the headset media buttons.
5. StatusBarNotifier --- Manages the special status bar notifications used by the phone app
其中PhoneStateBroadcaster最终会将call state change变化发给TelephonyRegistry,由其发给其他component,对于那些希望监听Call状态变化来处理对应逻辑的component来说,只要通过下面的方式就可以监听到Call state变化:
- 获取到Telephony Service,拿到TelephonyManager引用
- 调用TelephonyManager的listen方法来监听希望监听的通话状态变化
- 重写listen方法的第一个参数类(PhoneStateListener或者其子类)中的onCallStateChanged方法
eg:
1. private TelephonyManager mTelephonyManager;
mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
2. mTelephonyManager.listen(PhoneStateListener子类, PhoneStateListener.LISTEN_CALL_STATE);
3.
class XXX extends PhoneStateListener {
@Override
public void onCallStateChanged(int state, String incomingNumber) {
........
}
}
需要注意的是:PhoneStateBroadcaster不仅仅是Telephony提供给其他Component监听call状态变化的一个接口,看其注释:
它监听了Telephony支持的服务中的一切服务的变化,使得其他有需要的component通过上述的方式监听到Telephony中这些服务的变化,然后做相应的改变。
流程图 二 来电来电是直接从RILC上报UNSOL_RESPONSE_CALL_STATE_CHANGED开始的,也就是说缺少了去电拨打电话的过程,只不过在GsmCdmaCallTracker处理EVENT_POLL_CALLS_RESULT消息:handlePollCalls的时候,根据DriveCall的信息:
- 首先给来电创建一个GsmCdmaConnection
- 然后通过Phone对象将该Incoming Call notify出去,主要是为了去启动InCallUI
- 最后通过Phone对象将Call 状态变化notify出去,和上面去电的流程一样了。
介绍一下第二步骤:
三 更新InCallUI这里需要介绍一个比较重要的接口:InCallService,看其解释:
* This service is implemented by an app that wishes to provide functionality for managing * phone calls. *Becoming the Default Phone App
* The default dialer/phone app is one which provides the in-call user interface while the device is * in a call. A device is bundled with a system provided default dialer/phone app. public abstract class InCallService extends Service {
该接口(其实是抽象类)由Telecom提供给App(一般是Dialer或者拥有Dialer role的App)来实现,Dialer中实现类是InCallServiceImpl, 用于将Telecom进程的呼叫信息上报给Dialer(InCallUI现在是属于Dialer进程),同时用户从UI上对呼叫的管理(end,hold, swap等)都是由该类下发到Telecom的。
不管是来电还是去电,都是在CallsManager调用addCall时,通过InCallController来启动该InCallService。InCallController是添加到CallsManager中的其中一个监听,有两个作用:
- 启动InCallService
- 将Call状态上报给Dialer来更新InCallUI
使用InCallController来更新Call状态的流程为:
Dialer中的类根据这个回调进行更新,一般有:
InCallRouter — 车机上用来显示来电Notification的类
CallDetailLiveData – 车机上InCallUI上显示的Call details 信息
InCallPresent — 手机上InCallUI上的Call信息显示
等等。。。
| No. | 类名 | Comments | Path |
|---|---|---|---|
| 1. | TelecomManager | Provides access to information about active calls and registration/call-management functionality. Apps can use methods in this class to determine the current call state. Apps do not instantiate this class directly; instead, they retrieve a reference to an instance through Context.getSystemService(Context.TELECOM_SERVICE). Represents a phone call or connection to a remote endpoint that carries voice and/or video traffic. Implementations create a custom subclass of | frameworks/base/telecomm |
| 2. | TelecomService/TelecomServiceImpl | TelecomManager的服务类 | packages/services/Telecomm |
| 3. | TelephonyManager | Provides access to information about network and device states. Provide interface to access some types of subscriber information. Applications can register a listener to receive notification of telephony state (call/service/data connection state, signal strength, call info, etc) changes | frameworks/base/telephony |
| 4. | PhoneInterfaceManager | Implementation of the ITelephony interface,其实也就是TelephonyManager的服务类 | frameworks/base/ |
| 5. | PhoneStateListener | A listener class for monitoring changes in specific telephony states on the device, including call state, service state, signal strength, message waiting indicator (voicemail), and others. Provide interface to access some types of subscriber information. Note that access to some telephony information is permission-protected. Your application won’t receive updates for protected information unless it has the appropriate permissions declared in its manifest file. Where permissions apply, they are noted in the appropriate LISTEN_ flags. | frameworks/base/telephony |
| 6. | TelephonyRegistry | Manager phone’s overall service state, call state, data state, cell info, signal strength: Register defaultPhoneNotifier to both BluetoothPhone and onStarPhone submodules for 1st hand status change notification. Provide interface for client to register observer for specified state change that it may have interest Will also broadcast intent to whole system when state changes | frameworks/base/service |
| 7. | Connection | Represents a phone call or connection to a remote endpoint that carries voice and/or video traffic. Implementations create a custom subclass of | frameworks/opt/telephony |
| 8. | PhoneAccount | Represents a distinct method to place or receive a phone call. Apps which can place calls and want those calls to be integrated into the dialer and in-call UI should build an instance of this class and register it with the system using TelecomManager. | |
| 9. | Call | Encapsulates all aspects of a given phone call throughout its lifecycle, starting from the time the call intent was received by Telecom (vs. the time the call was connected etc). | packages/services/Telecomm |
| 10. | Call | Represents an ongoing phone call that the in-call app should present to the user. | frameworks/base/telecomm |
| 11. | Call | {@hide} | frameworks/opt/telephony |
越写越觉得都是关键类,都需要说明了,So暂时先不写了
四 RILJ 和RILC的交互方式RILJ 和RILC的交互有两种方式:
-
RILC主动上报, 格式一般是:UNSOL_RESPONSE_XXX_STATE_CHANGED
UNSOL_RESPONSE_CALL_STATE_CHANGED 就是主动上报的。主动上报的消息一般是在RaidoIndication中接收,处理逻辑一般是通知观察者一般观察者的注册是在对应的Tracker中。
-
RILJ发起请求,然后RILC进行反馈,比如说DIAL请求。
反馈回来的消息是在RadioResponse中接收,命名一般是在下发的method name+Response的方式。 对应的方法主要作用是将之前RILC得到的数据通过消息的方式发给下发命令的时候对应的message去处理。一般也是在对应的Tracker中来接收对应的message
一般来讲,从UI测主动发起来请求,最终会通过RILJ将请求发给底层Modem,用的也就是上述第二种方式,比如有拨打变化DIAL和创建数据连接SETUP_DATA_CALL。当底层数据需要主要上报给Android测时,上报信息会通过RILC主动上报,也就是用到上述第一种方式,像通call的详细信息,数据详细信息的上报都是如此。



