Telephony基础之DataCall业务(DcTracker创建过程)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/cornerOfHeart/article/details/79895995

一、DcTracker介绍
DcTracker是Telephony框架中负责数据业务的核心.
所有对数据网络的请求(打开关闭数据开关、切换数据卡、修改APN参数等)都会发送到该处理中心来处理。

DcTracker是在Phone对象创建过程中被创建的,确切来说,如果当前使用的是GsmCdmaPhone,那么在GsmCdmaPhone创建过程中就会创建DcTracker对象:
GsmCdmaPhone.java
    public GsmCdmaPhone(Context context, CommandsInterface ci, PhoneNotifier notifier,
                        boolean unitTestMode, int phoneId, int precisePhoneType,
                        TelephonyComponentFactory telephonyComponentFactory) {
    
        mSST = mTelephonyComponentFactory.makeServiceStateTracker(this, this.mCi);
        // DcTracker uses SST so needs to be created after it is instantiated
        mDcTracker = mTelephonyComponentFactory.makeDcTracker(this);
 
    }

TelephonyComponentFactory.java
    public DcTracker makeDcTracker(Phone phone) {
        Rlog.d(LOG_TAG, "makeDcTracker");
        return new DcTracker(phone);
    }

DcTracker本质是什么:
public class DcTracker extends Handler


