第2章 来电流程

编程入门 行业动态 更新时间:2024-10-10 01:17:03

第2章 来电<a href=https://www.elefans.com/category/jswz/34/1770115.html style=流程"/>

第2章 来电流程

第2章 来电流程

2.1 callState发生变化

当callstate发生改变时,RadioIndication.callStateChanged()调用RIL的processIndication向底层发送确认收到消息;notifyRegistrants通知他的观察者。

RadioIndication继承的RadioIndication.Stub在IRadio.hal中定义了接口。

RIL层在接收底层的消息后,发起了notify通知,关于registerForCallStateChanged有三个地方注册了接口:BasedCommands、GsmCdmaCallTracker、CommandsInterface,继续跟进GsmCdmaCallTracker,其继承于CallTracker,本质是个Handler处理类,关键方法在于handleMessage方法。

2.2 GsmCdmaCallTracker发生响应

当callstate发生变化的时候,GsmCdmaCallTracker.handleMessage()响应并处理EVENT_CALL_STATE_CHANGE消息:

-àCallTracker.pollCallsWhenSafe()

ß-返回EVENT_POLL_CALLS_RESULT

pollCallsWhenSafe()调用RIL的mCi.getCurrentCalls()去查询当前Call的情况。

getCurrentCalls()主要作用:获取一个Radio代理进行通信、创建一个请求消息、向底层发起请求。《----返回RIL_REQUEST_GET_CURRENT_CALLS

2.3 底层返回结果给RIL

在发送请求后,等待modem返回结果给RIL层,在RIL层中,底层消息反馈的处理方法有两个:processResponse和processResponseDone,这两个方法在RadioResponse.java中被调用。

RadioResponse.java继承于IRadioResponse.Stub,继承于一个底层服务,观察各个处理方法发现其中是各中上层请求的返回处理方法,那么继续追踪CurrentCall的消息,getCurrentCallsResponse---》responseCurrentCalls方法—》mRil.processResponse。

图1 responseCurrentCalls方法—》mRil.processResponse

responseCurrentCalls()通过底层返回的消息创建了dcCalls对象,也就是当前Call状态信息,对dc状态进行判断后如果有需要就notify通知,如果没有异常则通过sendMessageResponse (rr.mResult, dcCalls)方法发送消息;这一部分和之前一样,将返回值返回给当初的请求者,由请求者去决定如何处理。

2.4 回到GsmCdmaCallTracker

1)回到GsmCdmaCallTracker.handleMessage()中,

处理之前发送请求时收到的反馈消息EVENT_POLL_CALLS_RESULT---》GsmCdmaCallTracker.handlePollCalls()。

handlePollCalls先对底层反馈消息进行解析,获取其通话状态,判断如果是来电则发出notifyNewRingingConnection响铃消息通知,然后进行一些通话断开连接的操作及更新phone状态。

handlePollCalls中获取RIL传来的Call列表,并通过DriverCall对象与connections对象判断是MO还是MT还是通话状态改变等。如果是来电会通知响铃。更新Phone对象的状态(引申Call的9种状态,Phone的三种状态),所以通过TelephonyManager的Listener可以监听到三种状态。

注意:handlePollCalls根据RIL发出的CallList对象判断Call状态,并发出不同的通知。

a.新来电通知是:phone.notifyNewRingingConnection;

b.通话断开通知是:onDisconnected;

c.Call状态变化通知是:phone.notifyPreciseCallStateChanged。

2)handlePollCalls—》GsmCdmaPhone.notifyNewRingingConnection()—》GsmCdmaPhone.notifyNewRingingConnectionP—》Phone.notifyNewRingingConnectionP。

发现主要的监听有:PstnIncomingCallNotifier.java、PhoneMock.java、CallManager.java、Phone.java

GsmCdmaCallTracker调用的实际是phone的notify方法,所以可以排除PhoneMock.java和Phone.Java,主要继续跟踪CallManager.java和PstnIncomingCallNotifier.java

在CallManager.handleMessage中,EVENT_NEW_RINGING_CONNECTION的处理为:判断是否需要挂断,如果需要则直接挂断,不需要则进一步通知此消息,所以对此消息的最终处理还是在PstnIncomingCallNotifier.java中。

图2 CallManager处理

CallManager在对此消息进行判断后,确认是否需要挂断,如果不需要则进一步通知此消息;所以其实还是PstnIncomingCallNotifier中来处理此消息。

