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 只关注卡槽。
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;}

这篇关于【笔记】Android Telephony | SIM 卡管理和subId、slotId、phoneId 定义关系说明的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!

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

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

相关文章

<Linux> 生产者消费者模型

目录 前言&#xff1a; 一、什么是生产者消费者模型 &#xff08;一&#xff09;概念 &#xff08;二&#xff09;生产者消费者之间的关系 &#xff08;三&#xff09;生产者消费者模型特点 &#xff08;四&#xff09;生产者消费者模型的优点 二、基于阻塞队列实现生产…

Java 如何实现多线程之间的通讯和协作

该文章专注于面试,面试只要回答关键点即可,不需要对框架有非常深入的回答,如果你想应付面试,是足够了,抓住关键点 Java 如何实现多线程之间的通讯和协作 在Java中,多线程之间的通讯和协作可以通过以下几种方式实现: 使用wait()、notify()、notifyAll()方法:这些方法是…

面试算法-44-两数之和 II - 输入有序数组

题目 给你一个下标从 1 开始的整数数组 numbers &#xff0c;该数组已按 非递减顺序排列 &#xff0c;请你从数组中找出满足相加之和等于目标数 target 的两个数。如果设这两个数分别是 numbers[index1] 和 numbers[index2] &#xff0c;则 1 < index1 < index2 < nu…

前端标准 JsDoc 代码片段注释 ( 快速生成代码片段网站 )

{ "快速单行注释": {"prefix": "z","body": [" /**"," * $1"," * param { }"," * return { }"," */"],"description": "快速注释" } } 配置之后…

嵌入式科普(12)西门子PROFINET ERTECH 200P-3路演

目录 一、路演观后感/总结 二、分享两个公众号 2.1 HMS工业网络 2.2 Omdia 三、ERTECH 200P-3资料 四、ERTECH 200P-3路演分享 嵌入式科普(12)西门子PROFINET ERTECH 200P-3路演 一、路演观后感/总结 老罗砸西门子冰箱时候的傲慢 -> 路演的谦逊 国外工程师包吃住差旅…

Linux(openEuler)部署SpringBoot前后端分离项目(Nginx负载均衡)

假如数据库在本地&#xff0c;没有放在Linux中 1.先把数据库中root的主机改成% 2.项目中的数据库链接配置换成本机ip 3.打包 4.把打包好的jar包放到Linux中 一般把jar包放到opt下 5.把前端部分拷贝到Linux的nginx中 5.1在package.json中修改build的值为图中这样 5.2同时由于在…

动态规划(算法竞赛、蓝桥杯)--单调队列优化修建草坪

1、B站视频链接&#xff1a;E44 单调队列优化DP 修剪草坪_哔哩哔哩_bilibili #include <bits/stdc.h> using namespace std; typedef long long LL; const int N1e510; int n,k,q[N]; LL w[N],f[N],sum;int main(){cin>>n>>k; k; //for(int i1;i<n;i){ci…

Vue多文件学习项目综合案例——小兔鲜,黑马vue教程

文章目录 一、项目截图二、主要知识点三、Main.js四、App.vue五、componentsXtxBanner.vueXtxFooter.vueXtxHeaderNav.vueXtxHotBrand.vueXtxNewGoods.vueXtxShortCut.vueXtxTopic.vue 六、stylesbase.csscommon.css 一、项目截图 二、主要知识点 把静态页面拆分成一个个vue组…

数据库简介与MySQL编译安装

1数据库基础 什么是数据库 数据库&#xff08;Database&#xff09;是一个有组织的数据存储系统&#xff0c;用于有效地存储、检索、管理和维护数据。数据库系统允许用户以结构化的方式存储和操作大量数据&#xff0c;并提供了一种可靠的方法来管理和维护这些数据&#xff0c…

数据库的基本概念与安装MySQL

一、数据库的基本概念 1、什么是数据&#xff1f; 描述事物的符合记录包括数字、文字、图形、图像、声音、档案记录等以“记录”形式按统一的格式进行存储 2、什么是表&#xff1f; 将不同的记录组织在一起用来存储具体数据 3、什么是数据库 表的集合&#xff0c;是存储数…

