1. subid和slotid(phoneid)

slotid(phoneid)是指卡槽:双卡机器的卡槽1值为0,卡槽2值为1,依次类推。

subid:SubscriptionId(Subscription
Identifier)。subid是数据库telephony.db的表siminfo的主键递增项,其中telephony.db在"/data
/user_de/0/com.android.providers.telephony/databases"下。subid的值从1开始,每插入一个新卡,subId的值就会加1。插入双卡后数据库中就会有subid值为1和2的两个数据条目,拔卡插卡交换卡槽后,数据库并不会增加新项,只有插入一张新的sim卡才会增加一条id为3的数据条目。

注意:
subid对应卡,slotid对应卡槽

2. Subscription和SubscriptionInfo

每一张SIM卡都对应一个Subscription,用谁家的SIM卡就相当于订阅(Subscription)谁家的业务。
SIM卡的信息就是SubscriptionInfo(Subscription Information),比如iccid、MNC、MCC等,多张SIM卡就有多个SubscriptionInfo。
其中ICCID:Integrate circuit card identity,集成电路卡识别码,即SIM卡卡号,相当于手机号码的身份证。

//frameworks/base/telephony/java/android/telephony/SubscriptionInfo.java
public class SubscriptionInfo implements Parcelable {//实现Parcelable是为了进程间ipc通信。(Inter-Process Communication)
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(mId); //数据库id,递增主键,每一个iccid的卡会占用1个id
dest.writeString(mIccId); //sim卡的iccid,每张sim卡是唯一的
dest.writeInt(mSimSlotIndex); //sim卡插入卡槽值,0是卡1,1是卡2,没有插入则是-1
dest.writeCharSequence(mDisplayName); //sim卡名称,用户可以自定义
dest.writeCharSequence(mCarrierName); //运营商名称
dest.writeInt(mNameSource); //名称来源,是用户设置或者是从sim卡读取(一般就是运营商名称)等
dest.writeInt(mIconTint); //sim卡图标染色值,tint的概念可以百度google
dest.writeString(mNumber); //sim卡关联号码
dest.writeInt(mDataRoaming); //sim卡是否启用数据漫游
dest.writeInt(mMcc); //mcc,移动国家码,3位数字,中国是460
dest.writeInt(mMnc); //mnc,移动网络码,2位数字,如00,01等,表示运营商
dest.writeString(mCountryIso); //国家iso代码
mIconBitmap.writeToParcel(dest, flags); //sim卡图标
}
......
}

它是和TelephonyProvider数据库中的siminfo对应的。

//vendor/mediatek/proprietary/packages/providers/TelephonyProvider/src/com/android/providers/telephony/TelephonyProvider.java
private void createSimInfoTable(SQLiteDatabase db) {
if (DBG) log("dbh.createSimInfoTable:+");
db.execSQL("CREATE TABLE " + SIMINFO_TABLE + "("
+ SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
+ SubscriptionManager.ICC_ID + " TEXT NOT NULL,"
+ SubscriptionManager.SIM_SLOT_INDEX + " INTEGER DEFAULT " + SubscriptionManager.SIM_NOT_INSERTED + ","
+ SubscriptionManager.DISPLAY_NAME + " TEXT,"
+ SubscriptionManager.CARRIER_NAME + " TEXT,"
+ SubscriptionManager.NAME_SOURCE + " INTEGER DEFAULT " + SubscriptionManager.NAME_SOURCE_DEFAULT_SOURCE + ","
+ SubscriptionManager.COLOR + " INTEGER DEFAULT " + SubscriptionManager.COLOR_DEFAULT + ","
+ SubscriptionManager.NUMBER + " TEXT,"
+ SubscriptionManager.DISPLAY_NUMBER_FORMAT + " INTEGER NOT NULL DEFAULT " + SubscriptionManager.DISPLAY_NUMBER_DEFAULT + ","
+ SubscriptionManager.DATA_ROAMING + " INTEGER DEFAULT " + SubscriptionManager.DATA_ROAMING_DEFAULT + ","
+ SubscriptionManager.MCC + " INTEGER DEFAULT 0,"
+ SubscriptionManager.MNC + " INTEGER DEFAULT 0,"
...
+ SubscriptionManager.CB_OPT_OUT_DIALOG + " INTEGER DEFAULT 1"
+ ");");
if (DBG) log("dbh.createSimInfoTable:-");
}

