本文将结合前面五篇文章所讲解的知识,综合起来,实现一个接口扩展的功能。 
如果还没有阅读过前面五篇文章的内容,请先阅读: 
《Android Telephony分析(一) — Phone详解 》 
《Android Telephony分析(二) — RegistrantList详解 》 
《Android Telephony分析(三) — RILJ详解 》 
《Android Telephony分析(四) — TelephonyManager详解 》 
《Android Telephony分析(五) — TelephonyRegistry详解 》

至于接口扩展,也就是新增一个接口给APP调用,从APP至RIL,大体流程如下:

APPAPPTelephonyManagerTelephonyManagerPhonePhoneRILRIL发送Requestmodem处理返回结果返回结果

本文来自http://blog.csdn.net/linyongan ,禁止转载。


1. 发送请求的实现

1.1 扩展BaseCommands接口

扩展BaseCommands接口主要为了在RIL.java 中实现向modem发送请求的方法。 
RILJ的继承关系如下: 

所以要在RILJ中新增一个向modem发送Request的方法,需要扩展BaseCommands,再在RIL.java重写该方法。 
在BaseCommands.java (frameworks\opt\telephony\src\java\com\Android\internal\telephony)添加一个方法:

    public void setValueToModem(int input,Message response) {//这个方法为空,由让子类按需要去重写}
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

在RILConstants.java (frameworks\base\telephony\java\com\android\internal\telephony)中新增一个主动请求的消息:

    //200这个数字需要根据实际项目进行修改int RIL_REQUEST_SET_VALUE = 200;
  • 1
  • 2
  • 1
  • 2

在RIL.java (frameworks\opt\telephony\src\java\com\android\internal\telephony)中新增发送请求的方法:

    @Overridepublic void setValueToModem(int input,Message response) {//得到一个RILRequest对象RILRequest rr= RILRequest.obtain(RIL_REQUEST_SET_VALUE, response);//将APP传递过来的参数放到RILRequest对象中rr.mParcel.writeInt(input);//输出关键logif (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)+ " " + input);send(rr);//for test//response.sendToTarget();}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

至于RILC的扩展省略,调试为了这个接口是否可用,故意写了 
response.sendToTarget();这行代码用于调试。

1.2 扩展PhoneInternalInterface接口

扩展PhoneInternalInterface接口主要为了封装RILJ的方法,只要得到Phone的实例即可间接调用RILJ的方法。 
Phone的继承关系如下: 
 
Phone.java是整个关系的中心枢纽,所以假如不用针对ImsPhone而走IMS流程的话,我们可以扩展PhoneInternalInterface接口,然后在Phone.java中具体实现即可。 
先在PhoneInternalInterface.java (frameworks\opt\telephony\src\java\com\android\internal\telephony)中新增一个接口:

    void setValueToModem(int value);
  • 1
  • 2
  • 1
  • 2

在Phone.java (frameworks\opt\telephony\src\java\com\android\internal\telephony)统一实现该接口,Phone所有子类都使用这个方法:

    @Overridepublic void setValueToModem(int input){//对于回调事件的处理,第2小节再讲Message resp = obtainMessage(EVENT_SET_VALUE_DONE,0,0);//直接调用RILJ中的方法mCi.setValueToModem(input,resp);}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

1.3 扩展ITelephony接口

扩展ITelephony接口主要是为了进一步封装Phone对象中的方法,让那些不能直接得到Phone对象的类也可以间接地调用Phone对象中的方法。 
先在ITelephony.aidl(frameworks\base\telephony\java\com\android\internal\telephony)中新增一个接口:

    void setValueToModem(int input);
  • 1
  • 1

在PhoneInterfaceManager.java (packages\services\telephony\src\com\android\phone)中实现该接口:

    @Overridepublic void setValueToModem(int input){try{//得到Phone对象Phone phone = PhoneFactory.getDefaultPhone();if(phone != null){phone.setValueToModem(input);}}catch(IllegalStateException e){}}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

由于PhoneInterfaceManager运行在Phone进程中,所以还需进一步封装,让不运行在Phone进程中的类也可以调用。 
在TelephonyManager.java (frameworks\base\telephony\java\android\telephony)中封装Phone Service的方法:

    /** @hide */public void setValueToModem(int input){try {//得到PhoneInterfaceManager的代理对象ITelephony telephony = getITelephony();if (telephony != null){telephony.setValueToModem(input);}} catch (RemoteException ex) {} catch (NullPointerException ex) {}}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

从RILJ—>Phone—>PhoneInterfaceManager—>TelephonyManager,经过一层层的封装,APP终于可以通过TelephonyManager来间接调用RILJ中的方法了。 
整个过程的时序图如下: 

2. 返回结果的实现

2.1 RILJ中的处理

在RILJ向modem发送请求之后,modem处理完会上报Solicited Response消息并且附带着结果 
所以我们需要在RIL.java (frameworks\opt\telephony\src\java\com\android\internal\telephony)的processSolicited()方法中增加

    case RIL_REQUEST_SET_VALUE:      ret = responseInts(p); break;
  • 1
  • 1

在requestToString方法中增加

    case RIL_REQUEST_SET_VALUE: return "RIL_REQUEST_SET_VALUE";
  • 1
  • 1

2.2 Phone中的处理

在《Android Telephony分析(三) — RILJ详解 》的2.2.1小节中我们说过,接着会通过rr.mResult.sendToTarget();返回到创建Message对象的地方,也就是上面1.2小节说到的 
在Phone.java (frameworks\opt\telephony\src\java\com\android\internal\telephony)中:

    @Overridepublic void setValueToModem(int input){//对于回调事件的处理,第2小节再讲Message resp = obtainMessage(EVENT_SET_VALUE_DONE,0,0);//直接调用RILJ中的方法mCi.setValueToModem(input,resp);}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

还需要对于回调事件进行处理,也就是先在Phone.java中定义EVENT_SET_VALUE_DONE消息:

    //100这个数字需要根据实际项目进行修改protected static final int EVENT_SET_VALUE_DONE                 = 100;protected static final int EVENT_LAST                           =EVENT_SET_VALUE_DONE;
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

接着在handleMessage()方法中增加对EVENT_SET_VALUE_DONE的处理:

            case EVENT_SET_VALUE_DONE://取出返回结果ar = (AsyncResult)msg.obj;String result = null;//如果返回结果不为空且没有异常if (ar != null && ar.exception == null) {result = "success";}else{result = "fail";}//其实最偷懒的方式是直接在这里发广播通知APP,//但是为了结合我们学过的知识,我还是通过PhoneNotifier来实现mNotifier.notifySetValueDone(result);break;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

2.3 扩展PhoneNotifier接口

扩展PhoneNotifier接口主要为了进一步上报消息并且附带这结果。PhoneNotifier的常用子类是DefaultPhoneNotifier。 
先在PhoneNotifier.java (frameworks\opt\telephony\src\java\com\android\internal\telephony)中新增一个接口:

    public void notifySetValueDone(String result);
  • 1
  • 1

接着在DefaultPhoneNotifier.java (frameworks\opt\telephony\src\java\com\android\internal\telephony)中实现该接口:

    @Overridepublic void notifySetValueDone(String result){try {if (mRegistry != null) {//需要依赖TelephonyRegistry进一步上报通知mRegistry.notifySetValueDone(result);}} catch (RemoteException ex) {ex.printStackTrace();}}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

2.4 扩展ITelephonyRegistry接口

先在ITelephonyRegistry.aidl(frameworks\base\telephony\java\com\android\internal\telephony)中新增接口:

    void notifySetValueDone(String result);
  • 1
  • 1

在TelephonyRegistry.java (frameworks\base\services\core\java\com\android\server)中实现该接口:

    @Overridepublic void notifySetValueDone(String result){synchronized (mRecords) {for (Record r : mRecords) {//通知所有监听了LISTEN_SET_VALUE_DONE的类if((r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_SET_VALUE_DONE))){try {r.callback.onSetValueDone(result);} catch (RemoteException ex) {mRemoveList.add(r.binder);}}}handleRemoveListLocked();}}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

2.5 扩展IPhoneStateListener接口

扩展IPhoneStateListener接口主要为了新增一个可以监听的事件LISTEN_SET_VALUE_DONE。通过APP事先监听,当有该事件上报的时候,就会通知到APP。 
先IPhoneStateListener.aidl(frameworks/base/telephony/java/com/android/internal/telephony)中新增接口:

    void onSetValueDone(String result);
  • 1
  • 1

在PhoneStateListener.java (frameworks\base\telephony\java\android\telephony)中新增可监听的事件,并且初步实现接口中的方法

    /** @hide *///这个数字按项目实际需要修改public static final int LISTEN_SET_VALUE_DONE                      = 0x00800000;/** @hide*/public void onSetValueDone(String result){//由子类来重写}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

在IPhoneStateListener callback = new IPhoneStateListener.Stub()中新增:

        public void onSetValueDone(String result){Message.obtain(mHandler, LISTEN_SET_VALUE_DONE, 0, 0, result).sendToTarget();}
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

在handleMessage中新增:

    case LISTEN_SET_VALUE_DONE://调用子类重写的方法,也就是APP中的方法PhoneStateListener.this.onSetValueDone((String)msg.obj);break;
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

到这里,从RILJ—>Phone—>DefaultPhoneNotifier—>TelephonyRegistry—>APP,消息和结果就上报到APP了。 
整个过程的时序图如下(步骤10~15): 

3. APP如何使用接口

在APP中可以这样调用并调试接口:

    //监听事件TelephonyManager.getDefault().listen(new PhoneStateListener(){@Overridepublic void onSetValueDone(String result){//对结果进行处理}}, PhoneStateListener.LISTEN_SET_VALUE_DONE);//发送请求TelephonyManager.getDefault().setValueToModem(1);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
原文地址: http://blog.csdn.net/linyongan/article/details/52151651

Android Telephony分析(六) ---- 接口扩展(实践篇)相关推荐

  1. Android Telephony分析(七) ---- 接口扩展(异步转同步)

    本文是基于上一篇<Android Telephony分析(六) -- 接口扩展(实践篇)>来写的.  上一篇介绍的接口扩展的方法需要实现两部分代码:  1. 从APP至RIL,发送请求:  ...

  2. Android Telephony分析(五) ---- TelephonyRegistry详解

    本文紧接着上一篇文章<Android Telephony分析(四) -- TelephonyManager详解 >的1.4小节.  从TelephonyRegistry的大部分方法中:  ...

  3. Android Telephony分析(三) ---- RILJ详解

    前言 本文主要讲解RILJ工作原理,以便更好地分析代码,分析业务的流程.  这里说的RILJ指的是RIL.java (frameworks\opt\telephony\src\java\com\And ...

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

    前言 本文主要讲解RegistrantList的原理,以及如何快速分析RegistrantList相关的代码流程.  在Telephony模块中,在RIL.Tracker(ServiceStateTr ...

  5. Android Telephony分析(四) ---- TelephonyManager详解

    前言 TelephonyManager主要提供Telephony相关信息的查询/修改功能,以及Phone状态监听功能,封装的方法主要是提供给APP上层使用.  TelephonyManager.jav ...

  6. Android Telephony 分析【全】

    11年下半年一直在做RIL的移植,主要解决第三方库的一些bug,使之能更好的工作在公司的PAD上.但是后来发现远远不够,有好多问题出现在Framework层.比方说我们想让PAD支持热插拔,尽管底层做 ...

  7. Android Telephony分析(一) ---- Phone详解

    本文主要讲解Telephony中Phone相关的知识. 1. Android N中Phone的改变 Android 6.0时,Phone的继承关系: 在Android N中,Phone的继承关系: 变 ...

  8. Android 短信模块分析(六) 接收Wappush信息及彩信附件增加删除

    一.Wappush接收的时序图如图1.1所示: 二.彩信附件增加删除 彩信附件添加:在ComposeMessageActivity里的addAttachment(int type) 函数 根据type ...

  9. 【Android 异步操作】FutureTask 分析 ( Future 接口解析 | Runnable 接口解析 | Callable 接口解析 )

    文章目录 一.Future 接口 1.Future 接口简介 2.取消任务方法 3.Future 接口源码注释 二.Callable 接口 三.Runnable 接口 上一篇博客 [Android 异 ...

最新文章

  1. [Mac] mac linux 多线程下载利器 axel
  2. Java定义接口变量为接收类型有什么好处(面向接口编程)
  3. 如何完全卸载Java
  4. 设计模式(二)————观察者模式
  5. 大剑无锋之new一个对象背后发生了什么?
  6. 【年度总结】2016年年度总结
  7. 国内互联网公司算法机器学习岗(阿里星)面试总结
  8. oracle数据库6月之后的数据,Oracle数据库SCN存在可能在2019年6月导致宕机问题
  9. selenium元素等待及滚动条滚动
  10. AcWing 896. 最长上升子序列 II(二分优化LIS)
  11. Sea Battle<海战>(思路题)
  12. 题目:输入某年某月某日,判断这一天是这一年的第几天?
  13. Latex 爬过的坑(4)——Latex中插入Emoji
  14. r语言和python的区别-Python与R语言的简要对比
  15. TFIDF与BM25
  16. 串口通信协议c语言程序,串口通信协议源代码.doc
  17. word表格边框消失怎么办_为什么我的word表格没了边框 - 卡饭网
  18. Matlab中不定积分和定积分的实现
  19. 毕业生写论文必备!! 设置奇数偶数页眉不同,奇数页是对应本章章节名,偶数页为论文名
  20. 父亲节手抄报内容大全

热门文章

  1. js数据类型判断和数组判断
  2. ORACLE 11G EXP导出空表方法
  3. 公安部:明年起闯红灯扣6分 挡车牌扣12分
  4. Sharepoint 2007 用代码聚合所有子网站文章 (populating data sources in code)
  5. 添加用户和赋予root权限
  6. Markdown中数学公式练习
  7. 6.6 数据集的存储与表达
  8. 随机信号通过带通滤波器
  9. 天池实验室Python能力测验
  10. 科大星云诗社动态20220113