第1层:系统架构概述
用户应用/系统服务
↓
CarrierConfigManager.getConfigForSubId(subId)
↓
ICarrierConfigLoader Binder服务
↓
┌─────────────────────────────────────┐
│ CarrierConfigLoader │
├─────────────────────────────────────┤
│ 1. 从DefaultApp获取配置 │
│ 2. 从Carrier App获取配置 │
│ 3. 缓存到XML文件 │
│ 4. 合并配置优先级 │
└─────────────────────────────────────┘
↓
PersistableBundle(配置数据)
第2层:配置优先级(最高到最低)
1️⃣ Test Override Configs (测试覆盖)
↓
2️⃣ Persistent Override Configs (持久覆盖)
↓
3️⃣ Carrier App Config (运营商App配置)
↓
4️⃣ Default App Config (系统默认App配置)
↓
5️⃣ Platform Defaults (平台硬编码默认值)
第3层:配置加载流程
// CarrierConfigManager.java - 公共API
public PersistableBundle getConfigForSubId(int subId, String... keys) {
// 1. 校验subscriptionId
if (!SubscriptionManager.isValidSubscriptionId(subId)) {
return getDefaultConfig();
}
// 2. 调用Binder服务获取配置
ICarrierConfigLoader service =
TelephonyFrameworkInitializer.getTelephonyServiceManager()
.getCarrierConfigLoaderServiceManager()
.getCarrierConfigLoader();
// 3. 指定key过滤
PersistableBundle result = service.getConfigForSubId(subId, keys);
// 4. 返回配置束
return result;
}
第4层:CarrierConfigLoader 的配置加载策略
Phase 1: 启动时的配置加载
// CarrierConfigLoader.java
public class CarrierConfigLoader {
// 配置存储位置
private PersistableBundle[] mConfigFromDefaultApp; // /data/user/0/.../
private PersistableBundle[] mConfigFromCarrierApp; //
private PersistableBundle[] mPersistentOverrideConfigs; // 测试覆盖
private void onBootOrUpdate() {
for (int phoneId = 0; phoneId < mNumPhones; phoneId++) {
// 1. 先尝试从缓存XML恢复
PersistableBundle config = restoreConfigFromXml(
mPlatformCarrierConfigPackage, // "com.android.carrierconfig"
"",
phoneId
);
if (config != null) {
// 缓存有效,使用缓存
mConfigFromDefaultApp[phoneId] = config;
} else {
// 缓存失效或不存在,绑定到DefaultApp
bindToConfigPackage(
mPlatformCarrierConfigPackage,
phoneId,
EVENT_CONNECTED_TO_DEFAULT
);
}
}
}
}
Phase 2: 配置文件格式
// XML缓存文件结构
File cacheFile = new File(
context.getFilesDir(),
"carrier_config_" + iccid + "_" + carrierId + ".xml"
);
// 内容格式: PersistableBundle
PersistableBundle config = new PersistableBundle();
config.putString("carrier_config_version_string", "1.0");
config.putBoolean("carrier_default_wfc_ims_enabled_bool", true);
config.putInt("carrier_default_wfc_ims_mode_int", 2);
config.putStringArray("carrier_metered_apn_types_strings",
new String[]{"default", "mms", "dun"});
// 序列化到文件
try (FileOutputStream out = new FileOutputStream(cacheFile)) {
config.writeToStream(out);
}
第5层:默认配置定义
在 CarrierConfigManager.java 中定义的关键常量
public class CarrierConfigManager {
// ===== VoLTE/IMS配置 =====
public static final String KEY_CARRIER_VOLTE_ENABLED_BOOL =
"carrier_volte_enabled_bool"; // VoLTE是否启用
public static final String KEY_CARRIER_DEFAULT_WFC_IMS_ENABLED_BOOL =
"carrier_default_wfc_ims_enabled_bool"; // WiFi通话是否默认启用
public static final String KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT =
"carrier_default_wfc_ims_mode_int"; // WiFi通话模式
// 值: 0=仅WiFi, 1=优先移动网络, 2=优先WiFi
// ===== 数据相关配置 =====
public static final String KEY_CARRIER_METERED_APN_TYPES_STRINGS =
"carrier_metered_apn_types_strings"; // 计费的APN类型
public static final String KEY_APN_SETTINGS_DEFAULT_APN_TYPES_STRING_ARRAY =
"apn_settings_default_apn_types_string_array"; // 默认APN类型
public static final String KEY_ALLOW_ADDING_APNS_BOOL =
"allow_adding_apns_bool"; // 是否允许用户添加APN
// ===== 通话功能配置 =====
public static final String KEY_CARRIER_ALLOW_TRANSFER_IMS_CALL_BOOL =
"carrier_allow_transfer_ims_call_bool"; // IMS通话转接
public static final String KEY_CARRIER_ALLOW_DEFLECT_IMS_CALL_BOOL =
"carrier_allow_deflect_ims_call_bool"; // IMS通话拒接
// ===== 5G配置 =====
public static final String KEY_CARRIER_NR_AVAILABILITY_INT =
"carrier_nr_availability_int"; // 5G可用性
// 值: CARRIER_NR_AVAILABILITY_NSA, CARRIER_NR_AVAILABILITY_SA
// ===== 紧急呼救相关 =====
public static final String KEY_EMERGENCY_OVER_IMS_SUPPORTED_3GPP_NETWORK_TYPES_INT_ARRAY =
"emergency_over_ims_supported_3gpp_network_types_int_array";
// ===== Tethering热点配置 =====
public static final String KEY_CARRIER_SUPPORTS_TETHERING_BOOL =
"carrier_supports_tethering_bool"; // 运营商是否支持热点
}
第6层:完整的默认值集合
// CarrierConfigManager.java - sDefaults 初始化
private static void initDefaults() {
sDefaults = new PersistableBundle();
// 版本信息
sDefaults.putString(KEY_CARRIER_CONFIG_VERSION_STRING, "1.0.0");
// VoLTE/WiFi通话
sDefaults.putBoolean(KEY_CARRIER_VOLTE_ENABLED_BOOL, false);
sDefaults.putBoolean(KEY_CARRIER_DEFAULT_WFC_IMS_ENABLED_BOOL, false);
sDefaults.putInt(KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT, 0); // WiFi only
// 数据APN
sDefaults.putStringArray(KEY_CARRIER_METERED_APN_TYPES_STRINGS,
new String[]{"default", "mms", "dun", "supl", "enterprise"});
sDefaults.putStringArray(KEY_CARRIER_METERED_ROAMING_APN_TYPES_STRINGS,
new String[]{"default", "mms", "dun", "supl", "enterprise"});
// 通话功能
sDefaults.putBoolean(KEY_CARRIER_ALLOW_TRANSFER_IMS_CALL_BOOL, false);
sDefaults.putBoolean(KEY_CARRIER_ALLOW_DEFLECT_IMS_CALL_BOOL, false);
// 5G
sDefaults.putInt(KEY_CARRIER_NR_AVAILABILITY_INT,
CARRIER_NR_AVAILABILITY_NSA);
// Tethering
sDefaults.putBoolean(KEY_CARRIER_SUPPORTS_TETHERING_BOOL, true);
// MTU设置
sDefaults.putInt(KEY_DEFAULT_MTU_INT, 1500);
// APN设置
sDefaults.putBoolean(KEY_ALLOW_ADDING_APNS_BOOL, true);
sDefaults.putStringArray(KEY_READ_ONLY_APN_TYPES_STRING_ARRAY,
new String[]{"dun"}); // DUN为只读
// 数据重试
sDefaults.putLong(KEY_CARRIER_DATA_CALL_APN_RETRY_AFTER_DISCONNECT_LONG,
3000); // 3秒后重试
}
第7层:运营商App如何提供配置
开发运营商配置App的步骤
1. 继承 CarrierService
// com.example.carrier/CarrierConfigService.java
public class CarrierConfigService extends CarrierService {
@Override
public PersistableBundle onLoadConfig(int subscriptionId,
@Nullable CarrierIdentifier id) {
PersistableBundle config = new PersistableBundle();
if (id == null) {
return config;
}
// 使用CarrierId而不是MCCMNC(更准确)
int carrierId = id.getCarrierId();
switch (carrierId) {
case TelephonyManager.CARRIER_ID_CHINA_MOBILE: // 中国移动
config = getChinaMobileConfig();
break;
case TelephonyManager.CARRIER_ID_CHINA_UNICOM: // 中国联通
config = getChinaUnicomConfig();
break;
case TelephonyManager.CARRIER_ID_CHINA_TELECOM: // 中国电信
config = getChinaTelecomConfig();
break;
default:
// 使用MCCMNC作为备选
String mccmnc = id.getMccMnc();
if ("46000".equals(mccmnc)) { // 中国移动
config = getChinaMobileConfig();
}
break;
}
return config;
}
private PersistableBundle getChinaMobileConfig() {
PersistableBundle config = new PersistableBundle();
// VoLTE/VoWiFi配置
config.putBoolean("carrier_volte_enabled_bool", true);
config.putBoolean("carrier_default_wfc_ims_enabled_bool", true);
config.putInt("carrier_default_wfc_ims_mode_int", 2); // 优先WiFi
// APN配置
config.putStringArray("carrier_metered_apn_types_strings",
new String[]{"default", "mms", "dun", "supl"});
// 功能配置
config.putBoolean("carrier_allow_transfer_ims_call_bool", true);
config.putBoolean("carrier_allow_deflect_ims_call_bool", true);
// 5G配置
config.putInt("carrier_nr_availability_int", 2); // SA mode
// 版本信息
config.putString("carrier_config_version_string",
"ChinaMobile_v1.0_" + System.currentTimeMillis());
return config;
}
}
2. 在 AndroidManifest.xml 中声明
<service
android:name=".CarrierConfigService"
android:permission="android.permission.BIND_CARRIER_CONFIG_SERVICE"
android:exported="true">
<intent-filter>
<action android:name="android.service.carrier.CarrierService" />
</intent-filter>
</service>
第8层:配置更新和监听
通知配置变化
// 在运营商App中
CarrierConfigManager configManager =
context.getSystemService(CarrierConfigManager.class);
// 通知系统配置已更新
configManager.notifyConfigChangedForSubId(subscriptionId);
监听配置变化
// 在系统服务中
BroadcastReceiver configReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED
.equals(intent.getAction())) {
int slotIndex = intent.getIntExtra(
CarrierConfigManager.EXTRA_SLOT_INDEX, -1);
int subId = intent.getIntExtra(
CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX, -1);
// 重新加载配置
reloadCarrierConfig(subId);
}
}
};
IntentFilter filter = new IntentFilter(
CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
context.registerReceiver(configReceiver, filter);
第9层:配置查询和使用
标准查询模式
public class MyTelephonyService {
public void loadCarrierConfig(int subId) {
CarrierConfigManager configManager =
context.getSystemService(CarrierConfigManager.class);
// 方式1:获取全部配置
PersistableBundle fullConfig =
configManager.getConfigForSubId(subId);
// 方式2:仅获取指定的配置项
PersistableBundle selectedConfig =
configManager.getConfigForSubId(subId,
CarrierConfigManager.KEY_CARRIER_VOLTE_ENABLED_BOOL,
CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_ENABLED_BOOL,
CarrierConfigManager.KEY_CARRIER_NR_AVAILABILITY_INT
);
// 方式3:获取默认配置(无SIM或配置不可用)
PersistableBundle defaultConfig =
CarrierConfigManager.getDefaultConfig();
// 检查配置是否来自已识别的运营商
boolean isIdentified =
CarrierConfigManager.isConfigForIdentifiedCarrier(fullConfig);
if (!isIdentified) {
Log.w(TAG, "Config is from unknown carrier, using defaults");
}
}
public void useCarrierConfig(PersistableBundle config) {
// 读取配置值
boolean volteEnabled = config.getBoolean(
CarrierConfigManager.KEY_CARRIER_VOLTE_ENABLED_BOOL,
false // 默认值
);
int wfcMode = config.getInt(
CarrierConfigManager.KEY_CARRIER_DEFAULT_WFC_IMS_MODE_INT,
0 // 默认为WiFi only
);
String[] meteredApnTypes = config.getStringArray(
CarrierConfigManager.KEY_CARRIER_METERED_APN_TYPES_STRINGS
);
int nrAvailability = config.getInt(
CarrierConfigManager.KEY_CARRIER_NR_AVAILABILITY_INT,
CarrierConfigManager.CARRIER_NR_AVAILABILITY_NSA
);
// 应用配置到系统行为
applyVoLteSettings(volteEnabled);
applyWiFiCallingMode(wfcMode);
apply5GSettings(nrAvailability);
}
}
第10层:主要配置分类参考表
| 分类 | 配置项 | 类型 | 说明 |
|---|---|---|---|
| VoLTE/IMS | VOLTE_ENABLED | bool | VoLTE是否启用 |
| WFC_IMS_ENABLED | bool | WiFi通话是否启用 | |
| WFC_IMS_MODE | int | WiFi优先/移动优先 | |
| 数据/APN | METERED_APN_TYPES | str[] | 按流量计费的APN |
| ALLOW_ADDING_APNS | bool | 允许用户添加APN | |
| READ_ONLY_APN_TYPES | str[] | 只读APN类型 | |
| 5G/网络 | NR_AVAILABILITY | int | 5G支持(NSA/SA) |
| PREFERRED_NETWORK_MODE | int | 首选网络模式 | |
| 通话功能 | ALLOW_TRANSFER_IMS_CALL | bool | IMS通话转接 |
| ALLOW_DEFLECT_IMS_CALL | bool | IMS通话拒接 | |
| 热点/共享 | SUPPORTS_TETHERING | bool | 支持热点共享 |
| REQUIRE_ENTITLEMENT_CHECKS | bool | 热点权限检查 | |
| 紧急呼救 | EMERGENCY_OVER_IMS | int[] | IMS紧急呼救 |
| EMERGENCY_OVER_CS | int[] | CS紧急呼救 | |
| 其他 | DEFAULT_MTU | int | MTU大小(字节) |
| CONFIG_VERSION | str | 配置版本号 |
第11层:文件存储位置
/data/user/0/com.android.phone/
├── carrier_config_<ICCID>_<CARRIER_ID>.xml # 缓存的运营商配置
├── carrier_config_default.xml # 默认配置缓存
└── no_sim_carrier_config_<CARRIER_ID>.xml # 无SIM时的配置
第12层:常见问题处理
public class CarrierConfigDebug {
// 问题1: 如何强制重新加载配置
public void forceReloadConfig(Context context, int subId) {
CarrierConfigManager ccm =
context.getSystemService(CarrierConfigManager.class);
// 通知配置已变更,强制重新加载
ccm.notifyConfigChangedForSubId(subId);
}
// 问题2: 如何检查是否使用了默认配置
public boolean isUsingDefaultConfig(PersistableBundle config) {
// 检查是否来自已识别的运营商
return !CarrierConfigManager.isConfigForIdentifiedCarrier(config);
}
// 问题3: 如何查看当前加载的配置版本
public String getConfigVersion(Context context, int subId) {
CarrierConfigManager ccm =
context.getSystemService(CarrierConfigManager.class);
PersistableBundle config = ccm.getConfigForSubId(subId);
return config.getString(
CarrierConfigManager.KEY_CARRIER_CONFIG_VERSION_STRING,
"Unknown"
);
}
// 问题4: 调试日志输出
public void dumpCarrierConfig(Context context, int subId, PrintWriter pw) {
CarrierConfigManager ccm =
context.getSystemService(CarrierConfigManager.class);
PersistableBundle config = ccm.getConfigForSubId(subId);
pw.println("Carrier Config for subId=" + subId);
pw.println("Is Identified: " +
CarrierConfigManager.isConfigForIdentifiedCarrier(config));
pw.println("Version: " +
config.getString(KEY_CARRIER_CONFIG_VERSION_STRING));
for (String key : config.keySet()) {
Object value = config.get(key);
pw.println(" " + key + " = " + value);
}
}
}
这就是完整的 Android CarrierConfig 系统!它是运营商定制行为的核心机制。