【笔记】Android Telephony | SIM 卡管理和subId、slotId、phoneId 定义关系说明

相关业务背景

DSDS双卡双待 :手机可以插入两张手机卡,而且能同时待机,但是某一时刻只能有一张卡上有电话。

一个SIM卡代表一个账号,那么双卡手机就意味着多账户,需要增加多账户管理和业务处理。

  • 账号管理:双卡手机提供界面给设置默认打电话、发短信和上网卡等。
  • 业务管理:基于两卡的独立性,双卡设备需要提供双卡进行通话业务设置(呼叫限制、呼叫转移)和网络业务设置(数据开关、数据漫游开关、VoLTE、VoWiFi业务开关等)。

和单卡业务类似,只是处理前需要选定一个账号,因此就需要正确的subId、slotId、phoneId等参数确认和区分业务卡。

SIM卡有关ID介绍

为了区分不同的卡,在Android上实现了多种id,如:slotId、phoneId、subId等,定义区别如下:

XID定义和特殊场景说明
ICCID

SIM 卡的唯一标识。

在SIM卡加载完成后,Telephony 以ICCID为关键字在数据库中查找,如果没有找到 ,则说明此卡第一次插入,则在数据库中添加此SIM卡记录(siminfo表);如果找到则更新原有记录,但是此记录在数据库中的序号不变,即subId不变。

Sub Id

siminfo表中的Primary Key,从1开始的整数,标识卡记录在数据库表中的顺序号。

第1张插入的卡是1,之后累加。

- SIM卡可以切换卡槽 ,但是subId不会变。phoneId和slotId会0/1变化。

- Android 平台,在手机关机时会将当前使用的SIM卡Slot ID设为-1,在下次开机时检测到加载成功的SIM卡后将对应的Slot ID设为0或1(这样当通过SubscriptionManager接口请求当前可用Sub info时,就能从db中检索SlotID不为-1的SIM卡即可)。

Phone IdPhone 实例对应的ID,双卡设备的phoneId是0或1。
Slot Id卡槽ID,当前可以认为slotId 和 phoneId 是相同的。

ID 变化规则和关系

ICCID、Sub ID 和 slot ID 都是 siminfo 数据库中的字段

  • Phone ID 和 Slot ID 当前可认为是一样的,跟卡槽对应,卡1的 ID 是0,卡2是1;
  • 切换卡槽,subId不变,phoneId 和 slotId 变化
  • SubscrptionManager 提供接口对 phoneId 进行转换。
    • subId 指示当前使用的SIM卡,phoneId/slotId 只关注卡槽。
  • 每张SIM卡都有一个对应的Subscription,用运营商的SIM卡就相当于订阅(Subscription)其业务。
API 函数名参数 ID隐藏/公开功能作用
getActiveSubscriptionInfo(int sudId)subId公开获取指定 subId 的当前可用的SIM卡信息
isNetworkRoaming(int subId)subId公开查询指定 subId 的漫游数据开关状态
getAcitiveSubscriptionInfoForSimSlotIndex(int slotIndex)slotId公开获取指定SlotId的当前可用SIM卡信息
getActiveSubscriptionInfoForIccIndex(String iccId)ICCIDhide获取指定ICCID的当前可用SIM卡信息
setDisplayName(String displayName, int subId)subIdhide将指定subId 的SIM卡显示名称保存到数据库
setDataRoaming(int roaming,  int subId)subIdhide将指定subId 的SIM卡漫游开关保存到数据库
getSlotIndex(int subId)subIdhide获取subId对应的slotId
getSubId(int slotIndex)subIdhide获取slotId对应的subId

数据库

双卡业务相关设置项分别保存在Settings 数据库、网络端(通话设置:呼叫转移和呼叫限制)和Telephony 数据库(telephony.db,需要权限)

获取telephony.db数据库文件:

adb  pull data/user_de/0/com.android.providers.telephony/databases

双卡设置在Settings 应用界面。

