This article is a simple analysis of using SIM card to access the Internet. WiFi is not involved.
Generally, if we want to use the SIM card dial-up Internet access function, we need to make a simple configuration in the settings, the steps are as follows:
Set-wireless and network-mobile network-(data/data roaming/Access Point Name Enabled/only use 2G network/network operator)
We must select the "data enabled" option, and then configure the Access Point name to access the Internet. Of course, some settings have set the access point according to your SIM card type by default, in this case, you can set the Internet function only after selecting "data enabled.
What have these setup steps been done? Now we will analyze the source code.
1. First, find "mobile network" Settings UI ------- settings. Java (/packages/apps/phone/src/COM/Android/phone/settings. Java)
Settings. Java:
The code for the "data enabled" option is as follows:
......else if (preference == mButtonDataEnabled) { if (DBG) log("onPreferenceTreeClick: preference == mButtonDataEnabled."); ConnectivityManager cm = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE); cm.setMobileDataEnabled(mButtonDataEnabled.isChecked()); return true; }......
In the code, we get a connectivitymanager object and call the setmobiledataenable (Boolean B) method of this object. We can set it based on the input parameters. Let's take a look at the connectivitymanager class.
2. connectivitymanager. Java (/frameworks/base/CORE/Java/Android/NET/connectivitymanager. Java)
At this time, the data has entered the frameworks layer.
The setmobiledataenable () method code is as follows:
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) { } }
Here we need to know that the iconnectivitymanager class is based on iconnectivitymanager. A Java class automatically generated by the aidl interface, and one of our own services inherits the internal class of this class: stub. In our own implementation for dial-up Internet access, this service is connectivityservice, therefore, according to aidl, we know that the mservice in the Code is actually the connectivityservice class object, so the Code actually calls the setmobiledataenable () method of the connectivityservice object.
3. connectivityservice. Java (/frameworks/./base/services/Java/COM/Android/Server/connectivityservice. Java)
The setmobiledataenable () method code is as follows:
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)); }
A message is sent here. After mhandler receives the message:
case EVENT_SET_MOBILE_DATA: { boolean enabled = (msg.arg1 == ENABLED); handleSetMobileData(enabled); break; }
After receiving the message, call the handlesetmobiledata () method:
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(); } ...... } }
If the "enabled data" option has been selected, the "enabled" parameter passed in at this time should be "true", so the if statement block in the code will be processed, that is, the execution:
mNetTrackers[ConnectivityManager.TYPE_MOBILE].reconnect();
In connectivitymanager, type_mobile is 0, so it is equivalent to calling
mNetTracker[0].reconnect()
However, networkstatetracker is an abstract class. Therefore, the specific task must be handled by its subclass mobiledatastatetracker. java.
4. mobiledatastatetracker. Java (/frameworks/base/CORE/Java/Android/NET/mobiledatastatetracker. Java)
This class includes multiple data connections, including MMS, supl, dun, etc,
The Calling process in mobiledatastatetracker. Java is as follows:
mPhoneService = ITelephony.Stub.asInterface(ServiceManager.getService("phone"));
......
Reconnect-> mphoneservice. enableapntype (apntype );
Mphoneservice is the client of the telephone service, and its server is actually a phoneinterfacemanager object
5. phoneinterfacemanager. Java (/packages/apps/phone/src/COM/Android/phone/phoneinterfacemanager. Java)
Check the enableapntype method of phoneinterfacemanager:
public int enableApnType(String type) { enforceModifyPermission(); return mPhone.enableApnType(type); }
In this way, the request to connect to the APN is sent to the Telephony framework layer. The APN is specified in the setup application, typically in the system/etc/apns-conf.xml file under your project directory
6. The above mphone is the phoneproxy object,
Call process:
Phoneproxy. Java:
mActivePhone.enableApnType(type)
Mactivephone is the phonebase object of the upstream interface of gsmphone or cdmaphone.
Phonebase. Java:
mDataConnection.enableApnType(type);
Call the enableapntype method of dataconnectiontracker.
Dataconnectiontracker. Java:
Enableapntype (string type)-> setenabled-> onenableapn-> onenablenewapn
The onenablenewapn method is implemented in the gsmdataconnectiontracker and CDMA dataconnectiontracker Derived classes of dataconnectiontracker to differentiate the data connection processes of different phone types.
Taking GSM as an example, the call process is onenablenewapn-> cleanupconnection-> conn. Disconnect.
Conn is a dataconnection object that identifies a data connection within one minute. It can be seen that a data connection state machine is actually implemented here.
The data connection status in the dataconnection object is divided:
Dcdefaultstate, default state. Dcinactivestate: inactive. Dcactivatingstate: the status of dcactivestate is being activated. The status of dcdisconnectingstate is being activated. The status of dcdisconnectingbaddnsstate is being disconnected (due to incorrect DNS)
After the connection is successful, yydefadata calls yultphonenotifier's notifydataconnection method.
Defaultphonenotifier is the client of the itelephonyregistry interface, and its server is telephonyregistry (COM. Android. server. telephonyregistry)
Telephonyregistry's notifydataconnection method calls the following statement:
r.callback.onDataConnectionStateChanged(state, networkType);
R is an element in the current mrecords and contains the implementation callback of the iphonestatelistener interface. Each call in telephonyregistry traverses the elements in mrecords. If an element registers a corresponding answer,
Call a callback function.
The client calls the listener to obtain the phone status in the following way. Take mphonestatelistener in statusbarpolicy. Java as an example:
(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 is a phonestatelistener instance. phonestatelistener implements the iphonestatelistener interface. If you inherit the phonestatelistener subclass, you must first determine the listener you are interested in.
Event, and then override the corresponding method. Call the listen method as above.
Telephonyregistry's methods, listener actions, and methods you want to override correspond to the following:
Telephonyregistry method --------------------- listener action ----------------------------------------------------------- callback in the phonestatelistener subclass
Notifyservicestate ---------- phonestatelistener. listen_service_state --------------- public void onservicestatechanged (servicestate state)
Policysignalstrength ------- phonestatelistener. listen_signal_strengths --------- -- Public void onsignalstrengthschanged (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)
........
Therefore, the entire call chain is: defaultphonenotifier: notifydataconnection --------- telephonyregistry: yydataconnection ---------
Phonestatelistener. Callback: ondataconnectionstatechanged -------------- ondataconnectionstatechanged of the phonestatelistener subclass
In addition, telephonyregistry also sends an action_any_data_connection_state_changed, which contains detailed information about the data connection.
The mobiledatastatetracker in Mobile Data Service receives this action, and its boadcastreceiver class mobiledatastatereceiver extracts the data connection information and sets the status.
setDetailedState(DetailedState.CONNECTING, reason, apnName);
Mobiledatastatetracker sends the event_state_changed message to connectivityservice according to the status change.
Connectivityservice calls handleconnect to execute related hype, including disabling data connections with lower priority and updating the status bar.
Note: the latter part draws on http://blog.csdn.net/yinlijun2004/article/details/6656788.
There are still many areas that haven't been figured out, and we will continue later.