Android 2.3 撥接流程分析–java層

來源:互聯網
上載者:User

這篇文章是分析使用SIM卡上網功能的簡單分析,並沒有涉及到WIFI上網,請大家知悉.

通常,如果我們想使用SIM卡撥接功能,我們要在設定中進行簡單的配置,步驟如下:

設定 -》無線和網路 -》移動網路 -》(已啟用資料/數據漫遊/存取點名稱/僅使用2G網路/網路電訊廠商)

我們必須選中其中的“已啟用資料”選項,然後配置存取點名稱後就可以上網了,當然有的設定中已經根據你的SIM卡類型預設設定了存取點,這時候你只選擇“已啟用資料”項後就可以完成上網功能設定。

這些設定步驟究竟做了哪些事情呢?我們現在就從源碼的角度進行分析。

1. 首先,我們找到“移動網路”的設定UI-------Settings.java(/packages/apps/Phone/src/com/android/phone/Settings.java)

Settings.java:

"已啟用資料"選項的相關代碼如下:

......else if (preference == mButtonDataEnabled) {            if (DBG) log("onPreferenceTreeClick: preference == mButtonDataEnabled.");            ConnectivityManager cm =                    (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);            cm.setMobileDataEnabled(mButtonDataEnabled.isChecked());            return true;        }......

代碼中,我們得到一個ConnectivityManager對象,並調用該對象的setMobileDataEnable(boolean b)方法,根據傳入的參數進行設定,我們看一下ConnectivityManager類。

2. ConnectivityManager.java(/frameworks/base/core/java/android/net/ConnectivityManager.java)

這個時候,資料已經進入frameworks層。

setMobileDataEnable()方法代碼如下:

IConnectivityManager mService;...... public ConnectivityManager(IConnectivityManager service) {        if (service == null) {            throw new IllegalArgumentException(                "ConnectivityManager() cannot be constructed with null service");        }        mService = service;    }......public void setMobileDataEnabled(boolean enabled) {        try {            mService.setMobileDataEnabled(enabled);        } catch (RemoteException e) {        }    }

這裡我們要知道IConnectivityManager類,是根據IConnectivityManager.aidl介面自動產生的一個java類,而我們自己有一個Service則繼承了該類的內部類:Stub,在我們自己為撥接實現的這個Service就是ConnectivityService,所以根據AIDL只是,我們知道,代碼中的mService其實就是ConnectivityService類的對象,所以代碼在這裡實際上是調用了ConnectivityService對象的setMobileDataEnable()方法。

3. ConnectivityService.java(/frameworks/./base/services/java/com/android/server/ConnectivityService.java)

setMobileDataEnable()方法代碼如下:

public void setMobileDataEnabled(boolean enabled) {        enforceChangePermission();        if (DBG) Slog.d(TAG, "setMobileDataEnabled(" + enabled + ")");        mHandler.sendMessage(mHandler.obtainMessage(EVENT_SET_MOBILE_DATA,            (enabled ? ENABLED : DISABLED), 0));    }

這裡發送了一個訊息出去,mHandler收到該訊息以後:

case EVENT_SET_MOBILE_DATA:                {                    boolean enabled = (msg.arg1 == ENABLED);                    handleSetMobileData(enabled);                    break;                }

收到該訊息後,調用handleSetMobileData()方法:

private NetworkStateTracker mNetTrackers[];......private void handleSetMobileData(boolean enabled) {        ......                if (enabled) {            if (mNetTrackers[ConnectivityManager.TYPE_MOBILE] != null) {                if (DBG) {                    Slog.d(TAG, "starting up " + mNetTrackers[ConnectivityManager.TYPE_MOBILE]);                }                mNetTrackers[ConnectivityManager.TYPE_MOBILE].reconnect();            }            ......        } }

如果“已啟用資料”選項已經選擇,那這個時候傳進來的參數“enabled”應該是“true”,所以會處理代碼中if語句塊,即執行:

mNetTrackers[ConnectivityManager.TYPE_MOBILE].reconnect();

而在ConnectivityManager中,TYPE_MOBILE 為 0,所以這裡相當於調用了

mNetTracker[0].reconnect()

但是,NetworkStateTracker是一個抽象類別,所以具體的事情要交給它的子類MobileDataStateTracker.java來幹。

4. MobileDataStateTracker.java(/frameworks/base/core/java/android/net/MobileDataStateTracker.java)

該類包含多種資料連線,包括MMS,SUPL,DUN等,

在MobileDataStateTracker.java裡面的調用流程是這樣的:

mPhoneService = ITelephony.Stub.asInterface(ServiceManager.getService("phone"));

......
reconnect->mPhoneService.enableApnType(apnType);

mPhoneService是電話的服務的用戶端,它的server端實際上是PhoneInterfaceManager對象

5. PhoneInterfaceManager.java(/packages/apps/Phone/src/com/android/phone/PhoneInterfaceManager.java)

看PhoneInterfaceManager的enableApnType方法:

    public int enableApnType(String type) {        enforceModifyPermission();        return mPhone.enableApnType(type);    }