建表函数createSimInfoTable,常量都是在SubscriptionManager中定义,可以从名字看出和SubscriptionInfo是对应的,当然后面mtk加了不少字段。

3. SubscriptionManager及其相关方法

SubscriptionManager为第三方app层使用,用于:
1). 获取和设置当前双卡设置(如当前默认拨号卡);
2). 进行slotid和subId转换等;
3). 获取当前的卡信息SubscriptionInfo。

SubscriptionManager //frameworks/base/telephony/java/android/telephony/SubscriptionManager.java
1). 获取SubscriptionManager对象
public static SubscriptionManager from(Context context);
//SubscriptionManager mSubscrMgr = SubscriptionManager.from(mContext);//get Manager 2). 第三方app获取slot和subId
public int getDefaultDataPhoneId()  默认数据slotId
public static int getDefaultDataSubscriptionId() 默认数据subId public int getDefaultSmsPhoneId()  默认短信slotId
public static int getDefaultSmsSubscriptionId() 默认短信subId public static int getDefaultVoicePhoneId()  默认通话slotId
public static int getDefaultVoiceSubscriptionId() 默认通话subId 上述三个都返回-1的话使用
public static int getDefaultSubscriptionId() 获取默认subId 3). slotid和subId转换
public static int getSlotIndex(int subId)
public static int getPhoneId(int subId)
public static int[] getSubId(int slotIndex) 4). 第三方app获取SubscriptionInfo
public SubscriptionInfo getActiveSubscriptionInfoForSimSlotIndex(int slotIndex) //根据卡槽获取对应的SubscriptionInfo
public SubscriptionInfo getActiveSubscriptionInfo(int subId) //根据subId获取对应的SubscriptionInfo

SubscriptionInfo代表了sim卡的相关数据,其常用方法如下:

SubscriptionInfo//frameworks/base/telephony/java/android/telephony/SubscriptionInfo.java
public int getDataRoaming();//return the data roaming state for this subscription
public CharSequence getDisplayName() ;//return the name displayed to the user that identifies this subscription
public String getIccId() ;
public int getMcc();
public int getMnc() ;
public String getNumber();//return the number of this subscription.
public int getSimSlotIndex() //return the slot index of this Subscription's SIM card.
public int getSubscriptionId() //return the subscription ID - subId

可以发现,通过slotId得到对应的subId,再通过SubscriptionManager的getActiviteSubscriptionInfo()方法获取SIM卡的subscriptionInfo,进而可以获取该卡的mcc/mnc/iccid等信息。

也可以直接使用slotId,调用SubscriptionManager的getActiviteSubscriptionInfoFromSimSlotIndex()方法,获取SIM卡的subscriptionInfo。

注:由slotId得到subId,也可使用MtkSubscriptionManager(mtk自己定义的Subscription管理类)的静态方法getSubIdUsingPhoneId()

4. SubscriptionManager和SubscriptionController

SubscriptionManager是SubscriptionController的应用程序接口,提供有关当前电话订阅的信息。
SubscriptionController运行在phone进程中,是双卡相关功能正真实现端,为SubscriptionManager提供服务。
SubscriptionManager的功能基本都是通过binder调用SubscriptionController服务端来实现,使用ISub.aidl和SubscriptionController进行沟通
同理,MtkSubscriptionManager使用IMtkSub.aidl和MtkSubscriptionControllerEx进行沟通
以getSubIdUsingPhoneId()方法展示各个类之间的关系:

MtkSubscriptionManager
public static int getSubIdUsingPhoneId(int phoneId) {
if (VDBG) Rlog.d(LOG_TAG, "[getSubIdUsingPhoneId]+ phoneId:" + phoneId); int subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; try {
IMtkSub iSub = IMtkSub.Stub.asInterface(ServiceManager.getService("isubstub"));
if (iSub != null) {
subId = iSub.getSubIdUsingPhoneId(phoneId);
}
} catch (RemoteException ex) {
// ignore it
}
return subId;
}

