CarrierConfigManager解析
来源:互联网 发布:男士风衣品牌 知乎 编辑:程序博客网 时间:2024/06/15 01:04
最近做一个高通项目的移植,发现网络设置中的cdma和gsm设置项目是同时出现的,之前mtk的项目也是遇到过同样的问题。修改起来很简单,不过要探究根源还是小费力气的。packages/services/Telephony/src/com/android/phone/MobileNetworkSettings.java
private void updateBody() { ... PersistableBundle carrierConfig = PhoneGlobals.getInstance().getCarrierConfigForSubId(mPhone.getSubId()); ... } else if (carrierConfig.getBoolean(CarrierConfigManager.KEY_WORLD_PHONE_BOOL) == true) { prefSet.removePreference(mButtonEnabledNetworks); // set the listener for the mButtonPreferredNetworkMode list preference so we can issue // change Preferred Network Mode. mButtonPreferredNetworkMode.setOnPreferenceChangeListener(this); mCdmaOptions = new CdmaOptions(this, prefSet, mPhone); mGsmUmtsOptions = new GsmUmtsOptions(this, prefSet, phoneSubId); ...}发现走到了CarrierConfigManager.KEY_WORLD_PHONE_BOOL的分支,所以两个设置项全部会显示。
packages/services/Telephony/src/com/android/phone/PhoneGlobals.java
public PersistableBundle getCarrierConfigForSubId(int subId) { return configLoader.getConfigForSubId(subId); }
PhoneGlobals只是简单跳转,真正工作在packages/services/Telephony/src/com/android/phone/CarrierConfigLoader.java
@Override public @NonNull PersistableBundle getConfigForSubId(int subId) { try { mContext.enforceCallingOrSelfPermission(READ_PRIVILEGED_PHONE_STATE, null); // SKIP checking run-time READ_PHONE_STATE since using PRIVILEGED } catch (SecurityException e) { mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, null); } int phoneId = SubscriptionManager.getPhoneId(subId); PersistableBundle retConfig = CarrierConfigManager.getDefaultConfig(); //获取初始设置 if (SubscriptionManager.isValidPhoneId(phoneId)) { PersistableBundle config = mConfigFromDefaultApp[phoneId]; //从默认app获取设置 if (config != null) retConfig.putAll(config); config = mConfigFromCarrierApp[phoneId]; //从其它app获取设置 if (config != null) retConfig.putAll(config); } return retConfig; }
可见设置值的来源有三处
1.初始设置
frameworks/base/telephony/java/android/telephony/CarrierConfigManager.java
public static PersistableBundle getDefaultConfig() { return new PersistableBundle(sDefaults); }
/** The default value for every variable. */ private final static PersistableBundle sDefaults; static { sDefaults = new PersistableBundle(); sDefaults.putBoolean(KEY_ADDITIONAL_CALL_SETTING_BOOL, true); sDefaults.putBoolean(KEY_ALLOW_EMERGENCY_NUMBERS_IN_CALL_LOG_BOOL, false); sDefaults.putBoolean(KEY_ALLOW_LOCAL_DTMF_TONES_BOOL, true); ... }
是在代码中静态初始化的
2.默认app
packages/apps/CarrierConfig
首先看AndroidManifest.xml
<service android:name=".DefaultCarrierConfigService" android:permission="android.permission.BIND_CARRIER_SERVICES"> <intent-filter> <action android:name="android.service.carrier.CarrierService" /> </intent-filter> </service>这个apk的核心就是一个服务,action是android.service.carrier.CarrierService,实现该action的apk都可以作为设置来源。该apk也只有一个java文件
packages/apps/CarrierConfig/src/com/android/carrierconfig/DefaultCarrierConfigService.java
读取配置的核心代码如下
public PersistableBundle onLoadConfig(CarrierIdentifier id) { ... PersistableBundle config = null; try { synchronized (this) { if (mFactory == null) { mFactory = XmlPullParserFactory.newInstance(); } } XmlPullParser parser = mFactory.newPullParser(); String fileName = "carrier_config_" + id.getMcc() + id.getMnc() + ".xml"; //从asets中读取配置 parser.setInput(getApplicationContext().getAssets().open(fileName), "utf-8"); config = readConfigFromXml(parser, id); } catch (IOException | XmlPullParserException e) { Log.d(TAG, e.toString()); // We can return an empty config for unknown networks. config = new PersistableBundle(); } // Treat vendor.xml as if it were appended to the carrier config file we read. XmlPullParser vendorInput = getApplicationContext().getResources().getXml(R.xml.vendor); //从vendor.xml读取配置 try { PersistableBundle vendorConfig = readConfigFromXml(vendorInput, id); config.putAll(vendorConfig); } catch (IOException | XmlPullParserException e) { Log.e(TAG, e.toString()); } return config; }分为两步,一是从assets目录依据mcc和mnc读取xml配置,例如中国移动的
packages/apps/CarrierConfig/assets/carrier_config_46000.xml
<carrier_config_list> <carrier_config> <boolean name="carrier_volte_available_bool" value="true" /> <boolean name="hide_network_settings_bool" value="true" /> </carrier_config></carrier_config_list>其中之配置了两个项目。
二是从res中的vendor.xml读取,这个xml默认代码是空的。
3.其它app
private String getCarrierPackageForPhoneId(int phoneId) { List<String> carrierPackageNames = TelephonyManager.from(mContext) .getCarrierPackageNamesForIntentAndPhone( new Intent(CarrierService.CARRIER_SERVICE_INTERFACE), phoneId); if (carrierPackageNames != null && carrierPackageNames.size() > 0) { loge("carrierPackageNames = " + carrierPackageNames.get(0)); return carrierPackageNames.get(0); } else { return null; } }
public static final String CARRIER_SERVICE_INTERFACE = "android.service.carrier.CarrierService";其中可以看出匹配action为android.service.carrier.CarrierService的apk就可以作为配置来源,这个就要厂商自己实现了,默认代码是没有的。
其中CarrierConfigManager.KEY_WORLD_PHONE_BOOL在初始配置中就是为true的,app没有配置。
- CarrierConfigManager解析
- 解析
- 解析
- 解析
- 解析
- 解析
- 解析
- 解析
- 解析
- 解析
- 解析[ ]
- 解析
- ffmpeg解析-----解析文件格式
- Xen解析 netfilter解析
- JSON解析,XML解析
- 硬解析 软解析
- 解析xml dom 解析
- JSON解析、XML解析
- 【文献阅读】Densely Connected Convolutional Networks-best paper-CVPR-2017
- POJ-2689 Prime Distance(区间素数筛--经典题)
- python常用的十进制、16进制、字符串、字节串之间的转换
- Android ANR的产生与分析
- java常用三种排序算法---(插入,冒泡,顺序)及其时间复杂度
- CarrierConfigManager解析
- css学习笔记之垂直居中
- 活体检测的实现
- NTT(快速数论变换)
- JsonCpp遍历json
- 利用hadoop+hive抽取pcap源地址、目的地址、源端口和目的端口等相关数据
- SVN版本管理工具使用手册
- Android 插件化原理 完胜360插件框架 技术实战
- 定义结构体时变量名后的冒号和数字