1、Android 暗码的注册与监听
packages/services/Telephony/AndroidManifest.xml
2、添加监听处理 Receiver
packages/services/Telephony/src/com/fly/phone/LteSupportChangeReceiver.java
package com.fly.phone;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.provider.Settings;
import android.telephony.SubscriptionManager;
import android.telephony.SubscriptionInfo;
import android.telephony.TelephonyManager;
import android.util.Log;
import com.android.ims.ImsManager;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneFactory;
import com.android.internal.telephony.RILConstants;
import com.android.phone.R;
import java.util.List;
import java.io.File;
import java.io.IOException;
/**
* deal with the changes of whether support 4G or not
*/
public class LteSupportChangeReceiver extends BroadcastReceiver {
private final static String TAG = "LteSupportChangeReceiver";
private Context mContext;
private static final String SECRET_CODE_ACTION = "android.provider.Telephony.SECRET_CODE";
private static final String SECTET_CODE_ENABLE_4G = "5744";
private static final String SECTET_CODE_DISABLE_4G = "4244";
private static final String FILE_NAME="/persist/tele/4G.FLG";
private static final int PREF_NETWORK_MODE_LTE_ON =
RILConstants.NETWORK_MODE_TD_SCDMA_LTE_CDMA_EVDO_GSM_WCDMA;
private static final int PREF_NETWORK_MODE_LTE_OFF =
RILConstants.NETWORK_MODE_TD_SCDMA_GSM_WCDMA_CDMA_EVDO;
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
mContext = context;
if (SECRET_CODE_ACTION.equals(action)) {
String host = intent.getData() != null ? intent.getData().getHost(): null;
Log.d(TAG, "onReceive: SECRET_CODE_ACTION -- HOST = " + host);
if (SECTET_CODE_ENABLE_4G.equals(host)) {
try {
File file = new File(FILE_NAME);
if (!file.exists()) {
file.createNewFile();
Log.d(TAG, "onReceive: enable 4G, create 4G.FLG");
} else {
Log.d(TAG, "onReceive: enable 4G, 4G.FLG has existed");
}
} catch (IOException e) {
Log.d(TAG, "onReceive: IOException"+e);
}
changePreferredNetworkMode(PREF_NETWORK_MODE_LTE_ON);
} else {
File file = new File(FILE_NAME);
if (file.exists()) {
file.delete();
Log.d(TAG, "onReceive: disable 4G, delete 4G.FLG");
} else {
Log.d(TAG, "onReceive: disable 4G, No 4G.FLG");
}
changePreferredNetworkMode(PREF_NETWORK_MODE_LTE_OFF);
}
}
}
private void changePreferredNetworkMode(int nwMode) {
int defaultDataSubId = SubscriptionManager.getDefaultDataSubId();
int phoneId = SubscriptionManager.getPhoneId(defaultDataSubId);
Phone dataPhone = PhoneFactory.getPhone(phoneId);
Log.d(TAG, "defaultDataSubId = " + defaultDataSubId + ", phoneId = " + phoneId);
if (dataPhone == null) {
Log.d(TAG, "dataPhone is null, get default phone !");
dataPhone = PhoneFactory.getDefaultPhone();
}
List subInfoList = SubscriptionManager.from(mContext).getAllSubscriptionInfoList();
Log.d(TAG, "changePreferredNetworkMode, allSubInfoList = " + subInfoList);
int subInfoCount = subInfoList != null ? subInfoList.size() : 0;
int oldNwMode;
boolean changeModemNetworkType;
boolean isLteNetworkType;
for (int i = 0; i < subInfoCount; i++) {
int subId = subInfoList.get(i).getSubscriptionId();
oldNwMode = android.provider.Settings.Global.getInt(
mContext.getContentResolver(),
Settings.Global.PREFERRED_NETWORK_MODE + subId, -1);
changeModemNetworkType = false;
isLteNetworkType = PhoneFactory . isLteNetworkType(oldNwMode);
if (isLteNetworkType && nwMode == PREF_NETWORK_MODE_LTE_OFF) {
changeModemNetworkType = true;
Log.d(TAG, "changePreferredNetworkMode: nwMode = " + nwMode + ", subId = " + subId);
}
if (isNeedChangeToLte(oldNwMode) && nwMode == PREF_NETWORK_MODE_LTE_ON) {
changeModemNetworkType = true;
Log.d(TAG, "changePreferredNetworkMode: nwMode = " + nwMode + ", subId = " + subId);
}
// we assume that it is impossible that saved network type is not same with modem type.
if (changeModemNetworkType && subId == defaultDataSubId) {
Log.d(TAG, "changePreferredNetworkMode: set data phone nwMode to " + nwMode);
TelephonyManager.putIntAtIndex(
mContext.getContentResolver(),
Settings.Global.PREFERRED_NETWORK_MODE, dataPhone.getPhoneId(), nwMode);
dataPhone.setPreferredNetworkType(nwMode, null);
// we need close volte for non lte support mode. But we will not open it if ltet
// is enabled. Let user to decided.
if (nwMode != PREF_NETWORK_MODE_LTE_ON) {
ImsManager.setEnhanced4gLteModeSetting(mContext, false);
}
}
}
// we need make sure network type for another phone is also changed to avoid problems.
if (TelephonyManager.from(mContext).getPhoneCount() > 1) {
int anotherPhoneId = dataPhone.getPhoneId() == 0 ? 1 : 0;
TelephonyManager.putIntAtIndex(
mContext.getContentResolver(),
Settings.Global.PREFERRED_NETWORK_MODE, anotherPhoneId, nwMode);
}
}
private boolean isNeedChangeToLte(int networkType) {
if (networkType == RILConstants.NETWORK_MODE_GSM_ONLY
|| networkType == RILConstants.NETWORK_MODE_CDMA_NO_EVDO
|| networkType == RILConstants.NETWORK_MODE_EVDO_NO_CDMA
|| networkType == RILConstants.NETWORK_MODE_WCDMA_ONLY
|| networkType == RILConstants.NETWORK_MODE_TD_SCDMA_ONLY) {
return false;
} else {
return true;
}
}
}
3、关于selinux权限 和 用户权限组 修改
device/feixiang/sepolicy/radio.te
allow radio persist_file:dir {search getattr read write add_name remove_name};
allow radio persist_file:file {getattr read write create open unlink};
system/core/rootdir/init.rc
mkdir /persist/tele 0770 radio system // 修改用户权限组
PS: root 权限手机手动关闭 selinux权限 用于调试 (重启恢复)
$ adb shell setenforce 0
$ adb shell getenforce // 查看是否生效
4、标志文件使用
frameworks/opt/telephony/src/java/com/android/internal/telephony/PhoneFactory.java
public static boolean isNonLteMode(Context context) {
File file = new File("/persist/tele/4G.FLG");
if (!file.exists()) {
Rlog.d(LOG_TAG,"4G.FLG exists, return true");
return true;
} else {
Rlog.d(LOG_TAG,"4G.FLG not exist, return false");
return false;
}
}
public static boolean isLteNetworkType(int networkType) {
if (networkType == RILConstants.NETWORK_MODE_TD_SCDMA_LTE_CDMA_EVDO_GSM_WCDMA
|| networkType == RILConstants.NETWORK_MODE_LTE_GSM_WCDMA
|| networkType == RILConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA
|| networkType == RILConstants.NETWORK_MODE_LTE_ONLY
|| networkType == RILConstants.NETWORK_MODE_LTE_WCDMA
|| networkType == RILConstants.NETWORK_MODE_TD_SCDMA_LTE
|| networkType == RILConstants.NETWORK_MODE_TD_SCDMA_GSM_LTE
|| networkType == RILConstants.NETWORK_MODE_TD_SCDMA_WCDMA_LTE
|| networkType == RILConstants.NETWORK_MODE_TD_SCDMA_GSM_WCDMA_LTE
|| networkType == RILConstants.NETWORK_MODE_LTE_CDMA_EVDO) {
return true;
} else {
return false;
}
}
frameworks/opt/telephony/src/java/com/android/internal/telephony/RIL.java
@Override
public void setPreferredNetworkType(int networkType , Message response) {
if (PhoneFactory.isNonLteMode(mContext)
&& PhoneFactory.isLteNetworkType(networkType)) {
riljLog("Non LTE mode, force change network type to non lte mode 21");
networkType = NETWORK_MODE_TD_SCDMA_GSM_WCDMA_CDMA_EVDO;
}
RILRequest rr = RILRequest.obtain(
RILConstants.RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE, response);
rr.mParcel.writeInt(1);
rr.mParcel.writeInt(networkType);
mPreferredNetworkType = networkType;
if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
+ " : " + networkType);
send(rr);
}