首先,如前面的博文所讲的,Android5.0开始支持双卡了。另外,对于双卡的卡信息的管理,也有了实现,尽管还不是完全彻底完整,如卡的slot id, display name,iccid,color等,其设计思路竟然跟之前接触到的一个平台是一样的,都是同不同颜色来标识不同的卡,让用户一目了然,只是5.0的实现目前还局限在FW框架里,应用层的实现还没有,相信,等到5.1或者再之后的版本中,我们就可以在setting里看到对卡表示颜色、名称等进行设置的功能菜单啦。

下面进入正题,来分析Android5.0的双卡信息是如何来维护的:

1 卡信息的存储

先说结论,5.0是将所有卡信息通过数据库进行保存的。数据库表URL:content://telephony/siminfo,对应到的数据库为telephony.db中的siminfo表,代码文件在TelephonyProvider.java,在这里可以看到createTable的详情,来看看这个表都包含哪些字段。

总共设计了11个字段,下面这张图是从5.0模拟器上拉出来的telephony.db里截取到的,可以用来做示例:

表名:

表数据示例:

下面分别介绍一下这些字段的含义。

1.1 _id

  这个自不必说,android里的每个db都有的,是数据库里的数据主key,这里的_id值也是以后代码里看到的subId,是在数据库中保存时所在的条目的唯一标识。有多少条数据,就说明保存了多少个sim卡的信息;

1.2 icc_id

  从卡上读取得到,是卡的唯一身份标识,世界上的所有sim卡,每个卡都有不同的iccid,就像身份证一样;如上面图中的16进制串89014103211118510720;

1.3 sim_id

  分配给卡的id序号,android设计从0开始,最大为卡槽个数,比如如果是双卡终端,那么只有可能是0或者1;当然无卡时其值为-1,所以这里其实是与卡槽固定对应的,卡槽如果有卡就取对应id,如果无卡,就设为-1;

1.4 display_name

  分配给卡的显示名字,从代码上来看开机后会尝试使用运营商名字,如果取不到,就使用简单的SUB 01这样的字串表示,等拿到运营商名字之后重新set,另外从下面的name_source字段的设计来看,android是允许用户来自己指定这个显示名的;

1.5 name_source

  表明display_name字段的来源,有两种来源,一是系统自动,name_source取值为0,另一种就是来自用户指定,取值为1;

 1 /**
 2 * The name_source is the default
 3 * @hide
 4 */
 5 publicstaticfinalint NAME_SOURCE_DEFAULT_SOURCE =0;
 6
 7 /**
 8 * The name_source is from the SIM
 9 * @hide
10 */
11 publicstaticfinalint NAME_SOURCE_SIM_SOURCE =1;
12
13 /**
14 * The name_source is from the user
15 * @hide
16 */
17 publicstaticfinalint NAME_SOURCE_USER_INPUT =2;

1.6 color

  显示颜色,将使用颜色在UI上明显区分卡1和卡2;android设定每个卡都只能从固定的几个颜色中取,如下:

 1 /** @hide */
 2 publicstaticfinal String COLOR ="color";
 3
 4 /** @hide */
 5 publicstaticfinalint COLOR_1 =0;
 6
 7 /** @hide */
 8 publicstaticfinalint COLOR_2 =1;
 9
10 /** @hide */
11 publicstaticfinalint COLOR_3 =2;
12
13 /** @hide */
14 publicstaticfinalint COLOR_4 =3;
15
16 /** @hide */
17 publicstaticfinalint COLOR_DEFAULT = COLOR_1;

  这四种颜色根据主题是dark还是light分别对应4种颜色,这些颜色其实并非是色值,而是固定颜色的背景9.png图片,都定义在资源drawable里,看来是用来做backgroud用的。如

  sim_dark_blue sim_light_purple

其他几种颜色可以参考 SubscriptionController. setSimResource函数里去color资源数组的初始化。

1.7 number

  该卡对应的号码,phone number。 //TODO:研究一下这个是怎么获取到呢?

1.8 display_number_format

  标识number字段的格式,总共有固定的3种,取其一。

/** @hide */
publicstaticfinalint DISPLAY_NUMBER_NONE =0;/** @hide */
publicstaticfinalint DISPLAY_NUMBER_FIRST =1;/** @hide */
publicstaticfinalint DISPLAY_NUMBER_LAST =2;/** @hide */
publicstaticfinalint DISLPAY_NUMBER_DEFAULT = DISPLAY_NUMBER_FIRST;

  从SubscriptionController. setDisplayNumberFormat()函数的注释可以看出点门道,

    *Set number display format. 0: none, 1: the first four digits, 2: the last four digits

  但搜了一下,对应的setDisplayNumber()函数并没有跟这个format有关联,直接保存传入的number到数据库了。所以还不太清楚the first four digits 和 the last four digits的具体含义,等以后android应用层完善后应该能看到具体的使用方式。

