SignalStrenth的获取可分为2中方式:
1.BP侧上报状态变化,从而触发AP侧查询
2.AP侧主动查询
默认情况下,这两种查询方式都是有效的,但是,一旦modem主动上报信号状态后,就会disable掉AP侧的主动查询。
1.BP侧上报状态变化,从而触发AP侧查询
还是先从初始化流程来分析。
首先来看ServiceStateTracker的构造函数,会注册监听SignalStrengthUpdate的事件。
public ServiceStateTracker(GsmCdmaPhone phone, CommandsInterface ci) {
......
mCi.setOnSignalStrengthUpdate(this, EVENT_SIGNAL_STRENGTH_UPDATE, null);
......
}
当RIL收到RIL_UNSOL_SIGNAL_STRENGTH通知后,就会触发ServiceStateTracker的EVENT_SIGNAL_STRENGTH_UPDATE事件。
这里会把mDontPollSignalStrength设为true,即禁止AP主动查询SignalStrenth。
然后就是调用onSignalStrengthResult方法处理收到的信息。
public void handleMessage(Message msg) {
......
case EVENT_SIGNAL_STRENGTH_UPDATE:
......
// The radio is telling us about signal strength changes
// we don't have to ask it
mDontPollSignalStrength = true;
onSignalStrengthResult(ar);
break;
......
}
在queueNextSignalStrengthPoll方法中,如果mDontPollSignalStrength为true,就会停掉AP侧周期性的查询操作。
private void queueNextSignalStrengthPoll() {
if (mDontPollSignalStrength) {
// The radio is telling us about signal strength changes
// we don't have to ask it
return;
}
......
msg.what = EVENT_POLL_SIGNAL_STRENGTH;
......
sendMessageDelayed(msg, POLL_PERIOD_MILLIS);
}
onSignalStrengthResult方法中会对modem上报的内容进行解析并保存,然后再通知其它模块SignalStrength发生改变。
protected boolean onSignalStrengthResult(AsyncResult ar) {
......
if ((ar.exception == null) && (ar.result != null)) {
mSignalStrength = (SignalStrength) ar.result;
mSignalStrength.validateInput(); // 将无效的信号值设置为有效值
mSignalStrength.setGsm(isGsm);
mSignalStrength.setLteRsrpBoost(mSS.getLteEarfcnRsrpBoost());
......
boolean ssChanged = notifySignalStrength();
}
通知信号发生改变。
protected boolean notifySignalStrength() {
boolean notified = false;
if (!mSignalStrength.equals(mLastSignalStrength)) {
try {
mPhone.notifySignalStrength();
notified = true;
......
}
通知流程最终会走到TelephonyRegistry.notifySignalStrengthForPhoneId()方法。
所有通过TelephonyRegistry注册监听了PhoneStateListener.LISTEN_SIGNAL_STRENGTHS事件的对象都会以回调的形式进行通知。
同时还会发送广播TelephonyIntents.ACTION_SIGNAL_STRENGTH_CHANGED进行通知。
public void notifySignalStrengthForPhoneId(int phoneId, int subId,
SignalStrength signalStrength) {
......
if (r.matchPhoneStateListenerEvent(
PhoneStateListener.LISTEN_SIGNAL_STRENGTHS) &&
idMatch(r.subId, subId, phoneId)) {
try {
......
r.callback.onSignalStrengthsChanged(new SignalStrength(signalStrength));
......
broadcastSignalStrengthChanged(signalStrength, phoneId, subId);
}
在发送广播前,我们发现SignalStrength还会被传递给BatteryStats用于统计网络信号强度的历史信息。
在这里曾经还遇到一个bug,就是对于双卡手机,当只插入一张卡时,无卡的Phone会周期性的查询信号强度,
然后BatteryStats也会将其记录下来,结果就导致网络的历史记录中出现了很多无服务的状态。
而正常的流程应该是无卡的Phone不会发起周期性的查询信号强度的操作。
private void broadcastSignalStrengthChanged(SignalStrength signalStrength, int phoneId,
int subId) {
......
mBatteryStats.notePhoneSignalStrength(signalStrength);
......
Intent intent = new Intent(TelephonyIntents.ACTION_SIGNAL_STRENGTH_CHANGED);
......
mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
}
2.AP侧主动查询
在很多种情况下,AP都会发起查询SignalStrength的操作,我们以下面3种事件为例来进行说明:
EVENT_SIM_READY (Only for gsm phone)
EVENT_RADIO_STATE_CHANGED/EVENT_PHONE_TYPE_SWITCHED
先来看看EVENT_SIM_READY事件,这是gsm phone专属的(cdma phone为EVENT_RUIM_READY),
当收到此事件后,首先会调用pollState方法查询网络状态,如运营商名称、voice/data注册状态、选网模式。
然后就是调用queueNextSignalStrengthPoll方法启动查询SignalStrength的任务。
public void handleMessage(Message msg) {
......
// GSM
case EVENT_SIM_READY:
......
pollState();
// Signal strength polling stops when radio is off
queueNextSignalStrengthPoll();
break;
case EVENT_RADIO_STATE_CHANGED:
case EVENT_PHONE_TYPE_SWITCHED:
if(!mPhone.isPhoneTypeGsm() &&
mCi.getRadioState() == CommandsInterface.RadioState.RADIO_ON) {
......
// Signal strength polling stops when radio is off.
queueNextSignalStrengthPoll();
......
}
再来看EVENT_RADIO_STATE_CHANGED/EVENT_PHONE_TYPE_SWITCHED事件,对于cdma phone当Radio_On时也会
调用queueNextSignalStrengthPoll方法启动查询SignalStrength的任务。
queueNextSignalStrengthPoll中并不会立即去查询SignalStrength,而是在20s后触发EVENT_POLL_SIGNAL_STRENGTH事件去执行查询操作。
private void queueNextSignalStrengthPoll() {
......
msg.what = EVENT_POLL_SIGNAL_STRENGTH;
......
sendMessageDelayed(msg, POLL_PERIOD_MILLIS);
}
查询完成后会触发EVENT_GET_SIGNAL_STRENGTH事件。
在这里我们可以看到,如果radio未开启,就不会触发下一次查询操作,而需要等到radio再次开启时才会再去查询;
而如果radio开启的话,就会再次调用queueNextSignalStrengthPoll方法触发20s继续查询,
这样就实现了每隔20s进行一次的循环查询操作。
而处理查询结果的流程跟modem主动上报SignalStrength时相同,都是调用onSignalStrengthResult方法处理。
public void handleMessage(Message msg) {
......
case EVENT_GET_SIGNAL_STRENGTH:
if (!(mCi.getRadioState().isOn())) {
// Polling will continue when radio turns back on
return;
}
ar = (AsyncResult) msg.obj;
onSignalStrengthResult(ar);
queueNextSignalStrengthPoll();
break;
......
case EVENT_POLL_SIGNAL_STRENGTH:
mCi.getSignalStrength(obtainMessage(EVENT_GET_SIGNAL_STRENGTH));
break;
......
}
分析完了SignalStrength的查询流程,接下来我们在来看看它是怎么传给状态栏显示的。
我们前面提到过,所有通过TelephonyRegistry注册监听了PhoneStateListener.LISTEN_SIGNAL_STRENGTHS事件的对象都会以回调的形式进行通知。
而MobileSignalController通过其registerListener方法注册监听了PhoneStateListener.LISTEN_SIGNAL_STRENGTHS事件。
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);
......
}
所以,当查询到SignalStrength变化后,就会回调mPhoneStateListener.onSignalStrengthsChanged()方法。
class MobilePhoneStateListener extends PhoneStateListener {
......
public void onSignalStrengthsChanged(SignalStrength signalStrength) {
......
mSignalStrength = signalStrength;
updateTelephony();
}
......
}
在updateTelephony方法中就会去获取信号格数。
在往后就是根据信号格数进行显示了,这里就不再继续分析了。
private final void updateTelephony() {
......
if (!mSignalStrength.isGsm() && mConfig.alwaysShowCdmaRssi) {
mCurrentState.level = mSignalStrength.getCdmaLevel();
} else {
mCurrentState.level = mSignalStrength.getLevel();
if (mConfig.showRsrpSignalLevelforLTE) {
int dataType = mServiceState.getDataNetworkType();
if (dataType == TelephonyManager.NETWORK_TYPE_LTE ||
dataType == TelephonyManager.NETWORK_TYPE_LTE_CA) {
mCurrentState.level = getAlternateLteLevel(mSignalStrength);
}
}
}
......
}
转载于:https://my.oschina.net/igiantpanda/blog/2222415