基于Android P的信号更新流程

1、概述

    关于信号更新,从很早个人未看相关代码时,一直以为很简单。ril上报信号,UI进行更新就行。话是这么说,但Google设计方案可没那么简单,就好比如1+1=2,Google非得这么告诉你x+y=2,其实这是体现出代码设计的重要性。而关于信号更新流程,设计中就使用到了代理模式,观察者模式。另本文档主要集中讲解信号的数据收到后,如何在APP上拿到。也就是讲解信号数据的来龙去脉,方便后面针对相关问题快速定位分析。

2、类图

    从整体的框架结构来看,信号更新流程可分析3层,自下到上分别为应用层、接口层、服务层。

    应用层用于接收到信号后,进行对应用的逻辑处理,如UI显示这些;

    接口层用于注册事件回调,提供观察者服务,这一层的实现是由AIDL机制完成。

    服务层则收到信号数据的来源,然后上报给接口层处理。

    而贯穿这三个层次的数据是SingnalStringth类,里面存放着各制式下的信号值,三个层次都是围绕着这个类进行传递和处理。 

    而关于信号更新流程的处理逻辑,也可分析三个步骤,分别为初始化、注册、回调。

    初始化其实分三部分进行,分别为服务层,接口层及应用层,也就是对应的ServiceStateTracker、TelephonyRegistry和MobileSignalController的初始化,这三个层都是跨进程,所以才分别进行初始化。

    注册是应用层向接口层的事件注册,应用层无需跟服务层有交互,由接口层进行代理,这个设计就就使用到了观察者模式。

    回调是由服务层向接口层提供信号数据,然后由接口层根据谁注册了相关事件进行分发。

关键类的功能作用:

    Phone.java  电话类的功能。

    GsmCdmaPhone.java  继承Phone的类。

    PhoneFactory.java  Phone的工厂类,创建GsmCdmaPhone。

    DefaultPhoneNotifier.java  用于回调TelephonyRegistry的相关函数。

    ServiceStateTracker.java   与RIL通信的类,重点是维护信号,网络信息,小区信息等。

    SignalStrength.java  信号类

    TelephonyRegistry.java  一个AIDL服务,提供系统接口。

    TelephonyManager.java 为TelephonyRegistry提供间接接口,相当于TelephonyRegistry的代理。

    Record.java  保存callback的类

    MobileSignalController.java 状态栏信号管理的一个类

    MobilePhoneStateListener.java 是MobileSignalController的子类,用于实现函数回调,事件注册的类。

3、流程说明

    3.1 初始化

        3.1.1 ServiceStateTracker初始化

        是由GsmCdmaPhone来完成,而GsmCdmaPhone的初始化是由packages\services\Telephony来完成。具体见如下时序图。

        

         在ServiceStateTracker初始化过程中,有个重要的对象sPhoneNotifier,其作用是用于跟接口层TelephonyRegistry交互,完成数据上报。具体的上报调用流程是ServiceStateTracker调用Phone,Phone再调用PhoneNotifier,PhoneNotifier最后调用TelephonyRegistry。

        3.1.2 TelephonyRegistry初始化

        TelephonyRegistry其实是个AIDL服务,对外提供接口,是一个可以跨进程调用的服务。竟然是AIDL服务,这个一般都是在SystemServer.java里面进行初始化。具体见如下代码:

        

 TelePhonyManager其实是TelephonyRegistry的一个代理,动作全由它来帮对接转发。

        3.1.3 MobileSignalController初始化

        MobileSignalController的初始化是由SystemUI的一个APK来完成,SystemUI就是状态栏。此APK因了解的不多,暂讲解到这。

    3.2 注册

        应用层通过注册一些想要知道Telephony的变化事件来执行相关的功能处理。在注册中,应用层必须要实现一个类来继承PhoneStateListener,然后把此类生成的对象注册到TelephonyRegistry里。时序图如下。

        

         在MobileSignalController里来继承PhoneStateListener的类是MobilePhoneStateListener,代码实现见如下图:        

         然后在MobileSignalController的构造函数里完成初始化动作,代码实现见如下图:        

         最后再调用注册函数来完成事件注册,代码实现见如下图,其中mPhone是TelePhonyManager的对象。

       

        通过TelephonyRegistry.java可以了解到,notifySignalStrengthForPhoneId函数里会调用r.callback.onSignalStrengthsChanged,其中callback就是MobilePhoneStateListener。

    3.3 回调

        信号的数据是从RIL上报到ServiceStateTracker,ServiceStateTracker数据收到后,通过调用GsmCdmaPhone的对象,然后再调用PhoneNotifier的对象发给TelephonyRegistry,TelephonyRegistry最后就分发给注册者MobilePhoneStateListener。

        关于回调的流程见如下时序图的6~16步骤:        

        EVENT_GET_SIGNAL_STRENGTH这个消息一开始是由初始化ServiceStateTracker对象时,向ril请求,见如下图:

        

        ril查询完成后,回调此消息,执行的代码如下:

        

        然后就执行onSignalStrengthResult,见上面的时序图。但此时还会调用queueNextSignalStrengthPoll,此函数作用是20S后,重新查询信号,一直循环下去。

        另信号也有主动上报,在ServiceStateTracker构造函数里向RIL注册了EVENT_SIGNAL_STRENGTH_UPDATE此消息,回调后同样执行onSignalStrengthResult,不再分析。        

4、案例分析

    RIL上报的信号很强,但为何UI上显示空三角?

    了解了上面流程后,信号多少是直接在UI显示多少等级的原理,我们就可以直接查看MobileSignalController类里面的onSignalStrengthsChanged函数。

    1、先确认此函数打印的信号是否为有效值。一般此处正常,确认这一步只是用来确定信号的强度如何而已。

    2、再进入到updateTelephony函数里,见如下代码,信号满足更新前得卡是注册上的状态,见connected。    

    关于connected的条件是hasService() && mSignalStrength != null,mSignalStrength这个好了解,是从ServiceStateTracker.java获取,为NULL的话,连更新的机会都没有。

    接下来看下hasService的函数内容如下,可以看到其中一个条件是voice必须为STATE_IN_SERVICE。如果voice不是STATE_IN_SERVICE,可以从data的状态进一步来判断。        

    而voice或data是如何变成STATE_IN_SERVICE的状态呢,通过ServiceStateTracker可以看到,ril上报的状态如果是REG_STATE_HOME或REG_STATE_ROAMING就修改成了STATE_IN_SERVICE

    

    所以信号为何显示空三角,还需要重点确认步骤2的一些状态值。

5、总结

    本文档其实细节的内容讲的不多,根据时序图去跟踪即可,重点是讲了框架,总结下优秀的代码实现过程,方便后面借鉴学习。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值