DcTracker的初始化过程:

    public DcTracker(Phone phone) {
        super();
    //初始化几个全局的成员变量
        mPhone = phone;
        if (DBG) log("DCT.constructor");
        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);

    //注册一个广播监听器,监听屏幕开关,WIFI变化的广播
        IntentFilter filter = new IntentFilter();
        filter.addAction(Intent.ACTION_SCREEN_ON);
        filter.addAction(Intent.ACTION_SCREEN_OFF);
        filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
        filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
        filter.addAction(INTENT_DATA_STALL_ALARM);
        filter.addAction(INTENT_PROVISIONING_APN_ALARM);
        filter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
        mPhone.getContext().registerReceiver(mIntentReceiver, filter, null, mPhone);


    //向SubscriptionManager添加监听器,猜测是用于双卡切换处理的
        mSubscriptionManager = SubscriptionManager.from(mPhone.getContext());
        mSubscriptionManager.addOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener);
    
    //创建并启动一个HandlerThread,暂时不清楚具体作用
        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自身给mDataConnectionTracker
        mDataConnectionTracker = this;
    
    //方法内部通过当前Phone对象分别向RIL ,CallTracker以及ServiceStateTracker注册监听器
        registerForAllEvents();
    
    //方法内部已通过mPhone.getIccRecords()获取IccRecords实例后做相关处理
        update();

    //监听APN数据库的状态,比如在Settings下新增APN
        mApnObserver = new ApnChangeObserver();
        phone.getContext().getContentResolver().registerContentObserver(
                Telephony.Carriers.CONTENT_URI, true, mApnObserver);
    
    //初始化ApnContexts
        initApnContexts();

    //对每个ApnContext注册广播监听器,应该是跟retry data相关,具体流程暂时不清楚
        for (ApnContext apnContext : mApnContexts.values()) {
            // Register the reconnect and restart actions.
            filter = new IntentFilter();
            filter.addAction(INTENT_RECONNECT_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" + phone.getPhoneId();
    
    //通过SettingsObserver监听Setting下面漫游的情况,在前面的ServiceStateTracker有相似的监听,目前不清楚这两者的区别
        mSettingsObserver = new SettingsObserver(mPhone.getContext(), this);
        registerSettingsObserver();
    }

在上面这个初始化过程中,主要完成了三个任务:
1、初始化一些成员变量;
2、注册监听,包括广播监听器,Listener,Observer;
3、初始化一些基本的APN参数;



二、DcTracker中监听器的初始化

1,registerForAllEvents():
Listener主要是通过当前Phone对象分别向RIL ,CallTracker以及ServiceStateTracker注册监听器
    private void registerForAllEvents() {
    //向RIL注册监听器
        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.mCi.registerForPcoData(this, DctConstants.EVENT_PCO_DATA_RECEIVED, null);

    //向CallTracker注册监听器
        mPhone.getCallTracker().registerForVoiceCallEnded(this,
                DctConstants.EVENT_VOICE_CALL_ENDED, null);
        mPhone.getCallTracker().registerForVoiceCallStarted(this,
                DctConstants.EVENT_VOICE_CALL_STARTED, null);

    //向ServiceStateTracker注册监听器
        registerServiceStateTrackerEvents()
 
    }

    public void registerServiceStateTrackerEvents() {
        mPhone.getServiceStateTracker().registerForDataConnectionAttached(this,
                DctConstants.EVENT_DATA_CONNECTION_ATTACHED, null);
        mPhone.getServiceStateTracker().registerForDataConnectionDetached(this,
                DctConstants.EVENT_DATA_CONNECTION_DETACHED, null);
        mPhone.getServiceStateTracker().registerForDataRoamingOn(this,
                DctConstants.EVENT_ROAMING_ON, null);
        mPhone.getServiceStateTracker().registerForDataRoamingOff(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);
    }

这些监听器包括:
RIL:
  DctConstants.EVENT_RADIO_AVAILABLE
  DctConstants.EVENT_RADIO_OFF_OR_NOT_AVAILABLE
  DctConstants.EVENT_DATA_STATE_CHANGED
  DctConstants.EVENT_PCO_DATA_RECEIVED

CallTracker:
  DctConstants.EVENT_VOICE_CALL_ENDED
  DctConstants.EVENT_VOICE_CALL_STARTED

ServiceStateTracker:
  DctConstants.EVENT_DATA_CONNECTION_ATTACHED
  DctConstants.EVENT_DATA_CONNECTION_DETACHED
  DctConstants.EVENT_ROAMING_ON
  DctConstants.EVENT_ROAMING_OFF
  DctConstants.EVENT_PS_RESTRICT_ENABLED
  DctConstants.EVENT_PS_RESTRICT_DISABLED
  DctConstants.EVENT_DATA_RAT_CHANGED
与dataCall流程关系紧密,会回调 handleMessage ()来处理.



2,update()

    public void update() {
        log("update sub = " + mPhone.getSubId());
        log("update(): Active DDS, register for all events now!");

    //更新ICC,y与UICC框架相关,暂时说不清楚
        onUpdateIcc();

        mDataEnabledSettings.setUserDataEnabled(getDataEnabled());
        mAutoAttachOnCreation.set(false);

    //使用当前Sim卡更新数据库的operatorNumeric
        ((GsmCdmaPhone)mPhone).updateCurrentCarrierInProvider();
    }


    private void onUpdateIcc() {
        if (mUiccController == null ) {
            return;
        }

        IccRecords newIccRecords = mPhone.getIccRecords();

        IccRecords r = mIccRecords.get();
        if (r != newIccRecords) {
            if (r != null) {
                log("Removing stale icc objects.");
                r.unregisterForRecordsLoaded(this);
                mIccRecords.set(null);
            }
            if (newIccRecords != null) {
/* [PSN]Telephony FEATURE_PSN_TEL_00069 add Start */
//                if (mSubscriptionManager.isActiveSubId(mPhone.getSubId())) {
                log("onUpdateIcc: isValidDefaultFallbackSubId= " + SubscriptionController.getInstance().isValidDefaultFallbackSubId());
                if (SubscriptionController.getInstance().isValidDefaultFallbackSubId()) {
/* [PSN]Telephony FEATURE_PSN_TEL_00069 add End */
                    log("New records found.");
                    mIccRecords.set(newIccRecords);

            ////监听SIM各项数据是否载入完毕  
                    newIccRecords.registerForRecordsLoaded(
                            this, DctConstants.EVENT_RECORDS_LOADED, null);
                    // reset carrier actions on sim loaded
                    final ServiceStateTracker sst = mPhone.getServiceStateTracker();

            //重新开启Radio
                    sst.setRadioPowerFromCarrier(true);
                    mDataEnabledSettings.setCarrierDataEnabled(true);
                    mPhone.getCarrierSignalAgent().reset();
                }
            } else {
                onSimNotReady();
            }
        }
    }

3,initApnContexts()

initApnContexts()的主要作用就是载入networkAttributes数组中预置的APN参数:
    private void initApnContexts() {
        log("initApnContexts: E");
       
     //载入networkAttributes数组  
        String[] networkConfigStrings = mPhone.getContext().getResources().getStringArray(
                com.android.internal.R.array.networkAttributes);
        for (String networkConfigString : networkConfigStrings) {
            NetworkConfig networkConfig = new NetworkConfig(networkConfigString);
            ApnContext apnContext = null;
        
        //根据不同类型创建不同ApnContext
            switch (networkConfig.type) {
            case ConnectivityManager.TYPE_MOBILE:
                apnContext = addApnContext(PhoneConstants.APN_TYPE_DEFAULT, networkConfig);
                break;
            case ConnectivityManager.TYPE_MOBILE_MMS:
                apnContext = addApnContext(PhoneConstants.APN_TYPE_MMS, networkConfig);
                break;
            case ConnectivityManager.TYPE_MOBILE_SUPL:
                apnContext = addApnContext(PhoneConstants.APN_TYPE_SUPL, networkConfig);
                break;
            case ConnectivityManager.TYPE_MOBILE_DUN:
                apnContext = addApnContext(PhoneConstants.APN_TYPE_DUN, networkConfig);
                break;
            case ConnectivityManager.TYPE_MOBILE_HIPRI:
                apnContext = addApnContext(PhoneConstants.APN_TYPE_HIPRI, networkConfig);
                break;
            case ConnectivityManager.TYPE_MOBILE_FOTA:
                apnContext = addApnContext(PhoneConstants.APN_TYPE_FOTA, networkConfig);
                break;
            case ConnectivityManager.TYPE_MOBILE_IMS:
                apnContext = addApnContext(PhoneConstants.APN_TYPE_IMS, networkConfig);
                break;
            case ConnectivityManager.TYPE_MOBILE_CBS:
                apnContext = addApnContext(PhoneConstants.APN_TYPE_CBS, networkConfig);
                break;
            case ConnectivityManager.TYPE_MOBILE_IA:
                apnContext = addApnContext(PhoneConstants.APN_TYPE_IA, networkConfig);
                break;
            case ConnectivityManager.TYPE_MOBILE_EMERGENCY:
                apnContext = addApnContext(PhoneConstants.APN_TYPE_EMERGENCY, networkConfig);
                break;
            default:
                log("initApnContexts: skipping unknown type=" + networkConfig.type);
                continue;
            }
            log("initApnContexts: apnContext=" + apnContext);
        }

        if (VDBG) log("initApnContexts: X mApnContexts=" + mApnContexts);
    }

4,initEmergencyApnSetting()和addEmergencyApnSetting()
通过initEmergencyApnSetting()载入紧急APN;
通过addEmergencyApnSetting()将紧急APN添加到APN列表中;
    private void initEmergencyApnSetting() {
        // Operator Numeric is not available when sim records are not loaded.
        // Query Telephony.db with APN type as EPDN request does not
        // require APN name, plmn and all operators support same APN config.
        // DB will contain only one entry for Emergency APN
        String selection = "type=\"emergency\"";
        Cursor cursor = mPhone.getContext().getContentResolver().query(
                Telephony.Carriers.CONTENT_URI, null, selection, null, null);

        if (cursor != null) {
            if (cursor.getCount() > 0) {
                if (cursor.moveToFirst()) {
                    mEmergencyApn = makeApnSetting(cursor);
                }
            }
            cursor.close();
        }
    }
这个载入过程其实就是从数据库中搜索条件为"type="emergency""的APN参数,那么这个数据库中的内容是哪里来的呢?
这些参数是在TelephonyProvider被创建的时候被初始化,下面简单看一下初始化流程:
    @TelephonyProvider.java  
    private void initDatabase(SQLiteDatabase db) {  
        Resources r = mContext.getResources();  
        //从apns文件读取APN参数  
        XmlResourceParser parser = r.getXml(com.android.internal.R.xml.apns);  
        int publicversion = -1;  
        try {  
            XmlUtils.beginDocument(parser, "apns");  
            //解析该文件  
            publicversion = Integer.parseInt(parser.getAttributeValue(null, "version"));  
            loadApns(db, parser);  
        } catch (Exception e) {  
        } finally {  
            parser.close();  
        }  
      
      
        XmlPullParser confparser = null;  
        //从"etc/apns-conf.xml"配置文件读取APN参数  
        File confFile = new File(Environment.getRootDirectory(), PARTNER_APNS_PATH);  
        FileReader confreader = null;  
        try {  
            confreader = new FileReader(confFile);  
            confparser = Xml.newPullParser();  
            confparser.setInput(confreader);  
            XmlUtils.beginDocument(confparser, "apns");  
      
      
            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);  
        } catch (FileNotFoundException e) {  
        } catch (Exception e) {  
        } finally {  
            try { if (confreader != null) confreader.close(); } catch (IOException e) { }  
        }  
    }  

