Android 中 RegistrantList消息处理机制 以android 5.0 MT为例

UICCcontroller 注册监听(RegistrantList) 主要讲解RegistrantList的原理,以及如何快速分析RegistrantList相关的代码流程。 在Telephony模块中,在RIL、Tracker(ServiceStateTracker、CallTracker、DcTracker)、Phone(PhoneBase及其子类)、UICC框架、CallManager等等中都大量使用到的RegistrantList,可见RegistrantL... 阅读详情

转载请注明出处: http://blog.youkuaiyun.com/aaa111/article/details/43833757

这其实是观察者模式的一种实现形式

先明确两个身份 1.RefistrantList 通知者 2.Registrant 观察者,这是一个一对多的关系,在有事件更新时,凡是通知者列表内的对象,都会收到通知。
RegistrantList 作为通知者支持对Registrant 的增加(add/addUnique)删除(remove),并且能够发出通知(notifyRegitrants),而Registrant作为观察者,响应通知者发出的通知,调用internalNotifyRegistrant()把add()时携带的Message发出去处理。
总体思想是:一个对象中开辟一个空间用于存放Message,当调用regist方法时将Message存放进去,当调用notify方法时将所有Message取出并发送到MessageQueue中等待处理。
下面我们以android 5.0上 来电流程为例讲一下RegistrantList机制的使用。

注册为观察者

1.PstnIncomingCallNotifier这个类中调用mphoneBase中的registerForNewRingingConnection方法注册为观察者,android中的注册为观察者的方法通常写为registerFor***()形式,即为某事件注册消息通知。
PstnIncomingCallNotifier.java

    private void registerForNotifications() {
        Phone newPhone = mPhoneProxy.getActivePhone();
        if (newPhone != mPhoneBase) {
            unregisterForNotifications();
            if (newPhone != null) {
                Log.i(this, "Registering: %s", newPhone);
                mPhoneBase = newPhone;
                // 调用registerForNewRingingConnection()方法往RegistrantList中添加Registrant,**注意参数包括handler和message**
                mPhoneBase.registerForNewRingingConnection(
                        mHandler, EVENT_NEW_RINGING_CONNECTION, null);
                mPhoneBase.registerForCallWaiting(
                        mHandler, EVENT_CDMA_CALL_WAITING, null);
                mPhoneBase.registerForUnknownConnection(mHandler, EVENT_UNKNOWN_CONNECTION,
                        null);
            }
        }
    }

2.然后我们看registerForNewRingingConnection()内部做了哪些操作:
调用addUnique()方法添加为观察者。
phoneBase.java

    // Inherited documentation suffices.
    @Override
    public void registerForNewRingingConnection(
            Handler h, int what, Object obj) {
        checkCorrectThread(h);
        mNewRingingConnectionRegistrants.addUnique(h, what, obj);
    }

而这个mNewRingingConnectionRegistrants是什么呢?

    protected final RegistrantList mNewRingingConnectionRegistrants = new RegistrantList();

mNewRingingConnectionRegistrants是一个RegistrantList 。

3.添加到通知者列表
用传进来的三个参数新建一个观察者,继续调用RegistrantList内部的add()方法
RefistrantList.java

    public synchronized void
    addUnique(Handler h, int what, Object obj)
    {
        // if the handler is already in the registrant list, remove it
        remove(h);
        // 新建Registrant
       add(new Registrant(h, what, obj));
    }

3.1新建一个Registrant观察者

    public
    Registrant(Handler h, int what, Object obj)
    {
        refH = new WeakReference(h);//Handler 泛型WeakReference
        this.what = what;//消息类型
        userObj = obj;//Object数据对象,用于封装传递的数据
    }

3.2添加到通知者要通知的列表中,用列表保存观察者。registrants是一个ArrayList。

    ArrayList registrants = new ArrayList();      // of Registrant
    public synchronized void
    add(Registrant r)
    {
        removeCleared();
        registrants.add(r);
    }

