spn-conf.xml 与运营商名字显示

一.运营商spn的配置

正常运营商:
配置spn-conf.xm。
格式:<spnOverride numeric="52001" spn="AIS"/>

虚拟运营商:
没有自己的实体网络,通过租用正常运营商的网络来提供网络服务。虚拟运营商的SIM卡与正常运营商的SIM的区别是:虚拟运营商会在SIM卡中的某支文件中定义某个栏位,以表示自己是虚拟运营商,根据增加栏位的文件不同,分为以下几种情况(MTK):
1. EF_SPN方式,对应MVNO配置到Virtual-spn-conf-by-efspn.xml中
2. EF_IMSI方式,对应MVNO配置到Virtual-spn-conf-by-imsi.xml中
3. EF_PNN方式,对应MVNO配置到Virtual-spn-conf-by-efpnn.xml中
4. EF_GID1方式,对应MVNO配置到Virtual-spn-conf-by-efgid1.xml中

区分当前SIM卡是支持哪种MVNO的配置,就需要知道当前哪支文件上存储了虚拟运营商的栏位。通过读取以上4个文件的内容,如果值不为空,则表明通过这个栏位定义在这个文件内。如下:frameworks\opt\telephony\src\java\com\android\internal\telephony\uicc\SIMRecords.java(IccRecords.java所有子类下)

    public String getMvnoMatchType() {
        String IMSI = getIMSI();
        String SPN = getSpNameInEfSpn();
        String PNN = getFirstFullNameInEfPnn();
        String GID1 = getGid1();
        String MCCMNC = getOperatorNumeric();
        if (DBG) {
            log("getMvnoMatchType(): imsi = " + IMSI + ", mccmnc = " + MCCMNC + ", spn = " + SPN);
        }

        if (SpnOverride.getInstance().getSpnByEfSpn(MCCMNC, SPN) != null)
            return PhoneConstants.MVNO_TYPE_SPN;
        if (SpnOverride.getInstance().getSpnByImsi(MCCMNC, IMSI) != null)
            return PhoneConstants.MVNO_TYPE_IMSI;
        if (SpnOverride.getInstance().getSpnByEfPnn(MCCMNC, PNN) != null)
            return PhoneConstants.MVNO_TYPE_PNN;
        if (SpnOverride.getInstance().getSpnByEfGid1(MCCMNC, GID1) != null)
            return PhoneConstants.MVNO_TYPE_GID;
        return PhoneConstants.MVNO_TYPE_NONE;
    }

至于虚拟运营商的spn文件如何配置,可能每个芯片厂商设置的不一样,MTK的设置如下:

(1)通过EF_SPN区分

这中方式是读取SIM中的文件EF_SPN,结合SIM的mccmnc+spn,在virtual-spn-conf-by-efspn.xml 中查找有没有对应的记录,如果有这表示这个SIM是MVNO的卡,同时取name字段的内容当作运营商名称。
如果知道MVNO的SIM卡中的SPN是“abc”,MNO的MCC/MNC是10000,期望显示运营商名是”MVNO“,那就这样加记录(在Virtual-spn-conf-by-efspn.xml中)

<virtualSpnOverride mccmncspn="10000abc“ name="MVNO">

相应的,apn中要添加mvno属性,以表示是虚拟运营商的参数:

      mvno_type="spn" 
      mvno_match_data="abc"

(2)通过EF_IMSI区分

这中方式是imsi中有一段特殊的数字标识用于和MNO区分
例如MNO的MCC/MNC是46692,MVNO的IMSI是466923302848289,IMSI的第9位起连续2个数字为特殊标识(28),期望显示的运营商名称是“MVNO”,那就这样加记录(Virtual-spn-conf-by-imsi.xml中)

<virtualSpnOverride imsipattern="4669246692×××28×××××" name=“MVNO”>

相应的,apn中要添加mvno属性,以表示是虚拟运营商的参数:

      mvno_type="imsi"
      mvno_match_data="46692×××28×××××"

(3)通过EF_PNN区分

EF_PNN是SIM中的一个option的文件,里面存放一组网络运营商名称(PLMN Network Name)。这种方式即是读取EF_PNN中的第一个pnn来匹配。如果MNO的MCC/MNC是10000,MVNO中EF_PNN的第一个pnn是“abc”,期望显示的运营商名称是“MVNO”,那就这样加记录(Virtual-spn-conf-by-efpnn.xml中)

<virtualSpnOverride mccmncpnn="10000abc“ name="MVNO">

相应的,apn中要添加mvno属性,以表示是虚拟运营商的参数:

      mvno_type="pnn"   
      mvno_match_data="abc"

(4)通过EF_GID1区分

EF_GID1是SIM中的一个option的文件,里面存放了n个byte的数据;如果MNO的MCC/MNC是10000,MVNO的EF_GID1的内容是”11”,期望显示的运营商名称是”MVNO”,那就这样加记录(Virtual-spn-conf-by-efgid1.xml中)

<virtualSpnOverride mccmncgid1="1000011" name="MVNO">

相应的,apn中要添加mvno属性,以表示是虚拟运营商的参数:

       mvno_type="gid"
      mvno_match_data="11"

二.运营商名字的显示规则

请参考Gsm sec 51.011 EF_SPN的部分还有cphs spec;
code的部分,请参考SIMRecords. getDisplayRule和GsmServiceStateTracker. updateSpnDisplay:

(1) Sim卡中文件,如EF_SPN, EF_OPN, EF_SOPN, EF_OPL, EF_PNN, EF_SPDI…
(2) 注册到的网络的plmn,对应Spn-conf.xml
(3) NITZ,即网络下发的名字

