注:本文基于Android O。
Phone状态的监听主要是通过TelephonyRegistry和PhoneStateListener来实现的。
TelephonyRegistry是一个service,负责监听事件的注册及通知,在整个流程中起一个桥梁的作用。
PhoneStateListener则是作为监听器,需要监听者实现监听到响应事件后需要进行的处理。
PhoneStateListener中定义了可以监听的事件:
public static final int LISTEN_NONE = 0; public static final int LISTEN_SERVICE_STATE = 0x00000001; public static final int LISTEN_SIGNAL_STRENGTH = 0x00000002; public static final int LISTEN_MESSAGE_WAITING_INDICATOR = 0x00000004; public static final int LISTEN_CALL_FORWARDING_INDICATOR = 0x00000008; public static final int LISTEN_CELL_LOCATION = 0x00000010; public static final int LISTEN_CALL_STATE = 0x00000020; public static final int LISTEN_DATA_CONNECTION_STATE = 0x00000040; public static final int LISTEN_DATA_ACTIVITY = 0x00000080; public static final int LISTEN_SIGNAL_STRENGTHS = 0x00000100; public static final int LISTEN_OTASP_CHANGED = 0x00000200; public static final int LISTEN_CELL_INFO = 0x00000400; public static final int LISTEN_PRECISE_CALL_STATE = 0x00000800; public static final int LISTEN_PRECISE_DATA_CONNECTION_STATE = 0x00001000; public static final int LISTEN_DATA_CONNECTION_REAL_TIME_INFO = 0x00002000; public static final int LISTEN_VOLTE_STATE = 0x00004000; public static final int LISTEN_OEM_HOOK_RAW_EVENT = 0x00008000; public static final int LISTEN_CARRIER_NETWORK_CHANGE = 0x00010000; public static final int LISTEN_VOICE_ACTIVATION_STATE = 0x00020000; public static final int LISTEN_DATA_ACTIVATION_STATE = 0x00040000;
监听者在注册监听相关事件时,需要继承PhoneStateListener对象,并重写需要监听的事件对应的方法,这个方法在相应事件发生后会被回调,因此,我们重写这个方法的目的也就是添加事件发生后的处理流程,例如,如果我们要监听service state的变化,就需要重写onServiceStateChanged方法。我们来看看MobileSignalController中的例子:
mPhoneStateListener = new MobilePhoneStateListener(info.getSubscriptionId(), receiverLooper); class MobilePhoneStateListener extends PhoneStateListener { public MobilePhoneStateListener(int subId, Looper looper) { super(subId, looper); } @Override public void onSignalStrengthsChanged(SignalStrength signalStrength) { ...... mSignalStrength = signalStrength; updateTelephony(); } @Override public void onServiceStateChanged(ServiceState state) { ...... } @Override public void onDataConnectionStateChanged(int state, int networkType) { ...... } @Override public void onDataActivity(int direction) { ...... } @Override public void onCarrierNetworkChange(boolean active) { ...... } }; public void registerListener() { mPhone.listen(mPhoneStateListener, PhoneStateListener.LISTEN_SERVICE_STATE | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS | PhoneStateListener.LISTEN_CALL_STATE | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE | PhoneStateListener.LISTEN_DATA_ACTIVITY | PhoneStateListener.LISTEN_CARRIER_NETWORK_CHANGE); ...... }
MobilePhoneStateListener继承了PhoneStateListener,并重写了与监听事件相关的方法,然后调用mPhone.listen()进行注册监听,mPhone是一个TelephonyManager对象。
我们在传递监听事件时,可同时监听多个事件,上述例子中就监听了service state和signal strength等多个事件。
监听者通过TelephonyManager的listen()方法注册监听,listen()方法中调用了TelephonyRegistry的listenForSubscriber()方法。
其中,传入的参数listener.callback是一个IPhoneStateListenerStub对象;events参数是监听的事件;还有一个参数notifyNow,其为true时,注册后相应的callback会被立即回调一次,在这里,它的值是由获取到的PhoneInterfaceManager对象是否为null来决定的,不为null时notifyNow为true。
public void listen(PhoneStateListener listener, int events) { ...... boolean notifyNow = (getITelephony() != null); ...... sRegistry.listenForSubscriber(listener.mSubId, getOpPackageName(), listener.callback, events, notifyNow); ......}
TelephonyRegistry实际上是一个Service,在开机时就会被添加到ServiceManager。其作用就是给其它App提供监听Phone相关状态的接口。
SystemServer.javaprivate void startOtherServices() { ...... telephonyRegistry = new TelephonyRegistry(context); ServiceManager.addService("telephony.registry", telephonyRegistry); ......}
另外,在代码中对此类有如下介绍:
Since phone process can be restarted, this class provides a centralized place that applications can register and be called back from.
也就是说,之所以要单独使用一个service来做这个监听的任务,是因为即使phone进程重启,
我们之前注册监听的事件也都还在,如果直接向phone进程进行注册,那么phone进程重启后,
就需要之前注册了的App重新再去注册,这种做法显然是不合理的。
TelephonyRegistry的listenForSubscriber方法直接调用其listen方法。
public void listenForSubscriber(int subId, String pkgForDebug, IPhoneStateListener callback, int events, boolean notifyNow) { listen(pkgForDebug, callback, events, notifyNow, subId);}
listen方法中首先会判断要监听的事件是什么,如果监听的事件为空的话,就认为调用者是想取消之前注册的listener,然后就会将之前的注册信息删除掉。
对于正常的注册监听流程,首先会进行一系列的权限判断,以确保Caller具有相应事件的监听权限,然后就是在已注册的记录中查找当前的callback是否已经注册,若已注册,则更新之前的记录,若未注册,则会创建一个新的记录。 最后,还会根据传入的notifyNow参数以及PhoneId是否有效来决定是否立即回调一次callback,而正常情况下是会立即回调的。private void listen(String callingPackage, IPhoneStateListener callback, int events, boolean notifyNow, int subId) { ...... if (events != PhoneStateListener.LISTEN_NONE) { // 权限判断,略... ...... synchronized (mRecords) { // register Record r; find_and_add: { 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; // 当前callback之前已经注册了 } } r = new Record(); // 当前callback未注册,则新建一条记录 r.binder = b; mRecords.add(r); if (DBG) log("listen: add new record"); } // 保存相关数据到原有/新建的记录中 r.callback = callback; r.callingPackage = callingPackage; r.callerUserId = callerUserId; boolean isPhoneStateEvent = (events & (CHECK_PHONE_STATE_PERMISSION_MASK | ENFORCE_PHONE_STATE_PERMISSION_MASK)) != 0; r.canReadPhoneState = isPhoneStateEvent && canReadPhoneState(callingPackage); // Legacy applications pass SubscriptionManager.DEFAULT_SUB_ID, // force all illegal subId to SubscriptionManager.DEFAULT_SUB_ID if (!SubscriptionManager.isValidSubscriptionId(subId)) { r.subId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID; } else {//APP specify subID r.subId = subId; } r.phoneId = SubscriptionManager.getPhoneId(r.subId); int phoneId = r.phoneId; r.events = events; ...... // 判断是否立即回调callback if (notifyNow && validatePhoneId(phoneId)) { if ((events & PhoneStateListener.LISTEN_SERVICE_STATE) != 0) { ...... r.callback.onServiceStateChanged( new ServiceState(mServiceState[phoneId])); ...... } ...... } } } else { // 没有监听的事件,则注销之前已注册的callback remove(callback.asBinder()); }}
至此,注册监听的流程就结束了,接下来我们再来看看各事件发生后是怎么通知到相应监听者的。
以LISTEN_SERVICE_STATE为例,其在PhoneStateListener之前的大致流程为:
-> GsmServiceStateTracker调用pollState()方法查询Service State-> GsmCdmaPhone.notifyServiceStateChanged()-> Phone.notifyServiceStateChangedP()-> DefaultPhoneNotifier.notifyServiceState()-> TelephonyRegistry.notifyServiceStateForPhoneId()-> PhoneStateListener.callback.onServiceStateChanged()
下面再来看PhoneStateListener内部的调用流程,而这部分流程对于所有监听的事件都是类似的。
我们看看PhoneStateListener中的callback,一个IPhoneStateListenerStub对象,它的onServiceStateChanged方法被调用后,会发送一个LISTEN_SERVICE_STATE事件。private static class IPhoneStateListenerStub extends IPhoneStateListener.Stub { ...... public void onServiceStateChanged(ServiceState serviceState) { send(LISTEN_SERVICE_STATE, 0, 0, serviceState); } private void send(int what, int arg1, int arg2, Object obj) { PhoneStateListener listener = mPhoneStateListenerWeakRef.get(); if (listener != null) { Message.obtain(listener.mHandler, what, arg1, arg2, obj).sendToTarget(); } } ......}IPhoneStateListener callback = new IPhoneStateListenerStub(this);
然后PhoneStateListener又会收到这个LISTEN_SERVICE_STATE事件,并调用自己的onServiceStateChanged()方法,而这个onServiceStateChanged()方法在最初注册监听时是被caller重写了的,因此实际被调用的是被重写了的onServiceStateChanged方法,就这样,caller就监听到相应事件并进行处理了。
public void handleMessage(Message msg) { ...... case LISTEN_SERVICE_STATE: PhoneStateListener.this.onServiceStateChanged((ServiceState)msg.obj); break; ......}
附:PhoneStateListener相关事件的处理流程
1) LISTEN_SERVICE_STATE
-> GsmServiceStateTracker调用pollState()方法查询Service State-> GsmCdmaPhone.notifyServiceStateChanged()-> Phone.notifyServiceStateChangedP()-> DefaultPhoneNotifier.notifyServiceState()-> TelephonyRegistry.notifyServiceStateForPhoneId()-> PhoneStateListener.callback.onServiceStateChanged()
2) LISTEN_SIGNAL_STRENGTH
deprecated by LISTEN_SIGNAL_STRENGTHS3) LISTEN_MESSAGE_WAITING_INDICATOR VoiceMail相关的,不作介绍。4) LISTEN_CALL_FORWARDING_INDICATOR 参考5) LISTEN_CELL_LOCATION 6) LISTEN_CALL_STATE 7) LISTEN_DATA_CONNECTION_STATE 8) LISTEN_DATA_ACTIVITY 9) LISTEN_SIGNAL_STRENGTHS-> ServiceStateTracker查询Signal Strength-> Phone.notifySignalStrength()-> DefaultPhoneNotifier.notifySignalStrength()-> TelephonyRegistry.notifySignalStrengthForPhoneId()-> PhoneStateListener.callback.onSignalStrengthsChanged()-> PhoneStateListener.onSignalStrengthsChanged()
10) LISTEN_OTASP_CHANGED 11) LISTEN_CELL_INFO 12) LISTEN_PRECISE_CALL_STATE 13) LISTEN_PRECISE_DATA_CONNECTION_STATE 14) LISTEN_DATA_CONNECTION_REAL_TIME_INFO 15) LISTEN_VOLTE_STATE 16) LISTEN_OEM_HOOK_RAW_EVENT 17) LISTEN_CARRIER_NETWORK_CHANGE 18) LISTEN_VOICE_ACTIVATION_STATE 19) LISTEN_DATA_ACTIVATION_STATE