其中MtkSubscriptionController.getMtkInstance()返回MtkSubscriptionController实例

public class MtkSubscriptionController extends SubscriptionController {
public static MtkSubscriptionController getMtkInstance() {
synchronized (MtkSubscriptionController.class) {
return sMtkInstance;
}
}
}

但是MtkSubscriptionController类内并无getSubIdUsingPhoneId()方法,调用的是父类SubscriptionController的getSubIdUsingPhoneId()方法,getSubIdUsingPhoneId()方法调用的是getSubId()方法

public class SubscriptionController extends ISub.Stub {
public int getSubIdUsingPhoneId(int phoneId) {
int[] subIds = getSubId(phoneId);
if (subIds == null || subIds.length == 0) {
return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
}
return subIds[0];
} /**
* Return the subId for specified slot Id.
* @deprecated
*/
@Override
@Deprecated
public int[] getSubId(int slotIndex) {
if (VDBG) printStackTrace("[getSubId]+ slotIndex=" + slotIndex); // Map default slotIndex to the current default subId.
// TODO: Not used anywhere sp consider deleting as it's somewhat nebulous
// as a slot maybe used for multiple different type of "connections"
// such as: voice, data and sms. But we're doing the best we can and using
// getDefaultSubId which makes a best guess.
if (slotIndex == SubscriptionManager.DEFAULT_SIM_SLOT_INDEX) {
slotIndex = getSlotIndex(getDefaultSubId());
if (VDBG) logd("[getSubId] map default slotIndex=" + slotIndex);
}
......
// Create an array of subIds that are in this slot?
ArrayList<Integer> subIds = new ArrayList<Integer>();
for (Entry<Integer, Integer> entry: sSlotIndexToSubId.entrySet()) {
int slot = entry.getKey();
int sub = entry.getValue();
if (slotIndex == slot) {
subIds.add(sub);
}
} // Convert ArrayList to array
int numSubIds = subIds.size();
if (numSubIds > 0) {
int[] subIdArr = new int[numSubIds];
for (int i = 0; i < numSubIds; i++) {
subIdArr[i] = subIds.get(i);
}
if (VDBG) logd("[getSubId]- subIdArr=" + subIdArr);
return subIdArr;
} else {
if (DBG) logd("[getSubId]- numSubIds == 0, return DummySubIds slotIndex=" + slotIndex);
return getDummySubIds(slotIndex);
}
}
}

从SubscriptionController类的继承上可以推测,SubscriptionManager的getSubId()的真正实现也是在SubscriptionController类的getSubId()中

public class SubscriptionManager {
/** @hide */
public static int[] getSubId(int slotIndex) {
if (!isValidSlotIndex(slotIndex)) {
logd("[getSubId]- fail");
return null;
}
int[] subId = null;
try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) {
subId = iSub.getSubId(slotIndex);
}
} catch (RemoteException ex) {
// ignore it
}
return subId;
}
}

转自:

作者:getskill
链接:https://www.jianshu.com/p/c43a71bf7815
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