从上面可以看到,从com.android.internal.R.xml.apns和"etc/apns-conf.xml"两个路径下读取了APN的配置文件并解析,然后存入了数据库,这些配置文件的配置内容如下:
    @apns-conf.xml  
    <?xml version="1.0" encoding="utf-8"?>  
    <apns version="8">  
        <apn carrier="T-Mobile US"  
             mcc="310"  
             mnc="260"  
             apn="epc.tmobile.com"  
             user="none"  
             server="*"  
             password="none"  
             mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc"  
        />  
        <apn carrier="T-Mobile US 250"  
             mcc="310"  
             mnc="250"  
             apn="epc.tmobile.com"  
             user="none"  
             server="*"  
             password="none"  
             mmsc="http://mms.msg.eng.t-mobile.com/mms/wapenc"  
        />  
    </apns>  

       从这个配置文件中可以看到,其每一项数据都包含了某个运营商的PLMN name、MCC、MNC、apn、user、server、password、mmsc等信息。
        上面是数据库初始化的过程,回到DcTracker的紧急APN初始化过程中来,当从数据库中搜索到"type="emergency""的紧急APN参数后,通过initEmergencyApnSetting()方法将这些参数放入mEmergencyApn中,接下来还需要通过addEmergencyApnSetting()方法把这些紧急APN存入统一的APN库中

private void addEmergencyApnSetting() {  
     if(mEmergencyApn != null) {  
         if(mAllApnSettings == null) {  
             mAllApnSettings = new ArrayList<ApnSetting>();  
         } else {  
             boolean hasEmergencyApn = false;  
             for (ApnSetting apn : mAllApnSettings) {  
                 if (ArrayUtils.contains(apn.types, PhoneConstants.APN_TYPE_EMERGENCY)) {  
                     //如果之前的SIM APN中已经包含了紧急APN,就无需再次添加  
                     hasEmergencyApn = true;  
                     break;  
                 }  
             }  
             if(hasEmergencyApn == false) {  
                 //将mEmergencyApn添加到APN列表中  
                 mAllApnSettings.add(mEmergencyApn);  
             } else {  
                 log("addEmergencyApnSetting - E-APN setting is already present");  
             }  
         }  
     }  
 }

通过以上步骤,紧急APN的创建过程就完成了。
至此,DcTracker所有初始化工作全部完成,在这个过程中注册了监听器、广播接收器,初始化了紧急APN,接下来就是等待监听器被触发。




 

猜你喜欢

转载自blog.csdn.net/cornerOfHeart/article/details/79895995