registerForNewRingingConnection()方法完成了往RegistrantList中添加Registrant的操作。
同时我们也看到,RegistrantList管理了一个Registrants列表,Registrants保存了多个Registrant。

发出通知

1.handlePollCalls方法根据RIL发出的Call List对象判断Call的状态,并发出不同的通知,
有新的来电将执行: phone.notifyNewRingingConnection; 形如notify***()也是惯用写法。
GsmCallTracker.java

    Connection newRinging = null; //or waiting
    handlePollCalls(){
    ...
    if (newRinging != null) {
        mPhone.notifyNewRingingConnection(newRinging);
    }

2.GSMPhone.java

    public void notifyNewRingingConnection(Connection c) {
        super.notifyNewRingingConnectionP(c);
    }

调用父类 PhoneBase.java notifyNewRingingConnectionP()发出来电通知

    mNewRingingConnectionRegistrants.notifyRegistrants(ar);

前面有说过mNewRingingConnectionRegistrants是一个RegistrantList。

    /**
     * Notify registrants of a new ringing Connection.
     * Subclasses of Phone probably want to replace this with a
     * version scoped to their packages
     */
    public void notifyNewRingingConnectionP(Connection cn) {
        if (!mIsVoiceCapable)
            return;
        AsyncResult ar = new AsyncResult(null, cn, null);
        // 调用RegistrantLis 的notifyRegistrants() 方法
        mNewRingingConnectionRegistrants.notifyRegistrants(ar);
    }

通知者RegistrantList.java

    public /*synchronized*/ void
    notifyRegistrants(AsyncResult ar)
    {
        internalNotifyRegistrants(ar.result, ar.exception);
    }

一般来说观察者不止一个,所以用for循环遍历观察者,调用观察者内部的internalNotifyRegistrant()响应通知

    private synchronized void
    internalNotifyRegistrants (Object result, Throwable exception)
    {
       for (int i = 0, s = registrants.size(); i < s ; i++) {
            Registrant  r = (Registrant) registrants.get(i);
            r.internalNotifyRegistrant(result, exception);
       }
    }

响应通知消息

Registrant.java
这里是处理RegistrantList 的通知,主要是将message发出出去。
这里的handler和message是之前调用RegistrantList 的addUnique() 方法时添加进去的(add(new Registrant(h, what, obj));)。

    /*package*/ void
    internalNotifyRegistrant (Object result, Throwable exception)
    {
       // 得到handler
        Handler h = getHandler();
        if (h == null) {
            clear();
        } else {
            Message msg = Message.obtain();
            msg.what = what;
            msg.obj = new AsyncResult(userObj, result, exception);
            // 发送消息            
            h.sendMessage(msg);
        }
    }

PstnIncomingCallNotifier.java

    private final Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch(msg.what) {
                case EVENT_NEW_RINGING_CONNECTION:
                    handleNewRingingConnection((AsyncResult) msg.obj);
                    break;
                case EVENT_CDMA_CALL_WAITING:
                    handleCdmaCallWaiting((AsyncResult) msg.obj);
                    break;
                case EVENT_UNKNOWN_CONNECTION:
                    handleNewUnknownConnection((AsyncResult) msg.obj);
                    break;
                default:
                    break;
            }
        }
    };

至于响应通知后续做了什么工作不是这次的重点。

=====补充======

Message msg = Message.obtain():
Handler h = getHandler();
h.sendMessage(msg);

从obtain()的源代码中我们可以知道,它是静态方法,而且只有在spool = null 的情况下才会new出一个Message(),返回一个Message对象,如果在不为空的情况下,Message的对象都是从Message对象池里面拿的实例从而重复使用的,这也为了Android中的Message对象能够更好的回收。

使用Handler中的sendMessage (Message msg)方式来发送消息.