這樣,就將串連apn的請求發送到telephony架構層下去了。apn在設定應用裡面有指定,一般在你的工程目錄下的system/etc/apns-conf.xml檔案

6. 上面的mPhone是PhoneProxy對象,

調用流程:

PhoneProxy.java:

mActivePhone.enableApnType(type)

mActivePhone是GSMPhone或者CDMAPhone的上溯介面PhoneBase對象

PhoneBase.java:

mDataConnection.enableApnType(type);

調用到 DataConnectionTracker的enableApnType方法

DataConnectionTracker.java:

enableApnType(String type)->setEnabled->onEnableApn->onEnableNewApn

onEnableNewApn方法在DataConnectionTracker的衍生類別GsmDataConnectionTracker和CdmaDataConnectionTracker中實現,從而區別不同類型PHONE的資料連線流程。

以GSM為例,調用流程:onEnableNewApn->cleanUpConnection->conn.disconnect

conn是DataConnection對象,標識一鐘資料連線,可以看出這裡實際上實現了一個資料連線的狀態機器。

在DataConnection對象裡面資料連線的狀態分為:

DcDefaultState,預設狀態。DcInactiveState,非啟用狀態。DcActivatingState,正在啟用狀態DcActiveState,啟用狀態DcDisconnectingState,正在斷開狀態DcDisconnectingBadDnsState,斷開狀態(因為錯誤的DNS)

串連成功以後,notifyDefaultData調用到DefaultPhoneNotifier的notifyDataConnection方法。

DefaultPhoneNotifier是ITelephonyRegistry介面的用戶端,其服務端是TelephonyRegistry(com.android.server.TelephonyRegistry)

TelephonyRegistry的notifyDataConnection方法調用如下語句

 r.callback.onDataConnectionStateChanged(state, networkType);

r是當前mRecords中的元素,包含有IPhoneStateListener介面的實現callback,TelephonyRegistry中的每個調用都會遍曆mRecords中的元素,如果某個元素註冊了對應接聽,

則調用callback的某個函數。

用戶端通過如下方式調用取得電話狀態的監聽, 以StatusBarPolicy.java中的mPhoneStateListener為例:

            ((TelephonyManager)mContext.getSystemService(Context.TELEPHONY_SERVICE))

                    .listen(mPhoneStateListener,
                              PhoneStateListener.LISTEN_SERVICE_STATE
                            | PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
                            | PhoneStateListener.LISTEN_CALL_STATE
                            | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
                            | PhoneStateListener.LISTEN_DATA_ACTIVITY);

mPhoneStateListener是PhoneStateListener執行個體,PhoneStateListener實現了IPhoneStateListener介面,假如你繼承PhoneStateListener子類,首先你要確定你感興趣的監聽

事件,然後重寫對應的方法。再像上面那樣調用listen方法就可以了。

TelephonyRegistry的方法、監聽動作、已經你要重寫的方法對應關係如下:

TelephonyRegistry的方法  ---------------------監聽動作-------------------------------------------------------PhoneStateListener子類中的中的回調

notifyServiceState   ---------- PhoneStateListener.LISTEN_SERVICE_STATE       -----------------  public void onServiceStateChanged(ServiceState state) 

notifySignalStrength   ------- PhoneStateListener.LISTEN_SIGNAL_STRENGTHS     --------- --  public void onSignalStrengthsChanged(SignalStrength signalStrength)

notifyCallState  ---------------- PhoneStateListener.LISTEN_CALL_STATE    -------------------------   public void onCallStateChanged(int state, String incomingNumber)

notifyDataConnection ------- PhoneStateListener.LISTEN_DATA_CONNECTION_STATE    ---   public void onDataConnectionStateChanged(int state, int networkType)

notifyDataActivity  -------------- PhoneStateListener.LISTEN_DATA_ACTIVITY -----------------------   public void onDataActivity(int direction)

。。。。。。。。

因此整個調用鏈是:DefaultPhoneNotifier:notifyDataConnection ---------》 TelephonyRegistry :notifyDataConnection---------》

PhoneStateListener.callback:onDataConnectionStateChanged --------------》PhoneStateListener子類的onDataConnectionStateChanged

除此之外,TelephonyRegistry還發出一個ACTION_ANY_DATA_CONNECTION_STATE_CHANGED,包含資料連線的詳細資料。

而Mobile Data Service裡面的MobileDataStateTracker會接收到這個動作,由它的BoadcastReceiver類MobileDataStateReceiver提取出資料連線的資訊,然後設定好狀態

setDetailedState(DetailedState.CONNECTING, reason, apnName);

MobileDataStateTracker根據狀態變化給ConnectivityService發送EVENT_STATE_CHANGED訊息。

ConnectivityService調用handleConnect去執行相關炒作,包括關閉優先順序比它低的資料連線,更新狀態列等等。

註:後半部分借鑒了http://blog.csdn.net/yinlijun2004/article/details/6656788。

還有很多地方還沒有搞明白,以後再續。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.