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——RIL 机制源代码分析

Android——4.2 - 3G移植之路之 reference-ril .pppd 拨号上网 (三)

Android——4.2 - 3G移植之路之 APN (五)的更多相关文章

  1. Android——4.2 - 3G移植之路之 AT 通信 (四)

    在前文Android--4.2 - 3G移植之路之 reference-ril .pppd 拨号上网 (三)中分析了3G连接网络的流程,当中有说道通过AT指令建立连接, 在这里记录一下3G中的AT通信 ...

  2. Android——4.2 - 3G移植之路之 reference-ril .pppd 拨号上网 (三)

    Android的RIL机制中的 reference-ril.c 即为厂商提供的驱动接口.这个驱动源代码各个厂商都是有提供的,网上也有下载.我如今用的就是huawei wcdma的.最后编译成libre ...

  3. 基于MT6752/32平台 Android L版本驱动移植步骤

    基于MT6752/32平台 Android L版本驱动移植步骤 根据MK官网所述,在Android L 版本上Turnkey ABS 架构将会phase out,而Mediatek Turnkey架构 ...

  4. Android Vector曲折的兼容之路

    Android Vector曲折的兼容之路 两年前写书的时候,就在研究Android L提出的Vector,可研究下来发现,完全不具备兼容性,相信这也是它没有被广泛使用的一个原因,经过Google的不 ...

  5. Android wifi驱动的移植 realtek 8188

    Android wifi驱动的移植 一般我们拿到的android源代码中wifi应用层部分是好的, 主要是wifi芯片的驱动要移植并添加进去. wifi驱动的移植, 以realtek的8188etv为 ...

  6. Android程序员的进阶之路

    本文主要论述的是Android程序员的进阶之路,博主本人就是一名android开发攻城狮,所以这里讲述的大多数是android开发攻城狮的技术进阶之路,如有问题请多指正. 大家都知道程序员之中有有菜鸟 ...

  7. Android安卓书籍推荐《Android驱动开发与移植实战详解》下载

    百度云下载地址:点我 Android凭借其开源性.优异的用户体验和极为方便的开发方式,赢得了广大用户和开发者的青睐,目前已经发展成为市场占有率很高的智能手机操作系统. <Android驱动开发与 ...

  8. Python之路【第五篇】:面向对象及相关

    Python之路[第五篇]:面向对象及相关   面向对象基础 基础内容介绍详见一下两篇博文: 面向对象初级篇 面向对象进阶篇 其他相关 一.isinstance(obj, cls) 检查是否obj是否 ...

  9. Python之路【第五篇】:面向对象和相关

    Python之路[第五篇]:面向对象及相关   面向对象基础 基础内容介绍详见一下两篇博文: 面向对象初级篇 面向对象进阶篇 其他相关 一.isinstance(obj, cls) 检查是否obj是否 ...

随机推荐

  1. 模块-时间模块(new)

    模块-时间模块 导入: import time 方法: _STRUCT_TM_ITEMS __doc__ __loader__ __name__ __package__ __spec__ altzon ...

  2. 紫书 习题8-3 UVa 12545 (构造法)

    参考了https://blog.csdn.net/catglory/article/details/47188949 最后推出来操作的个数为问号的个数 加上 同一位置上S串为0而T串为1的位置数量 与 ...

  3. 11.Laravel5学习笔记:扩展 Validator 类

    简单介绍 在 Laravel5 中,本身已经提供了丰富的验证规则供我们使用,可是天下应用奇葩多,做为程序猿你会发现永远都有新的验证规则诞生,光是组合已经解救不了你的项目了.这个时候就须要我们扩展 Va ...

  4. XCL-Chart柱形图的期望线/分界线

    周日在柱形图上加了两个小功能,当中之中的一个是加上了期望线/分界线,功能非常小,但我个人非常喜欢这个功能(好像之前也没看到别的图表库原生支持这个. ) 主要是加上这些小小的横线后,能非常明显的区分出数 ...

  5. 6.5.2 C# 中的函数组合

    6.5.2 C# 中的函数组合 C# 中的函数组合是可能的.但使用非常有限,这是部分是由于在 C# 中散应用不能非常easy使用.但更重要的是,由于大多数操作是用成员来写的.而不是函数.但我们至少能够 ...

  6. 漫谈linux之文件IO篇(SSD写性能和机械硬盘差不多,读是4到10倍)

    前同事的文章,觉得写得很清晰,收藏了. http://blog.chinaunix.net/uid-27105712-id-3270102.html 在Linux 开发中,有几个关系到性能的东西,技术 ...

  7. 威胁报告:mDNS 反射式 DDoS 攻击

    威胁报告:mDNS 反射式 DDoS 攻击 转自:https://www.akamai.com/cn/zh/about/our-thinking/threat-advisories/akamai-md ...

  8. ELK搭建(filebeat、elasticsearch、logstash、kibana)

    ELK部署(文章有点儿长,搭建时请到官网将tar包下载好,按步骤可以完成搭建使用) ELK指的是ElasticSearch.LogStash.Kibana三个开源工具 LogStash是负责数据的收集 ...

  9. NOIP2017 小凯的疑惑 解题报告(赛瓦维斯特定理)

    题目描述 小凯手中有两种面值的金币,两种面值均为正整数且彼此互素.每种金币小凯都有 无数个.在不找零的情况下,仅凭这两种金币,有些物品他是无法准确支付的.现在小 凯想知道在无法准确支付的物品中,最贵的 ...

  10. 互不侵犯_状压$dp$

    如果有想学习状压\(dp\)的童鞋,请光临博客状压\(dp\)初学 互不侵犯 题目描述 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八 ...