Android——4.2 - 3G移植之路之 APN (五)

來源:互聯網
上載者:User

標籤:ios   conf   loading   reader   配置   shared   資料連線   td-scdma   environ   

            APN,這東西對於剛接觸的人來說並非那麼好理解。對於3G移植上網不可缺少,這裡記錄一下。


                                              撰寫不易,轉載請註明出處:http://blog.csdn.net/jscese/article/details/41248939


概念:

 APN(Access Point Name),也就是 存取點 ,行動裝置使用資料流量上網必須配置的一個參數,代表以何種方式來串連服務台開啟資料流量功能.

一般有訪問WAP或者connect 網際網路,國內的電訊廠商2G,3G標識例如以下:

移動公司:2G:GSM、3G:TD-SCDMA
聯通公司:2G:GSM、3G:WCDMA
電信公司:2G:CDMA、3G:CDMA2000

關於詳細某個電訊廠商的幾G網路 的APN 是什麼詳細可參考/device/sample/etc/apns-full-conf.xml

這個xml檔案裡有google預置的多國經常使用的APN



使用: apns-full-conf.xml

上面說道了apns-full-conf.xml 這個設定檔,這裡面基本上是這種模組:

  <apn carrier="沃3G串連互連網 (China Unicom)"      mcc="460"      mnc="01"      apn="3gnet"      type="default,supl"  />

其他選項都是網路參數,當中的apn就是我們最重要的存取點.也可自行加入apn屬性模組.


移植3G時,就須要用到這個xml設定檔了。在android的device.mk 裡面加個PRODUCT_COPY_FILES:

PRODUCT_COPY_FILES +=      device/sample/etc/apns-full-conf.xml:system/etc/apns-conf.xml


telephony.db

這個檔案被載入的地方可參考/packages/providers/TelephonyProvider/src/com/android/providers/telephony/TelephonyProvider.java:

    private static final String DATABASE_NAME = "telephony.db";  //資料庫db檔案    private static final String PARTNER_APNS_PATH = "etc/apns-conf.xml";  //上面說到的copy到系統system/etc檔案夾下...    private static class DatabaseHelper extends SQLiteOpenHelper {        // Context to access resources with        private Context mContext;        /**         * DatabaseHelper helper class for loading apns into a database.         *         * @param context of the user.         */        public DatabaseHelper(Context context) {            super(context, DATABASE_NAME, null, getVersion(context));            mContext = context;        }...        @Override        public void onCreate(SQLiteDatabase db) {            // Set up the database schema            db.execSQL("CREATE TABLE " + CARRIERS_TABLE +    //建表                "(_id INTEGER PRIMARY KEY," +                    "name TEXT," +                    "numeric TEXT," +                    "mcc TEXT," +                    "mnc TEXT," +                    "apn TEXT," +                    "user TEXT," +                    "server TEXT," +                    "password TEXT," +                    "proxy TEXT," +                    "port TEXT," +                    "mmsproxy TEXT," +                    "mmsport TEXT," +                    "mmsc TEXT," +                    "authtype INTEGER," +                    "type TEXT," +                    "current INTEGER," +                    "protocol TEXT," +                    "roaming_protocol TEXT," +                    "carrier_enabled BOOLEAN," +                    "bearer INTEGER);");            initDatabase(db);        }    private void initDatabase(SQLiteDatabase db) {...            // Environment.getRootDirectory() is a fancy way of saying ANDROID_ROOT or "/system".            File confFile = new File(Environment.getRootDirectory(), PARTNER_APNS_PATH);      //這裡就是載入解析 load進db 了            FileReader confreader = null;            try {                confreader = new FileReader(confFile);                confparser = Xml.newPullParser();                confparser.setInput(confreader);                XmlUtils.beginDocument(confparser, "apns");                // Sanity check. Force internal version and confidential versions to agree                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);            } ...   }}


由於Content Provider採用的是懶載入機制,所以僅僅有檢測load上sim卡的時候才會被建立這個db:


可使用sqlite3查看:



createAllApnList

 在android中資料流量由/frameworks/opt/telephony/src/java/com/android/internal/telephony/DataConnectionTracker.java

以及它的子類GsmDataConnectionTracker.java(GSM模式) 或者 CdmaDataConnectionTracker.java(CDMA模式),(前者為移動,聯通,後者為電信專用)

來控制,當中啟動資料流量開關為onSetUserDataEnabled(boolean enabled).