我们可以知道android 中发送消息不管是Message中的几种重载的obtain()方式,还是Handler中的几种重载的sendMessage最终都是通过Handler.sendMessage来发送的,而Handler中的几种sendMessage()重载方法最终都会调用到sendMessageAtTime()方法来完成消息的入队操作。

发送一个消息到消息队列的对尾,它会在处理这个时间的线程中的handleMessage(Message),方法中被接受到并且处理。


第 36 章:电话与 RIL 无线接口层是 Java 电话框架和厂商调制解调器固件之间的桥梁。早期 RIL 是 C 语言守护进程 rild,通过 Unix 套接字、自定义二进制协议与框架通信。Android12 及以后迁移到稳定 AIDL HAL,把旧的单体 IRadio HIDL 接口拆分为多个按业务域划分的 AIDL 接口。# 列出全部radio‑hal aidl文件# 统计IRadioVoice接口方法数量# 统计IRadioData接口方法数量# 查看语音通话数据结构体Call.aidl。 阅读详情

相关推荐

Android 4.4 Kitkat Phone工作流程浅析(五)__MT(来电)流程分析

上一篇文章简单分析了RILJ的工作流程,实际上MTK对于RILJ的改动还是较大的,添加了很多request和respone类型。对于MT(来电)来讲,首先还是会由Modem接收到信息,然后发给RILC,RILC再发送给RILJ,并在RILJ的RILReceiver中接收到并进行处理。MTK对于Modem侧的AT指令进行一些定制,这和AOSP原生使用CLCC方式后去来电信息不同,MTK这里使用了自己添加的AT指令ECPI来反馈通话状态改变的信息。后面会针对MTK的log进行一个简单的分析,根据log来分析 M

Keep Awake,Keep Studying,Keep Moving,Keep... 1万+

追踪Android源码,理解Registrant运行机制

追踪Android源码,理解Registrant运行机制

Jing 1224

Android Telephony 概述分析

整体上描述了ANDROID Telephony的架构,并分模块以图形方式描述了内部类关系,

Android 基础篇 -- Registrant

 在Tele工作时,遇到过很多的Registrant,此前没有系统的研究过,趁此空挡,查看了下源码,算是做个笔记。  个人对于Registrant的理解是:一个对象A向另一个对象B注册消息,当B满足或者受到这个消息的时候,就通知A,A在此时去处理某些事。例如在创建Phone对象是,GsmCdmaPhone 会向Ril去注册一条voice_radio_tech_change的消息,当ril收到mo...

Clear_ws的博客 1384

WEBGL Shader零基础教程(四):片元着色器核心逻辑

本文系统介绍了WebGL渲染管线中片元着色器的核心概念与应用。主要内容包括:1)片元着色器在渲染管线中的定位与作用,作为逐像素处理单元接收插值数据并计算最终颜色;2)输入数据类型与使用规则,重点讲解varying变量和uniform变量的应用场景;3)颜色计算的核心逻辑,涵盖基础色、渐变、纹理采样和颜色混合;4)进阶特效实现与性能优化技巧,包括交互效果、内置函数组合和GPU计算优化;5)通过综合案例演示了纹理、波纹与交互效果的整合实现。文章提供了完整的代码示例和调试建议,为后续学习光照模型、后期处理等高级渲

分享知识,拥抱变化 1374

绑定压力的计算方法

压强的公式为P=F/S,其中P为ACF要求的本压压强范围,S为受压面积,F为本压压头施加的力。绑定参数需要按线体按压头进行DOE确认,并使用DOE确认好的参数按压头重新绑定标识好送ACF厂商实测固化率、粒子变形的情况,避免绑定参数导致的异常,在绑定参数的设定过程中温度和时间可以使用仪器实测但绑定的压力则需要换算。工程上绑定压力换算的原则是:1、FPC属于柔性物料,柔性物料的受压面积按FPC绑定的受压面积=FPC绑定的长度。一、工程上FOG FPC本压压力换算(柔性材料以挤压的接触面积=受力面积)F=P。

