subid和slotid

概述

slotid或者phoneid是指卡槽,双卡机器卡槽一值为0,卡槽2为1,依次类推,不过国内也就双卡和单卡机器了,三卡机器只听说在遥远的印度有。

subid用过数据库的同学比较好理解,subid就是主键递增项,值从1开始,机器每插入一个新卡(iccid是没有见的,值就会加1,iccid每个sim卡是唯一的)。插入双卡后数据库中就会有subid值为1和2的两个数据条目,拔卡插卡交换卡槽数据库并不会增加新项,只有插入一张新的sim卡才会增加一条id为3的数据条目

subid是跟卡走的,slotid是跟卡槽走的。一般来说slotid比较好理解,subid不好理解。

Android5.0之后google终于加入了多sim卡的代码,5.0之前的多卡(一般也就是双卡)机制是各写各的,mtk和高通的代码各有千秋,但是基本上用slotid较多,subid只有mtk在用也很少。Google一统千秋后subid反而用的比slotid多了,例如TelephonyManager:

frameworks/base/telephony/java/android/telephony/TelephonyManager.java

    public int getSimState(int slotIdx) 
 public String getSimOperator(int subId) 

都是int类型,但是一定要瞪大眼睛看清楚是subid还是slotid,按照一般情况双卡机器一般也就插两张卡,那么subid可以是1和2,slotid是0和1,拿一张卡做开发的同学可能掉到坑里,因为1对subid还是slotid都是合法的值


三方app获取slot和subId

这个小节是针对文章下面的评论加的。

frameworks/base/telephony/java/android/telephony/SubscriptionManager.java

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

public static int getDefaultSubscriptionId() 获取默认subId,上述三个都返回-1的话使用这个


双卡设置中短信和通话的设置只是设置SettingsProvider中的一个字段,而设置数据业务卡槽除了设置数据库字段外还会导致modem的重启、网络类型切换(数据业务卡能上4G,而另一张卡只能用2G)等一系列操作。所以手机开发厂商一般说主卡就是数据业务卡。


互换方法

两个id互换的方法在SubscriptionManager类中

frameworks/base/telephony/java/android/telephony/SubscriptionManager.java

public static int getSubIdUsingPhoneId(int phoneId)
public static int getSlotId(int subId)

getSubIdUsingPhoneId方法是mtk加的,高通的可以用下面:

    public static int getSubIdbySlot(Context ctx, int slot) {  
    	int subid[] =  SubscriptionManager.getSubId(slot);
    	if(subid != null) {
    		return subid[0];    		
    	}
    	return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
    }
<think>我们正在分析一条与RCS服务订阅更新相关的系统日志: "TelephonyRcsService updateFeatureControllerSubscription slotId=1 oldSubId=-1 subId=-1 existing feature=false" 这条日志来自Android的RCS服务,表明在更新FeatureController的订阅信息时出现了异常情况(subId=-1)。 根据引用[2]的内容,我们知道在Android双卡系统中,每个SIM卡都有唯一的subId(订阅ID)、slotId(卡槽ID)phoneId(逻辑电话ID)。正常情况下,subId应该是一个正整数(从1开始),而-1表示无效的订阅ID。 因此,这条日志表明:在slotId=1的卡槽上,尝试更新RCS功能控制器(FeatureController)的订阅信息时,发现新旧订阅ID均为无效值(-1),并且该卡槽上原本不存在RCS功能控制器(existing feature=false)。 接下来,我们将分步骤分析可能的原因排查方法: ### 1. 日志含义解析 - **TelephonyRcsService**: 提供RCS(Rich Communication Services)服务的系统组件。 - **updateFeatureControllerSubscription**: 方法名,表示更新RCS功能控制器的订阅信息。 - **slotId=1**: 操作针对卡槽1(物理SIM卡插槽位置1)。 - **oldSubId=-1**: 更新前的订阅ID为-1(无效值)。 - **subId=-1**: 更新后的订阅ID仍为-1(无效值)。 - **existing feature=false**: 该卡槽上原本没有RCS功能控制器实例。 综合理解:系统尝试为卡槽1创建或更新RCS功能控制器,但无法获取有效的订阅ID(subId),因此无法进行后续操作。 ### 2. 可能原因分析 根据引用[1][2][4]中关于SIM卡管理的描述,以下情况可能导致subId无效: - **SIM卡未识别**:卡槽1没有插入SIM卡,或者插入的SIM卡未被系统识别(如损坏、接触不良)。 - **SIM卡状态异常**:SIM卡处于禁用状态(例如在设置中关闭了该卡),或者正在初始化中(状态为`SIM_STATE_ABSENT`、`SIM_STATE_UNKNOWN`等)。 - **订阅信息未加载**:系统启动时Telephony服务尚未完成初始化,SIM卡的订阅信息未从数据库(TelephonyProvider)加载。 - **多SIM卡管理异常**:在多SIM卡场景下,订阅信息的分配或同步出现错误(如引用[2]中提到的默认卡设置冲突)。 ### 3. 问题排查步骤 #### 3.1 确认SIM卡状态 通过`adb shell`命令检查卡槽1的SIM卡状态: ```bash adb shell dumpsys telephony.registry | grep -A 10 "mSlotIndex=1" ``` 输出关键字段: - `mSimState=READY`(正常状态应为`READY`或`LOADED`) - `mSubId=`(应为正整数,如1、2) 若状态异常(如`ABSENT`),需检查物理SIM卡或重启设备。 #### 3.2 检查订阅信息数据库 查询系统数据库中卡槽1的订阅信息: ```bash adb shell content query --uri content://telephony/siminfo --where "slot_index=1" ``` 正常输出示例: ``` _id=1, slot_index=1, display_name=中国移动, ..., subscription_id=1 ``` 若`subscription_id`为-1或记录不存在,说明数据库未正确记录SIM卡信息。 #### 3.3 分析Telephony服务日志 过滤Telephony相关日志,查找订阅信息加载过程: ```bash adb logcat -b all | grep -Ei "SubscriptionController|TelephonyRegistry|simstate" ``` 关键线索: - SIM卡状态变化事件(如`SIM_STATE_READY`) - 订阅信息更新日志(如`onSubscriptionsChanged`) #### 3.4 验证RCS配置 根据引用[3],RCS功能依赖运营商配置(CarrierConfig)。检查卡槽1的配置: ```bash adb shell dumpsys carrier_config | grep -A 10 "slotId=1" ``` 确认以下配置项存在且有效: ```java KEY_RCS_CONFIG_SERVER_URL_STRING // RCS配置服务器地址 KEY_ALLOWED_INITIAL_ATTACH_APN_TYPES_STRING_ARRAY // 包含"rcs"类型 ``` ### 4. 解决方案 根据排查结果采取相应措施: - **SIM卡问题**:重新插拔SIM卡或更换卡槽测试。 - **数据库异常**:清除Telephony服务数据(谨慎操作): ```bash adb shell pm clear com.android.phone ``` - **系统服务未就绪**:在设备完全启动后延迟初始化RCS组件(修改系统代码)。 - **配置缺失**:联系运营商更新CarrierConfig(引用[3])。 ### 5. 代码级修复建议(针对系统开发者) 在`TelephonyRcsService`中增加订阅有效性检查,避免无效订阅ID的操作: ```java // 伪代码:更新订阅前校验subId void updateFeatureControllerSubscription(int slotId, int newSubId) { int oldSubId = getCurrentSubIdForSlot(slotId); if (!SubscriptionManager.isValidSubscriptionId(newSubId)) { Log.w(TAG, "Invalid subId=" + newSubId + " for slotId=" + slotId); return; // 跳过更新 } // 正常处理逻辑... } ``` --- ### 相关问题 1. Android中如何通过ADB命令强制刷新CarrierConfig配置? 2. SIM卡状态`SIM_STATE_READY``SIM_STATE_LOADED`有何区别? 3. RCS服务初始化时依赖哪些系统服务? 4. 双卡设备中如何为特定卡槽启用RCS功能? 5. 如何捕获Android系统的SIM卡状态变化广播? > 分析基于Android 10+的RCS架构[^1][^3],具体实现可能因OEM定制而异。</think>### Android TelephonyRcsService 日志分析:`updateFeatureControllerSubscription slotId=1 oldSubId=-1 subId=-1 existing feature=false` #### 1. **日志关键参数解析** | 参数 | 值 | 含义说明 | |------|-----|----------| | `slotId` | 1 | 物理SIM卡槽位置(卡槽1) | | `oldSubId` | -1 | 更新前的订阅ID(-1表示无效订阅) | | `subId` | -1 | 更新后的订阅ID(仍为无效值) | | `existing feature` | false | 该卡槽不存在活跃的RCS功能控制器 | 此日志表明**系统尝试为卡槽1更新RCS订阅信息,但未找到有效的SIM卡订阅**(subId=-1),且该卡槽尚未初始化RCS功能控制器[^1][^2]。 --- #### 2. **问题根本原因分析** ##### 2.1 **SIM卡状态异常(最常见原因)** - **SIM卡未识别**:卡槽1无SIM卡或SIM卡接触不良 - **SIM卡状态未就绪**:检查SIM卡状态: ```bash adb shell dumpsys telephony.registry | grep "mSlotIndex=1" -A 15 ``` 关注输出: ``` mSimState=READY # 正常状态应为READY/LOADED mSubId=1 # 正常应为正整数(非-1) ``` ##### 2.2 **订阅信息未同步** - Telephony服务未正确初始化SIM卡订阅信息: ```java // 参考:SubscriptionController.addSubInfoRecord() if (subId == -1) { Log.e(TAG, "Invalid subId for slot:" + slotId); // 数据库未写入有效订阅 } ``` ##### 2.3 **RCS服务配置问题** - 运营商配置缺失(参考引用[3]): ```java // CarrierConfigManager.java String[] allowedApn = config.getStringArray( KEY_ALLOWED_INITIAL_ATTACH_APN_TYPES_STRING_ARRAY); // 需包含"rcs" ``` - 验证配置: ```bash adb shell dumpsys carrier_config | grep "KEY_ALLOWED_INITIAL_ATTACH" ``` --- #### 3. **排查步骤** ##### 3.1 检查SIM卡状态 ```bash # 检查卡槽1的SIM状态 adb shell service call iphonesubinfo 15 i32 1 | grep -E "subId|state" # 预期正常输出(示例): Result: Parcel(subId=1, state=5(READY)) ``` ##### 3.2 验证订阅数据库 ```bash # 查询卡槽1的订阅信息 adb shell content query --uri content://telephony/siminfo \ --where "slot_index=1" # 异常输出示例: _id=0, slot_index=1, subscription_id=-1 # subscription_id=-1表示异常 ``` ##### 3.3 跟踪RCS服务初始化 过滤关键日志: ```bash adb logcat -s TelephonyRcsService | grep -E "createFeatureController|subscriptionChanged" # 正常流程应出现: I/TelephonyRcsService: createFeatureController for slotId=1 I/TelephonyRcsService: subscriptionChanged: slotId=1 -> subId=1 ``` --- #### 4. **解决方案** ##### 4.1 代码修复建议(系统层) ```java // 在updateFeatureControllerSubscription()中添加有效性校验 void updateFeatureControllerSubscription(int slotId, int newSubId) { if (!SubscriptionManager.isValidSubscriptionId(newSubId)) { Log.w(TAG, "Invalid subId=" + newSubId + " for slotId=" + slotId); return; // 跳过无效更新 } // ...正常处理逻辑 } ``` ##### 4.2 运营商配置修复 确保`carrier_config.xml`包含RCS配置: ```xml <boolean name="enable_rcs_bool" value="true"/> <string-array name="allowed_initial_attach_apn_types_string_array"> <item>default</item> <item>ia</item> <item>rcs</item> <!-- 必须包含rcs --> </string-array> ``` ##### 4.3 用户端操作 1. 重新插拔SIM卡 2. 进入**设置 > 网络互联网 > SIM卡** 强制刷新订阅 3. 重置网络设置(会清除WiFi/蓝牙配对) --- ### 相关问题 1. Android中如何通过ADB命令模拟SIM卡状态变化? 2. `subId=-1`在Telephony服务中还有哪些常见触发场景? 3. 双卡设备中RCS服务如何区分不同卡槽的配置?[^4] 4. 如何检测CarrierConfig是否成功加载到设备? 5. RCS服务的"initial attach"过程与普通数据连接有何区别?[^3] > 分析基于Android 12 Telephony架构[^1][^2],具体实现可能因OEM定制而异。当subId持续为-1时,建议优先检查SIM卡物理状态运营商配置[^3][^4]。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值