1. Smart Phones Are Still Phones.
After working with Android telephony for a while and learning about it mostly by looking at the code, I
realized that there was not enough documentation about it besides the code itself. This post will
provide detailed walk through about the java telephony internals.
The android telephony architecture is split between java and native code. As of today there is a clear
documentation about the native layer (http://pdk.android.com/online-pdk/guide/telephony.html), however
there is no documentation about the java layer architecture itself.
The android framework classes interact with the Phone API (com.android.internal.telephony.Phone)
through two basic method types. Both are based on asynchronous message exchanges.
public void get[...](Message response);
The first type provides a way to get radio and/or network related information asynchronously by passing
an android.os.Message class instance. The message will be delivered to the message's handler when the
response from the underlying radio interface layers becomes available.
public void registerFor[...](Handler h, int what, Object obj);
The second type provides a way to get radio/network state updates by registering to receive response
messages of the specified type (what parameter) to the specified handler (h parameter) and an optional
user object (obj parameter) within the message instance.
The first type of method will call the underlying com.android.internal.telephony.RIL class directly,
passing down the message object to be dispatched when the response is available from the underlying
layers. The second type may have one or more android.os.Handler instances registered for status
updates, they are wrapped on android.os.Registrant objects as weak references in order to allow them to
be garbage collected. Because they are not referenced anywhere else, it does not worth sending updates
or keeping track of them. The registrants for each register method are stored on
android.os.RegistrantList instances so they can be referenced for the future updates.
2. The communication between the java and native layers is done through a Linux local socket. Every
request to the native layer is wrapped into an instance of the
com.android.internal.telephony.RILRequest class in order to keep the request information stored until
the response is returned the bottom layers. When the response arrives the RILRequest object for the
original request will be retrieved from the pending requests list in order to resolve the destination
handler to dispatch the response to. The RILRequest class has the following attributes in order to keep
the request information:
• int mSerial; // The request sequence number
• int mRequest; // The request code
• Message mResult; // The result message to be dispatched upon response
• Parcel mp; // The parcel where the raw data will be written and sent though the socket
Once the request object is retrieved or created from the requests pool, every public void get[...]
(Message response); method will write its parameters (if any) into the request object's Parcel instance
field(mp) and send it to the com.android.internal.telephony.RIL.RILSender class. The RILSender class is
a handler that runs on its own looper thread, waiting for new RIL requests to be sent to the native
layers through the socket connected to the RIL daemon as shown on the diagram above. The sender main
responsibilities are to store the request object instance into the pending requests list, marshall the
parcel into a raw byte array and send it through the socket. The raw request format is specified
bellow:
Right now you already know how the requests are sent down to the native layers, but how the request
handlers get the response messages back? The com.android.internal.telephony.RIL.RILReceiver class runs
on its own thread listening on the RIL daemon socket for asynchronous responses. Its main
responsibilities in opposition to the RILSender are to unmarshall the raw data into a
android.os.Parcel, process the response and dispatch it inside a message object to its target handler.
There are two kinds of responses that come from the native RIL, solicited and unsolicited commands (see
details at http://pdk.android.com/online-pdk/guide/telephony.html). The raw response format for the
response types is specified bellow:
Solicited Commands:
Unsolicited Commands:
In conclusion, the java and native layers communicate with each other asynchronously through a socket
passing requests/responses up and down the stack.
NOTE: All this article information is based on the Android Open Source Project source code. For details
see http://source.android.com/.
Hope you all the best,
David Marques