weixin_53757859的博客 1533

Android中的消息注册Registrant机制

前面说过MessageHandle机制,它保证了android上层代码线程间的通信。 消息注册机制更加丰富了MessageHandle的流程,它把过程严格阶段化了,分成消息注册和通知消息处理两个部分,让人一目了然。 消息注册机制的总体思想是:一个对象中开辟一个空间用于存放Message,当调用regist方法时将Message存放进去,当其调用notify方法时将所有Messag...

jinghuainfo 297

实战对比:Lmcache+vllm将KVcache卸载到CPU和SSD的性能差异(附完整配置)

本文通过实战对比Lmcache与vLLM在KV Cache卸载到CPU和SSD的性能差异,详细解析了配置优化、基准测试及高级调优策略。实验显示,CPU卸载在低并发下表现优异,而SSD方案在高并发场景中更具性价比优势,为LLM推理任务提供了高效的存储解决方案。

weixin_30664051的博客 700

Android Telephony分析(二) ---- RegistrantList详解

前言 本文主要讲解RegistrantList的原理,以及如何快速分析RegistrantList相关的代码流程。 在Telephony模块中,在RIL、Tracker(ServiceStateTracker、CallTracker、DcTracker)、Phone(PhoneBase及其子类)、UICC框架、CallManager等等中都大量使用到的RegistrantList,可见Regi

linyongan 1万+

VT System故障排查指南:从License验证到硬件连接全解析

本文详细解析VT System故障排查全流程,从License验证、Real Bus模式设置到硬件连接与VT6000组网配置。针对VT7900板卡等特殊设备提供专业解决方案,并分享系统级故障的二分法排查技巧,帮助工程师快速定位和解决CANoe环境下的各类硬件识别问题。

weixin_29269441的博客 255

联想ThinkServer SR588 重装raid5阵列信息(装完centos7后,找不到硬盘)

这里写自定义目录标题找不到硬盘选择光盘启动 找不到硬盘 装完centos7之后,提示重启,重启之后,就一直无法启动。 进入bios 看了,确实是有设置硬盘为第一启动选项。 选择光盘启动 本地标准硬盘也是找不到。 1、 重启进入bios在系统手设置里找到存储信息, 然后找到如图选项回车进入。 选择主目录进入。 进入Configuration Management 里面 先清除原来的设置信息 选择已启用在yes 提示清除成功。 返回上一目录选择,选择 Create Virtual Drive 再选择S

熠铭心时空的博客 2万+

观察者模式与RegistrantList机制

观测者模式介绍: 常用于GUI系统,订阅发布系统。其主要作用就是解耦。将观察者和被观察者解耦。 观察者模式定义: 定义对象间一对多的关系,每当一个对象改变时所有依赖于它的对象都会得到通知并自动更新。 简单实现: 1.主题拥有一个观察者的对象集合 2.有注册去注册方法和更新方法,其中更新方法会调用观察者对象自身的update方法

泊客 1700

Sinutrain下载安装与开启OPC UA---kalrry

Sinutrain 开启 OPC UA 本教程只适用于版本,其他版本配置目录有所改变建议安装到默认路径,否则后期修改路径时候容易忽略细节本教程提供安装包为官方包,网上有些非官方包安装后容易出现授权问题,比如授权管理器无法启动,官方技术会建议你重装系统,很多时候是因为安装包非官方包在首次安装前,建议重启一遍系统。

kalrry 1万+

android RIL Java 详解 -------- RegistrantList

Android RIL java

我的专栏 1540

「UG/NX」Block UI 曲线收集器CurveCollector

曲线收集器块用于选择一条或多条曲线,包括通过选择意图连接的末端曲线链。曲线选择意图用于此块,但它不支持“交点处停止”、“跟随圆角”、“中间链”和“特征内链”等规则选项。

