模拟插入sim卡功能基于CarrierTestOverride.java实现的。
代码路径:frameworks/opt/telephony/src/java/com/android/internal/telephony/uicc/CarrierTestOverride.java
下面以Android S为例(Android S之前的实现略有差异,可以找对应平台的对应代码看一下)
public class CarrierTestOverride {
static final String LOG_TAG = "CarrierTestOverride";
/**
* Config file that can be created and adb-pushed by tester/developer
*
* Sample xml:
* <carrierTestOverrides>
<carrierTestOverride key="isInTestMode" value="true"/>
<carrierTestOverride key="mccmnc" value="310010" />
<carrierTestOverride key="gid1" value="bae0000000000000"/>
<carrierTestOverride key="gid2" value="ffffffffffffffff"/>
<carrierTestOverride key="imsi" value="310010123456789"/>
<carrierTestOverride key="spn" value="Verizon"/>
<carrierTestOverride key="pnn" value="Verizon network"/>
<carrierTestOverride key="iccid" value="123456789012345678901"/>
</carrierTestOverrides>
*/
static final String DATA_CARRIER_TEST_OVERRIDE_PATH =
"/user_de/0/com.android.phone/files/carrier_test_conf_sim";
static final String CARRIER_TEST_XML_HEADER = "carrierTestOverrides";
static final String CARRIER_TEST_XML_SUBHEADER = "carrierTestOverride";
static final String CARRIER_TEST_XML_ITEM_KEY = "key";
static final String CARRIER_TEST_XML_ITEM_VALUE = "value";
static final String CARRIER_TEST_XML_ITEM_KEY_STRING_ISINTESTMODE = "isInTestMode";
static final String CARRIER_TEST_XML_ITEM_KEY_STRING_MCCMNC = "mccmnc";
static final String CARRIER_TEST_XML_ITEM_KEY_STRING_GID1 = "gid1";
static final String CARRIER_TEST_XML_ITEM_KEY_STRING_GID2 = "gid2";
static final String CARRIER_TEST_XML_ITEM_KEY_STRING_IMSI = "imsi";
static final String CARRIER_TEST_XML_ITEM_KEY_STRING_SPN = "spn";
static final String CARRIER_TEST_XML_ITEM_KEY_STRING_PNN = "pnn";
static final String CARRIER_TEST_XML_ITEM_KEY_STRING_ICCID = "iccid";
private HashMap<String, String> mCarrierTestParamMap;
CarrierTestOverride(int phoneId) {
mCarrierTestParamMap = new HashMap<String, String>();
loadCarrierTestOverrides(phoneId);
}
boolean isInTestMode() {
return mCarrierTestParamMap.containsKey(CARRIER_TEST_XML_ITEM_KEY_STRING_ISINTESTMODE)
&& mCarrierTestParamMap.get(CARRIER_TEST_XML_ITEM_KEY_STRING_ISINTESTMODE)
.equals("true");
}
// ......
String getFakeMccMnc() {
try {
String mccmnc = mCarrierTestParamMap.get(CARRIER_TEST_XML_ITEM_KEY_STRING_MCCMNC);
Rlog.d(LOG_TAG, "reading mccmnc from CarrierTestConfig file: " + mccmnc);
return mccmnc;
} catch (NullPointerException e) {
Rlog.w(LOG_TAG, "No mccmnc in CarrierTestConfig file ");
return null;
}
}
void override(String mccmnc, String imsi, String iccid, String gid1, String gid2, String pnn,
String spn) {
mCarrierTestParamMap.put(CARRIER_TEST_XML_ITEM_KEY_STRING_ISINTESTMODE, "true");
mCarrierTestParamMap.put(CARRIER_TEST_XML_ITEM_KEY_STRING_MCCMNC, mccmnc);
mCarrierTestParamMap.put(CARRIER_TEST_XML_ITEM_KEY_STRING_IMSI, imsi);
mCarrierTestParamMap.put(CARRIER_TEST_XML_ITEM_KEY_STRING_ICCID, iccid);
mCarrierTestParamMap.put(CARRIER_TEST_XML_ITEM_KEY_STRING_GID1, gid1);
mCarrierTestParamMap.put(CARRIER_TEST_XML_ITEM_KEY_STRING_GID2, gid2);
mCarrierTestParamMap.put(CARRIER_TEST_XML_ITEM_KEY_STRING_PNN, pnn);
mCarrierTestParamMap.put(CARRIER_TEST_XML_ITEM_KEY_STRING_SPN, spn);
}
private void loadCarrierTestOverrides(int phoneId) {
FileReader carrierTestConfigReader;
String filePath = DATA_CARRIER_TEST_OVERRIDE_PATH + Integer.toString(phoneId) + ".xml";
Rlog.d(LOG_TAG, "File path : " + filePath);
File carrierTestConfigFile = new File(Environment.getDataDirectory(), filePath);
try {
carrierTestConfigReader = new FileReader(carrierTestConfigFile);
Rlog.d(LOG_TAG, "CarrierTestConfig file Modified Timestamp: "
+ carrierTestConfigFile.lastModified());
} catch (FileNotFoundException e) {
Rlog.w(LOG_TAG, "Can not open " + carrierTestConfigFile.getAbsolutePath());
return;
}
try {
XmlPullParser parser = Xml.newPullParser();
parser.setInput(carrierTestConfigReader);
XmlUtils.beginDocument(parser, CARRIER_TEST_XML_HEADER);
while (true) {
XmlUtils.nextElement(parser);
String name = parser.getName();
if (!CARRIER_TEST_XML_SUBHEADER.equals(name)) {
break;
}
String key = parser.getAttributeValue(null, CARRIER_TEST_XML_ITEM_KEY);
String value = parser.getAttributeValue(null, CARRIER_TEST_XML_ITEM_VALUE);
Rlog.d(LOG_TAG,
"extracting key-values from CarrierTestConfig file: " + key + "|" + value);
mCarrierTestParamMap.put(key, value);
}
carrierTestConfigReader.close();
} catch (XmlPullParserException e) {
Rlog.w(LOG_TAG, "Exception in carrier_test_conf parser " + e);
} catch (IOException e) {
Rlog.w(LOG_TAG, "Exception in carrier_test_conf parser " + e);
}
}
}
看loadCarrierTestOverrides方法,
String filePath = DATA_CARRIER_TEST_OVERRIDE_PATH + Integer.toString(phoneId) + ".xml";
这就是定义的debug文件。
实践
1、首先,手机插入任意一张sim卡,然后我们通过下面命令可以看到
这里的persist.sys.mcc.mnc是我之前做运营商适配时候加入的属性值,实现如下:
private void subscriptionOrCarrierConfigChanged() {
if (DEBUG) Log.d(TAG, "received SIM related action: ");
TelephonyManager phone = (TelephonyManager)
mContext.getSystemService(Context.TELEPHONY_SERVICE);
CarrierConfigManager configManager = (CarrierConfigManager)
mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);
int ddSubId = SubscriptionManager.getDefaultDataSubscriptionId();
if (SubscriptionManager.isValidSubscriptionId(ddSubId)) {
phone = phone.createForSubscriptionId(ddSubId);
}
String mccMnc = phone.getSimOperator();
boolean isKeepLppProfile = false;
if (!TextUtils.isEmpty(mccMnc)) {
if (DEBUG) Log.d(TAG, "SIM MCC/MNC is available: " + mccMnc);
// setprop while sim card is available
SystemProperties.set("persist.sys.mcc.mnc", mccMnc);
// ......
reloadGpsProperties();
} else {
if (DEBUG) Log.d(TAG, "SIM MCC/MNC is still not available");
// Reload gnss config for no SIM case
mGnssConfiguration.reloadGpsProperties();
}
}
看logcat也行:
2、Push XML
从之前读属性的时候,我们看到插卡后的ril.mcc.mnc1读出来46009了,所以对应的phoneId为1
按照CarrierTestOverride.java中给到的Sample xml,写一个xml出来:
<carrierTestOverrides>
<carrierTestOverride key="isInTestMode" value="true"/>
<carrierTestOverride key="mccmnc" value="310010" />
<carrierTestOverride key="gid1" value="bae0000000000000"/>
<carrierTestOverride key="gid2" value="ffffffffffffffff"/>
<carrierTestOverride key="imsi" value="310010123456789"/>
<carrierTestOverride key="spn" value="Verizon"/>
<carrierTestOverride key="pnn" value="Verizon network"/>
<carrierTestOverride key="iccid" value="123456789012345678901"/>
</carrierTestOverrides>
然后push到手机的/data/user_de/0/com.android.phone/files/目录下:
3、重启com.android.phone进程:
先查看com.android.phone进程号,查到了本次运行期间,com.android.phone的进程号为3037。
杀掉com.android.phone:
进程重启,重启后com.android.phone的进程号变成7439
然后我们可以看到/data/user_de/0/com.android.phone/files/下生成了一个新的xml文件——carrierconfig-com.android.carrierconfig-123456789012345678901-310010.xml
4、看logcat
读到了sim card变更的广播,mccmnc变成310010
5、改回来
debug结束后,回来原来的状态:
可以将xml文件中的isInTestMode的值改为false,可以,但没麻烦。
我们可以将push进手机的carrier_test_conf_sim1.xml删除掉,将生成的carrierconfig-com.android.carrierconfig-123456789012345678901-310010.xml删除掉。
然后再重启com.android.phone进程就行了
再看logcat,mccmnc又变回46009了。