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是否 ...
随机推荐
- 理解ZBrush中的笔触
笔触主要配合笔刷来使用,同样的笔刷搭配不同的笔触可以绘制出各种不同的效果.简言之,ZBrush 4R8就是提供了各种各样的笔触效果,例如,有模拟连贯笔触的效果,也有模拟喷枪喷洒的笔触效果. 下面简单认 ...
- 转义JavaScript特殊字符
JavaScriptUtils.javaScriptEscape("%admin' or '1=1") //转义JavaScript特殊字符
- [转载]vim常用命令总结
内容出处https://www.jianshu.com/p/a8ab13cff1ea 如有侵权请告知 移动.跳转 h.j.k.l:分别对应左.下.上.右.按键盘分布,从左到右,逆时针. w:移动到下一 ...
- linux下mysqldump简单命令导出数据库和表
进入mysql的bin目录执行: 导出单个表: mysqldump -uroot -ppassword --database dbname --tables users > /home/root ...
- jquery 遍历 table 下所有得tr td
$("#middle").contents().find("tbody tr").each(function(i,n){ var child = $(this) ...
- NYIST 1108 最低的惩罚
最低的惩罚 时间限制:3000 ms | 内存限制:65535 KB 难度:3 描述 那么现在问题就来了... 给你N(1=<N<=15)个任务,每个任务有一个截止完成时间t(1= ...
- securefx连接linux后文件夹中文乱码问题解决
首先在选项中设置字符编码为UTF-8 然后在全局选项中找到Securefx的配置文件 进入到该目录中,选择“Sessions”: 在“Sessions”中找到链接地址的ini文件,并用文本编辑器打开: ...
- 清华EMBA课程系列思考之六 -- 比較文明视野下的中华领导智慧、企业管理与经济解析
告别马年的最后一缕阳光,踏着猴年的钟声,度过了温馨的春节,已然开启了新学期的第一堂课.看题目其貌不扬,但一旦进入课堂,已然聚精会神.唯恐掉队,就请大家跟我一起进入四天的心路修炼旅程,開始我们的新一期思 ...
- java9新特性-6-多版本兼容jar包
1.官方Feature 238: Multi-Release JAR Files 2.使用说明 当一个新版本的Java出现的时候,你的库用户要花费数年时间才会切换到这个新的版本.这就意味着库得去向后兼 ...
- Asp.Net 中使用 水晶报表(上)
Asp.Net中使用水晶报表(上) 在我们对VS.Net中的水晶报表(Crystal Reports)进行研究之前,我和我朋友对如何将这个复杂的东东加入我们的Web应用有着非常的好奇心.一周以后,在阅 ...