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表中
至此告一段落。