1.9 data_roaming

  是否允许这张卡进行数据漫游,默认禁止漫游。

1 /** @hide */
2 publicstaticfinalint DATA_ROAMING_ENABLE =1;
3
4 /** @hide */
5 publicstaticfinalint DATA_ROAMING_DISABLE =0;
6
7 /** @hide */
8 publicstaticfinalint DATA_ROAMING_DEFAULT = DATA_ROAMING_DISABLE;

1.10 mcc

移动国家码,从卡上读取得到,卡的mcc码;

1.11 mnc

移动网络码,从卡上读取得到,卡的mnc码。度娘到对于mcc和mnc的解释:

MCC 是 Mobile Country Code 的缩写,译为移动国家代码。它由三位数字组成。用于标识一个国家,但一个国家可以被分配多个 MCC 。比如美国的 MCC 有 310,311,和316。中国的 MCC 只有 460。 MNC 是 Mobile Network Code 的缩写,译为移动网络代码。它由二到三位数字组成。MNC和 MCC 合在一起唯一标识一个移动网络提供者。比如中国移动的 MNC 是 00,中国联通的 MNC 是 01,中国联通 CDMA 的 MNC 是 03,中国卫星全球星网的 MNC 是 04。 因此,460 00 就唯一标识了中国移动。

  所以卡的displayname应该也是通过mcc+mnc得到的。

2 主要工作类

  上面介绍了卡信息的数据设计,接下来看看有哪些类围绕着这些数据来对外提供接口和功能。

功能介绍

TelephonyProvider

siminfo数据库provider,直接操作DB,实现siminfo表的增删改查。

SubscriptionController

实现为远程service,在phone初始化时被创建,作为数据库的对外接口提供功能,其内部维护从数据库读取到的siminfo list,并实现了大量的如getSubId getDisplayName setDisplayName等getter和setter方法,这些方法维护siminfo list以及通过URL访问数据库来实现功能。

SubscriptionManager

该类所有的内部接口都实现为了static,也就是该类是一个纯粹提供接口的静态类,其内部并不实现具体的逻辑,只是通过调用SubscriptionController这个service的对应接口来完成工作,所以该类是一个对外接口的封装,APP可以直接通过SubscriptionManager.getSubId等来实现功能,不需要直接操作service。目前还是Hide的,估计以后会开放给SDK。这种设计模式,android FW层用的很多,如SmsMnager、TelephonyManager等。

SubInfoRecordUpdater

卡信息变化的监听者和更新者,其在PhoneFactory中创建完phones之后被创建,起来之后会注册对 ACTION_SIM_STATE_CHANGED 的监听,收到监听之后更新对应siminfo的信息,如iccid、displayname(运营商名)、phonenumber。并且在自己内部维护了每个卡的卡状态,这里的卡状态区别与ACTION_SIM_STATE_CHANGED所携带的卡状态,ACTION_SIM_STATE_CHANGED的卡状态有 LOCKED、READY、NOT READY、ABSENT等,是指的卡的具体状态,而这里的卡状态是指 有没有插卡、该卡槽的卡是不是变过了(换了一张卡)、卡槽的卡是一张没见过的新卡、卡槽的卡是位置互换啦、卡槽的卡没变化。【状态还真有点绕,管的挺多的啊。。。】这些状态是在收到ACTION_SIM_STATE_CHANGED之后,根据卡状态以及卡的iccid等一些信息算出来的,如果发现有新卡插入会进行广播。

SubInfoRecord

subinfo的可序列化实现,封装数据库数据。

  另外,在代码中还可以看到 Subscription 和 SubscriptionData这两个类,这两个其实只是数据封装,并不直接跟卡信息管理相关,其只是保存了一些卡的数据来提供给phone等使用,目前还找不到组织他们的接口,全局搜索会发现,好多地方google都注释掉了,逻辑还没完整。SubscriptionData是Subscription list,目前从代码来看,这两个还没有真正用起来,所以可以先无视了,不过要吐槽下google的代码,起名咋这么绕啊。另外还有个 CdmaSubscriptionSourceManager的类,这个是跟CDMA的卡提供者信息有关的,会影响到具体的网络行为,也跟本文的双卡信息管理无关。

3 工作流程

  通过上面主要类的介绍,基本上整个双卡信息管理的框架就出来了,画了一个图方便理解。

4总结

  5.0通过DB来保存和维护双卡信息,SubInfoRecordUpdater通过监听卡的变化动态更新数据库里的卡数据;SubscriptionController和SubscriptionManager通过各种接口来向外提供卡信息的查询和修改,这样看来逻辑还是比较清晰明了的。

