一、Android DcTracker的創建及準備工作

DcTracker是在每個Phone構造的時候創建的,DcTrackerBase是DcTracker,他們的核心都是Handler。

@GSMPhone.java  
public GSMPhone (Context context, CommandsInterface ci, PhoneNotifier notifier, boolean unitTestMode) {  
    //創建DcTracker對象,傳遞的參數就是當前的GSMPhone對象  
    mDcTracker = new DcTracker(this);  
}  

DcTracker作爲數據鏈接中最重要的一個管理者核心,數據鏈接都會從DcTracker中發起,其中會做一些列的狀態檢查與判斷,DcTracker處於的環節如下圖中的淺藍色部分
這裏寫圖片描述
首先看DcTracker的構造

public DcTracker(PhoneBase p) { 
    super(p);

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

    initApnContexts();

    for (ApnContext apnContext : mApnContexts.values()) {
        // Register the reconnect and restart actions.
        IntentFilter filter = new IntentFilter();
        filter.addAction(INTENT_RECONNECT_ALARM + '.' + apnContext.getApnType());
        filter.addAction(INTENT_RESTART_TRYSETUP_ALARM + '.' + apnContext.getApnType());
        mPhone.getContext().registerReceiver(mIntentReceiver, filter, null, mPhone);
    }

    // Add Emergency APN to APN setting list by default to support EPDN in sim absent cases
    initEmergencyApnSetting();
    addEmergencyApnSetting();

    mProvisionActionName = "com.android.internal.telephony.PROVISION" + p.getPhoneId();
}    

首先調用的是update(),這裏註冊了大量的監聽事件,並註冊了APN參數的監聽器

public void update() {  
     if (isActiveDataSubscription()) {  
         //註冊各種監聽器  
         registerForAllEvents(); 
         //註冊SIM卡狀態監聽器  
         onUpdateIcc();
         //mUserDataEnabled就是用戶是否打開網絡開關的標誌位,當爲0時,表示當前數據流量被關閉  
         mUserDataEnabled = Settings.Global.getInt(mPhone.getContext().getContentResolver(), Settings.Global.MOBILE_DATA, 1) == 1;  
     }
 }   

接下來繼續來看registerForAllEvents()和onUpdateIcc()中註冊的事件類型

protected void registerForAllEvents() {  
    //監聽射頻是否打開,沒有處理動作  
    mPhone.mCi.registerForAvailable(this, DctConstants.EVENT_RADIO_AVAILABLE, null);  
    //監聽射頻是否可用,沒有處理動作  
    mPhone.mCi.registerForOffOrNotAvailable(this, DctConstants.EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);  
    //監聽當前連接狀態,沒有處理動作  
    mPhone.mCi.registerForDataNetworkStateChanged(this, DctConstants.EVENT_DATA_STATE_CHANGED, null);  
    //監聽當前通話狀態,沒有處理動作  
    mPhone.getCallTracker().registerForVoiceCallEnded (this, DctConstants.EVENT_VOICE_CALL_ENDED, null);  
    //監聽當前通話狀態,沒有處理動作  
    mPhone.getCallTracker().registerForVoiceCallStarted (this, DctConstants.EVENT_VOICE_CALL_STARTED, null);  
    //監聽是否PS域Attach狀態  
    mPhone.getServiceStateTracker().registerForDataConnectionAttached(this, DctConstants.EVENT_DATA_CONNECTION_ATTACHED, null);  
    //監聽是否PS域Detach狀態  
    mPhone.getServiceStateTracker().registerForDataConnectionDetached(this, DctConstants.EVENT_DATA_CONNECTION_DETACHED, null);  
    //監聽漫遊狀態,沒有處理動作  
    mPhone.getServiceStateTracker().registerForRoamingOn(this, DctConstants.EVENT_ROAMING_ON, null);  
    //監聽漫遊狀態,沒有處理動作  
    mPhone.getServiceStateTracker().registerForRoamingOff(this, DctConstants.EVENT_ROAMING_OFF, null);  
    mPhone.getServiceStateTracker().registerForPsRestrictedEnabled(this, DctConstants.EVENT_PS_RESTRICT_ENABLED, null);  
    mPhone.getServiceStateTracker().registerForPsRestrictedDisabled(this, DctConstants.EVENT_PS_RESTRICT_DISABLED, null);  
    //監聽接入技術狀態  
    mPhone.getServiceStateTracker().registerForDataRegStateOrRatChanged(this, DctConstants.EVENT_DATA_RAT_CHANGED, null);  
}  

registerForAllEvents()註冊了大量的事件,但是其中最重要的事件是EVENT_DATA_CONNECTION_ATTACHED
—-監聽PS的Attach事件(代碼中看出來應該是DataRegState的狀態由STATE_OUT_OF_SERVICE -> STATE_IN_SERVICE),觸發時將進入onDataConnectionAttached()

