Mobile Phone Handheld Hardware Hardware Rick Rogers John Lombardo O'Reilly Media, Inc. O'Reilly Media Android Application Development, 1st Edition15.2. Android Telephony InternalsThe rest of this chapter covers telephony-related classes in
the internals package that only PhoneApp uses,
android.internal.telephony. This package is layered
over an implementation of telephony internals for a particular telephony
technology, such as GSM or CDMA. That layer, in turn, communicates with a
Radio Interface Layer (RIL) that is implemented as a daemon in Android. Figure 15-1 shows
the architecture of the Android telephony system. PhoneApp supports an
Intent that enables other applications to start phone calls. The Telephony
Manager is available through Listeners, as shown in the previous
section. 
15.2.1. Inter-Process Communication and AIDL in the android.internal.telephony PackageMany of the internal packages use the remote methods feature
discussed in Section 13.2. The
TelephonyManager and
PhoneStateListener classes rely on this to
communicate with PhoneApp. The ServiceManager class
is also used. To marshall data for remote methods, the package includes AIDL
files. For instance, the following AIDL comes from IPhoneStateListener.aidl: oneway interface IPhoneStateListener {
void onServiceStateChanged(in ServiceState serviceState);
void onSignalStrengthChanged(int asu);
void onMessageWaitingIndicatorChanged(boolean mwi);
void onCallForwardingIndicatorChanged(boolean cfi);
// we use bundle here instead of CellLocation so it can get the right subclass
void onCellLocationChanged(in Bundle location);
void onCallStateChanged(int state, String incomingNumber);
void onDataConnectionStateChanged(int state);
void onDataActivity(int direction);
}15.2.2. The android.internal.telephony PackageThis package contains the classes and interfaces PhoneApp uses to
provide services to other applications that want to start phone calls,
and classes that define an API to the RIL. PhoneApp, like all parts of Android, is theoretically replaceable.
If your application needs to modify the classes used by PhoneApp, your
application will probably have to replace or modify PhoneApp, and should
provide the same services to other applications, using the classes in
this package. The description of these classes should help you understand how
Android interfaces to a mobile radio, and the capabilities that are
exposed—and not exposed—by PhoneApp to other applications. This is a
large and complex package, and a complete understanding will require
reading the Android source code. These descriptions will help you find
where to start for your purposes:
ATParseEx Extends RuntimeException and is thrown by methods of the
ATResponseParser class.
ATResponseParser This class parses part of the AT command syntax used to communicate
with the mobile radio hardware in a mobile handset. This is, in
fact, a command syntax very much like the AT command syntax used
by modems, a standard described in the 3GPP document number TS
27.007 and related specifications. This protocol for controlling
mobile radios is widely used.
Call This class is an abstract base class. Other classes use it as a
basis for objects that represent phone calls and the state of
those calls.
CallerInfo This class holds information about the party that originated
an incoming call. This class starts with caller ID information
from the mobile network interface and looks up other information
about a caller in the database of contacts.
CallerInfoAsyncQuery This class enables asynchronous database queries for
information that could be found about a caller based on the caller
ID information.
CallStateException The class extends Exception and is thrown by methods that
maintain call state in cases where state is inconsistent.
Connection This class is an abstract base class used by other classes,
and is a basis for objects that represent connections on the
mobile network and the state of these connections.
Connection objects can be associated with a
Call object, but they can also exist
independently. The data in a Connection object
can be especially useful in diagnosing the reason a call
failed.
DefaultPhoneNotifier This class implements the PhoneNotifier interface in order to
receive notifications from a Phone object. It
then uses the Android service system to communicate state to
Activity instances that have registered to receive those
notifications. See the Handler and
Mailbox classes for information on how to
receive notifications.
IPhoneStateListener This interface defines the signatures of methods an
application implements to receive notification of call state
change, and changes to forwarding and message-waiting
states.
IPhoneSubInfo This interface is used to obtain subscriber information.
ITelephony This interface defines the inter-process interface used
in TelephonyManager to enable applications to communicate with
PhoneApp.
ITelephonyRegistry This interface is the callback interface from the RIL
daemon.
MmiCode This interface defines callbacks related to "MMI codes."
These are special numbers a user can dial and key sequences that a
user can enter during a call to access, control, and administer
supplementary services, such as call waiting, call hold, etc. MMI
codes and related functionality are described in the 3GPP document
number TS 22.030.
Phone This interface includes callbacks and methods for
accessing the state of a mobile phone.
PhoneBase This class is an abstract base class that implements the
Phone interface.
PhoneFactory This class contains methods used to create instances of
the GSMPhone class, a subclass of the
Phone class.
PhoneNotifier This interface specifies the API a telephony implementation uses to
notify a phone state listener of state changes.
PhoneStateIntentReceiver This class handles Intent objects
that have intent types specified in the
TelephonyIntents class. This class enables
Android applications to use the Intents system to obtain phone
state information.
PhoneSubInfo This class contains methods for obtaining information about a
mobile service subscriber, such as the unique identifying number
for the handset (IMEI), the unique identifying number for the
subscriber (IMSI), the serial number of the SIM card, etc.
SimCard This interface defines the API for accessing the SIM
card.
TelephonyIntents This class defines constants for broadcast intents that have
similar functionality to the TelephonyManager API.
TelephonyProperties This class defines the constants used with the
SystemProperties class for setting and getting
telephony-related properties.
These classes are not documented in the Android SDK documentation,
but the descriptions here should give you some understanding of the
source code for these classes. 15.2.3. The android.internal.telephony.gsm PackageMany of the classes and interfaces in the previous section are
typical of a Java API that can have multiple implementations. The
implementations of the API defined in the
telephony.internal package correspond to a library
used in the RIL. To better understand this API, we will look at one
implementation here that supports GSM. Thus, this section delves further into the telephony internals of
Android, looking especially at how the interfaces and abstract base
classes are implemented and subclassed to enable access to the
functionality of GSM telephony. Although it may seem that specifications
such as TS 27.007 cover mobile telephony in general, this layer of
Android actually has to accommodate variations in mobile telephony
standards. In CDMA telephony, for instance, the SIM card is an optional
part of the standard and is rarely present in CDMA handsets. In this
case, the package described in this section would be replaced by a
CDMA-oriented package with a similar architectural relationship to the
higher-level classes described in the previous section. The RIL code is
also specific to the type of telephony in the handset. At the RIL layer, the differences between GSM and CDMA are mainly
outside the core functionality of making phone calls, so you may be
wondering why all these layers and APIs are necessary. But, as the
description of the classes specific to communicating with a GSM RIL will
show, there are plenty of differences in detail, such as SIM cards, the
type of mobile data network, etc. These make it impractical to design a
universal interface to mobile radios, despite the use of a standard
protocol for communicating with them:
AdnRecord This class is used to load and store Abbreviated Dialing Numbers (ADNs) to and from the
SIM card. ADNs are short numbers used for information calls,
emergency calls, etc.
AdnRecordCache This class caches and enables access to ADNs.
ApnSetting This class holds data specifying the access point name (APN)
and other parameters for connecting to General Packet Radio
Service (GPRS) and 3G mobile data networks. This mobile data
technology is specific to GSM networks.
BaseCommands This class implements the CommandsInterface interface, which
is used throughout the GSM telephony classes to
communicate with the GSM radio.
CallFailCause This interface defines constants for decoding failure
cause codes.
CallForwardInfo This class holds data that corresponds to the parameters of a
call-forwarding command to the RIL.
CallTracker This class maps information from the RIL to state transitions
for the GSMCall class.
CommandException This class is an exception thrown when the RIL reports an
error from a command.
CommandsInterface This interface defines the API to the GSM RIL. This interface is
implemented by the BaseCommands class.
DataConnectionTracker This tracks the state of GPRS packet data protocol (PDP)
connections. This type of connection is specific to GSM mobile
data.
DataLink This class implements the DataLinkInterface interface and is
used in the PPPLink class, which manages point
to point protocol (PPP) links in GPRS networking.
DataLinkInterface This class defines the API for connecting and
disconnecting PPP links.
DriverCall This class parses information, in AT command syntax, from the
mobile radio, and turns it into call state information.
EncodeException This class is an exception thrown by methods of the
GSM alphabet class, which encodes UTF-16 (as
used in Java) into the 7-bit SMS character set.
GSMAlphabet This class is a utility class containing static methods for
encoding UTF-16 to the 7-bit SMS character set.
GSMCall This class extends the Call class,
and implements the abstract methods of that class, thereby
implementing parts of the Android telephony internals API. This
class models calls in GSM telephony.
GSMConnection This class extends the Connection class,
and like the GSMCall class, implements the
abstract methods of the Connection class. This
class models connections in GSM telephony.
GSMPhone This class extends the Phone class and, as
with both the GSMCall and GSMConnection
classes, implements the abstract methods of the
Phone class.
GsmMmiCode This class implements the MmiCode interface and the part of
the telephony API defined in that interface.
GsmSimCard This class implements the SimCard interface, another part of
the implementation of the telephony internals API. This class
enables access to data in the SIM card.
ISimPhoneBook This interface defines an API for accessing ADN records stored in
the SIM card.
ISms This interface defines the API for sending SMS
messages.
MccTable This class is a utility class that contains a table of Mobile
Country Codes (MCCs). In principle, these codes are not specific
to a GSM RIL, but they are specific to this implementation of a
GSM RIL.
NetworkInfo This class is a container for network state
information.
PDPContextState This contains data about a PDP session, including the IP
address.
PdpConnection This class contains information about the data
connection associated with a PDP context.
PppLink This class extends DataLink and implements DataLinkInterface
to provide an implementation
of this part of the RIL interface.
RIL This class extends the BaseCommands class
and also implements the CommandsInterface interface, forming
a complete implementation of the interface for sending commands to
the RIL. This is where communication with the RIL takes place. An
instance of the RIL class is created in the
PhoneFactory class, in the course of creating
an instance of the GSMPhone class.
RILConstants This interface defines constants used in the
RIL class.
ServiceStateTracker This class polls the RIL daemon for signal strength and tracks
other aspects of the state of mobile service.
SIMFileHandler This enables access to the SIM filesystem.
SIMRecords This class enables access to specific files in the SIM
filesystem containing information such as the subscriber's
IMSI.
SimConstants This interface contains constants used in other classes accessing
data in the SIM.
SimException This class extends Exception and is used in other classes to throw an
exception related to errors accessing data in the SIM.
SimFileNotFound This class extends SimException and is used in the
SimIoResult class in specific error
conditions.
SimPhoneBookInterfaceManager This class extends
ISimPhoneBook and provides a service interface for accessing ADN
records in the SIM.
SimProvider This class extends ContentProvider and
creates a content provider interface to SIM ADN/SDN/FDN records in
the SIM.
SimSmsInterfaceManager This class extends ISms and creates a service interface for accessing SMS
messages stored in the SIM.
SimTlv This class is an object interface for accessing
tag-length-value records in the SIM, and is used in the
SIMRecords class.
SimUtils This class contains static utility methods for manipulating
data encoded in binary-coded
decimal and other encodings encountered in SIM data.
SMSDispatcher This class implements the sending of SMS messages and notifies
applications that use the Handler interface to this class
regarding the status of SMS messages.
SmsHeader This class contains constants and methods for decoding SMS
headers.
SmsRawData This class implements Parcelable and is used in implementing
service interfaces for accessing SIM data.
SmsResponse This class associates a message reference with an
acknowledgment.
SuppServiceNotification This class contains constants for decoding information about
supplementary services.
VoiceMailConstants This class parses information in the etc/voicemail-conf.xml
file.
There is another package organized hierarchically under the
internal.telephony.gsm package: the
stk package, which contains classes for accessing the
SIM. This package is not exposed outside the
internal.telephony.gsm package and is beyond the
scope of this chapter. 15.2.4. Exploring Android Telephony InternalsA lot of code lies between creating an ACTION_CALL Intent object and dialing a call. Here we will go even deeper into
Android's telephony system to see what Android is telling the mobile
radio, and match that up with what we have done in the example
application earlier in this chapter. To see how, and when, Android actually commands the hardware to
dial a number, we can use Android's logging system. To access the log
buffer for information about the traffic between Android software and
the mobile radio, we will also have to use the Android Debug Bridge,
adb. We will start a shell that can run commands
in the emulator, and we will use the logcat utility to display logging information as it becomes
available. First, set a breakpoint in the example application on line 25,
where the Intent object is created and before the
call to the startActivity method. Then, start the application with the debugger: Select Run Debug.
When the "Debug as" dialog appears, select Android Application. The application will run and stop at the breakpoint. Now look at the log. Open a command-line window and change your
working directory to the directory where you have put the Android SDK.
There you should see a directory named tools. Change your working directory to
tools. You should see a program
there named adb. Next, use adb to find the name of the
emulator that is running as a result of starting the application with
the debugger. Type the following: ./adb devices adb will list all the emulators running,
which should be just one. The output will look something like
this: ...
emulator-5554 device
Now use adb to start a shell that can run
programs in the emulator (if adb finds an emulator with a different name on your
system, use that name instead of "emulator-5554"): ./adb -s emulator-5554 shell This will result in a shell prompt: # The shell you are now typing commands into is executing those
commands in the emulator. Now use the logcat
command to show the log of traffic between the mobile radio and the
RIL: # logcat -b radio This will result in a lengthy listing of AT commands and
responses. For the most part, they are asking for and reporting the
signal strength. This is what the RIL and the mobile radio are doing
when nothing else is going on. The lines tagged D/AT are the verbatim AT
commands exchanged between the mobile radio and the RIL. The ones
labeled AT> are from the RIL to the mobile radio,
and the ones labeled AT< are from the mobile radio
to the RIL. The other lines in the log are a more-readable decoding of
the information in the AT commands. You can see the part of the RIL
interface in Java logging requests sent to the RIL daemon, RILD, and the
RIL code in RILD logging as it sends the appropriate AT commands to the
mobile radio and decodes the results. Now use the Eclipse debugger to step over the line where the
Intent object is created. Looking at the log output,
you see that nothing interesting has happened yet: the RIL and the
mobile radio (really, an emulation of a mobile radio) are polling the
signal strength. Step over the next line, where the phone number is
added to the Intent object and, similarly, nothing
has happened yet. Now step over the next line, which should look like this: startActivity(callIntent); Here we get quite a bit of interesting output from the logger. It
should look something like this: D/GSM ( 85): [GSMConn] update: parent=DIALING, hasNewParent=false,
wasConnectingInOrOut=true, wasHolding=false, isConnectingInOrOut=true,changed=false
D/RILJ ( 85): [0161]> SET_MUTE false
D/RIL ( 22): onRequest: SET_MUTE
D/RILJ ( 85): [0161]< SET_MUTE error:
com.android.internal.telephony.gsm.CommandException: REQUEST_NOT_SUPPORTED
D/RILJ ( 85): [UNSL]< CALL_STATE_CHANGED
D/RILJ ( 85): [0162]> GET_CURRENT_CALLS
D/RIL ( 22): onRequest: GET_CURRENT_CALLS
D/AT ( 22): AT> AT+CLCC
D/AT ( 22): AT< +CLCC: 1,0,2,0,0,"9785551212",129
D/AT ( 22): AT< OK
D/RILJ ( 85): [0162]< GET_CURRENT_CALLS [id=1,mo,DIALING,voice,norm,129,0]
D/GSM ( 85): [GSMConn] update: parent=DIALING, hasNewParent=false,
wasConnectingInOrOut=true, wasHolding=false, isConnectingInOrOut=true, changed=false
D/AT ( 22): AT< RING
D/RILJ ( 85): [UNSL]< CALL_STATE_CHANGED
D/RILJ ( 85): [0163]> GET_CURRENT_CALLS
D/RIL ( 22): onRequest: GET_CURRENT_CALLS
D/AT ( 22): AT> AT+CLCC
D/AT ( 22): AT< +CLCC: 1,0,3,0,0,"9785551212",129
D/AT ( 22): AT< OK
D/RILJ ( 85): [0163]< GET_CURRENT_CALLS [id=1,mo,ALERTING,voice,norm,129,0]
D/GSM ( 85): [GSMConn] update: parent=ALERTING, hasNewParent=false,
wasConnectingInOrOut=true, wasHolding=false, isConnectingInOrOut=true, changed=true
D/RILJ ( 85): [0164]> SET_MUTE false
D/RIL ( 22): onRequest: SET_MUTE
D/RILJ ( 85): [0164]< SET_MUTE error:
com.android.internal.telephony.gsm.CommandException:
REQUEST_NOT_SUPPORTED
D/RILJ ( 85): [UNSL]< CALL_STATE_CHANGED
D/RILJ ( 85): [0165]> GET_CURRENT_CALLS
D/RIL ( 22): onRequest: GET_CURRENT_CALLS
D/AT ( 22): AT> AT+CLCC
D/AT ( 22): AT< +CLCC: 1,0,3,0,0,"9785551212",129
D/AT ( 22): AT< OK
D/RILJ ( 85): [0165]< GET_CURRENT_CALLS [id=1,mo,ALERTING,voice,norm,129,0]
D/GSM ( 85): [GSMConn] update: parent=ALERTING, hasNewParent=false,
wasConnectingInOrOut=true,
wasHolding=false, isConnectingInOrOut=true, changed=false
D/RILJ ( 85): [UNSL]< CALL_STATE_CHANGED
D/RILJ ( 85): [0166]> GET_CURRENT_CALLS
D/RIL ( 22): onRequest: GET_CURRENT_CALLS
D/AT ( 22): AT> AT+CLCC
D/AT ( 22): AT< +CLCC: 1,0,3,0,0,"9785551212",129
D/AT ( 22): AT< OK
D/RILJ ( 85): [0166]< GET_CURRENT_CALLS [id=1,mo,ALERTING,voice,norm,129,0]
D/GSM ( 85): [GSMConn] update: parent=ALERTING, hasNewParent=false,
wasConnectingInOrOut=true,
wasHolding=false, isConnectingInOrOut=true, changed=false
D/RILJ ( 85): [UNSL]< CALL_STATE_CHANGED
D/RILJ ( 85): [0167]> GET_CURRENT_CALLS
D/RIL ( 22): onRequest: GET_CURRENT_CALLS
D/AT ( 22): AT> AT+CLCC
D/AT ( 22): AT< RING
D/AT ( 22): AT< +CLCC: 1,0,0,0,0,"9785551212",129
D/AT ( 22): AT< OK
D/RILJ ( 85): [UNSL]< CALL_STATE_CHANGED
D/RILJ ( 85): [0167]< GET_CURRENT_CALLS [id=1,mo,ACTIVE,voice,norm,129,0]
D/RILJ ( 85): [0168]> GET_CURRENT_CALLS
D/RIL ( 22): onRequest: GET_CURRENT_CALLS
D/AT ( 22): AT> AT+CLCC
D/AT ( 22): AT< +CLCC: 1,0,0,0,0,"9785551212",129
D/AT ( 22): AT< OK
D/RILJ ( 85): [0168]< GET_CURRENT_CALLS [id=1,mo,ACTIVE,voice,norm,129,0]
D/GSM ( 85): [GSMConn] update: parent=ACTIVE, hasNewParent=false,
wasConnectingInOrOut=true,
wasHolding=false, isConnectingInOrOut=false, changed=true
D/GSM ( 85): [GSMConn] onConnectedInOrOut: connectTime=1225978001674
D/RILJ ( 85): [UNSL]< CALL_STATE_CHANGED
D/RILJ ( 85): [0169]> SET_MUTE false
D/RIL ( 22): onRequest: SET_MUTE
D/RILJ ( 85): [0169]< SET_MUTE error:
com.android.internal.telephony.gsm.CommandException:
REQUEST_NOT_SUPPORTED
D/RILJ ( 85): [0170]> GET_CURRENT_CALLS
D/RIL ( 22): onRequest: GET_CURRENT_CALLS
D/AT ( 22): AT> AT+CLCC
D/AT ( 22): AT< +CLCC: 1,0,0,0,0,"9785551212",129
D/AT ( 22): AT< OK
D/RILJ ( 85): [0170]< GET_CURRENT_CALLS [id=1,mo,ACTIVE,voice,norm,129,0]
D/GSM ( 85): [GSMConn] update: parent=ACTIVE, hasNewParent=false,
wasConnectingInOrOut=false,
wasHolding=false, isConnectingInOrOut=false, changed=false What you are seeing here is a mobile call being started. The call
goes through three states: "dialing," "alerting," and "active." Take a
look at how the mobile radio reports the state of a call. Here the call
is in the "dialing" state: +CLCC: 1,0,2,0,0,"9785551212",129 Here the call is in the "alerting" state: +CLCC: 1,0,3,0,0,"9785551212",129 Here the call is in the "active" state: +CLCC: 1,0,0,0,0,"9785551212",129 The third number in the list of parameters in the AT command
response indicates the state of this call. The classes that model the
connection, call, and network state in PhoneApp and the TelephonyManager
API keep track of what RILD is telling the mobile radio and what the
mobile radio is telling RILD, and this is where that information comes
from. Now press the red End button (the one with the picture of a
telephone receiver) to end the call. Look for the AT commands that read
the state change from the mobile radio, and at the corresponding
TelephonyManager method call that notifies the
application of the change.
 |