這裡單以GSM模式來說,在SIM 被load時調用:

    private void onRecordsLoaded() {        if (DBG) log("onRecordsLoaded: createAllApnList");        createAllApnList();        if(!mUserDataEnabled)            return;//jscese add judgement        if (mPhone.mCM.getRadioState().isOn()) {            if (DBG) log("onRecordsLoaded: notifying data availability");            notifyOffApnsOfAvailability(Phone.REASON_SIM_LOADED);        }        setupDataOnReadyApns(Phone.REASON_SIM_LOADED);    }


調用進createAllApnList

    /**     * Based on the sim operator numeric, create a list for all possible     * Data Connections and setup the preferredApn.     */    private void createAllApnList() {        mAllApns = new ArrayList<ApnSetting>();        IccRecords r = mIccRecords.get();        String operator = (r != null) ? r.getOperatorNumeric() : "";        if (operator != null) {            String selection = "numeric = ‘" + operator + "‘";            // query only enabled apn.            // carrier_enabled : 1 means enabled apn, 0 disabled apn.            selection += " and carrier_enabled = 1";            if (DBG) log("createAllApnList: selection=" + selection);            Cursor cursor = mPhone.getContext().getContentResolver().query(   //用當前SIM卡相應的電訊廠商查詢系統的全部APN。往下調用createApnList                    Telephony.Carriers.CONTENT_URI, null, selection, null, null);            if (cursor != null) {                if (cursor.getCount() > 0) {                    mAllApns = createApnList(cursor);  //能夠跟進去看查詢Telephony.Carriers並返回一個Apn的list                }                cursor.close();            }        }        if (mAllApns.isEmpty()) {            if (DBG) log("createAllApnList: No APN found for carrier: " + operator);            mPreferredApn = null;            // TODO: What is the right behaviour?

//notifyNoData(GsmDataConnection.FailCause.MISSING_UNKNOWN_APN); } else { mPreferredApn = getPreferredApn(); if (mPreferredApn != null && !mPreferredApn.numeric.equals(operator)) { mPreferredApn = null; setPreferredApn(-1); } if (DBG) log("createAllApnList: mPreferredApn=" + mPreferredApn); } if (DBG) log("createAllApnList: X mAllApns=" + mAllApns); }



onSetUserDataEnabled(true):

 代表開啟資料流量。終於調用到  

private boolean trySetupData(ApnContext apnContext){...       if (apnContext.getState() == DctConstants.State.IDLE) {                ArrayList<ApnSetting> waitingApns = buildWaitingApns(apnContext.getApnType());//使用使用者佈建的preferred APN構建一個可用於資料連線的備選APN列表,即waitingApns列表(當有preferred APN,該列表就僅僅有一個)。

//若使用者沒有設定preferred APN,則將全部類型匹配的APN加入到waitingApns列表(如default類型) if (waitingApns.isEmpty()) { if (DBG) log("trySetupData: No APN found"); notifyNoData(GsmDataConnection.FailCause.MISSING_UNKNOWN_APN, apnContext); notifyOffApnsOfAvailability(apnContext.getReason()); return false; } else { apnContext.setWaitingApns(waitingApns); if (DBG) { log ("trySetupData: Create from mAllApns : " + apnListToString(mAllApns)); } } } if (DBG) { log ("Setup watingApns : " + apnListToString(apnContext.getWaitingApns())); } // apnContext.setReason(apnContext.getReason()); boolean retValue = setupData(apnContext); // waitingApns列表中有可用的APN時,嘗試建立串連 notifyOffApnsOfAvailability(apnContext.getReason()); return retValue;...}


另外幾個對apn操作的幾個函數都在這個檔案中面。分別的作用例如以下:

onApnChanged:當APN被使用者更改時,將調用到此函數,又一次建立資料連線


setPreferredApn:當使用者沒有設定preferred APN時,將當前資料連線成功的那個APN設定為preferred APN。

能夠去看onDataSetupComplete時的操作。


getPreferredApn:使用者擷取使用者佈建的preferred APN,這個在上面說到的createAllApnList時會去擷取一次。看是否存在.

對於這個preferredApn會以xml的形式儲存在:

[email protected]:/data/data/com.android.providers.telephony/shared_prefs # cat preferred-apn.xmlml                                                                            <<?

xml version=‘1.0‘ encoding=‘utf-8‘ standalone=‘yes‘ ?><map><long name="apn_id" value="1124" /></map>


這是代表開啟資料流量成功之後儲存的apn map。能夠像上面一樣去 telephony.db裡面查查看看:

sqlite> select * from carriers where _id=‘1124‘;1124|沃3G串連互連網 (China Unicom)|46001|460|01|3gnet|||||||||-1|default,supl|1|IP|IP|1|0




這裡僅僅是分析了一下apn的由來以及在framework層的使用,終於是通過RIL.java 的setupDataCall通過一個rild 的socket發請求到hardware的ril.cpp:

public void    setupDataCall(String radioTechnology, String profile, String apn, /*上面傳下來的apn*/            String user, String password, String authType, String protocol,            Message result) {        RILRequest rr                = RILRequest.obtain(RIL_REQUEST_SETUP_DATA_CALL, result);        rr.mp.writeInt(7);        rr.mp.writeString(radioTechnology);        rr.mp.writeString(profile);        rr.mp.writeString(apn);        rr.mp.writeString(user);        rr.mp.writeString(password);        rr.mp.writeString(authType);        rr.mp.writeString(protocol);        if (RILJ_LOGD) riljLog(rr.serialString() + "> "                + requestToString(rr.mRequest) + " " + radioTechnology + " "                + profile + " " + apn + " " + user + " "                + password + " " + authType + " " + protocol);        send(rr); //裡面就是 socket了    }

再之後怎麼擷取到這個socket event處理而且交給reference-ril 發送這個apn接入網路可參考我前面的部落格:

Android——RIL 機制原始碼分析  

Android——4.2 - 3G移植之路之 reference-ril .pppd 撥接 (三)






Android——4.2 - 3G移植之路之 APN (五)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.