Android运营商名称显示之PLMN与SPN显示规则(原)
2016-02-17 20:06
621 查看
前面的两节分别介绍了PLMN和SPN的读取方法,那么在锁屏、状态栏、通知栏这些地方的运营商名称究竟是来自于PLMN呢?还是来自于SPN呢?
在3GPP中规定的运营商名称显示规则如下:
1、名称可以为SPN或PLMN
2、如果没有SPN文件,那么就显示PLMN
3、若有SPN,并且注册的PLMN是HPLMN或者注册的PLMN在SIM卡文件EF_SPDI中,那么:
(1)如果有SPN就要显示SPN
(2)如果SPN的bit1 = 1, 则需要同时显示PLMN,如果SPN的bit1=0,则不需要同时显示PLMN
4、若有SPN,注册的PLMN是Roaming PLMN且注册的PLMN也不在SIM卡文件EF_SPDI中,那么
(1)显示PLMN
(2)如果SPN的bit2=0,则需要同时显示SPN,如果SPN的bit2=1,则不需要同时显示SPN
下面我们用代码来梳理上面的规则。
在GsmServiceStateTracker中,接收到EVENT_SIM_RECORDS_LOADED消息或者ACTION_LOCALE_CHANGED广播后,就会触发SPN的更新显示机制。其入口为updateSpnDisplay():
在读取过程中,先对当前的网络状态进行分类:
1、如果当前网络处于STATE_OUT_OF_SERVICE或者STATE_EMERGENCY_ONLY状态,则分别显示“No service”和“Emergency calls only”字串。
2、对于当前网络注册成功的情况(STATE_IN_SERVICE),则根据3GPP协议来确定当前显示的PLMN显示规则。
我们主要关注第二种情况下显示规则的确认。
我们先来看一下显示的rule,他是通过以下调用来定义的:
然后回到updateSpnDisplay()方法中,此时将会通过mSS.getOperatorAlphaLong()得到当前的PLMN值,以及通过rule得到当前是否需要显示PLMN(showPlmn),然后通过iccRecords.getServiceProviderName()得到当前的SPN以及通过rule得到当前是否需要显示SPN。
拿到上面的数据之后,就通过广播(SPN_STRINGS_UPDATED_ACTION)的形式通知其他模块SPN的变化。
这就是SPN的显示机制,以下是该机制的逻辑图:
在3GPP中规定的运营商名称显示规则如下:
1、名称可以为SPN或PLMN
2、如果没有SPN文件,那么就显示PLMN
3、若有SPN,并且注册的PLMN是HPLMN或者注册的PLMN在SIM卡文件EF_SPDI中,那么:
(1)如果有SPN就要显示SPN
(2)如果SPN的bit1 = 1, 则需要同时显示PLMN,如果SPN的bit1=0,则不需要同时显示PLMN
4、若有SPN,注册的PLMN是Roaming PLMN且注册的PLMN也不在SIM卡文件EF_SPDI中,那么
(1)显示PLMN
(2)如果SPN的bit2=0,则需要同时显示SPN,如果SPN的bit2=1,则不需要同时显示SPN
下面我们用代码来梳理上面的规则。
在GsmServiceStateTracker中,接收到EVENT_SIM_RECORDS_LOADED消息或者ACTION_LOCALE_CHANGED广播后,就会触发SPN的更新显示机制。其入口为updateSpnDisplay():
@GsmServiceStateTracker.java protected void updateSpnDisplay() { IccRecords iccRecords = mIccRecords; String plmn = null; boolean showPlmn = false; int rule = (iccRecords != null) ? iccRecords.getDisplayRule(mSS.getOperatorNumeric()) : 0; if (mSS.getVoiceRegState() == ServiceState.STATE_OUT_OF_SERVICE || mSS.getVoiceRegState() == ServiceState.STATE_EMERGENCY_ONLY) { //当前无网络 showPlmn = true; if (mEmergencyOnly) { // No service but emergency call allowed plmn = Resources.getSystem(). getText(com.android.internal.R.string.emergency_calls_only).toString(); } else { // No service at all plmn = Resources.getSystem(). getText(com.android.internal.R.string.lockscreen_carrier_default).toString(); } } else if (mSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE) { //当前注册网络OK plmn = mSS.getOperatorAlphaLong(); showPlmn = !TextUtils.isEmpty(plmn) && ((rule & SIMRecords.SPN_RULE_SHOW_PLMN) == SIMRecords.SPN_RULE_SHOW_PLMN); } else { if (DBG) log("updateSpnDisplay: radio is off w/ showPlmn=" + showPlmn + " plmn=" + plmn); } String spn = (iccRecords != null) ? iccRecords.getServiceProviderName() : ""; boolean showSpn = !TextUtils.isEmpty(spn) && ((rule & SIMRecords.SPN_RULE_SHOW_SPN) == SIMRecords.SPN_RULE_SHOW_SPN); //发送Intent通知 if (showPlmn != mCurShowPlmn || showSpn != mCurShowSpn || !TextUtils.equals(spn, mCurSpn) || !TextUtils.equals(plmn, mCurPlmn)) { Intent intent = new Intent(TelephonyIntents.SPN_STRINGS_UPDATED_ACTION); intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); intent.putExtra(TelephonyIntents.EXTRA_SHOW_SPN, showSpn); intent.putExtra(TelephonyIntents.EXTRA_SPN, spn); intent.putExtra(TelephonyIntents.EXTRA_SHOW_PLMN, showPlmn); intent.putExtra(TelephonyIntents.EXTRA_PLMN, plmn); mPhone.getContext().sendStickyBroadcastAsUser(intent, UserHandle.ALL); } mCurShowSpn = showSpn; mCurShowPlmn = showPlmn; mCurSpn = spn; mCurPlmn = plmn; }上面的更新过程分为两步,分别完成SPN的读取和广播的发送,我们主要来看读取SPN的过程。
在读取过程中,先对当前的网络状态进行分类:
1、如果当前网络处于STATE_OUT_OF_SERVICE或者STATE_EMERGENCY_ONLY状态,则分别显示“No service”和“Emergency calls only”字串。
2、对于当前网络注册成功的情况(STATE_IN_SERVICE),则根据3GPP协议来确定当前显示的PLMN显示规则。
我们主要关注第二种情况下显示规则的确认。
我们先来看一下显示的rule,他是通过以下调用来定义的:
int rule = (iccRecords != null) ? iccRecords.getDisplayRule(mSS.getOperatorNumeric()) : 0;也就时说,这里的rule是通过SIMRecords的getDisplayRule()方法得到的:
@SIMRecords.java public int getDisplayRule(String plmn) { int rule; if (TextUtils.isEmpty(mSpn) || mSpnDisplayCondition == -1) { //如果SPN为空,则显示PLMN(Rule 2) rule = SPN_RULE_SHOW_PLMN; } else if (isOnMatchingPlmn(plmn)) { //如果当前注册的PLMN为HPLMN或者注册的PLMN存在于SIM中的EF_SPDI字段内,则显示SPN(Rule 3.1) rule = SPN_RULE_SHOW_SPN; if ((mSpnDisplayCondition & 0x01) == 0x01) { //如果SPN的bit1=1,则需要同时显示SPN和PLMN(Rule 3.2) rule |= SPN_RULE_SHOW_PLMN; } } else { //如果注册的PLMN为Roaming PLMN,并且注册的PLMN不在EF_SPDI中,则显示PLMN(Rule 4.1) rule = SPN_RULE_SHOW_PLMN; if ((mSpnDisplayCondition & 0x02) == 0x00) { //如果注册的PLMN为Roaming PLMN,并且注册的PLMN不在EF_SPDI中,并且SPN的bit2=0,则要同时显示PLMN和SPN(Rule 4.2) rule |= SPN_RULE_SHOW_SPN; } } return rule; }上面的过程刚好匹配3GPP对PLMN的显示规则,其中的mSpnDisplayCondition就是在SIMRecords获取到SPN时解析出来的data的bit1数据。当该方法结束时,返回出来了int类型的rule变量,该变量只有前两位bit有效,其中bit1=1代表显示SPN,bit2=1代表显示PLMN。
然后回到updateSpnDisplay()方法中,此时将会通过mSS.getOperatorAlphaLong()得到当前的PLMN值,以及通过rule得到当前是否需要显示PLMN(showPlmn),然后通过iccRecords.getServiceProviderName()得到当前的SPN以及通过rule得到当前是否需要显示SPN。
拿到上面的数据之后,就通过广播(SPN_STRINGS_UPDATED_ACTION)的形式通知其他模块SPN的变化。
这就是SPN的显示机制,以下是该机制的逻辑图:
相关文章推荐
- 【google M】android 网络服务状态运行机制(语音、数据注册状态;运营商信息PLMN,SPN;radio技术;信号强度)
- Android运营商名称显示(原)
- Android运营商名称显示之PLMN的读取(原)
- Android运营商名称显示之SPN的读取(原)
- PLMN coding in SIM
- 再说“服务器上的安全数据库没有此工作站信任关系的计算机账户”问题
- KB: Operations Manager为什么刚装好就显示数据访问服务SPN未注册 推荐
- SCCM 2012 R2 LAB Part3.层次结构安装之SQL Server的准备 推荐
- 中国运营商PLMN分布
- PLMN和PSTN
- SIM卡运营商信息整理
- 运营商名称充spn 中获取
- Android运营商名称显示
- Android开发学习之路-Android Design Support Library使用(CoordinatorLayout的使用)
- (转载)Android 最火的快速开发框架XUtils
- Android 捕获全局异常信息并进行相关处理
- 这些年正Android - 母亲
- Android 的性能工具用法 I-渲染分析工具