DcTracker中关于插卡后apn的流程

  • Post author:
  • Post category:其他


DcTracker流程

1:oncreate()

1-1:mUiccController = UiccController.getInstance();

mUiccController.registerForIccChanged(this, DctConstants.EVENT_ICC_CHANGED, null);//监听SIM卡的变化,如果变化会发送EVENT_ICC_CHANGED消息,就跳转到handleMessage())

2:handleMessage()

    case DctConstants.EVENT_ICC_CHANGED: {
        onUpdateIcc();
        break;
    }          //调用onUpdateIcc()

3:oncreate中注册telephony.db数据库

    mApnObserver = new ApnChangeObserver();
    p.getContext().getContentResolver().registerContentObserver(
       Telephony.Carriers.CONTENT_URI, true, mApnObserver);

4:ApnChangeObserver是DcTracker的内部类,

 private class ApnChangeObserver extends ContentObserver {
     public ApnChangeObserver () {
          super(mDataConnectionTracker);
     }
 @Override
 public void onChange(boolean selfChange) {
     sendMessage(obtainMessage(DctConstants.EVENT_APN_CHANGED));
 }
 }

5:DcTracker继承Handler,因此一旦telephony.db数据库发生变化,就会调用ApnChangeObserver的onChage()方法,

然后调用handleMessage中的case EVENT_APN_CHANGED。

case DctConstants.EVENT_APN_CHANGED:
    onApnChanged();
    break;

6:onApnChanged()

### 6-1:createAllApnList();  //创建当前SIM卡的APN,

6_1_1:在数据库telephony.db数据库的carriers表单中查询当前SIM卡对应的APN信息

并调用createApnList()方法构造ApnSetting对象。一般一个APN对应一个ApnSetting对象,这样就完成了数据库中APN到ApnSetting对象的映射。

Cursor cursor = mPhone.getContext().getContentResolver().query(
                    Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "filtered"),
                    null, selection, null, Telephony.Carriers._ID);
​
            if (cursor != null) {
                if (cursor.getCount() > 0) {
                    mAllApnSettings = createApnList(cursor);
                }
                cursor.close();
            }

6_1_2:添加emergencyApnSettings并删除重复的APN

    addEmergencyApnSetting();
    dedupeApnSettings();

6_1_3:设置默认APN,getPreferredApn()从数据库的siminfo表中独读出默认的APN,如果该APN与当前卡的APN不匹配,则调用setPreferredApn()删除数据库中的siminfo表中APN信息

mPreferredApn = getPreferredApn(mAllApnSettings);
if (mPreferredApn != null && !mPreferredApn.numeric.equals(operator)) {
     mPreferredApn = null;
     setPreferredApn(-1);//又优选apn就选择,如果没,就设置为-1
}

setPreferredApn()方法详细

private void setPreferredApn(int pos) {
        if (!mCanSetPreferApn) {
            log("setPreferredApn: X !canSEtPreferApn");
            return;
        }
​
        String subId = Long.toString(mPhone.getSubId());
        Uri uri = Uri.withAppendedPath(PREFERAPN_NO_UPDATE_URI_USING_SUBID, subId);
        log("setPreferredApn: delete");
        ContentResolver resolver = mPhone.getContext().getContentResolver();
        resolver.delete(uri, null, null);//删除数据库中的sim表中APN信息
​
        if (pos >= 0) { //因为pos==-1,所以不执行insert方法
            log("setPreferredApn: insert");
            ContentValues values = new ContentValues();
            values.put(APN_ID, pos);
            resolver.insert(uri, values);//插入默认的APN信息,(不执行)
        }
    }

createApnList()详细,

        if (cursor.moveToFirst()) {
            do {
                ApnSetting apn = makeApnSetting(cursor);
                if (apn == null) {
                    continue;
                }
​
                if (apn.hasMvnoParams()) {
                    if (r != null && ApnSetting.mvnoMatches(r, apn.mvnoType, apn.mvnoMatchData)) {
                        mvnoApns.add(apn);//虚拟运营商
                    }
                } else {
                    mnoApns.add(apn);//运营商
/* Add Panasonic_EXTEND [070-009-002] 2018.8.23 Start */
                    if ((mIsInTethering == 1) && mIsDunApn){
                        log("createApnList: mnoApns.add(0,apn)");
                        mnoApns.add(0,apn);
                    } else {
                        mnoApns.add(apn);
                    }
/* Add Panasonic_EXTEND [070-009-002] 2018.8.23 End */
                }
            } while (cursor.moveToNext());
        }

### 6-2:setInitialAttachApn();  //设置初始apn,会通过RIL下发RIL_REQUEST_SET_INITIAL_ATTACH_APN命令。
setInitialAttachApn(mAllApnSettings, mPreferredApn);

一般第一次开机时,mPreferredApn为null。mAllApnSettings为当前SIM卡的对应APN,主要逻辑如下

1,为三个变量赋值

        ApnSetting iaApnSetting = null;//可用APN类型包含APN_TYPE_IA(ia)的APN
        ApnSetting defaultApnSetting = null;//可用APN中包含default类型的APN
        ApnSetting firstApnSetting = null;//可用APN第一个APN
        .......
            firstApnSetting = mAllApnSettings.get(0);
            log("setInitialApn: firstApnSetting=" + firstApnSetting);
​
            // Search for Initial APN setting and the first apn that can handle default
            for (ApnSetting apn : mAllApnSettings) {
                if (apn.canHandleType(PhoneConstants.APN_TYPE_IA)) {
                    // 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赋值
                }
            }

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

ApnSetting initialAttachApnSetting = null;
        if (iaApnSetting != null) {
            if (DBG) log("setInitialAttachApn: using iaApnSetting");
            initialAttachApnSetting = iaApnSetting;
        } else if (mPreferredApn != null) {
            if (DBG) log("setInitialAttachApn: using mPreferredApn");
            initialAttachApnSetting = mPreferredApn;
        } else if (defaultApnSetting != null) {
            if (DBG) log("setInitialAttachApn: using defaultApnSetting");
            initialAttachApnSetting = defaultApnSetting;
        } else if (firstApnSetting != null) {
            if (DBG) log("setInitialAttachApn: using firstApnSetting");
            initialAttachApnSetting = firstApnSetting;
        }

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);

通过RIL下发RIL_REQUEST_SET_INITIAL_ATTACH_APN命令

### 6-3:cleanUpConnectionsOnUpdatedApns();  //断开当前的数据连接
### 6-4:setupDataOnConnectableApns();   //发起拨号请求

等连接好了,就会调用trySetupData (这里是porting的地方之一)

if (apnContext.isConnectable()) {
            log("isConnectable() call trySetupData");
            apnContext.setReason(reason);
            trySetupData(apnContext);
        }

7 trySetupData()

7-1:buildWaitingApns() //porting修改的地方之一

buildWaitingApns方法对apn列表进行进一步过滤

8 onDataSetupComplete()

if (mPreferredApn != null) {
   setPreferredApn(mPreferredApn.id);
}   //该方法讲目前已经拨号上网的APN写入telephony.db数据库的siminfo表中

至此告一段落。

参考:

https://www.jianshu.com/p/f720b6f152ea


https://blog.csdn.net/u012439416/article/details/78940935



版权声明:本文为sinat_38430122原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。