2.5 消息处理

PstnIncomingCallNotifier.handleMessage()—》handleNewRingingConnection()

图3调用handleNewRingingConnection

handleNewRingingConnection—》sendIncommingCallIntent发送Intent,这里其实就已经从RIL传递消息到了应用层。

sendIncomingCallIntent(),这里会构造intent的extras放入号码、当前呼入时间,返回一个可用的PhoneAcountHandle。

图4 通过aidl接口调用telecomService的addNewIncomingCall方法

2.6 TelecomServiceImpl

TelecomServiceImpl.addNewIncoming()

这个方法里面会检查包名、检查phoneaccount、然后构造完整的intent。

---》mCallIntentProcessorAdapter.processIncomingCallIntent(

mCallsManager, intent) ---》CallsManager.processIncomingCallIntent()—》call.startCreateConnection【Call.java的方法】

主要做了:创建了一个Call对象并着手建立与ConnectionService的链接;对于self-managed进行处理;添加监听。

2.7 创建连接

Call.startCreateConnection()—》CreateConnectionProcessor.process()

使用一个PhoneAccount创建connection失败时,对所有可用PhoneAcount尝试。handleCreateConnectionFailure --》attempNextPhoneAccount—》ConnectionServiceWrapper.createConnection()

主要内容:使用递归尝试找到一个PhoneAccount建立通话连接。

2.8 绑定服务

ConnectionServiceWrapper.createConnection()—》Binder2.bind()—》ServiceBinderConnection.onServiceConnection()—》setBinder()—》setServiceInterface()

 这里调用的是ConnectionServiceWrapper中的setServiceInterface()—》ServiceBinderConnection.handleSuccessfulConnection()—》ConnectionServiceWrapper.callBack.onSuccess()

在这里绑定服务(action名为android.telecom.ConnectionService),如果BindService 成功,最终回调ConnectionServiceWrapper的onSuccess。

设置了mServiceInterface = IConnectionService.Stub.asInterface(binder);

调用bindService获取远程服务的aidl接口,成功获取到aidl接口后将其赋值给mServiceInterface,当绑定完成后会调用handleSuccessFulConnection方法其中回调了CallBack的onSuccess方法。onSuccess调用了aidl接口的createConnection方法。mServiceInterface.createConnection。(mServiceInterface 是IConnectionService类型的)

2.9 创建连接

ConnectionService.createConnection()

无论如何都会调用createConnection

判断是来电还是去电:当判断是来电时会通过onCreateIncomingConnection创建连接,跟进去发现是空,那么该方法的实现应在其子类TelephonyConnectionService中;

TelephonyConnectionService.onCreateIncomingConnection()—》createConnectionFor()    根据GSM、CDMA生成Connection。

创建成功后会回到ConnectionService.java调用handleCreateConnectionComplete()这里通过AIDL进行通信,搜索IConnectionServiceAdapter.Stub,跟进到ConnectionServiceWrapper.java。【ConnectionServiceWrapper有Adapter extends IConnectionServiceAdapter.Stub】

2.10 ConnectionServiceWrapper

ConnectionServiceWrapper.handleCreateConnectionComplete()

图5走到ConnectionServiceWrapper.handleCreateConnectionComplete—》handleCreateConnectionComplete

 

mPendingResponses是hashMap容器,每次在createConnection的时候会将对象加入该容器,如果此时connection还未断开,会移除此connection,调用CreateConnectionProcessor.java的handleCreateConnectionSuccess方法。

2.11 根据来电类型触发回调

CreateConnectionProcess.handleCreateConnectionSuccess()

 

图7调用Call.handleCreateConnectionSuccess()

图8 Call类的handleCreateConnectionSuccess—》CallsManager.onSuccessfulIncomingCall()

根据来电类型触发回调,监听者会收到通知,之前在CallManager中执行processIncomingCallIntent方法创建Call的时候就添加了监听,最后会回调到CallsManager中。

2.12 传递消息

CallsManager.onSuccessfulIncomingCall()

CallsManager的管理作用:创建Calls并添加监听,在完成Call的相关初始化后进行进一步处理,其实就是传递消息到别的地方去。

 

图9 CallsManager.onSuccessfulIncomingCall()

这里用到了迭代器模式,一个来电触发三个对象的处理,最后创建一个IncomingCallFilter并调用performFiltering()。

图10调用 onCallFilteringComplete

