Android运营商名称显示之PLMN与SPN显示规则(原)

原创 2016年02月17日 20:06:04
        前面的两节分别介绍了PLMNSPN的读取方法,那么在锁屏、状态栏、通知栏这些地方的运营商名称究竟是来自于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():
        @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的显示机制,以下是该机制的逻辑图:
        





版权声明:本文为博主原创文章,未经博主允许不得转载。

Android运营商名称显示之SPN的读取(原)

SPN(Service Provider Name)就是当前发行SIM卡的运营商的名称,可以从以下两个路径获取:         1、从SIM文件系统读取         2、从配置文件读取     ...

Android 虚拟运营商apn与spn配置

可以通过EF_SPN、EF_IMSI、EF_PNN、EF_GID1区分

Android运营商名称显示之SPN的读取

上一节介绍了PLMN的读取流程,本节来介绍SPN的读取流程。         SPN(Service Provider Name)就是当前发行SIM卡的运营商的名称,可以从以下两个路径获取:     ...

Android运营商名称显示之PLMN与SPN显示规则

前面的两节分别介绍了PLMN和SPN的读取方法,那么在锁屏、状态栏、通知栏这些地方的运营商名称究竟是来自于PLMN呢?还是来自于SPN呢?         在3GPP中规定的运营商名称显示规则如下:...

OPN/SPN/PLMN的区别

OPN 是指此SIM卡的提供商名称 PLMN 当前注册的网络提供商名称 SPN 服务提供商名称 OPN和SPN都是提前预置在SIM卡中的 网络提供商和服务提供商可能不是同一个企...
  • xjbclz
  • xjbclz
  • 2016年06月22日 21:10
  • 720

statusbar—SIM broadcast

1:TelephonyIntents.SPN_STRINGS_UPDATED_ACTION 触发条件:

定制个性化屏保

定制个性化屏保每次我们锁键盘的时候,都看到如下页面:        看多了就产生审美疲劳, 手机是追求个性化的消费品,想到就是替换她,再找一个。       如何替换呢?Android 提供如下函数:...

【google M】android 网络服务状态运行机制(语音、数据注册状态;运营商信息PLMN,SPN;radio技术;信号强度)

涉及的framework telephony类有: frameworks/base/telephony/.../ServiceState.java frameworks/opt/telephony/....
  • r10w1
  • r10w1
  • 2015年12月07日 13:53
  • 1349

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

Android运营商名称显示之PLMN的读取(原)

Plmn的全称是Public Land Mobile Network(公共陆地移动网络),而在运营商显示方面主要是指当前SIM所驻留的网络,比如当中国移动的SIM(46000)如果漫游到联通的网络(4...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Android运营商名称显示之PLMN与SPN显示规则(原)
举报原因:
原因补充:

(最多只允许输入30个字)