protected void onUpdateIcc() {  
   if (mUiccController == null ) {  
       return;  
   }  
   IccRecords newIccRecords = getUiccRecords(UiccController.APP_FAM_3GPP);  
   IccRecords r = mIccRecords.get();  
   if (r != newIccRecords) {  
       if (r != null) {  
           r.unregisterForRecordsLoaded(this);  
           mIccRecords.set(null);  
       }  
       if (newIccRecords != null) {  
           mIccRecords.set(newIccRecords);  
           //監聽SIM各項數據是否載入完畢  
           newIccRecords.registerForRecordsLoaded( this, DctConstants.EVENT_RECORDS_LOADED, null);  
       }  
   }  
}  

其中註冊了EVENT_RECORDS_LOADED事件,這個事件在SIM卡被裝載完成後被通知
緊接着在DcTracker的構造中註冊了APN參數變化的監聽器,在用戶手動切換選擇APN時這個監聽器會相應,將當前的APN參數更新爲用戶選擇的APN參數

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

接下來在initApnContexts()中會初始化好當前系統支持的ApnContexts類型,並增加緊急APN,至此DcTracker的構造就完成了,在DcTrackerBase中還會創建一些與DataConnection有關的對象,接下來看DcTrackerBase的構造內容

protected DcTrackerBase(PhoneBase phone) {
    super();
    mPhone = phone;
    mResolver = mPhone.getContext().getContentResolver();
    mUiccController = UiccController.getInstance();
    mUiccController.registerForIccChanged(this, DctConstants.EVENT_ICC_CHANGED, null);
    mAlarmManager =
            (AlarmManager) mPhone.getContext().getSystemService(Context.ALARM_SERVICE);
    mCm = (ConnectivityManager) mPhone.getContext().getSystemService(
            Context.CONNECTIVITY_SERVICE);   //拿到ConnectivityManager

    mUserDataEnabled = getDataEnabled();

    mPhone.getContext().registerReceiver(mIntentReceiver, filter, null, mPhone); 

    HandlerThread dcHandlerThread = new HandlerThread("DcHandlerThread");
    dcHandlerThread.start();
    Handler dcHandler = new Handler(dcHandlerThread.getLooper());
    mDcc = DcController.makeDcc(mPhone, this, dcHandler);
    mDcTesterFailBringUpAll = new DcTesterFailBringUpAll(mPhone, dcHandler);
}

其中mResolver = mPhone.getContext().getContentResolver();是拿到ContentResolver,查詢數據庫就是通過這個對象去操作的,比如後面的mUserDataEnabled = getDataEnabled();
mUserDataEnabled是保存在settings.db數據庫中表global中的mobile_data字段

public boolean getDataEnabled() {
    boolean retVal = "true".equalsIgnoreCase(SystemProperties.get(
            "ro.com.android.mobiledata", "true"));
    try {
        if (TelephonyManager.getDefault().getSimCount() == 1) {  //單卡path
            retVal = Settings.Global.getInt(mResolver, Settings.Global.MOBILE_DATA,
                    retVal ? 1 : 0) != 0;
        } else {
            int phoneSubId = mPhone.getSubId();                  //多卡path
            retVal = TelephonyManager.getIntWithSubId(mResolver, Settings.Global.MOBILE_DATA,
                    phoneSubId) != 0;
        }
        if (DBG) log("getDataEnabled: getIntWithSubId retVal=" + retVal);
    } 
    return retVal;
}

順便提一下這個字段(settings.db數據庫中表global中的mobile_data字段)的更新在DcTrackerBase.java中的onSetUserDataEnabled(boolean enabled)

protected void onSetUserDataEnabled(boolean enabled) {
    if (TelephonyManager.getDefault().getSimCount() == 1) {
        Settings.Global.putInt(mResolver, Settings.Global.MOBILE_DATA, enabled ? 1 : 0);
    } else {
         int phoneSubId = mPhone.getSubId();
         Settings.Global.putInt(mResolver, Settings.Global.MOBILE_DATA + phoneSubId,
                enabled ? 1 : 0);
    }
}

其中 mUiccController.registerForIccChanged(this, DctConstants.EVENT_ICC_CHANGED, null);註冊EVENT_ICC_CHANGED事件,當SIM卡發生改變時觸發
其中 mPhone.getContext().registerReceiver(mIntentReceiver, filter, null, mPhone); 註冊一些Intent事件,比如當手機屏幕關閉時,就會關閉數據上下行的統計,等等
接下來是比較重要的一部分,在這裏只是new HandlerThread,並創建了一個新的Handler放入DcController,創建了DcController對象,在後續中還會仔細分析這個Handler

    HandlerThread dcHandlerThread = new HandlerThread("DcHandlerThread");
    dcHandlerThread.start();
    Handler dcHandler = new Handler(dcHandlerThread.getLooper());
    mDcc = DcController.makeDcc(mPhone, this, dcHandler);
    mDcTesterFailBringUpAll = new DcTesterFailBringUpAll(mPhone, dcHandler);

至此,DcTracker算是完成了構造過程,接下來分析數據鏈接的動態過程

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章