Python实战:爬虫基础与Scrapy框架入门

1、Python爬虫基础 1.1、了解网页结构 在进行爬虫之前&#xff0c;首先需要了解网页的结构。大多数网页都是使用HTML&#xff08;超文本标记语言&#xff09;编写的&#xff0c;而现代网页通常还会使用CSS&#xff08;层叠样式表&#xff09;和JavaScript来增强视觉效果和交互…

2023年中国电商市场研究报告

研究范畴界定为中国国内2C电商市场 ⚠️ 关键点&#xff1a; 流量红利减少&#xff0c;电商市场进入存量增量 竞争的发展阶段&#xff1b;新兴电商平台不断挑战现有头部电商平台行业地位&#xff1b;消费者更加趋于理性&#xff0c;更加关注低价和服务&#xff1b;市场趋势&…

嵌入式和 Java选哪个?

今日话题&#xff0c;嵌入式和 Java 走哪个?对于嵌入式领域有浓厚兴趣的人&#xff0c;并不会比Java行业薪资低&#xff0c;处于上中游水平。特别是从2020年开始&#xff0c;嵌入式领域受益于芯片产业的兴起&#xff0c;表现出了强劲的增长势头。薪资水平受多方面因素影响。嵌…

AndroidLinux GPIO控制方法

目录 1 GPIO整体架构 2 user space 层 gpio使用方法 2.1 sysfs控制方法 2.1.1 kernel版本区别 2.1.2 /sys/class/gpio 2.1.3 /sys/bug/gpio/devices 2.2 chardev控制方法 2.2.1 chardev 示例代码 2.2.2 示例代码主要步骤描述 2.2.3 include/linux/gpio.h 全部代码 2.3…

mmz批量多页抓取数据-AES.CBC算法-爬虫

目标&#xff1a;mmz多页下载 方法&#xff1a;加一个for循环实现多页的下载 问题&#xff1a;浏览器传输服务器时对页码参数做了加密处理 解决方法&#xff1a; 1、判断加密算法模式&#xff08;mmz是AES-CBC算法&#xff09; 2、找到加密的key和iv 代码&#xff1a; i…

数据可信流通,从运维信任到技术信任

信任 共同观点&#xff1a; 信任是涉及交易或交换关系的基础 身份可确认利益可依赖能力有预期行为有后果 数据流通中的不可信风险 内循环&#xff1a;数据持有方在自己的运维安全域内对自己的额数据使用和安全拥有全责外循环&#xff1a;数据要素在离开持有方安全域后&#…

使用 git 先提交后拉取的时候远程分支不允许问题

问题场景 修改本地代码使用 git 先提交后拉取的时候远程分支不允许的问题 修改本地代码时&#xff0c;远程分支存在其他新提交先执行了 git commit -m xxx update然后再执行 git pull 拉取远程分支代码&#xff0c;出现如下提示 hint: You have divergent branches and need…

基于python 变配电室运行状态评估与预警系统flask-django-nodejs-php

变配电室电气设备运行状态和环境信息缺乏必要的监测评估预警手段&#xff0c;如有一日遭遇突发情况&#xff0c;将危及电气设备安全稳定运行,易造成设备损坏和电力供应中断[2]。 目前&#xff0c;我国变配电室常采用无人管理的室内站设计方案&#xff0c;长期以来变配电室运维工…

黑马程序员——javase进阶——day10——IO流,Properties集合,IO工具类

目录&#xff1a; IO流的介绍 为什么要学习IO流什么是IO流IO流的分类字节流输出流 字节输出流入门字节输出流写数据的方法写数据的换行和追加写入字节输入流 字节输入流介绍字节输入流读多个字节图片的拷贝异常的捕获处理字节输入流—次读—个字节数组字节缓冲区流 字节缓冲流…

【C语言_数组_复习篇】

目录 一、数组的概念 二、数组的类型 三、一维数组 3.1 一维数组的创建 3.2 一维数组的初始化 3.3 一维数组的访问 3.4 一维数组在内存中的存储 四、二维数组 4.1 二维数组的创建 4.2 二维数组的初始化 4.3 二维数组的访问 4.4 二维数组在内存中的存储 五、变长数组 六、…