Android——4.2 - 3G移植之路之 APN (五)
APN,这东西对于刚接触的人来说并非那么好理解。对于3G移植上网不可缺少,这里记录一下。
撰写不易,转载请注明出处:http://blog.csdn.net/jscese/article/details/41248939
概念:
APN(Access Point Name),也就是 接入点 ,移动设备使用数据流量上网必须配置的一个參数,代表以何种方式来连接服务台开启数据流量功能.
一般有訪问WAP或者connect 因特网,国内的运营商2G,3G标识例如以下:
移动公司:2G:GSM、3G:TD-SCDMA
联通公司:2G:GSM、3G:WCDMA
电信公司:2G:CDMA、3G:CDMA2000
关于详细某个运营商的几G网络 的APN 是什么详细可參考/device/sample/etc/apns-full-conf.xml
这个xml文件里有google预置的多国经常使用的APN
使用:
apns-full-conf.xml
上面说道了apns-full-conf.xml 这个配置文件,这里面基本上是这种模块:
<apn carrier="沃3G连接互联网 (China Unicom)"
mcc="460"
mnc="01"
apn="3gnet"
type="default,supl"
/>
其他选项都是网络參数,当中的apn就是我们最重要的接入点.也可自行加入apn属性模块.
移植3G时,就须要用到这个xml配置文件了。在android的device.mk 里面加个PRODUCT_COPY_FILES:
PRODUCT_COPY_FILES += \ device/sample/etc/apns-full-conf.xml:system/etc/apns-conf.xml
telephony.db
这个文件被载入的地方可參考/packages/providers/TelephonyProvider/src/com/android/providers/telephony/TelephonyProvider.java:
private static final String DATABASE_NAME = "telephony.db"; //数据库db文件 private static final String PARTNER_APNS_PATH = "etc/apns-conf.xml"; //上面说到的copy到系统system/etc文件夹下 ... private static class DatabaseHelper extends SQLiteOpenHelper {
// Context to access resources with
private Context mContext; /**
* DatabaseHelper helper class for loading apns into a database.
*
* @param context of the user.
*/
public DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, getVersion(context));
mContext = context;
} ...
@Override
public void onCreate(SQLiteDatabase db) {
// Set up the database schema
db.execSQL("CREATE TABLE " + CARRIERS_TABLE + //建表
"(_id INTEGER PRIMARY KEY," +
"name TEXT," +
"numeric TEXT," +
"mcc TEXT," +
"mnc TEXT," +
"apn TEXT," +
"user TEXT," +
"server TEXT," +
"password TEXT," +
"proxy TEXT," +
"port TEXT," +
"mmsproxy TEXT," +
"mmsport TEXT," +
"mmsc TEXT," +
"authtype INTEGER," +
"type TEXT," +
"current INTEGER," +
"protocol TEXT," +
"roaming_protocol TEXT," +
"carrier_enabled BOOLEAN," +
"bearer INTEGER);"); initDatabase(db);
}
private void initDatabase(SQLiteDatabase db) { ... // Environment.getRootDirectory() is a fancy way of saying ANDROID_ROOT or "/system".
File confFile = new File(Environment.getRootDirectory(), PARTNER_APNS_PATH); //这里就是载入解析 load进db 了
FileReader confreader = null;
try {
confreader = new FileReader(confFile);
confparser = Xml.newPullParser();
confparser.setInput(confreader);
XmlUtils.beginDocument(confparser, "apns"); // Sanity check. Force internal version and confidential versions to agree
int confversion = Integer.parseInt(confparser.getAttributeValue(null, "version"));
if (publicversion != confversion) {
throw new IllegalStateException("Internal APNS file version doesn't match "
+ confFile.getAbsolutePath());
} loadApns(db, confparser);
} ... } }
由于Content Provider採用的是懒载入机制,所以仅仅有检測load上sim卡的时候才会被创建这个db:
可使用sqlite3查看:
createAllApnList
在android中数据流量由/frameworks/opt/telephony/src/java/com/android/internal/telephony/DataConnectionTracker.java
以及它的子类GsmDataConnectionTracker.java(GSM模式) 或者 CdmaDataConnectionTracker.java(CDMA模式),(前者为移动,联通,后者为电信专用)
来控制,当中启动数据流量开关为onSetUserDataEnabled(boolean enabled).
这里单以GSM模式来说,在SIM 被load时调用:
private void onRecordsLoaded() {
if (DBG) log("onRecordsLoaded: createAllApnList");
createAllApnList();
if(!mUserDataEnabled)
return;//jscese add judgement
if (mPhone.mCM.getRadioState().isOn()) {
if (DBG) log("onRecordsLoaded: notifying data availability");
notifyOffApnsOfAvailability(Phone.REASON_SIM_LOADED);
}
setupDataOnReadyApns(Phone.REASON_SIM_LOADED);
}
调用进createAllApnList
/**
* Based on the sim operator numeric, create a list for all possible
* Data Connections and setup the preferredApn.
*/
private void createAllApnList() {
mAllApns = new ArrayList<ApnSetting>();
IccRecords r = mIccRecords.get();
String operator = (r != null) ? r.getOperatorNumeric() : "";
if (operator != null) {
String selection = "numeric = '" + operator + "'";
// query only enabled apn.
// carrier_enabled : 1 means enabled apn, 0 disabled apn.
selection += " and carrier_enabled = 1";
if (DBG) log("createAllApnList: selection=" + selection); Cursor cursor = mPhone.getContext().getContentResolver().query( //用当前SIM卡相应的运营商查询系统的全部APN。往下调用createApnList
Telephony.Carriers.CONTENT_URI, null, selection, null, null); if (cursor != null) {
if (cursor.getCount() > 0) {
mAllApns = createApnList(cursor); //能够跟进去看查询Telephony.Carriers并返回一个Apn的list
}
cursor.close();
}
} if (mAllApns.isEmpty()) {
if (DBG) log("createAllApnList: No APN found for carrier: " + operator);
mPreferredApn = null;
// TODO: What is the right behaviour? //notifyNoData(GsmDataConnection.FailCause.MISSING_UNKNOWN_APN);
} else {
mPreferredApn = getPreferredApn();
if (mPreferredApn != null && !mPreferredApn.numeric.equals(operator)) {
mPreferredApn = null;
setPreferredApn(-1);
}
if (DBG) log("createAllApnList: mPreferredApn=" + mPreferredApn);
}
if (DBG) log("createAllApnList: X mAllApns=" + mAllApns);
}
onSetUserDataEnabled(true):
代表打开数据流量。终于调用到
private boolean trySetupData(ApnContext apnContext) { ... if (apnContext.getState() == DctConstants.State.IDLE) {
ArrayList<ApnSetting> waitingApns = buildWaitingApns(apnContext.getApnType()); //使用用户设置的preferred APN构建一个可用于数据连接的备选APN列表,即waitingApns列表(当有preferred APN,该列表就仅仅有一个)。 //若用户没有设置preferred APN,则将全部类型匹配的APN加入到waitingApns列表(如default类型) if (waitingApns.isEmpty()) {
if (DBG) log("trySetupData: No APN found");
notifyNoData(GsmDataConnection.FailCause.MISSING_UNKNOWN_APN, apnContext);
notifyOffApnsOfAvailability(apnContext.getReason());
return false;
} else {
apnContext.setWaitingApns(waitingApns);
if (DBG) {
log ("trySetupData: Create from mAllApns : " + apnListToString(mAllApns));
}
}
} if (DBG) {
log ("Setup watingApns : " + apnListToString(apnContext.getWaitingApns()));
}
// apnContext.setReason(apnContext.getReason());
boolean retValue = setupData(apnContext); // waitingApns列表中有可用的APN时,尝试建立连接
notifyOffApnsOfAvailability(apnContext.getReason());
return retValue; ... }
另外几个对apn操作的几个函数都在这个文件中面。分别的作用例如以下:
onApnChanged:当APN被用户更改时,将调用到此函数,又一次建立数据连接
setPreferredApn:当用户没有设置preferred APN时,将当前数据连接成功的那个APN设置为preferred APN。
能够去看onDataSetupComplete时的操作。
getPreferredApn:用户获取用户设置的preferred APN,这个在上面说到的createAllApnList时会去获取一次。看是否存在.
对于这个preferredApn会以xml的形式保存在:
shell@android:/data/data/com.android.providers.telephony/shared_prefs # cat preferred-apn.xml
ml <
<? xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
<long name="apn_id" value="1124" />
</map>
这是代表打开数据流量成功之后保存的apn map。能够像上面一样去 telephony.db里面查查看看:
sqlite> select * from carriers where _id='1124';
1124|沃3G连接互联网 (China Unicom)|46001|460|01|3gnet|||||||||-1|default,supl|1|IP|IP|1|0
这里仅仅是分析了一下apn的由来以及在framework层的使用,终于是通过RIL.java 的setupDataCall通过一个rild 的socket发请求到hardware的ril.cpp:
public void
setupDataCall(String radioTechnology, String profile, String apn, /*上面传下来的apn*/
String user, String password, String authType, String protocol,
Message result) {
RILRequest rr
= RILRequest.obtain(RIL_REQUEST_SETUP_DATA_CALL, result); rr.mp.writeInt(7); rr.mp.writeString(radioTechnology);
rr.mp.writeString(profile);
rr.mp.writeString(apn);
rr.mp.writeString(user);
rr.mp.writeString(password);
rr.mp.writeString(authType);
rr.mp.writeString(protocol); if (RILJ_LOGD) riljLog(rr.serialString() + "> "
+ requestToString(rr.mRequest) + " " + radioTechnology + " "
+ profile + " " + apn + " " + user + " "
+ password + " " + authType + " " + protocol); send(rr); //里面就是 socket了
}
再之后怎么获取到这个socket event处理而且交给reference-ril 发送这个apn接入网路可參考我前面的博客:
Android——4.2 - 3G移植之路之 APN (五)的更多相关文章
- Android——4.2 - 3G移植之路之 AT 通信 (四)
在前文Android--4.2 - 3G移植之路之 reference-ril .pppd 拨号上网 (三)中分析了3G连接网络的流程,当中有说道通过AT指令建立连接, 在这里记录一下3G中的AT通信 ...
- Android——4.2 - 3G移植之路之 reference-ril .pppd 拨号上网 (三)
Android的RIL机制中的 reference-ril.c 即为厂商提供的驱动接口.这个驱动源代码各个厂商都是有提供的,网上也有下载.我如今用的就是huawei wcdma的.最后编译成libre ...
- 基于MT6752/32平台 Android L版本驱动移植步骤
基于MT6752/32平台 Android L版本驱动移植步骤 根据MK官网所述,在Android L 版本上Turnkey ABS 架构将会phase out,而Mediatek Turnkey架构 ...
- Android Vector曲折的兼容之路
Android Vector曲折的兼容之路 两年前写书的时候,就在研究Android L提出的Vector,可研究下来发现,完全不具备兼容性,相信这也是它没有被广泛使用的一个原因,经过Google的不 ...
- Android wifi驱动的移植 realtek 8188
Android wifi驱动的移植 一般我们拿到的android源代码中wifi应用层部分是好的, 主要是wifi芯片的驱动要移植并添加进去. wifi驱动的移植, 以realtek的8188etv为 ...
- Android程序员的进阶之路
本文主要论述的是Android程序员的进阶之路,博主本人就是一名android开发攻城狮,所以这里讲述的大多数是android开发攻城狮的技术进阶之路,如有问题请多指正. 大家都知道程序员之中有有菜鸟 ...
- Android安卓书籍推荐《Android驱动开发与移植实战详解》下载
百度云下载地址:点我 Android凭借其开源性.优异的用户体验和极为方便的开发方式,赢得了广大用户和开发者的青睐,目前已经发展成为市场占有率很高的智能手机操作系统. <Android驱动开发与 ...
- Python之路【第五篇】:面向对象及相关
Python之路[第五篇]:面向对象及相关 面向对象基础 基础内容介绍详见一下两篇博文: 面向对象初级篇 面向对象进阶篇 其他相关 一.isinstance(obj, cls) 检查是否obj是否 ...
- Python之路【第五篇】:面向对象和相关
Python之路[第五篇]:面向对象及相关 面向对象基础 基础内容介绍详见一下两篇博文: 面向对象初级篇 面向对象进阶篇 其他相关 一.isinstance(obj, cls) 检查是否obj是否 ...
随机推荐
- 3Ds Max制作克劳族少女教程
作者:Andrius Balciunas 使用软件:3ds Max, ZBrush 3ds Max下载:http://www.xy3dsmax.com/xiazai.html ZBrush下载:htt ...
- NOI2018 你的名字 后缀自动机_线段树合并_可持久化
相当复杂的一道题,同样也相当优美.考察的知识点很多:权值线段树的可持久化合并,后缀自动机,后缀树... 考虑 $68pts$ $l=1,r=|s|$的数据:这部分相对好做一些,不过思维难度对我来说已 ...
- linux下mysql 查看默认端口号与修改端口号方法
一.查看默认端口号 1.登录mysql [root@localhost ~]# mysql -uroot -pEnter password: 输入数据库密码: 2.使用show global vari ...
- 51nod 1526 分配笔名(Trie树+贪心)
建出Trie树然后求出一个点子树中有多少笔名和真名.然后贪心匹配即可. #include<iostream> #include<cstring> #include<cst ...
- BZOJ 4896 [Thusc2016]补退选 (Trie树维护vector)
题目大意:略 这竟然是$thusc$的题... 先把询问里加入的串全拎出来,建出$Trie$树,$Trie$里每个节点都开一个$vector$记录操作标号,再记录操作数量$sum$ 然后瞎**搞搞就行 ...
- 紫书 习题 11-17 UVa 1670 (图论构造)
一开始要符合题目条件, 那么肯定没有任何一个点是孤立的, 也就是说没有点的度数是1 所以我就想让度数是1的叶子节点相互连起来.然后WA 然后看这哥们的博客 https://blog.csdn.net/ ...
- POJ 1161 Walls(最短路+枚举)
POJ 1161 Walls(最短路+枚举) 题目背景 题目大意:题意是说有 n个小镇,他们两两之间可能存在一些墙(不是每两个都有),把整个二维平面分成多个区域,当然这些区域都是一些封闭的多边形(除了 ...
- JAVA SSL
http://docs.oracle.com/javase/1.5.0/docs/guide/security/jsse/JSSERefGuide.html#InstallationAndCustom ...
- Web长连接推送
http://www.workerman.net/web-sender http://wahahachuang5.iteye.com/blog/2311313
- 在VS2013中配置QT5 win7_64
转自 在VS2013中配置QT5 win7_64 环境: win x64 + vs2013+QT5+vs_addin 下面示例正确配置QT以及VS2013 + QT Addin开发环境: 下载VS20 ...