客户端在得到这个服务后,可以通过统一的listen方法将自己注册为状态的监听器,如果Phone状态发生了改变,系统就会遍历所有的监听器,主动向他们发消息,调用相应的回调函数。
@SystemServer.java telephonyRegistry = new TelephonyRegistry(context); ServiceManager.addService("telephony.registry", telephonyRegistry);
由此可见,这个服务被加载为“telephony.registry”的服务。如果需要获取该服务,就需要通过“telephony.registry”的名字向ServiceManager查询。
@TelephonyRegistry.java private static class Record { //调试用 String pkgForDebug; //回调函数的IBinder对象 IBinder binder; //回调函数 IPhoneStateListener callback; //客户端的uid,用于检查权限 int callerUid; //表示客户端注册的是哪个监听器 int events; //调试用,不去关心 public String toString() { } }这样的数据结构说明3个重要信息:1、客户端注册监听器时,需要提供一个IPhoneStateListener类型的对象;2、客户端需要告诉服务端,自己需要监听哪些消息(events);3、并不是所有的客户端都有权限去监听所有的状态(callerUid决定)。
@IPhoneStateListener.aidl oneway interface IPhoneStateListener { //服务状态改变 void onServiceStateChanged(in ServiceState serviceState); //信号改变 void onSignalStrengthChanged(int asu); //等待短信的改变,类似于语音信箱提醒短信 void onMessageWaitingIndicatorChanged(boolean mwi); //呼叫转移状态改变 void onCallForwardingIndicatorChanged(boolean cfi); void onCellLocationChanged(in Bundle location); //通话状态改变 void onCallStateChanged(int state, String incomingNumber); //数据连接状态改变 void onDataConnectionStateChanged(int state, int networkType); void onDataActivity(int direction); void onSignalStrengthsChanged(in SignalStrength signalStrength); void onOtaspChanged(in int otaspMode); void onCellInfoChanged(in List<CellInfo> cellInfo); }上面看到,IPhoneStateListener接口定义了有关Phone各个状态的监听器的回调函数。
@PhoneStateListener.java LISTEN_SERVICE_STATE 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可以看到,这些监听消息是和上面的IPhoneStateListener相对应的。
@TelephonyManager.java public TelephonyManager(Context context) { //得到TelephonyRegistry服务 sRegistry = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService( "telephony.registry")); } //通过TelephonyManager间接实现对TelephonyRegistry的注册: public void listen(PhoneStateListener listener, int events) { String pkgForDebug = sContext != null ? sContext.getPackageName() : "<unknown>"; try { Boolean notifyNow = (getITelephony() != null); sRegistry.listen(pkgForDebug, listener.callback, events, notifyNow); } catch (RemoteException ex) { } catch (NullPointerException ex) { } }也就是说, 客户端如果想要实现对TelephonyRegistry的监听,可以先得到TelephonyManager的服务,然后通过这个服务调用其listen方法把当前客户端注册给TelephonyRegistry,当Phone状态改变时,再由TelephonyRegistry发送通知给当前客户端。
@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)); } ........ } }上面的代码说明在listen中主要完成3个任务:
3、判断是否需要立刻发送通知。
@PhoneFactory.java sPhoneNotifier = new DefaultPhoneNotifier(); new GSMPhone(context,sCommandsInterface, sPhoneNotifier)也就是说,GSMPhone中的sPhoneNotifier是DefaultPhoneNotifier对象,我们来看看这个对象的构造函数:
@DefaultPhoneNotifier.java DefaultPhoneNotifier() { mRegistry = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService("telephony.registry")); }这说明,DefaultPhoneNotifier是TelephonyRegistry的“客户”,得到了远程的TelephonyRegistry对象。当RILJ中有Phone的消息需要上报时,将会采用如下的形式:
@GSMPhone.java void notifyPhoneStateChanged() { mNotifier.notifyPhoneState(this); }这里的mNotifier就是当初构建GSMPhone时传递的sPhoneNotifier,也就是DefaultPhoneNotifier对象,此时将会调用他的notifyPhoneState方法:
@DefaultPhoneNotifier.java public void notifyPhoneState(Phone sender) { Call ringingCall = sender.getRingingCall(); String incomingNumber = ""; if (ringingCall != null && ringingCall.getEarliestConnection() != null){ incomingNumber = ringingCall.getEarliestConnection().getAddress(); } try { //这里就是调用TelephonyRegistry的notifyCallState方法,通知所有其他的客户端 mRegistry.notifyCallState(convertCallState(sender.getState()), incomingNumber); } catch (RemoteException ex) { } }经过上面的步骤,系统从Modem发送的关于Phone、network的状态的改变,经过RIL和GSMPhone传递给DefaultPhoneNotifier,然后又传递给了TelephonyRegistry,由他负责将当前消息分发给所有注册了监听的客户端。
@TelephonyRegistry.java public void notifyCallState(int state, String incomingNumber) { for (Record r : mRecords) { if ((r.events & PhoneStateListener.LISTEN_CALL_STATE) != 0) { try { //通知所有的客户端,调用其onCallStateChanged方法 r.callback.onCallStateChanged(state, incomingNumber); } catch (RemoteException ex) { } } } //同时发送广播消息 broadcastCallStateChanged(state, incomingNumber); } private void broadcastServiceStateChanged(ServiceState state) { long ident = Binder.clearCallingIdentity(); mBatteryStats.notePhoneState(state.getState()); //发送ACTION_SERVICE_STATE_CHANGED的广播 Intent intent = new Intent(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED); Bundle data = new Bundle(); state.fillInNotifierBundle(data); intent.putExtras(data); //发送 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL); }从上面可以看出,在notifyCallState的过程中,我们看到消息的分发是通过两个通道实现的:
2、通过broadcastCallStateChanged方法发送广播。
我们现在用一个流程图来结束这一节的学习: