一、基础知识
一、基础知识
(1)ITelephonyRegistry.aidl:frameworks/base/telephony/java/com/android/internal/telephony (接口)
(2)TelephonyRegistry.java: frameworks\base\services\core\java\com\android\server (服务器端,继承ITelephonyRegistry.stub)
(3)ServiceManager.java: frameworks\base\core\java\android\os (系统服务)
(4)TelephonyManager.java: frameworks\base\telephony\java\android\telephony (封装服务,供上层使用)
(1)TelephonyRegistry.java是一个系统服务,因此需要通过方法ServiceManager.java中的方法addService加入到系统服务中。
服务器端TelephonyRegistry.java向系统注册过程,在开机时通过SystemServer添加到ServiceManager中,如下:
telephonyRegistry = new TelephonyRegistry(context); ServiceManager.addService("telephony.registry", telephonyRegistry);
(2)获取服务方法:sRegistry = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService( "telephony.registry"));
二、功能介绍
关于TelephonyRegistry功能,如下:
(1)客户端向服务器端注册,TelephonyRegistry监听phone状态,当phone状态发生改变时,通知注册的客户端。
监听的功能如下(还有好多):
notifyCallState:监听通话状态的改变
notifyServiceStateForPhoneId:监听网络状态的改变
notifyCallForwardingChanged :监听呼叫转移状态的改变
notifyDataActivity:监听数据连接状态的改变
(2)监听phone状态的改变,当发生改变时,发送系统广播
broadcastCallStateChanged
broadcastDataConnectionStateChanged
broadcastSignalStrengthChanged
三、客户端向服务器端注册的过程
服务器端通过维护一服务个mRecords的列表,当客户端加入到这个列表中,当phone状态发生改变时,就会遍历这个列表中的客户端,去调用他们当初注册的回调函数。首先分析一下这列表的数据结构:
private static class Record {
String callingPackage; 调试用
IBinder binder; 回调函数的binder对象
IPhoneStateListener callback; 回调函数
int callerUserId; 客户端的uid,用于检查权限
int events; 客户注册的是哪个监听器
}
(1)客户端注册服务器端,需要提供 IPhoneStateListener对象;
(2)客户端注册服务器端,需要提供监听哪些事件;
(3)并不是所有的监听者都有权限获取服务,这个由callerUserId决定。
IPhoneStateListener数据结构:定义了监听器的回调函数
void onServiceStateChanged(in ServiceState serviceState); void onSignalStrengthChanged(int asu); void onCallForwardingIndicatorChanged(boolean cfi); void onCallStateChanged(int state, String incomingNumber); void onDataConnectionStateChanged(int state, int networkType); void onOtaspChanged(in int otaspMode); void onVoLteServiceStateChanged(in VoLteServiceState lteState);
PhoneStateListener.java :客户端可以监听哪些消息
即客户端可以指定监听的事件,同时指定监听的回调函数,当事件发生时,TelephonyRegistry.java会回调客户端的回调函数。因此下面要分析一下客户端监听的过程。
- LISTEN_SIGNAL_STRENGTH
- LISTEN_MESSAGE_WAITING_INDICATOR
- LISTEN_CALL_FORWARDING_INDICATOR
- LISTEN_CELL_LOCATION
- LISTEN_CALL_STATE
- LISTEN_DATA_CONNECTION_STATE
- LISTEN_DATA_ACTIVITY
- LISTEN_SIGNAL_STRENGTHS
- LISTEN_OTASP_CHANGED
- LISTEN_CELL_INFO
上篇文章介绍了TelephonyManager和ITelehony.aidl调用关系的实现,即上层可以通过TelephonyManager.java实现系统服务。这个和TelephonyRegistry是一样的,其他客户端对TelephonyRegistry的注册,可以通过TelephonyManager实现,获得系统服务如下:四、客户端注册服务器端流程
public TelephonyManager(Context context, int subId) { if (sRegistry == null) { sRegistry = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService( "telephony.registry")); } }
客户端通过TelephonyManager.java的listen方法实现对服务器端的records的注册。
换句话说,如果客户端向注册到服务器端,首先要获取TelephonyManager服务,其次调用TelephonyManager的listen方法,首先客户端对服务器端的注册。注册成功后,当phone状态发生改变时,再有TelephonyRegistry通知给客户端。public void listen(PhoneStateListener listener, int events) { sRegistry.listenForSubscriber(listener.mSubId, getOpPackageName(),listener.callback, events, notifyNow); }
接下来我们继续看在TelephonyManager中调用listen的结果:
上面的代码说明在listen中主要完成3个任务:
- @TelephonyRegistry
- public void listen(String pkgForDebug, IPhoneStateListener callback, int events, boolean notifyNow) {
- int callerUid = UserHandle.getCallingUserId();
- //得到客户端的UID
- int myUid = UserHandle.myUserId();
- //检测调用者是否有权限进行监听
- checkListenerPermission(events);
- IBinder b = callback.asBinder();
- //先去查找当前的申请者是否已经注册了监听
- final int N = mRecords.size();
- for (int i = 0; i < N; i++) {
- r = mRecords.get(i);
- if (b == r.binder) {
- break find_and_add;
- }
- }
- //构建一个Record对象
- r = new Record();
- r.binder = b;
- r.callback = callback;
- r.pkgForDebug = pkgForDebug;
- r.callerUid = callerUid;
- //把当前客户端信息写入mRecords列表中
- mRecords.add(r);
- //需要立刻发送通知
- if (notifyNow) {
- if ((events & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) {
- r.callback.onServiceStateChanged(new ServiceState(mServiceState));
- }
- ........
- }
- }
1、检查客户端是否有权限监听;
2、构建客户端的Record并添加到mRecords列表中;
3、判断是否需要立刻发送通知。
五、服务端通知客户端过程
服务器端TelephonyRegistry对客户端的通知消息,是由其他客户端获取的,
(1)首先,在DefaultPhoneNotifier.java的构造方法中,获取了TelephonyRegistry.java的服务。
(2)其次,DefaultPhoneNotifier.java中,又注册了RIL,当modem主动上报消息,会将消息上报给DefaultPhoneNotifier.java,DefaultPhoneNotifier收到消息后,会根据不同的消息
调用TelephonyRegistry.java相应的方法,最终将RIL层反馈的消息派发给各个客户端。
(3)
也就是说,TelephonyRegistry充当了中介的角色,由其中某个客户端通过TelephonyRegistry去向其他所有的客户端进行消息派发。
现在以监听手机状态改变为例子: