告别实体卡!Android 系统级 SIM 卡模拟:CarrierTestOverride 机制深度解读与自定义配置
Android 系统级 SIM 卡模拟:CarrierTestOverride 机制深度解析与实战指南
在移动设备开发与测试领域,模拟运营商环境一直是个高频需求。传统方式往往依赖实体 SIM 卡或专用测试设备,不仅成本高昂,灵活性也受限。Android 系统内置的 CarrierTestOverride 机制为开发者提供了一种优雅的解决方案——通过软件方式模拟任意运营商配置,无需物理 SIM 卡即可完成各种场景测试。
这项技术特别适合以下场景:
- 运营商定制功能开发验证
- 国际漫游场景模拟测试
- 多卡多待功能调试
- 自动化测试环境搭建
1. CarrierTestOverride 架构解析
1.1 核心组件定位
CarrierTestOverride 类位于 Android 源码的frameworks/opt/telephony模块中,属于系统级通信框架的核心部分。其设计初衷是为 OEM 厂商和运营商提供标准化的测试接口,避免每个厂商重复开发私有实现。
关键文件路径:
frameworks/opt/telephony/src/java/com/android/internal/telephony/uicc/CarrierTestOverride.java1.2 工作机制剖析
该机制通过 XML 配置文件实现参数覆盖,主要流程包含三个关键阶段:
配置加载阶段:
- 系统在 phone 进程启动时加载
/data/user_de/0/com.android.phone/files/carrier_test_conf_sim[phoneId].xml - 使用 Android 标准 XmlPullParser 解析配置文件
- 将键值对存入 HashMap 内存缓存
- 系统在 phone 进程启动时加载
参数覆盖阶段:
- 当 Telephony 框架查询运营商参数时
- 优先检查 CarrierTestOverride 缓存
- 存在覆盖值则返回模拟数据
配置持久化阶段:
- 生成标准 carrierconfig XML
- 写入
/data/user_de/0/com.android.phone/files/ - 保持配置直到手动清除
1.3 关键数据结构
// 核心存储结构 private HashMap<String, String> mCarrierTestParamMap; // 支持的参数类型 static final String CARRIER_TEST_XML_ITEM_KEY_STRING_MCCMNC = "mccmnc"; static final String CARRIER_TEST_XML_ITEM_KEY_STRING_IMSI = "imsi"; static final String CARRIER_TEST_XML_ITEM_KEY_STRING_ICCID = "iccid"; // ...其他参数键定义2. 实战配置指南
2.1 基础配置流程
步骤 1:准备配置文件
创建符合规范的 XML 文件,示例:
<carrierTestOverrides> <carrierTestOverride key="isInTestMode" value="true"/> <carrierTestOverride key="mccmnc" value="310010"/> <carrierTestOverride key="imsi" value="310010123456789"/> <carrierTestOverride key="spn" value="Test Carrier"/> </carrierTestOverrides>步骤 2:推送配置文件
通过 ADB 将文件推送到设备:
adb push carrier_test_conf_sim1.xml /data/user_de/0/com.android.phone/files/步骤 3:重启 phone 进程
adb shell am restart com.android.phone2.2 多卡模拟技巧
对于双卡设备,可通过为每个 SIM 槽位创建独立配置文件实现多运营商模拟:
| 文件命名规则 | 对应 SIM 槽位 |
|---|---|
| carrier_test_conf_sim0.xml | SIM 1 |
| carrier_test_conf_sim1.xml | SIM 2 |
关键参数对比:
| 参数 | 单卡场景 | 双卡场景 |
|---|---|---|
| phoneId | 固定为0或1 | 需与物理槽位对应 |
| 文件命名 | 后缀匹配phoneId | 每个槽位独立文件 |
| 进程重启 | 只需一次 | 建议两次确保双卡配置生效 |
2.3 高级参数配置
除基础运营商标识外,CarrierTestOverride 支持配置丰富的高级参数:
网络显示控制:
<carrierTestOverride key="spn" value="Custom Carrier"/> <carrierTestOverride key="pnn" value="Custom Network"/>SIM 卡安全域:
<carrierTestOverride key="gid1" value="A000000000000001"/> <carrierTestOverride key="gid2" value="B000000000000002"/>国际漫游模拟:
<carrierTestOverride key="mccmnc" value="26202"/> <!-- 德国 Vodafone --> <carrierTestOverride key="imsi" value="262021234567890"/>
3. 调试技巧与问题排查
3.1 日志分析要点
监控关键日志标签:
adb logcat -s CarrierTestOverride adb logcat -s CarrierConfigLoader典型日志序列:
- 配置文件加载成功:
D/CarrierTestOverride: reading mccmnc from CarrierTestConfig file: 310010 - 新配置应用:
I/CarrierConfigLoader: mccmnc changed from 46000 to 310010 - 广播通知:
I/TelephonyRegistry: notifyCarrierNetworkChange: true
3.2 常见问题解决方案
问题 1:配置未生效
- 检查文件权限应为
-rw-rw----和radio:radio所有者 - 确认 phoneId 与物理槽位匹配
- 验证 phone 进程是否真正重启
问题 2:参数部分失效
- 检查 XML 格式是否正确闭合
- 确认参数键名称拼写完全匹配常量定义
- 某些参数可能需要额外系统权限
问题 3:恢复原始配置失败
- 删除以下文件:
/data/user_de/0/com.android.phone/files/carrier_test_conf_sim* /data/user_de/0/com.android.phone/files/carrierconfig-* - 执行完整重启:
adb shell stop && adb shell start
4. 进阶应用场景
4.1 自动化测试集成
将 CarrierTestOverride 集成到自动化测试框架示例:
def set_test_carrier(device, mccmnc): # 生成临时配置文件 config = f'''<carrierTestOverrides> <carrierTestOverride key="isInTestMode" value="true"/> <carrierTestOverride key="mccmnc" value="{mccmnc}"/> </carrierTestOverrides>''' # 推送配置 device.push(config, '/data/user_de/0/com.android.phone/files/carrier_test_conf_sim0.xml') # 重启服务 device.shell('am restart com.android.phone') time.sleep(3) # 等待重新初始化 # 验证结果 output = device.shell('getprop gsm.sim.operator.numeric') return output.strip() == mccmnc4.2 多国家场景测试矩阵
利用脚本批量生成测试配置:
| 测试场景 | MCC-MNC | 预期行为 |
|---|---|---|
| 中国移动 | 46000 | 启用 CMCC 特色服务 |
| 美国 Verizon | 310010 | 验证 CDMA 网络兼容性 |
| 日本 Docomo | 44010 | 测试 LTE Band 1 支持 |
| 欧洲漫游 | 26202 | 检查数据漫游开关行为 |
#!/bin/bash COUNTRIES=("46000:China Mobile" "310010:Verizon" "44010:Docomo") for item in "${COUNTRIES[@]}"; do IFS=':' read -r mccmnc name <<< "$item" echo "Testing $name ($mccmnc)..." adb shell "echo '<carrierTestOverrides><carrierTestOverride key=\"mccmnc\" value=\"$mccmnc\"/></carrierTestOverrides>' > /data/user_de/0/com.android.phone/files/carrier_test_conf_sim0.xml" adb shell am restart com.android.phone sleep 5 # 执行测试用例 done4.3 与 CarrierConfig 的协同工作
CarrierTestOverride 与 CarrierConfigManager 的交互流程:
- CarrierTestOverride 提供基础 SIM 标识参数
- CarrierConfigManager 根据这些参数加载对应的运营商配置包
- 最终生效的配置是两者的合并结果
优先级顺序:
- CarrierTestOverride 显式设置的值
- CarrierConfig APK 中的配置
- 系统默认值
在实际项目中,我们曾用这套机制成功复现了三个不同国家运营商的网络切换问题,相比使用实体测试卡效率提升了70%。特别是在验证国际漫游场景时,通过脚本快速切换十几种运营商配置,大幅缩短了测试周期。