如果没有超时则在异步查询结束后,会通过回调方法将CallFilterResult传回onCallFilteringComplete—》CallsManager.onCallFilteringComplete()

正常情况下会把Call状态置为ring,并添加Call

--》CallsManager.addCall()

添加观察者,在CallsManager构造函数初始化的时候添加了一系列观察者,还有就是通过addListener去添加。

图11通过addListener去添加

图12在CallsManager构造函数初始化的时候添加了一系列观察者

可以在构造函数中看到InCallController是观察者,所以会调用—》InCallController.onCallAdded()—》InCallService.addCall()。

图13 在InCallService类里面会返回MSG_ADD_CALL消息

handleMessage处理MSG_ADD_CALL—》Phone.internalAddCall—》Phone.fireCallAdded()—》listener.onCallAdded()

监听者的onCallAdded,InCallServiceImpl.onCallAdded()--》InCallPresenter.getInstance().onCallAdded—》CallList. onCallAdded()

 

2.13 调来电界面

InCallPresenter.onCallAdded()—》CallList.onCallAdded()—》CallList.onInComing—》listener.onInComingCall—》InCallPresenter.startOrFinishUI最终调用其InCall的来电界面

 

InCallPresenter.startOrFinishUI—》StatusBarNotifier.updateNotification—》updateInCallNotification—》showNotification—》buildAndSendNotification—》createInComingCallNotification—》addAnswerAction

----》NotificationManager.notify()

2.14 补充

补充:

一、Android开发中通过aidl实现远程方法调用

我们都知道Binder工作机制由客户端,Binder,服务端组成,客户端和服务端都是通过Binder来交流的。关于Binder的定义有很多种,在aidl生成的Java代码中,Stub类是继承于Binder类的,也就是说Stub实例就是Binder实例。

实例中服务端一般会实例化一个Binder对象”IXXX.Stub  stub  =  new  XXX.Stub()”,然后客户端中在Service绑定的时候可以获取这个Stub:”XXX  = IXXX.Stub.asInterface(service)”,如果客户端和服务端在同一个进程下,那么asInterface()将会返回Stub对象本身,否则返回Stub.Proxy对象:

1. 如果在同一个进程下的话,那么asInterface()将会返回服务端的Stub对象本身,因为此时根本不需要跨进程通信,那么直接调用Stub对象的接口就可以了;

2. 如果不是同一个进程,那么asInterface()返回的是Stub.Proxy对象,该对象持有着远程的Binder引用,因为现在需要跨进程通信,所以如果调用Stub.Proxy的接口的话,它们都将是IPC调用,会通过transact方法去与服务端通信。

在Android开发过程中我们可能遇见过这样的问题,就是一个应用中调用另一个应用的服务,并调用该服务中的方法。

我们可能对调用服务并不陌生,可是要执行服务中的方法,却不能直接调用,此时我们就要用到aidl,使用方法:

1. 创建服务,并配置意图过滤器,可以让其他程序通过隐式意图调用服务,并调用该服务中的方法;

2. 在AS中可以创建一个aidl文件,在eclipse中需要手动创建文件,后缀名为.aidl,在里面定义一个接口,书写方法和.java中写接口一样,写完之后开发工具会自动生成一个同名的Java文件。

3. 在服务中创建一个子类用来调用需要被远程调用的方法,该类继承上一步生成类的一个子类Stub,并在服务的onBind方法中返回该类的对象。同时将aidl文件复制到需要调用该服务的应用中,这里需要注意两个dial文件所在的包名必须相同。

4. 在需要调用服务的activity中创建ServiceConnection对象,并实现其抽象方法,通过aidl名.Stub.asInterface(Ibinder对象);获取到在服务中创建的子类对象,就可以操作远程服务中的方法了。

存根类Stub:实现了一个接口,但是实现后每个方法都是空的;

作用:如果一个接口有很多方法,而我们只需要其中的一两个方法,如果我们直接去实现这个接口就会需要实现其他无关方法;而如果通过继承存根类去实现接口就免去了麻烦。

2.15 HIDL

HIDL的全称是HAL interface definition language(硬件抽象层接口定义语言),在此之前Android有AIDL,架构在Android binder之上,用来定义Android基于Binder通信的Client与Service之间的接口。HIDL也是类似的作用,只不过定义的是Android Framework与Android HAL实现之间的接口。

更多推荐

第2章 来电流程

本文发布于:2024-03-23 02:09:51,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1739204.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:流程

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!