手机上运营商名称的显示,通常包括状态栏显示,锁屏界面显示以及设置下面部分菜单的显示,最常用的获取方式如下:
其中mSubInfoRecord为SubscriptionInfo,获取的是SubscriptionInfo中的mDisplayName,而SubscriptionInfo的获取为以下两种方式:
但是对于SubscriptionInfo中的mDisplayName,他的初始化可分为两种:
方式一:创建SubscriptionInfo对象的时候直接进行赋值:
方式二:创建setDisplayName(CharSequence name)进行赋值:
根据经验,通常系统SubscriptionManager都是会早早启动,但是运营商名称信息的话需要等识别到SIM卡相关信息之后才能更新,这就使得系统必须通过方式二去更新运营商名称。根据猜想于是抓取了开机log,从log信息中看到了以下:
查找handleSimLoaded信息,最中定位MtkSubscriptionInfoUpdater.java中进行的操作:
既然有怀疑对象,接着往下查看,重点对SubscriptionManager的setDisplayName方法进行分析:
继续往下查看setDisplayNameUsingSrc(String displayName, int subId, long nameSource)方法发现有做以下三件事情:
1.更新数据库的SIM卡信息;
2.通过refreshCachedActiveSubscriptionInfoList()更新Cache中的SubscriptionInfo信息;
3.通过notifySubscriptionInfoChanged()更新一些其他信息(待探索);
而SubscriptionInfo的信息的更新极大概率只会出现在2,3操作当中。
个人首先怀疑点是notifySubscriptionInfoChanged()去做的更新,但是通过查找相关代码,最终未能发现该方法之后有做任何关于SubscriptionInfo更新的操作,此路不通,需要重新寻找方法。
于是回到起点,SubscriptionInfo是通过SubscriptionManager.getActiveSubscriptionInfoList()获取到的一个集合中的数据,所以我们看找getActiveSubscriptionInfoList()方法的具体获取:
这个地方只是AIDL调用,还得找到实际操作的地方,最终找到SubscriptionController.java文件中的getActiveSubscriptionInfoList()的方法:
到此终于看到了数据的获取地点,最终的SubscriptionInfo数据是从mCacheActiveSubInfoList中获取出来的,再回去看SubscriptionController.java中的setDisplayNameUsingSrc(String displayName, int subId, long nameSource)中也包含更新Cache数据的操作,是否两者有联系?
于是查找refreshCachedActiveSubscriptionInfoList()方法:
查找mCacheActiveSubInfoList对应的get和set方法如下,从方法可以看出,SubscriptionController通过set将数据更新到mCacheActiveSubInfoList中,其他地方需要使用时通过get方法从mCacheActiveSubInfoList获取出来。
至此,SubscriptionInfo数据的获取和更新有了完成的流程!
此时再回到mSubscriptionManager.setDisplayName(nameToSet, subId)中,我们此时需要关注的是nameToSet是怎么来的?
既然mDisplayName是从handleSimLoaded(int slotId)方法中通过mSubscriptionManager.setDisplayName(nameToSet, subId)更新,那nameToSet参数的获取同样要从此方法中寻找:
顺序为:simMvnoName,simNumeric(网络下发的运营商名称),CARD+(slotId + 1),基本上不会出现CARD+(slotId + 1)的情况。具体最需要看的是simMvnoName。接着往下看:
从以上方法来看,simMvnoName的获取分五个步骤,具体如下:
1.首先确认Phone是否可用,不可用的话直接返回defaultName,其实就是null;
2.检查虚拟运营商信息;
3.判断是否是CT测试手机;
4.特殊运营商名称单独获取,之后再会去spn_conf.xml文件中查找;
5.返回查找的数据;
而我们最终关注的是虚拟运营商信息的检查部分,什么是虚拟运营商?
没有自己的实体网络,通过租用正常运营商的网络来提供网络服务。虚拟运营商的SIM卡与正常运营商的SIM的区别是:虚拟运营商会在SIM卡中的某支文件中定义某个栏位,以表示自己是虚拟运营商,根据增加栏位的文件不同,分为以下几种情况(MTK):
- EF_SPN方式,对应MVNO配置到Virtual-spn-conf-by-efspn.xml中
- EF_IMSI方式,对应MVNO配置到Virtual-spn-conf-by-imsi.xml中
- EF_PNN方式,对应MVNO配置到Virtual-spn-conf-by-efpnn.xml中
- EF_GID1方式,对应MVNO配置到Virtual-spn-conf-by-efgid1.xml中
具体的代码如下:
至于虚拟运营商的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中)
相应的,apn中要添加mvno属性,以表示是虚拟运营商的参数:
(2)通过EF_IMSI区分
这中方式是imsi中有一段特殊的数字标识用于和MNO区分,例如MNO的MCC/MNC是46692,MVNO的IMSI是466923302848289,IMSI的第9位起连续2个数字为特殊标识(28),期望显示的运营商名称是“MVNO”,那就这样加记录(Virtual-spn-conf-by-imsi.xml中)
相应的,apn中要添加mvno属性,以表示是虚拟运营商的参数:
(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中)
相应的,apn中要添加mvno属性,以表示是虚拟运营商的参数:
(4)通过EF_GID1区分
EF_GID1是SIM中的一个option的文件,里面存放了n个byte的数据;如果MNO的MCC/MNC是10000,MVNO的EF_GID1的内容是”11”,期望显示的运营商名称是”MVNO”,那就这样加记录(Virtual-spn-conf-by-efgid1.xml中)
相应的,apn中要添加mvno属性,以表示是虚拟运营商的参数:
本文地址:http://lanlanwork.gawce.com/quote/11025.html 阁恬下 http://lanlanwork.gawce.com/ , 查看更多