Android 5.0 双卡信息管理分析相关推荐

  1. Android8.0(34)----Android 8.0 Settings流程分析与变动

    Android 8.0 Settings流程分析与变动 一,相比Android Settings 7.0 如下图,在7.0的基础上,去掉了7.0新加的侧滑菜单(可能是觉得有点鸡肋吧).多加了一级页面, ...

  2. Android 7.0 源码分析项目一期竣工啦

    从 Android 入行开始,因为工作需求和解决疑难bug的原因陆陆续续的看过一些源码,但都不成系统,从2016年年底开始,在Github上建了一个Android Open Source Projec ...

  3. Android 7.0 Keyguard流程分析

    在android 6.0 上Keyguard作为了SystemUI的一个库文件被引用,所以编译的时候不会出现Keyguard.apk这个文件,Keyguard也伴随着SystemUI的启动而启动,其中 ...

  4. Android 7.0系统启动流程分析

    随着Android版本的升级,aosp项目中的代码也有了些变化,本文基于Android 7.0分析Android系统启动流程.当我们按下电源键后,整个Android设备大体经过了一下过程:  今天我们 ...

  5. AOSP Android 8.0 冷启动流程分析(二)

    前奏: Android系统虽然基于Linux系统的,但是由于Android属于嵌入式设备,并没有像PC那样的BISO程序,取而代之的是Bootloader----系统启动加载器. /boot : 存放 ...

  6. Android 6.0 JNI原理分析 和 Linux系统调用(syscall)原理

    JNI原理 引言:分析Android源码6.0的过程,一定离不开Java与C/C++代码直接的来回跳转,那么就很有必要掌握JNI,这是链接Java层和Native层的桥梁,本文涉及相关源码: fram ...

  7. android7dlopen,Android 7.0 dlopen 函数分析

    1. 说明 Android 7.0 后使用 dlopen 函数无法获取 soinfo 对应,因此也无法使用 dlsym 函数去调用第三方的 so 内的函数.这里给出 dlopen() 函数的源码分析. ...

  8. android 双卡打电话,Android 6.0 双卡拨号

    相关 api Android 5.0 之前的版本 获取 sim 卡数量 public static boolean isMultiSim(Context context){ boolean resul ...

  9. Android 8.0 recovery 流程分析

    这里主要分析non A/B模式下的recovery流程 A/B模式下的recovery在boot中 后续会不断补充,如果有疏漏或者错误的地方,请指出,共同学习,谢谢! 一.流程分析 首先列出recov ...

最新文章

  1. BaaS, IaaS, PaaS, SaaS介绍
  2. 国产光刻机正式宣布:今年出货150台
  3. 为什么写博客?如何在博客中更好的分享?
  4. angular1.0 $http jsonp callback
  5. C#教程4:数据类型
  6. 通俗易懂:贪心算法(一):分配问题 (力扣455分发饼干 和135分发糖果)
  7. Intent跳转传list集合
  8. 最近公司需要监测网络PING写了一个脚本
  9. 搭建分布式键值对文件系统FastDFS
  10. 提高django model效率的几个小方法
  11. 当前方法的代码已经过优化,因此无法计算表达式的值
  12. MySQL 效能监控工具--mysqlreport -转
  13. jdk优先级队列是如何实现的
  14. 计算机网络高级工程师证书,网络安全高级工程师的证书??
  15. attention权重解读
  16. Win7下无法安装CDC Comms Interface驱动的朋友进
  17. 如何控制局域网网速_无线路由器如何限制局域网网速 无线路由器限制局域网网速方法【介绍】...
  18. 怎么选最快dns服务器,dns设置(dns设置哪个最好最快)
  19. 非常好理解的python re正则表达式入手
  20. 南邮——计算机图像学——会动的立方体(变换)

热门文章

  1. 机器学习模型 知乎_知乎CTO李大海:谢邀,来分享下内容社区的AI架构搭建与应用...
  2. MySQL单表删除重复列SQL语句
  3. 蛋糕matlab,用matlab绘制生日蛋糕
  4. python elementtree 命名空间_用Python中的命名空间通过‘ElementTree’解析XML
  5. 10截图时屏幕变大_最全的MAC端截图工具推荐,寻找适合自己的截图工具
  6. 利用划分树求解整数区间内第K大的值
  7. Kubernetes中部署SpringBoot应用
  8. SpringBoot项目中图片的引用
  9. dell服务器硬盘锁_服务器十大排行
  10. 华南理工大学计算机科学与工程学院篡改,华南理工大学涉嫌篡改成绩人员已被停职调查...