APN设置 --- 之二

2.2 setInitialAttachApn

setInitialAttachApn方法调用流程图如下,

APN设置 --- 之二_第1张图片

DcTrackerBase的setInitialAttachApn方法如下,

setInitialAttachApn(mAllApnSettings, mPreferredApn);

一般第一次开机时, mPreferredApn为null。

mAllApnSettings为当前SIM卡的对应的APN。

setInitialAttachApn方法主要逻辑如下,

1,为三个APN变量赋值,

ApnSetting iaApnSetting = null; //可用APN中类型包含APN_TYPE_IA(ia)的APN
ApnSetting defaultApnSetting = null;  //可用APN中包含default类型的APN
ApnSetting firstApnSetting = null;  //可用APN的第一个APN
•••
firstApnSetting = apnList.get(0);
for (ApnSetting apn : apnList) {
    // Can't use apn.canHandleType(), as that returns true for APNs that have no type.
   if (ArrayUtils.contains(apn.types, PhoneConstants.APN_TYPE_IA) &&
 apn.carrierEnabled) {
        // The Initial Attach APN is highest priority so use it if there is one
        log("setInitialApn: iaApnSetting=" + apn);
        iaApnSetting = apn;  //为iaApnSetting 变量赋值
        break;
    } else if ((defaultApnSetting == null)
 && (apn.canHandleType(PhoneConstants.APN_TYPE_DEFAULT))) {
         // Use the first default apn if no better choice
         log("setInitialApn: defaultApnSetting=" + apn);
         defaultApnSetting = apn; //为defaultApnSetting变量赋值
    }
}

2,从4个ApnSetting 对象中选择一个进行发起拨号上网请求,优先级依次为iaApnSetting, preferredApn, defaultApnSetting, firstApnSetting,

ApnSetting initialAttachApnSetting = null;
if (iaApnSetting != null) {
    if (DBG) log("setInitialAttachApn: using iaApnSetting");
    initialAttachApnSetting = iaApnSetting;
} else if (preferredApn != null) {
    if (DBG) log("setInitialAttachApn: using preferredApn");
    initialAttachApnSetting = preferredApn;
•••

3,如果这4个值都为空,就不发起拨号请求;否则调用RIL的setInitialAttachApn方法发起拨号请求,

if (initialAttachApnSetting == null) {
    if (DBG) log("setInitialAttachApn: X There in no available apn");
} else {
    if (DBG) log("setInitialAttachApn: X selected Apn=" + initialAttachApnSetting);
mPhone.mCi.setInitialAttachApn(initialAttachApnSetting.apn,
       initialAttachApnSetting.protocol, initialAttachApnSetting.authType,
       initialAttachApnSetting.user, initialAttachApnSetting.password, null);
}

例如,以下是一份开机拨号上网的log,


在这份log中, defaultApnSetting, firstApnSetting的ApnSetting对象完全相同,因此还是选择的defaultApnSetting对象的信息进行attach请求。

RIL的setInitialAttachApn方法如下,

RILRequest rr = RILRequest.obtain(RIL_REQUEST_SET_INITIAL_ATTACH_APN, result);
•••
rr.mParcel.writeString(apn);
rr.mParcel.writeString(protocol);
rr.mParcel.writeInt(authType);
rr.mParcel.writeString(username);
rr.mParcel.writeString(password);
•••
send(rr);

通过socket给rild守护进程发送RIL_REQUEST_SET_INITIAL_ATTACH_APN消息。

到此,虽然还暂时没有设置mPreferredApn,但是已经向rild守护进程发送attach请求了。

2.3 setupDataOnConnectableApns

当SIM卡加载完成,并完成上面2个步骤之后,就会调用DcTracker 的setupDataOnConnectableApns方法。

setupDataOnConnectableApns方法调用流程图如下,

APN设置 --- 之二_第2张图片

setupDataOnConnectableApns逻辑如下,

1,逐个循环调用mPrioritySortedApnContexts变量中的ApnContext对象,调用buildWaitingApns方法获取对应的ApnSetting对象,

for (ApnContext apnContext : mPrioritySortedApnContexts) {
ArrayList waitingApns = null;
••••
 waitingApns = buildWaitingApns(apnContext.getApnType(), radioTech);

2,如果该APN已激活,则调用trySetupData方法发起拨号

if (apnContext.isConnectable()) {
   log("setupDataOnConnectableApns: isConnectable() call trySetupData");
   apnContext.setReason(reason);
   trySetupData(apnContext, waitingApns);
}

setupData最后的逻辑如下,

Message msg = obtainMessage();
msg.what = DctConstants.EVENT_DATA_SETUP_COMPLETE;
msg.obj = new Pair(apnContext, generation);
dcac.bringUp(apnContext, getInitialMaxRetry(), profileId, radioTech,
     mAutoAttachOnCreation.get(), msg, generation);

封装EVENT_DATA_SETUP_COMPLETE 消息,然后调用DcAsyncChannel的bringUp方法发起拨号过程。

如果完成拨号过程,就会回调DcTracker的父类DcTrackerBase的handleMessage方法

处理EVENT_DATA_SETUP_COMPLETE 消息,对该消息处理如下,

case DctConstants.EVENT_DATA_SETUP_COMPLETE:
    onDataSetupComplete((AsyncResult) msg.obj);
    break;

调用DcTracker的onDataSetupComplete方法,该方法会将调用setPreferredApn方法将当前已拨号上网的APN写入telephony.db数据库的siminfo表中。

因此,经过这一步骤,终于将siminfo表填写完整了。

详细的拨号上网过程在数据业务那一章节论述,至于 ApnContext是什么,怎么和ApnSetting对象映射的,后面再论述。

你可能感兴趣的:(---【数据业务】)