不同运营商都定义了不同的APN,但我们使用手机时,一般是不需要手动进行APN相关设置的,这是因为手机厂商已经在手机中预置了运营商的APN配置,而手机就会根据SIM卡中的mccmnc来自动选择合适的APN。Apn的主要类型有default、ims、xcap、mms等。每条apn都定义了不同的属性: mccmnc\numeric\carrier\apn\type等,在代码中使用这些属性来区分不同的apn。
carrier: 运营商名称, 显示在APN列表上的名称
mcc: 用于识别用户所在国家
mnc: 用于识别国家的运营商
apn: access point name(接入点名称), 由运营商给出
type: apn类型, 一般有default, dun, supl, mms, ims, xcap, hos
protocol: 注网时使用的协议, 一般是IPV4V6, IP, IPV6, 默认是IP
roaming_protocol: 漫游时注网时的协议, 类型同protocol
mmsc: mms专用, mms的服务器
mmsproxy: mms专用, mms的代理服务器
mmsport: mms专用, mms的端口
user: 用户名
password: 密码
authtype: 认证协议, 0: None, 1: PAP, 2: CHAP, 3: PAP or CHAP
mvno_type: 虚拟运营商类型, 一般为: imsi, spn, gid, pnn(这种类型还没见过), 用于识别是不是mvno
mvno_match_data: 虚拟运营商的值, 一般由运营商给出, 根据mvno_type设置
user_visible: 是否显示在ApnSettings UI当中, 0或者false为不显示, 1或者true为显示, 默认是显示
user_editable: 是否在ApnEditor UI中可编辑, 0或者false为不可编辑, 1或者true为可编辑, 默认是可编辑
apn的bearer_bitmask:
network_type_bitmask="1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19”
1~17表示该apn可以支持mobile下连接,也就是支持VoLTE
而"18"表示该apn可以支持wifi下连接,也就是支持Vowifi
19是预留位置,将来可能会用来支持某项功能
APN的加载
在手机开机时,TelephonyProvider.java(packages/providers/TelephonyProvider/)的createCarriersTable()方法首先在telephony.db数据库中创建carriers表,然后通过initDatabase()方法将apns-conf.xml文件中的全部apn信息加载到新创建的数据库telephony.db的carriers表中。ApnSettings(packages/apps/settings/)主要是Apn的UI界面显示,涉及到ApnSettings.java和ApnEditor.java两个文件, 分别用于APN显示和APN编辑。在手机上查看apn时,ApnSettings.java的filllist()方法会从数据库中筛选出当前运营商的apn显示到界面上。在编辑apn时,主要通过ApnEditor.java的validateAndSaveApnData()方法来更新数据库。
TelephonyProvider.java
TelephonyProvider.java
private static class DatabaseHelper extends SQLiteOpenHelper {
......
public void onCreate(SQLiteDatabase db) {
if (DBG) log("dbh.onCreate:+ db=" + db);
createSimInfoTable(db);
createCarriersTable(db, CARRIERS_TABLE); // 在数据库telephony.db中建立表carriers
initDatabase(db); // 加载数据到表carriers
if (DBG) log("dbh.onCreate:- db=" + db);
}
...
}
需要特别注意的是,在TelephonyProvider.java中query()方法查找对应运营商的apn时,首先匹配mcc/mnc/mvno;如果找不到,再匹配mccmnc;如果上述两个条件都匹配失败,那么按照carrierId匹配。实际运营商通常可以匹配上第二个条件,虚拟运营商匹配第一个条件。以此区分实际和虚拟运营商的sim卡的apn。
private Cursor getSubscriptionMatchingAPNList(SQLiteQueryBuilder qb, String[] projectionIn,
String selection, String[] selectionArgs, String sort, int subId) {
……………
// For query db one time, append all conditions in one selection and separate results after
// the query is completed. IMSI has special match rule, so just query the MCC / MNC and
// filter the MVNO by ourselves
………
if (DBG) log("match current APN size: " + ret.getCount());
// Separate the result into MatrixCursor
while (ret.moveToNext()) {
………
if (isMVNOAPN) {
// 1. The APN that query based on legacy SIM MCC/MCC and MVNO
currentCursor.addRow(data);
} else if (isMNOAPN) {
// 2. The APN that query based on SIM MCC/MNC
parentCursor.addRow(data);
} else if (isCarrierIdAPN) {
// The APN that query based on carrier Id (not include the MVNO or MNO APN)
carrierIdCursor.addRow(data);
}
}
……….
}
APN文件的修改和替换
apns-conf.xml文件路径:
MTK:device/mediate/config/apns-conf.xml,在修改apns-conf.xml文件时,需要同时修改版本号,且该文件中的版本号要与apns.xml(frameworks/base/core/res/res/xml/apns.xml)文件中的版本号保持一致,否则会导致无法识卡驻网。
Unisoc: vendor/sprd/telephony-res/apn/apns-conf_8_v2.xml,修改此文件时无需修改版本号,只需要修改内容即可。
QCOM: vendor/qcom/proprietary/commonsys/telephony-apps/etc/apns-conf.xml,无需修改版本号,一般不配置bearer_bitmask。
数据库的存储路径:data/user_de/0/com.android.providers.telephony/databases/telephony.db
apn数据存储在telephony.db的carriers表中:
替换apn-conf.xml(只能使用USRD版本且需要解锁)方法:
Unisoc:
<1> adb root
<2> adb remount
<3> adb push apns-conf.xml /product/etc/ 需要解锁
<4> adb reboot
<5> 重新插拔卡,若还是不生效,重置为默认设置
QCOM/MTK:
替换方法与unisoc相同只是apns-conf.xml文件的路径不同:/system/etc/