Android 9.0之前版本修改如下
//frameworks\base\packages\SettingsProvider\src\com\android\providers\settings\DatabaseHelper.java
loadSetting(stmt, Settings.Global.ENHANCED_4G_MODE_ENABLED, ImsConfig.FeatureValueConstants.OFF);
设置 ENHANCED_4G_MODE_ENABLED 为 ON/OFF 即可
Android 9.0及之后版本
DatabaseHelper.java 中设置项已经取消,修改如下
//frameworks\base\telephony\java\android\telephony\CarrierConfigManager.java
sDefaults.putBoolean(KEY_HIDE_ENHANCED_4G_LTE_BOOL, true);
sDefaults.putBoolean(KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL, false);
KEY_HIDE_ENHANCED_4G_LTE_BOOL 设置是否隐藏VoLTE开关;
KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL 设置VoLTE模式默认值。
MTK 平台代码修改
MTK增加了 ImsService 管理 IMS 相关服务,在开机或者是热插拔时,从modem侧获取 SIM 内数据后,会同步 SIM 自身保存内容到系统,如下:
//vendor/mediatek/proprietary/packages/services/Ims/src/com/mediatek/ims/ImsService.java
/**
*Ims service Message hanadler.
*@hide
*/
private class MyHandler extends Handler {
... ...
@Override
public void handleMessage(Message msg) {
AsyncResult ar;
Intent intent;
switch (msg.what) {
... ...
/// M: Sync volte setting value. @{
case EVENT_IMS_VOLTE_SETTING_URC:
/*ar = (AsyncResult) msg.obj;
boolean enable = ((int[]) ar.result)[0] == 1;
int simState = SubscriptionManager.getSimStateForSlotIndex(mSocketId);
if (simState == TelephonyManager.SIM_STATE_ABSENT
|| (getSubIdUsingPhoneId(mSocketId)
<= SubscriptionManager.INVALID_SUBSCRIPTION_ID)) {
if (mRegisterSubInfoChange == false) {
final IntentFilter filter = new IntentFilter();
filter.addAction(TelephonyIntents.ACTION_SUBINFO_RECORD_UPDATED);
mContext.registerReceiver(mSubInfoReceiver, filter);
mRegisterSubInfoChange = true;
}
mWaitSubInfoChange[mSocketId] = true;
} else {
mWaitSubInfoChange[mSocketId] = false;
}
mVolteEnable[mSocketId] = enable;
if (mWaitFeatureChange == 0) {
SystemProperties.set(PROPERTY_IMSCONFIG_FORCE_NOTIFY, "1");
IntentFilter filter = new IntentFilter();
filter.addAction(ImsConfig.ACTION_IMS_FEATURE_CHANGED);
mContext.registerReceiver(mFeatureValueReceiver, filter);
}
mWaitFeatureChange = mWaitFeatureChange | (1 << mSocketId);
setEnhanced4gLteModeSetting(mSocketId, enable);
log("handleMessage() : Volte_Setting_Enable=" + enable +
", register:" + mWaitSubInfoChange[mSocketId] +
", mWaitFeatureChange:" + mWaitFeatureChange);*/
break;
/// @}
... ...
}
需要将 EVENT_IMS_VOLTE_SETTING_URC 这部分移除,避免将 SIM 内保存的数据设置到机器中。
题外话:VoLTE 模式的设置及状态获取通过 MtkImsManager.java 的接口获取。
//vendor/mediatek/proprietary/frameworks/opt/net/ims/src/java/com/mediatek/ims/internal/MtkImsManager.java
@Override
public boolean isEnhanced4gLteModeSettingEnabledByUser() {
int sub = getSubId();
int setting = SubscriptionManager.getIntegerSubscriptionProperty(
sub, SubscriptionManager.ENHANCED_4G_MODE_ENABLED,
SUB_PROPERTY_NOT_INITIALIZED, mContext);
boolean onByDefault = getBooleanCarrierConfig(
CarrierConfigManager.KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL);
boolean isPSsupport = isPhoneIdSupportIms(mPhoneId);
// If sim not ready yet, default off
if (sub == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
onByDefault = false;
}
// If Enhanced 4G LTE Mode is uneditable or not initialized, we use the default value
if (!getBooleanCarrierConfig(CarrierConfigManager.KEY_EDITABLE_ENHANCED_4G_LTE_BOOL)
|| setting == SUB_PROPERTY_NOT_INITIALIZED) {
if (onByDefault) {
// For CT roaming case or dual mode card, it's mccmnc maybe 20404,
// carrier config volte value is not consist to CT request.
String iccid = SystemProperties.get(PROPERTY_ICCID_SIM[mPhoneId],
"N/A");
if (!TextUtils.isEmpty(iccid) && isOp09SimCard(iccid)) {
onByDefault = false;
log("volte_setting, Replace volte value for CT card case");
}
}
return onByDefault;
} else {
return (setting == ImsConfig.FeatureValueConstants.ON) && isPSsupport;
}
}
/**
* @param context
* @param enabled
* @param phoneId
*/
public static void setEnhanced4gLteModeSetting(Context context,
boolean enabled, int phoneId) {
if (!isSupportMims()) {
phoneId = getMainPhoneIdForSingleIms(context);
}
getAppropriateManagerForPlugin(context, phoneId)
.setEnhanced4gLteModeSetting(enabled);
}
这里最终还是调用的系统原生类 SubscriptionManager.java 去获取管理。SubscriptionManager 是 SubscriptionController 的应用程序接口了,通过binder跨进程去 SubscriptionController 中继续执行。SubscriptionController运行在phone进程中,为 SIM 卡相关功能服务。
try {
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) {
subInfo = iSub.getActiveSubscriptionInfo(subId, mContext.getOpPackageName());
}
} catch (RemoteException ex) {
// ignore it
}
SubscriptionController 包含了通过 getContentResolver 查询修改 telephony 数据库操作,telephony 数据库则由 TelephonyProvider.java 去创建,保存包括 siminfo 和 carriers 等表,记录 SIM 信息和 APN 信息等。数据库路径:data/user_de/0/com.android.providers.telephony/