设置项子设置项Android KEY保存位置
双卡设置默认数据卡Settings.Global.MULTI_SIM_DATA_CALL_SUBSCRIPTIONSettings数据库
默认通话卡Settings.Global.MULTI_SIM_VOICE_CALL_SUBSCRIPTION
默认彩信卡Settings.Global.MULTI_SIM_SMS_SUBSCRIPTION
网络设置(卡 1和卡2)数据开关Settings.Global.Mobile_DATA + subId
数据漫游开关Settings.Global.DATA_ROAMING + subId
网络模式选择Settings.Global.PREFERRED_NETWORK_MODE + subId
VoLTE功能开关SubscriptiionManager.ENHANCED_4G_MODE_ENABLEDTelephony.db 的siminfo表
ViLTE功能开关SubscriptiionManager.VT_IMS_ENABLED
WFC功能开关

SubscriptiionManager.WFC_IMS_ENABLED

代码案例

在注册状态变化时(onSubscriptionsChanged)更新PhoneId。

    //添加注册状态变化的监听器private final SubscriptionManager.OnSubscriptionsChangedListener mOnSubscriptionsChangedListener =new SubscriptionManager.OnSubscriptionsChangedListener() {@Overridepublic void onSubscriptionsChanged() {//获取上下文信息final Activity activity = getActivity();if (activity == null || activity.isFinishing() || activity.isDestroyed()) {return;}final List<SubscriptionInfo> mSubList =SubscriptionUtil.getAvailableSubscriptions(getContext());SubscriptionInfo mSubInfo = null;for (SubscriptionInfo subInfo : mSubList) {Log.d(TAG, "onSubscriptionsChanged: subInfo = " + subInfo.toString());if (subInfo.getSubscriptionId() == mSubId) {mSubInfo = subInfo;//校验PhoneId正常并更新的方法if (!SubscriptionManager.isValidPhoneId(mPhoneId)) {mPhoneId = SubscriptionManager.getPhoneId(mSubId);Log.d(TAG, "onSubscriptionsChanged: mPhoneId = " + mPhoneId);if (SubscriptionManager.isValidPhoneId(mPhoneId)) {mPhone = PhoneFactory.getPhone(mPhoneId);}}break;}}if (mSubInfo == null) {Log.d(TAG, "onSubscriptionsChanged: can't find subInfo for subId " + mSubId, so call finish()");}}};