Spec 51.011中EF_SPN定义的rule 总结就是:
1. 名称分为 SPN 和 Registered plmn(包括EONS, CPHS (即ONS), S-CPHS, NITZ, PLMN;优先级依次降低)
2. 如果没有SPN文件,那么就显示Registered plmn
3. 若有SPN,注册的plmn是HPLMN或者注册的plmn在SIM卡文件EF_SPDI中,那么
(1) 如果有SPN就要显示SPN
(2) 如果SPN的bit1 = 1, 则需要同时显示Registered plmn,如果SPN的bit1=0,则不需要同时显示Registered plmn
4. 若有SPN,注册的plmn是Roaming plmn且注册的plmn也不在SIM卡文件EF_SPDI中,那么
(1) 显示Registered plmn
(2) 如果SPN的bit2=0,则需要同时显示SPN,如果SPN的bit2=1,则不需要同时显示SPN

根据rule的结果就是,同个运营商,不同网络下,运营商的显示不尽相同。很多客户要求客制化运营商的显示,为了显示结果可控,一般都以Spn-conf.xml中配置的运营商名字为主。目前比较简洁的方法就是在updateSpnDisplay()方法中强制显示Spn-conf.xml中配置的运营商名字,如下:
frameworks\opt\telephony\src\java\com\android\internal\telephony\ServiceStateTracker.java

    @Override
    protected void updateSpnDisplay() {
                ......
                String strHomePlmn = ((MtkGsmCdmaPhone)mPhone).getOperatorNumeric();
                String strServingPlmn = mSS.getOperatorNumeric();
                boolean isNotMvnoType = "".equals(((MtkGsmCdmaPhone)mPhone).getMvnoMatchType());
                boolean isRoaming = strHomePlmn != null ? !strHomePlmn.equals(strServingPlmn):false;
                if(mSpnOverride != null && mSpnOverride.containsCarrierEx(strHomePlmn) && isNotMvnoType){
                    log(String.format("*****before updateSpnDisplay: changed" +
                            " sending intent rule=" + rule + "   strHomePlmn=" + strHomePlmn + "   strServingPlmn="+strServingPlmn +
                            " showPlmn='%b' plmn='%s' showSpn='%b' spn='%s' dataSpn='%s' subId='%d'",
                            showPlmn, plmn, showSpn, spn, dataSpn, subId));
                    if(!filterOperators(spn,plmn)){
                        String mPlmn = (mNewSS.getDataRoamingFromRegistration() && strServingPlmn != null) ? strServingPlmn : strHomePlmn;
                        spn = mSpnOverride.lookupOperatorName(subId,mPlmn,true,mPhone.getContext(),mPlmn);
                        if ((mSS.getVoiceRegState() == ServiceState.STATE_IN_SERVICE) || (mSS.getDataRegState() == ServiceState.STATE_IN_SERVICE)) {
                            plmn = spn;
                        }
                    }
                    SubscriptionInfo subInfo = SubscriptionManager.from(mPhone.getContext()).getActiveSubscriptionInfo(subId);
                    boolean isUserInput = subInfo != null && subInfo.getNameSource() != SubscriptionManager.NAME_SOURCE_USER_INPUT;
                    if (spn != null && !"".equals(spn) && !"null".equals(spn) && isUserInput) {
                        String displayName = spn;
                        if(mNewSS.getDataRoamingFromRegistration())displayName = mSpnOverride.getSpnEx(strHomePlmn);
                        SubscriptionManager.from(mPhone.getContext()).setDisplayName(displayName,subId);
                        TelephonyManager.getDefault().setSimOperatorNameForPhone(mPhone.getPhoneId(),displayName);
                    }
                    if(showPlmn && showSpn)showPlmn=false;
                    if(!showPlmn && !showSpn)showSpn=true;
                    log(String.format("*****after updateSpnDisplay: changed" +
                            " sending intent rule=" + rule +"  isUserInput="+isUserInput+
                            " showPlmn='%b' plmn='%s' showSpn='%b' spn='%s' dataSpn='%s' subId='%d'",
                            showPlmn, plmn, showSpn, spn, dataSpn, subId));
                    ......          
    }                
    //针对特殊情况处理。比如泰国52000,my和true-h都在用,要分开显示,my我们仍然客制化,如果是true-h,则不客制化,根据规则优先级显示。
    public boolean filterOperators(String spn, String plmn){
        boolean isSonOperators = false;
        String mOperatorNumeric = ((MtkGsmCdmaPhone)mPhone).getOperatorNumeric();
        if("TM".equalsIgnoreCase(spn) || "TM".equalsIgnoreCase(plmn)){
            isSonOperators = true;
        }
        if("Talk N Text".equalsIgnoreCase(spn) || "Talk N Text".equalsIgnoreCase(plmn)){
            isSonOperators = true;
        }
        if("TNT".equalsIgnoreCase(spn) || "TNT".equalsIgnoreCase(plmn)){
            isSonOperators = true;
        }
        if("52000".equals(mOperatorNumeric) && ("TRUE-H".equalsIgnoreCase(spn) || "TRUE-H".equalsIgnoreCase(plmn))){
            isSonOperators = true;
        }
        if("64106".equals(((MtkGsmCdmaPhone)mPhone).getOperatorNumeric()))return true;//XWWJHBLYW-1831
        return isSonOperators;
    }                                    

SpnOverride.lookupOperatorName()下面也需要对特殊情况做处理。

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值