何曾参静谧的博客 1090

扣子Coze工作流教程:采集公众号爆文,一键仿写自动发布

通过本教程,你学会了如何利用扣子(Coze)平台构建一个完整的公众号文章自动处理工作流。这个系统不仅能够大幅提升内容产出效率,还能通过AI二创保持内容新鲜度和原创性。最佳实践建议:初次使用时,建议先保存为草稿而不是直接发布,以便人工审核;从简单的工作流开始,逐步增加复杂度;定期检查工作流运行日志,优化节点配置。自动化内容创作是新媒体运营的未来趋势,掌握这项技能将使你在数字内容领域占据显著优势。

互联网架构师笔记 1238

RegistrantList机制 registerForXXX

GsmCdmaCallTracker构造函数,向RIL注册事件 /** GsmCdmaCallTracker构造函数,强关联GsmCdmaPhone RIL注册handle消息处理 registerForXXX mCi.registerForCallStateChanged==>>BaseCommands.registerForCallStateChanged(RIL父类)

qq_27104805的博客 785

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

从手机来电分析android消息机制

当RIL收到这个消息UNSOL_CALL_RING 然后调用mRingRegistrant.notifyRegistrant(new AsyncResult (null, ret, null)); mRingRegistrant是在哪里注册的呢? 在BaseCommands.java通过这个方法注册的: public void setOnCallRing(Handler h, int wh

但求成长,不求成功,让成功成为成长的必然结果,这就是成功最正确的道路 2486

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

Android BLE项目中相应的超时处理机制

最近的BLE项目中,需要处理各种超时,做一个小小的总结。1、蓝牙扫描超时处理蓝牙在扫描过程中是非常耗电的,需要在扫描一段时间后自动停止。这时候就可以借助一个Handler对象发送一个延时消息实现,如下://这里是发送一个延时任务 mHandler.postDelayed(new Runnable() { @Override public

猿诗人的博客 9731

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

RegistrantList队列使用

feiyunot的博客 219

RegistrantList消息机制

使用 1. 流程 注册作为监听者:A>B#registerFor*** 通知监听者:B#notify*** > A#ourHandler 2. 注册监听类 CLASS A{     private final int EVENT_**** = 4     Handler  ourHandler = new  OurHandler     Class OurHandler ext

liubin192837的博客 536

安卓10来电流程详细总结

来电过程, 是由com.android.phone进程发起的,因为 com.android.phone 进程中 Telephony 直接与Moderm层交互, com.android.phone 进程收到来来电消息后,发送消息给 system 进程, system 进程(Telecom作为中介)开始和com.android.phone 进程建立链接, 并通知 UI 进程 (com.android.dialer) 更新。大体上和拨号过程类似。 来电流程时序图: 对于MO Call来说,一般是由..

mike_jungle的博客 4906

【Java】【基础】wait和notify方法

waithe notify方法不是线程对象的方法,是java中任何一个java对象都有的方法,这两个方法是Object类中自带的 wait()方法和notify()方法的作用 wait()方法 Object o = new Object(); o.wait(); //表示让正在o对象上活动的线程(当前线程)进入等待状态,无期限等待,直到被唤醒为止 notify()方法 //将在o对象上等待的线程唤醒 o.notify();//唤醒o对象上正在等待的线程 wait()方法会让正在该对象上戳东

liuxiaowei 792

android call 流程,mt call消息流程 android来电流程

mt call消息流程 android来电流程 1、 RIL.java Receiver RIL 收到 RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED 消息,通过 RegistrantList 通知 GsmCallTracker 通话状态发生变化 2、 GsmCallTracker.java --- EVENT_CALL_STATE_CHANGE GsmCallTrac...

weixin_42506994的博客 677
上一篇: IDEA 快捷键 Android Studio快捷键
下一篇: Android L 5.0 MT流程 代码
十橙
博客等级 码龄24年 312粉丝 95原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值