通过subId获取phoneId。疑问:通过subid获取phoneId为什么会异常?
 

        if (mSubId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {int mPhoneId = SubscriptionManager.getPhoneId(mSubId); //会异常啊if (!SubscriptionManager.isValidPhoneId(mPhoneId)) {mPhoneId = getPhoneIdFromSubId(mSubId, phoneId);log("getPhone: phoneIdFromSubId: " + phoneId);}//phoneId合法,则根据ID获取Phone对象if (SubscriptionManager.isValidPhoneId(phoneId)) {log("updatePhone :: isValidPhoneId: ");mPhone = PhoneFactory.getPhone(phoneId);}}//类似源码命名:getActiveSubscriptionInfoForIccIndex,通过iccid获取subId,用for。//通过subId 获取PhoneId(源码命名是For的)private int getPhoneIdFromSubId(int subId, int phoneId){int phoneIdFromSubId = phoneId;//获取注册信息列表List<SubscriptionInfo> subscriptionInfoList = mSubscriptionManager.getAvailableSubscriptionInfoList();String iccidForSub = null;if (subscriptionInfoList != null) {for (SubscriptionInfo si : subscriptionInfoList) {if (si.getSubscriptionId() == subId){iccidForSub = si.getIccId();break;}}}List<UiccCardInfo> cardsInfos = mTelephonyManager.getUiccCardsInfo();if (cardsInfo != null) {for (UiccCardInfo info : cardsInfos) {if (info != null) {String iccid = info.getIccId();if (iccidForSub != null && iccidForSub.equals(iccid)) {phoneIdFromSubId = info.getSlotIndex();break;}}}}return phoneIdFromSubId;}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/643516.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Java 设计模式】行为型之责任链模式

文章目录 1. 定义2. 应用场景3. 代码实现结语 责任链模式&#xff08;Chain of Responsibility Pattern&#xff09;是一种行为型设计模式&#xff0c;用于将请求发送者和接收者解耦&#xff0c;使得多个对象都有机会处理请求。责任链模式通过创建一个处理请求的链&#xff0c;…

【STM32】STM32学习笔记-W25Q64简介(37)

00. 目录 文章目录 00. 目录01. SPI简介02. W25Q64简介03. 硬件电路04. W25Q64框图05. Flash操作注意事项06. 预留07. 附录 01. SPI简介 在大容量产品和互联型产品上&#xff0c;SPI接口可以配置为支持SPI协议或者支持I 2 S音频协议。SPI接口默认工作在SPI方式&#xff0c;可以…

(2)(2.4) CRSF/ELRS Telemetry

文章目录 前言 1 ArduPilot 参数编辑器 前言 &#xff01;Note ELRS&#xff08;ExpressLRS&#xff09;遥控系统使用穿越火线协议&#xff0c;连接方式类似。不过&#xff0c;它不像穿越火线那样提供双向遥测。 TBS CRSF 接收机与 ArduPilot 的接口中包含遥测和遥控信息。…

【 CSS 】HTML5、CSS3 提高

人生犹如航海&#xff0c;不在于船在港口的安全&#xff0c;而在于船能否顺利航行&#xff0c;穿越重重风浪&#xff0c;抵达梦想的彼岸。 1. HTML5新特性 1.1 概述 HTML5 的新增特性主要是针对于以前的不足&#xff0c;增加了一些新的标签、新的表单和新的表单属性等。 这些…

Webpack5 基本使用 - 2

常用 loader loader 是辅助打包工具。webpack 默认只能打包 js 文件&#xff0c;打包其它模块就需要配置 loader 来告诉 webpack 该怎么去打包其它文件。loader 可以将文件从不同的语言转换为 JavaScript。一类文件如果需要多个 loader 处理&#xff0c;loader 的执行顺序是从…

vue+openLayers闪烁图形/线段/点 都可以使用类似的方法

本文使用闪烁图形作为实例&#xff0c;线段和点都是类似的原理 基础方法 1.先定义两个样式&#xff0c;闪烁时两个样式相互交换 2.利用定时器&#xff08;单数的时候样式一&#xff0c;双数的时候样式二&#xff09;由此来实现闪烁效果 先给主要代码如下&#xff08;最后有全部…

uniapp vue3版本引用 jsencrypt加密库报错:“default“ is not exported by……

个人产生这个异常的原因&#xff1a;将历史项目&#xff08;vue2&#xff09;的jsencrypt文件复制到新项目&#xff08;vue3&#xff09;里直接引用报错。存在兼容问题&#xff0c;需要重新安装vue3版本的jsencrypt 安装依赖 npm install jsencrypt页面引入 import { JSEncry…

变压器消谐电阻器测试仪

产品概述 KDZD3000X消谐电阻器参数测试仪能实现自动检测消谐器在电流峰值为0.3mA、0.5mA 、1mA 、3mA 、5mA、10mA时相对应的电压峰值或有效值&#xff0c;并能自动绘制出消谐器伏安特性曲线图。 仪器依据的标准 Q/GDW415-2010《电磁式电压互感器用非线性电阻性消谐器技术规…

计算机二级Python基本排序题-序号45(补充)

1. 文件"singup.txt”中保存了若干条参加运动会学生的报名记录&#xff0c;每条记录的形式为“班级号_学号”&#xff0c;例如"A1_12”&#xff0c;将每个班级报名情按参加运动会人数从多到少排列&#xff08;假设不存在人数相同的情况&#xff09;并输出&#xff0c…

畅聊未来:低代码打造在线聊天系统

前言 现代社交网络的普及使得在线聊天成为人们日常生活中不可或缺的一部分。然而&#xff0c;传统的开发方式往往复杂且耗时&#xff0c;因此寻找一种更快捷、灵活且可视化的方法来构建在线聊天系统变得尤为重要。本文将介绍如何利用低代码平台来快速搭建一个功能齐全的在线聊…

存内计算引领新一代技术革新,开启算力新时代

文章目录 存内计算与传统计算的区别 存内计算与传统计算的区别 存内计算芯片的优势 存内计算在各个领域的应用 存内计算技术对未来发展的影响 CSDN存内计算开发者社区&#xff1a;引领新一代技术革新的最前沿 社区内容专业度 社区具备的资源 社区的开放性 社区招募令…

JVM篇----第三篇

系列文章目录 文章目录 系列文章目录前言一、解释 Java 堆空间及 GC?二、JVM 内存区域三、程序计数器(线程私有)前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,看懂了就去分享给你的码吧。 一…

Intel NUC x15电池独立显卡功耗异常解决办法

买了Intel NUC x15&#xff0c;所有驱动都是安装的官方的驱动&#xff0c;但是电池续航一直尿崩。经过查找资料&#xff0c;发现是独立显卡功耗异常导致&#xff0c;也有用户给出了解决办法&#xff0c;参考NUC X15 显卡待机功耗异常解决方案 - 哔哩哔哩 (bilibili.com)。https…

canvas绘制美国国旗(USA Flag)

查看专栏目录 canvas实例应用100专栏&#xff0c;提供canvas的基础知识&#xff0c;高级动画&#xff0c;相关应用扩展等信息。canvas作为html的一部分&#xff0c;是图像图标地图可视化的一个重要的基础&#xff0c;学好了canvas&#xff0c;在其他的一些应用上将会起到非常重…

8 容器化微服务

文章目录 DockerSpring Boot和Buildpacks在Docker中运行系统Docker化微服务Docker化前端Docker化配置导入器Docker Compose使用Docker扩展系统共享Docker镜像小结 前面的文章&#xff1a; 1、1 一个测试驱动的Spring Boot应用程序开发 2、2 使用React构造前端应用 3、3 试驱动的…

通信入门系列——复变函数

本节目录 一、复变函数 1、复数 2、复数的四则运算 二、复指数函数 三、欧拉公式本节内容 一、复变函数 1、复数 复数单位i&#xff0c;也就是满足i^2-1&#xff0c;将zxiy表示为复数z&#xff0c;x和y为任意的实数&#xff0c;称为复数z的实部和虚部。由复数zxiy对应的点(x,y…

虚拟歌姬学习:DiffSinger,让GitHub下载快的方法!

《三分钟上手DiffSinger》系列 ——基础篇https://www.bilibili.com/video/BV1ug4y1S7Dk/?spm_id_from333.337.search-card.all.click&vd_source124076d7d88eee393a1d8bf6fc787efa 下载DiffSinger 建议用edge浏览器还有steam&#xff0c;有时只是慢&#xff0c;但是还是…

02_正则表达式的应用

本课目标 理解正则表达式概述掌握Js的正则对象Regexp掌握正则表达式的常见用法完成页面注册的手机号码校验 1. 正则表达式概述 官方文档&#xff1a;正则表达式 - JavaScript | MDN 正则表达式在线测试 1.1 正则表达式的定义 介绍&#xff1a;正则表达式是用于匹配字符串中…

# 安徽锐锋科技IDMS系统简介

IDMS 由安徽锐锋科技独立开发 该系统负责和海算以及UE\UNITY的无缝衔接并具备远程数据库访问、高速数据库的自动创建及数据存储、支持MQTT等多种物联网接口&#xff0c;支持多种算法。主要完成由于物料、人员、生产、故障、不良异常、订单异常带来的生产损失&#xff0c;通过海…

macOS跨进程通信: TCP Socket 创建实例

macOS跨进程通信: TCP Socket 创建实例 一&#xff1a; 简介 Socket 是 网络传输的抽象概念。 一般我们常用的有Tcp Socket和 UDP Scoket&#xff0c; 和类Unix 系统&#xff08;包括Mac&#xff09;独有的 Unix Domain Socket&#xff08;UDS&#xff09;。 Tcp Socket 能够…