Android Telephony分析(五) ---- TelephonyRegistry详解
2016-08-05 19:07
525 查看
本文紧接着上一篇文章《Android Telephony分析(四) —- TelephonyManager详解 》的1.4小节。
从TelephonyRegistry的大部分方法中:
可以看出TelephonyRegistry主要的功能是上报消息,有两种方式:
1. 通过notifyXXX方法。
2. 通过发送broadcast。
至于发广播没什么好说的了,我们看看notifyXXX方法吧,以notifyCallState()方法为例
通过初步分析notifyCallState()方法,你会发现有两个疑问:
1. mRecords是什么?
2. Record.callback又是什么?
好了,带着上面两种疑问,我们继续分析代码吧。
接着你会发现mRecords是由Record对象组成的List集合
而Record是TelephonyRegistry中的内部类,TelephonyRegistry会把监听者的信息封装成一个Record对象,并且放进mRecords列表中管理。
在TelephonyRegistry.java的listen方法中,管理并维护着mRecords列表:
本文来自\color{red}{本文来自}http://blog.csdn.net/linyongan ,转载请务必注明出处。\color{red}{,转载请务必注明出处。}
常见的注册监听和发通知的流程,以监听Call状态变化为例:
总体看分成3步:
1. 根据需要监听的事件,重写PhoneStateListener中对应的方法,如果需要监听LISTEN_CALL_STATE,那么需要重写 onCallStateChanged()方法;如果需要监听LISTEN_SERVICE_STATE,则需要重写onServiceStateChanged()方法。(步骤1)
2. 调用TelephonyManager的listen()方法,传递PhoneStateListener对象和events。到这里监听的操作一直执行到步骤4就结束了。
3. 当有Call状态变化消息上来时,通知上报的路径:
RILJ—>CallTracker—>Phone—>DefaultPhoneNotifier—>TelephonyRegistry—>监听者
最后也是来到监听者重写的PhoneStateListener的那个方法中,整个过程也是一个回调。
(Call状态上报也是一个比较复杂的过程,后面会再写一篇文章详细讲解)
其他需要说明的是:
1. DefaultPhoneNotifier是TelephonyRegistry最常用的客户端,它继承自
在它构造方法中:
所以DefaultPhoneNotifier中大部分方法都依靠TelephonyRegistry对象来实现。
2 . 如何知道我需要监听的事件以及对应要重写的方法?
所有的可以监听的事件都定义在PhoneStateListener.java (frameworks\base\telephony\java\android\telephony)中,
需要重写的方法,初始都定义在IPhoneStateListener.aidl(frameworks/base/telephony/java/com/android/internal/telephony)中
接着由PhoneStateListener初步重写了IPhoneStateListener.aidl接口中的方法:
在这里就可以找到某个事件对应的方法是什么。
当然可以自己新增事件以及在IPhoneStateListener.aidl中新增对应的接口,再实现该接口就可以了。
从TelephonyRegistry的大部分方法中:
可以看出TelephonyRegistry主要的功能是上报消息,有两种方式:
1. 通过notifyXXX方法。
2. 通过发送broadcast。
至于发广播没什么好说的了,我们看看notifyXXX方法吧,以notifyCallState()方法为例
public void notifyCallStateForSubscriber(int subId, int state, String incomingNumber) { //先检测权限 if (!checkNotifyPermission("notifyCallState()")) { return; } //1.mRecords是什么? synchronized (mRecords) { int phoneId = SubscriptionManager.getPhoneId(subId); if (validatePhoneId(phoneId)) { mCallState[phoneId] = state; mCallIncomingNumber[phoneId] = incomingNumber; //遍历mRecords列表 for (Record r : mRecords) { //取出注册监听"LISTEN_CALL_STATE"这种事件的Record对象 if (r.matchPhoneStateListenerEvent(PhoneStateListener.LISTEN_CALL_STATE) && (r.subId == subId) && (r.subId != SubscriptionManager.DEFAULT_SUBSCRIPTION_ID)) { try { String incomingNumberOrEmpty = getCallIncomingNumber(r, phoneId); //2.Record.callback又是什么? r.callback.onCallStateChanged(state, incomingNumberOrEmpty); } catch (RemoteException ex) { mRemoveList.add(r.binder); } } } } handleRemoveListLocked(); } //同时调用发广播的方法 broadcastCallStateChanged(state, incomingNumber, subId); }
通过初步分析notifyCallState()方法,你会发现有两个疑问:
1. mRecords是什么?
2. Record.callback又是什么?
好了,带着上面两种疑问,我们继续分析代码吧。
接着你会发现mRecords是由Record对象组成的List集合
private final ArrayList<Record> mRecords = new ArrayList<Record>();
而Record是TelephonyRegistry中的内部类,TelephonyRegistry会把监听者的信息封装成一个Record对象,并且放进mRecords列表中管理。
class TelephonyRegistry extends ITelephonyRegistry.Stub { private static class Record { String callingPackage; IBinder binder; //Record.callback是实现了IPhoneStateListener接口的类, //也就是继承了或者重写了PhoneStateListener的类 IPhoneStateListener callback; IOnSubscriptionsChangedListener onSubscriptionsChangedListenerCallback; int callerUserId; //存储用来记录监听的事件 int events; int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; int phoneId = SubscriptionManager.INVALID_PHONE_INDEX; boolean canReadPhoneState; boolean matchPhoneStateListenerEvent(int events) { return (callback != null) && ((events & this.events) != 0); } boolean matchOnSubscriptionsChangedListener() { return (onSubscriptionsChangedListenerCallback != null); } }
在TelephonyRegistry.java的listen方法中,管理并维护着mRecords列表:
public void listenForSubscriber(int subId, String pkgForDebug, IPhoneStateListener callback, int events, boolean notifyNow) { listen(pkgForDebug, callback, events, notifyNow, subId); } private void listen(String callingPackage, IPhoneStateListener callback, int events, boolean notifyNow, int subId) { ... synchronized (mRecords) { // register Record r; find_and_add: { //得到监听者的信息 IBinder b = callback.asBinder(); //遍历mRecords列表 for (int i = 0; i < N; i++) { r = mRecords.get(i); if (b == r.binder) { //退出循环 break find_and_add; } } //如果监听者还没有被加到mRecords列表中 r = new Record(); r.binder = b; //新建一个Record对象并且加入mRecords列表中 mRecords.add(r); if (DBG) log("listen: add new record"); } //存储监听者 r.callback = callback; ... //存储监听者所监听的事件 r.events = events; //如果需要现在发通知的话 if (notifyNow && validatePhoneId(phoneId)) { if ((events & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) { try { //注册之后,马上通知一次监听者 r.callback.onServiceStateChanged( new ServiceState(mServiceState[phoneId])); } catch (RemoteException ex) { remove(r.binder); } } ... }
本文来自\color{red}{本文来自}http://blog.csdn.net/linyongan ,转载请务必注明出处。\color{red}{,转载请务必注明出处。}
常见的注册监听和发通知的流程,以监听Call状态变化为例:
总体看分成3步:
1. 根据需要监听的事件,重写PhoneStateListener中对应的方法,如果需要监听LISTEN_CALL_STATE,那么需要重写 onCallStateChanged()方法;如果需要监听LISTEN_SERVICE_STATE,则需要重写onServiceStateChanged()方法。(步骤1)
2. 调用TelephonyManager的listen()方法,传递PhoneStateListener对象和events。到这里监听的操作一直执行到步骤4就结束了。
3. 当有Call状态变化消息上来时,通知上报的路径:
RILJ—>CallTracker—>Phone—>DefaultPhoneNotifier—>TelephonyRegistry—>监听者
最后也是来到监听者重写的PhoneStateListener的那个方法中,整个过程也是一个回调。
(Call状态上报也是一个比较复杂的过程,后面会再写一篇文章详细讲解)
其他需要说明的是:
1. DefaultPhoneNotifier是TelephonyRegistry最常用的客户端,它继承自
public class DefaultPhoneNotifier implements PhoneNotifier {
在它构造方法中:
protected DefaultPhoneNotifier() { //通过ServiceManager得到了TelephonyRegistry的代理对象 mRegistry = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService( "telephony.registry")); }
所以DefaultPhoneNotifier中大部分方法都依靠TelephonyRegistry对象来实现。
2 . 如何知道我需要监听的事件以及对应要重写的方法?
所有的可以监听的事件都定义在PhoneStateListener.java (frameworks\base\telephony\java\android\telephony)中,
需要重写的方法,初始都定义在IPhoneStateListener.aidl(frameworks/base/telephony/java/com/android/internal/telephony)中
接着由PhoneStateListener初步重写了IPhoneStateListener.aidl接口中的方法:
/** * The callback methods need to be called on the handler thread where * this object was created. If the binder did that for us it'd be nice. */ IPhoneStateListener callback = new IPhoneStateListener.Stub() { public void onServiceStateChanged(ServiceState serviceState) { Message.obtain(mHandler, LISTEN_SERVICE_STATE, 0, 0, serviceState).sendToTarget(); } ... }
在这里就可以找到某个事件对应的方法是什么。
当然可以自己新增事件以及在IPhoneStateListener.aidl中新增对应的接口,再实现该接口就可以了。
相关文章推荐
- BO2K源码分析(一 WinMain()函数)
- 如何写系统分析书
- "陷阱"技术探秘----动态汉化Windows技术的分析
- Java 编程技术中汉字问题的分析及解决
- php4.0.0远程溢出源代码分析与测试程序
- Java 编程技术中汉字问题的分析及解决
- "陷阱"技术探秘 ----动态汉化Windows技术的分析
- 关于Basic程序解释器及编译原理的简单化(1)--词法分析和代数式求值
- 关于Basic程序解释器及编译原理的简单化(1)---Basic器的语法分析及主要代码
- Unix/ELF文件格式及病毒分析
- Linux开机过程的分析
- LILO使用指南 MBR 根分区 lilo.conf 出错分析 忘记密码
- C++的不足之处讨论系列(二)-- 全局分析
- BO2k源码分析(二)----命令循环机制
- BO2k源代码分析(一)----WinMain()函数
- [导入]Web搜索引擎设计和实现分析
- 分析网上销售软件是否能赚钱,数字最有说服力
- 万花谷网页病毒源码分析
- "陷阱"技术探秘 ──动态汉化Windows技术的分析