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是否 ...
随机推荐
- Oralce 视图 view
Oracle视图 Oracle的数据库对象分为五种:表,视图,序列,索引和同义词. 视图是基于一个表或多个表或视图的逻辑表,本身不包含数据,通过它可以对表里面的数据进行查询和修改.视图基于的表称为基表 ...
- SCIP,Clp,Gurobi和Cplex安装
SCIP安装 1.在自己的家目录下建立目录scip,并将获得的压缩包考入该文件夹并解压缩 tar -zxvf scipoptsuite-5.0.0.tgz 2.进入目录scipoptsuite-5.0 ...
- 洛谷 P1026 统计单词个数 (分组+子串预处理)(分组型dp再次总结)
一看完这道题就知道是划分型dp 有两个点要注意 (1)怎么预处理子串. 表示以i为开头,结尾在j之前(含),有没有子串,有就1,没有就0 (2)dp的过程 这种分成k组最优的题目已经高度模板化了,我总 ...
- ADT+NDK搭建jni编译环境
jni是android调用C++编写的库的接口.C++和java的差别不在此文的讨论范畴,另外这里也仅仅是记录下.怎样搭建好开发环境. 首先是下载ADT包和NDK包. ADT包包括了eclipse.所 ...
- Android核心服务解析篇(三)——Android系统的启动
从大的方面来说.Android系统的启动能够分为两个部分:第一部分是Linux核心的启动,第二部分是Android系统的启动. 第一部分主要包含系统引导,核心和驱动程序等,因为它们不属于本篇要讲的内容 ...
- 解决The hierarchy of the type is inconsistent错误
可能的原因:自己的类继承于某个类,这个类或者这个类继承的类或者再往上继承的某个类所在的jar包没有被引入. 比如:使用Spring的AOP时,假设须要继承MethodBeforeAdvice和Afte ...
- Android OpenGL ES(七)----理解纹理与纹理过滤
1.理解纹理 OpenGL中的纹理能够用来表示图像.照片,甚至由一个数学算法生成的分形数据.每一个二维的纹理都由很多小的纹理元素组成.它们是小块的数据,类似于我们前面讨论过的片段和像素.要使用纹理,最 ...
- Linux硬链接和软链接的差别
1.硬链接文件和原文件指向相同的数据,两者就像克隆一样,inode号也相同,当删除原 文件时. 硬链接文件仍然存在有效. 但硬链接文件不同于文件的复制.应该说硬链接文件的产生仅仅是原文件所 在文件夹文 ...
- POJ 3667 线段树+标记
自从某次考试写线段树写挂了以后 这是第一次写线段树,,,,,, 这是一个伤心的故事-- 题意: 思路: 标记 维护从左到右的最大值 从右到左的最大值 区间内的最大值-- 然后就一搞 就出来了 //By ...
- 使用HANDLECOLLISIONS的几个场景
使用HANDLECOLLISIONS的几个场景: 1.target丢失delete记录(missing delete),忽略该问题并不记录到discardfile 2.target丢失update记录 ...