subId、slotId、SubscriptionInfo和SubscriptionManager的解释及关系说明的更多相关文章

  1. Spark名词解释及关系

    随着对spark的业务更深入,对spark的了解也越多,然而目前还处于知道的越多,不知道的更多阶段,当然这也是成长最快的阶段.这篇文章用作总结最近收集及理解的spark相关概念及其关系. 名词 dri ...

  2. 【UML】具体解释六种关系

    UML中包括六中关系.各自是:关联(Association).聚合(Aggregation).组合(Composition).泛化(Generalization).依赖(Dependency).实现( ...

  3. 如何通过subId来获取phoneId?

    androidL中使用一张数据表来保存sim卡信息:telephony.db中有一张记录SIM卡信息的表,siminfo: CREATE TABLE siminfo(_id INTEGER PRIMA ...

  4. python介绍、安装及相关语法、python运维、编译与解释

    1.python介绍 Python(英国发音:/ˈpaɪθən/ 美国发音:/ˈpaɪθɑːn/)是一种广泛使用的解释型.高级编程.通用型编程语言,由吉多.范罗苏姆创造,第一版发布于1991年.可以视 ...

  5. UML 用例图、顺序图、状态图、类图、包图、协作图、流程图

    ​用例图.顺序图.状态图.类图.包图.协作图 面向对象的问题的处理的关键是建模问题.建模可以把在复杂世界的许多重要的细节给抽象出.许多建模工具封装了UML(也就是Unified Modeling La ...

  6. 69个经典Spring面试题和答案

    Spring 是个java企业级应用的开源开发框架.Spring主要用来开发Java应用,但是有些扩展是针对构建J2EE平台的web应用.Spring 框架目标是简化Java企业级应用开发,并通过PO ...

  7. Spring面试题

    69道Spring面试题和答案 原文地址    译者:深海(1422207401@qq.com)  校对:方腾飞 目录 Spring 概述 依赖注入 Spring beans Spring注解 Spr ...

  8. 69 个经典 Spring 面试题和答案

    Spring 概述 什么是spring?Spring 是个java企业级应用的开源开发框架.Spring主要用来开发Java应用,但是有些扩展是针对构建J2EE平台的web应用.Spring 框架目标 ...

  9. 【英语魔法俱乐部——读书笔记】 2 中级句型-复句&合句(Complex Sentences、Compound Sentences)

    [英语魔法俱乐部——读书笔记] 2 中级句型-复句&合句(Complex Sentences.Compound Sentences):(2.1)名词从句.(2.2)副词从句.(2.3)关系从句 ...

随机推荐

  1. 前台页面中json和字符串相互转化

    比如我有两个变量,我要将a转换成字符串,将b转换成JSON对象: var a={"name":"tom","sex":"男&quo ...

  2. JXOI2017 加法

    题目描述: 可怜有一个长度为 \(n\) 的正整数序列 \(A\),但是她觉得 \(A\) 中的数字太小了,这让她很不开心. 于是她选择了 \(m\) 个区间 \([l_i, r_i]\) 和两个正整 ...

  3. Linux串口驱动程序(3)-打开设备

    先来分析一下串口打开的过程: 1.用户调用open函数打开串口设备文件:2.在内核中通过tty子系统,把open操作层层传递到串口驱动程序中:3.在串口驱动程序中的xx_open最终实现这个操作.这里 ...

  4. tomcat8.5在centos部署阿里云免费证书

    最近在做微信小程序,部署完服务器之后,发现报了个错误,说是我的域名不在以下合法域名列表中.对比了一下才发现我的域名还是http的没升级到https,之后我就到阿里云去申请了证书.中间有一次审核失败,查 ...

  5. Android API Levels 详解

    Android API Levels 当你开发你的Android应用程序时,了解该平台API变更管理的基本方法和概念是很有帮助的.同样的,知道API级别标识以及该标识如何保障你的应用与实际硬件设备相兼 ...

  6. XSS漏洞的渗透利用另类玩法

    XSS漏洞的渗透利用另类玩法 2017-08-08 18:20程序设计/微软/手机 作者:色豹 i春秋社区 今天就来讲一下大家都熟悉的 xss漏洞的渗透利用.相信大家对xss已经很熟悉了,但是很多安全 ...

  7. 卿烨科技 Fireball

    9人开发病毒感染超2亿电脑!Fireball病毒境外做案被举报   原标题:名校毕业生研发病毒年获利8000万 2.5亿台电脑感染 海淀网友协助民警追踪跨境黑客 高材生开公司研发病毒 一年获利8000 ...

  8. PAT_A1028#List Sorting

    Source: PAT A1028 List Sorting (25 分) Description: Excel can sort records according to any column. N ...

  9. 2019河北省大学生程序设计竞赛(重现赛)J-舔狗 (拓扑排序)

    题目链接:https://ac.nowcoder.com/acm/contest/903/J 题意:给你 n 个舔狗和他喜欢的人,让你俩俩配对(只能和喜欢它的和它喜欢的),求剩下的单身狗数量. 思路: ...

  10. 前端(二十一)—— vue指令:文本类指令、避免页面闪烁、v-bind指令、v-on指令、v-model指令、条件渲染指令、列表渲染指令

    文本类指令.v-bind指令.v-on指令.v-model指令.条件渲染指令.列表渲染指令 一.文本操作 v-text:文本变量 <p v-text='msg'></p> &l ...