nullnullAndroid Telephony ArchitectureJun_YangMar 23 2012nullAgenda
1. Structure
2. Telephony Framework
3. Setup Data Connection
4. Net Status Notification
5. Q&A
nullStructure
Phone.apk, Mms, Settings...android.telephony.*com.android.internal.telephony.*RIL.javasocket “rild”Java
ApplicationJava
Frameworkrild daemonlibhuawei-ril.solibril.soModem driverRILdlopen
RIL_initRIL_startEventLoop()
RIL_register()
RIL_onRequestComplete()
...KernelAT commandsnullTelephony framework contains a set of telephony API for applications. There are two categaries of JAVA pacakges in telephony framework:
1.The internal telephony packages -
com.android.internal.telephony.*,
source code: frameworks/base/telephony/java/com/android/internal/telephony
2.The open telephony packages -
android.telephony.*.
source code: frameworks/base/telephony/java/android/telephony
The internal packages are used for Android default telephony application - Phone.apk, and the open packages are for any 3rd party telephony applications.Telephony FrameworknullThis figure show the relationship of these Classes
Telephony FrameworkPhoneBase (abstract class)GSMPhoneCDMAPhonePhoneProxyPhone (interface)extendsimplementscallCommandsInterface (interface)RILJBaseCommands
(abstarct class)PhoneFactorynullInternal Telephony Packages:
frameworks/base/telephony/java/com/android/internal/telephony
The public interface Phone is used to control the phone. The abstract class PhoneBase implements this interface. And the class GSMPhone extends this abstract class.
Phone.java
Telephony Framework
44 public interface Phone {
326 String getPhoneName();
332 int getPhoneType();
void setPreferredNetworkType(int networkType, Message response);
void getPreferredNetworkType(Message response);
...
nullThe default telephony application could use makeDefaultPhones() and getDefaultPhone() in the class PhoneFactory to obtain the unique instance of Phone. The code below shows how this be done.
packages/apps/Phone/src/com/android/phone/PhoneApp.java
PhoneFactory.java
Telephony Framework
410 public void onCreate() {
...
425 if (phone == null) {
426 // Initialize the telephony framework
427 PhoneFactory.makeDefaultPhones(this);
428
429 // Get the default phone
430 phone = PhoneFactory.getDefaultPhone();
56 public static void makeDefaultPhone(Context context) {
...
130 sCommandsInterface =
new RIL(context, networkMode, cdmaSubscription);
132 int phoneType = getPhoneType(networkMode);
if (phoneType == Phone.PHONE_TYPE_GSM) {
135 sProxyPhone = new PhoneProxy(new GSMPhone(context,
sCommandsInterface, sPhoneNotifier));
137 } else if (phoneType == Phone.PHONE_TYPE_CDMA) {nullLet’s suppose the current network mode is in GSM/GPRS, so the default telephony application could obtain a PhoneProxy to a GSMPhone, and use its API to achieve telephony functionalities. ProxyPhone is also extended from Phone. It is used to abstract the specific instance of a specific network mode.
PhoneProxy.java
Telephony Framework 57 public PhoneProxy(Phone phone) {
58 mActivePhone = phone;
...
66 mCommandsInterface = ((PhoneBase)mActivePhone).mCM;
67 mCommandsInterface.registerForRadioTechnologyChanged(
68 this, EVENT_RADIO_TECHNOLOGY_CHANGED, null);
69 }
...
549 public void getPreferredNetworkType(Message response) {
550 mActivePhone.getPreferredNetworkType(response);
551 } nullThe class PhoneBase has a member mCM of the type CommandsInterface. And this is assigned in the constructor of GSMPhone.
GSMPhone.java
PhoneBase.java
Telephony Framework114 public CommandsInterface mCM;
...
203 protected PhoneBase(PhoneNotifier notifier, Context context, CommandsInterface ci,
204 boolean unitTestMode) {
207 mLooper = Looper.myLooper();
mCM = ci;
...
757 public void getPreferredNetworkType(Message response) {
758 mCM.getPreferredNetworkType(response);
759 }130 GSMPhone (Context context, CommandsInterface ci, PhoneNotifier notifier,
boolean unitTestMode) {
131 super(notifier, context, ci, unitTestMode);
...nullAll the telephony functionalities which need sending AT command to RIL daemon should be achieved by the the interface CommandsInterface. And the class RIL implements this interface. Moreover, RIL also extends the abstract class BaseCommands to provide unsolicited result code to default telephony application.
CommandsInterface.java
BaseCommands.java
RIL.java
Telephony Framework27 public interface CommandsInterface {
1332 void getPreferredNetworkType(Message response);36 public abstract class BaseCommands implements CommandsInterface { 199 public final class RIL extends BaseCommands implements CommandsInterface {
1861 public void getPreferredNetworkType(Message response) {
1862 RILRequest rr = RILRequest.obtain(
1863 RILConstants.RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE, response);
1867 send(rr); //call sender and send to targetnullThis figure show how RILJ communicates with RILC
RIL_REQUEST_XXX and RIL_UNSOLE_XXX are defined the same in RILC and FrameworkTelephony FrameworkRILSenderRILReciverril-daemonModuleRIL_REQUEST_XXXAT_COMMAND_XXXRESPONSEUNSOLED RESPONSERIL_UNSOLE_XXXREQUEST_COMPLETEUnsolicited ResponseSolicited ResponsenullState Machine (frameworks/base/core/java/com/android/internal/util/StateMachine.java)
104 mP0
105 / \
106 mP1 mS0
107 / \
108 mS2 mS1
109 / \ \
110 mS3 mS4 mS5 ---> initial state
111 *
112 * After starting mS5 the list of active states is mP0, mP1, mS1 and mS5.
113 * So the order of calling processMessage when a message is received is mS5,
114 * mS1, mP1, mP0 assuming each processMessage indicates it can't handle this
115 * message by returning false or NOT_HANDLED.
116 *
117 * Now assume mS5.processMessage receives a message it can handle, and during
118 * the handling determines the machine should change states. It could call
119 * transitionTo(mS4) and return true or HANDLED. Immediately after returning from
120 * processMessage the state machine runtime will find the common parent,
121 * which is mP1. It will then call mS5.exit, mS1.exit, mS2.enter and then
122 * mS4.enter. The new list of active states is mP0, mP1, mS2 and mS4. So
123 * when the next message is received mS4.processMessage will be invoked.
Setup Data ConnectionMost used function:
enter() – Called when enter this state
exit() – Called when exit current state
transitionTo() –Switch to other state
deferMessage() –Push msg to the front of queue
when transitioned to next state
processMessage() –Like handleMessage()nullDcDefaultState (The parent state for all other states)DcDisconnectionError
CreatingConnectionDcActivingStateDcActiveStateDcDisconnectingStateDcInactiveState
(initial state)EVENT_CONNECT(EVENT_SETUP_DATA_CONNECTION_DONE
&&(ERR_BadCommand||ERR_RilError))
|| EVENT_GET_LAST_FAIL_DONEEVENT_DEACTIVATE_DONEEVENT_SETUP_DATA_CONNECTION_DONE && SetupResult ==SUCCESSEVENT_SETUP_DATA_CONNECTION_DONE
&& SetupResult == ERR_UnacceptableParameterEVENT_DEACTIVATE_DONEEVENT_DISCONNECTSetup Data ConnectionDataconnection.java maintained a dataconnection state machinenullGsmDataConnectionTrackerDataConnection/GsmDCRILJEVENT_CONNECTDcInactiveStateDISCONNECTDcActivingStateDcActiveStateOnDataSetupComplete->
NotifyDefaultData->
Phone.notifyDataConnection->
mNotifier.notifyDataConnection(this, reason);EVENT_SETUP_DATA_
CONNECTION_DONE(GsmDC)onConnect(cp)
phone.mCM.setupDataCallSetup Data ConnectiontrySetupData->setupData
dc.bringUp()RIL_REQUEST_SET
UP_DATA_CALLnullSetup Data ConnectionRILJ
RILSenderRILReceiverAT+CGDCONT=1,"IP",“3gnet“
AT+CGDATA="PPP",1
onRequest()onRequestComplete()Parcel p
{user, apn ,password…}
Modem
RIL_REQUEST_SETUP_DATA_CALLrequest_setup_default_pdp_ppp
setup_ppp_connection()
at_send_command()Switch(request){
case AT < OK
…pppd
enable_ppp_interface
(create two threads)start_ipcheck_threadstart_ppp_threadParcel p
{ ppp0, ip, dns…}RILDAT commandssocketCreate LCP
IPCP protocol
DNS saved in propertyHow to establish a connection in rilRIL_REQUEST_SETUP_DATA_CALLnullHow huawei lib-ril process RIL_REQUEST_SETUP_DATA_CALL:
Vendor version: huawei ril 2.3
ril-ps.c
55 void hwril_request_ps (int request, void *data, size_t datalen, RIL_Token token)
56 {
57 switch (request) {
58 case RIL_REQUEST_SETUP_DATA_CALL:
59 {
60 #ifdef HUAWEI_RMNET
61 request_setup_default_pdp_rmnet( request, data, datalen,token);
62 #else
63 request_setup_default_pdp_ppp( request, data, datalen,token);
...
//in function request_setup_default_pdp_ppp
204 apn = ((const char **)data)[2];
205 user = ((const char **)data)[3];
...
247 ret = setup_ppp_connection(t, pdp_apn, ppp_user, ppp_passwd);
...
//in function setup_ppp_connection
363 /* Step1: Define the CID */
366 asprintf(&cmd, "AT+CGDCONT=%s,\"IP\",\"%s\"", DEFAULT_CID, apn );
367 err = at_send_command(cmd, &p_response);
378 /* Step2: Active the PDP Context */
380 asprintf(&cmd, "AT+CGDATA=\"PPP\",%s", DEFAULT_CID);
389 /* Step3: Enable the network interface */
394 int ret = enable_ppp_interface(token,cid, user, passwd);Setup Data ConnectionnullHow huawei lib-ril process RIL_REQUEST_SETUP_DATA_CALL:
Vendor version: huawei ril 2.3
ril-ps-api.c
//in function enable_ppp_interface, start two threads
611 sprintf(shell, "/system/bin/pppd %s 115200 mru 1280 nodetach debug dump
defaultroute usepeerdns novj noauth novjccomp noipdefault
ipcp-accept-local ipcp-accept-remote connect-delay 5000 ", ppp_device_path);
618 if((ret = start_ppp_pthread()) < 0)
//call system(shell), and dns will saved in property “net.ppp0.dns1”
624 sleep(1);
625 if((ret = start_ip_check_pthread(token))<0)
//in function start_ip_check_pthread
495 RIL_Data_Call_Response_v6 *response =
(RIL_Data_Call_Response_v6 *)malloc(sizeof(RIL_Data_Call_Response_v6));
...
509 ifc_get_info("ppp0", &myaddr, NULL, NULL); //get ip address
516 property_get("net.ppp0.dns1", dns, ""); //get dns
...
537 response->ifname = "ppp0";
538 response->addresses = ipaddress;
539
540 RIL_onRequestComplete(t, RIL_E_SUCCESS, response,
sizeof(RIL_Data_Call_Response_v6));Setup Data ConnectionnullTelephony framework needs to track the network return value and events happened in RIL daemon. At the same time, default telephony application should also be able to be notified by telephony framework.
In the constructor of GSMPhone, a GsmServiceStateTracker would be created to track the network status. And in the contructor of GsmServiceStateTracker, it would register to RIL for network status message.
gsm/GSMPhone.java
gsm/GsmServiceStateTracker.java
101 GsmServiceStateTracker mSST;
130 public GSMPhone (Context context, CommandsInterface ci, PhoneNotifier notifier,
boolean unitTestMode) {
...
139 mSST = new GsmServiceStateTracker (this);186 public GsmServiceStateTracker(GSMPhone phone) {
189 this.phone = phone;
190 cm = phone.mCM;
204 cm.registerForVoiceNetworkStateChanged(this, EVENT_NETWORK_STATE_CHANGED, null);Net Status NotificationnullIt registers into a registrant list of BaseCommands.
BaseCommands.java
When network state changes, the endless loop waiting for the message in telephony framework will be notified by RIL daemon. And the message is deliverred to registrant.
RIL.java
58 protected RegistrantList mVoiceNetworkStateRegistrants = new RegistrantList();
...
324 public void registerForVoiceNetworkStateChanged(Handler h, int what, Object obj) {
325 Registrant r = new Registrant (h, what, obj);
327 mVoiceNetworkStateRegistrants.add(r);
328 }2395 private void
2396 processUnsolicited (Parcel p) {
...
2467 case RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED:
2468 if (RILJ_LOGD) unsljLog(response);
2469
2470 mVoiceNetworkStateRegistrants
2471 .notifyRegistrants(new AsyncResult(null, null, null));Net Status NotificationnullGsmServiceStateTracker is a subclass of Handler.
When RILJ call notifyRegistrants(), the registed handler obj will call sendMessage(msg), then handleMessage() will be call.
gsm/GsmServiceStateTracker.java
260 public void handleMessage (Message msg) {
261 AsyncResult ar;
262 int[] ints;
263 String[] strings;
264 Message message;
265
266 switch (msg.what) {
...
304 case EVENT_NETWORK_STATE_CHANGED:
305 pollState();
306 break;Net Status NotificationnullOpen telephony packages:
frameworks/base/telephony/java/android/telephony
TelephonyManager provides a way for 3rd application interacting with internal telephony packages.
Class Overview (from android sdk document)
Provides access to information about the telephony services on the device. Applications can use the methods in this class to determine telephony services and states, as well as to access some types of subscriber information. Applications can also register a listener to receive notification of telephony state changes.
You do not instantiate this class directly; instead, you retrieve a reference to an instance through Context.getSystemService(Context.TELEPHONY_SERVICE).
Note that access to some telephony information is permission-protected. Your application cannot access the protected information unless it has the appropriate permissions declared in its manifest file. Where permissions apply, they are noted in the the methods through which you access the protected information.
Net Status NotificationnullThe figure show the relationship among Internal and Open telephony package and 3 applications.
PhoneService (phone service)
PhoneApp
TelephonyManager3rd ApplicationTelephonyRegistryPhoneStateListenerBoardCastGSM/CDMAPhoneRILJPhoneProxyITelephonyITelephonyRegistryDefaultPhoneNotifierNet Status NotificationPhoneFactoryPhoneInterfaceManagermCMril-daemonsocketnullIf we want to track telephony state in 3rd application:
We should retrive an instance of TelephonyManager and get Phone service.
Implement a PhoneStateListener what you want to listen.
You can also register a BroadCastReceiver to receive broadcast if you want.
Don’t forget add permission in manifest file.
Take Settings as example to show how to achieve these.
packages/apps/Settings/src/com/android/settings/deviceinfo/ Status.java
111 private TelephonyManager mTelephonyManager;
169 private PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
170 @Override
171 public void onDataConnectionStateChanged(int state) {
UpdateDataState(); //you can override with your own code here
178 protected void onCreate(Bundle icicle) {
184 mTelephonyManager = (TelephonyManager)getSystemService(TELEPHONY_SERVICE);
268 protected void onResume() {
278 mTelephonyManager.listen(mPhoneStateListener,
279 PhoneStateListener.LISTEN_DATA_CONNECTION_STATE);
337 private void updateDataState() {
338 int state = mTelephonyManager.getDataState();
341 switch (state) {Net Status NotificationConstant value is “phone” nullframeworks/base/telephony/java/android/telephony/PhoneStateListener.java
frameworks/base/services/java/com/android/server/TelephonyRegistry.java
228 public void onDataConnectionStateChanged(int state) {
229 // default implementation empty
230 }
282 IPhoneStateListener callback = new IPhoneStateListener.Stub() {
310 public void onDataConnectionStateChanged(int state, int networkType) {
311 Message.obtain(mHandler, LISTEN_DATA_CONNECTION_STATE, state, networkType).
312 sendToTarget();
313 }
328 Handler mHandler = new Handler() {
329 public void handleMessage(Message msg) {
350 case LISTEN_DATA_CONNECTION_STATE:
351 PhoneStateListener.this.onDataConnectionStateChanged(msg.arg1, msg.arg2);
54 class TelephonyRegistry extends ITelephonyRegistry.Stub {
137 public void listen(String pkgForDebug, IPhoneStateListener callback, int events,
138 boolean notifyNow) {
159 r.callback = callback; //a IPhoneStateListener
432 if ((r.events & PhoneStateListener.LISTEN_DATA_CONNECTION_STATE) != 0) {
433 try {
434 r.callback.onDataConnectionStateChanged(mDataConnectionState,
435 mDataConnectionNetworkType);
Net Status Notificationnullframeworks/base/telephony/java/com/android/internal/telephony/DefaultPhoneNotifier.java
Net Status Notification33 public class DefaultPhoneNotifier implements PhoneNotifier {
37 private ITelephonyRegistry mRegistry;
40 DefaultPhoneNotifier() {
41 mRegistry = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(
42 "telephony.registry"));
43 }
103 public void notifyDataConnection(Phone sender, String reason, String apnType,
126 mRegistry.notifyDataConnection(
127 convertDataState(state), ...33 public class DefaultPhoneNotifier implements PhoneNotifier {
37 private ITelephonyRegistry mRegistry;
40 DefaultPhoneNotifier() {
41 mRegistry = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(
42 "telephony.registry"));
43 }
103 public void notifyDataConnection(Phone sender, String reason, String apnType,
126 mRegistry.notifyDataConnection(
127 convertDataState(state), ...33 public class DefaultPhoneNotifier implements PhoneNotifier {
37 private ITelephonyRegistry mRegistry;
40 DefaultPhoneNotifier() {
41 mRegistry = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService(
42 "telephony.registry"));
43 }
103 public void notifyDataConnection(Phone sender, String reason, String apnType,
126 mRegistry.notifyDataConnection(
127 convertDataState(state), ...OnDataSetupComplete->
NotifyDefaultData->
Phone.notifyDataConnection->
mNotifier.notifyDataConnection(this, reason); case ...
…
case
EVENT_SETUP_DATA_CONNECTION_DONEGsmDataConnectionTrackernullQ & A
Any questions?nullThanks!
本文档为【Android_Telephony_Architecture】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑,
图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。