Chapter 15. Telephony State Information and Android Telephony Classes

The previous chapter showed how to use Android’s built-in PhoneApp application, which simplifies the task of placing of phone calls. This chapter shows you how to get more information about telephone service and the actual calls you make.

After an example that puts one of the telephony features to use, we’ll present a short guide to PhoneApp internals.

Note

We use the term “telephony” to refer to the parts of the Android system that depend on a radio communicating with the public land mobile network (PLMN) to provide communication and location functions. Sharing the use of this radio among multiple applications is a key goal for Android’s telephony modules.

Operations Offered by the android.telephony Package

The android.telephony package contains a set of classes that can be used by any application in the Android environment to monitor the state of Android’s mobile network connection. It also contains classes for locating a device using the mobile network. Finally, it offers utility classes for parsing, formatting, and otherwise managing phone numbers, although there is no architectural benefit to locating those classes in this package.

The telephony package does not allow you to place, end, or otherwise meddle in phone calls; it focuses on retrieving information and giving users an interface to edit telephone numbers. We’ll explain later why Android reserves the actual control over phone calls to PhoneApp.

Package Summary

The android.telephony package contains the following packages:

CellLocation

Methods to request location information.

PhoneNumberFormattingTextWatcher

Callback methods that notify an application about changes to phone numbers themselves. When used with a TextView object, it formats the text as a phone number using methods in the PhoneNumberUtils class.

PhoneNumberUtils

A utility class that contains methods for processing strings containing phone numbers.

PhoneStateListener

Callback methods that track changes in the state of the mobile network connection, the call, or other telephony objects.

ServiceState

Methods that return information about the current mobile network service provider and the availability of service.

TelephonyManager

Methods that provide information about the state of mobile service, the call state, the SIM, the network, the subscriber to the mobile service, voicemail, and other related information.

Because these classes don’t control hardware or change state information about phone calls, they don’t have any access control.

Limitations on What Applications Can Do with the Phone

Some readers may be disappointed to see that the android.telephony package limits their access to getting information, and does not provide direct control over the dialer or the state of a call. There are good reasons for this. Essentially, providing a low-level telephony API that can be shared among multiple applications is perilous.

A mobile handset is a state machine that keeps track of the mobile radio reports, provides audible call state indications to the user, and enables the user to provide inputs that modify that state. Even if you could design an API that would, hypothetically, share a mobile radio among multiple applications on a per-call basis, the user interface and ergonomic design that would go along with shared control among multiple applications would be difficult and probably even intractable. A phone is not like a PC with a desktop user interface: you can’t share control over the parts of a device that constitute the phone the way you can share the screen of a PC.

Android provides a workable solution that keeps telephony usable while making as much of the system open to your applications as is practicable. As we saw in the previous chapter, PhoneApp exposes an Intent that lets other applications initiate phone calls, while enabling a single application to control the mobile radio in an Android handset. The android.telephony package further exposes information about telephone service and the calls made by an application.

It’s useful to think of telephony on Android as an interface that keeps critical functions private while providing public APIs for functions where it is safe to do so. This is a good example of a successful Android design strategy.

Example: Determining the State of a Call

This section shows how to track the state of a phone call. It adds some of the classes described in the previous section to the application shown in Creating an Example Application to Run the call Method, which finds and uses PhoneApp to start and control a phone call. Here, in addition to starting a phone call and letting PhoneApp control it, the application gets some information about the call as it is happening.

In order to get this information, we need to extend the PhoneStateListener class, make an instance of our subclass, and pass that instance to the TelephonyManager.listen method. Example 15-1 shows the code for our subclass of the PhoneStateListener class.

Example 15-1. Defining a Listener for telephone call state
private class ListenToPhoneState extends PhoneStateListener {

    public void onCallStateChanged(int state, String incomingNumber) {1
        Log.i("telephony-example", "State changed: " + stateName(state));2
    }

    String stateName(int state) {3
        switch (state) {
            case TelephonyManager.CALL_STATE_IDLE: return "Idle";
            case TelephonyManager.CALL_STATE_OFFHOOK: return "Off hook";
            case TelephonyManager.CALL_STATE_RINGING: return "Ringing";
        }
        return Integer.toString(state);
    }
}

The lines we’ve highlighted are:

1

Overrides the onCallStateChanged method of the PhoneStateListener class.

2

Adds a message to Android’s log whenever the state changes.

3

Chooses meaningful strings to represent call states.

In this subclass of the PhoneStateListener class, we override the onCallStateChanged method, which Android calls when a call’s state changes. We use the Log class, a static class with utility methods for logging information, to log the changes as Android passes them to us.

Finally, our stateName method decodes the states that correspond to the constants defined in the TelephonyManager class to make the log more readable.

Returning to our main application from Creating an Example Application to Run the call Method, we have to change it by creating a Listener and assigning our subclass of PhoneStateListener to it. Here is the code for the entire modified example application, which now tracks and logs state transitions:

package example.telephony;

import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.telephony.PhoneStateListener;1
import android.telephony.TelephonyManager;1
import android.util.Log;

public class telephonyExplorer extends Activity {
ListenToPhoneState listener;2

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        call();
    }

    private void call() {
        try {
            Intent callIntent = new Intent(Intent.ACTION_CALL);
            callIntent.setData(Uri.parse("tel:9785551212"));
            startActivity(callIntent);

            TelephonyManager tManager = (TelephonyManager) 
              getSystemService(Context.TELEPHONY_SERVICE);3
            listener = new ListenToPhoneState();4
            tManager.listen(listener, PhoneStateListener.LISTEN_CALL_STATE);
        } catch (ActivityNotFoundException activityException) {
            Log.e("telephony-example", "Call failed", activityException);
        }
    }

    private class ListenToPhoneState extends PhoneStateListener {5

        public void onCallStateChanged(int state, String incomingNumber) {
            Log.i("telephony-example", "State changed: " + stateName(state));
        }

        String stateName(int state) {
            switch (state) {
                case TelephonyManager.CALL_STATE_IDLE: return "Idle";
                case TelephonyManager.CALL_STATE_OFFHOOK: return "Off hook";
                case TelephonyManager.CALL_STATE_RINGING: return "Ringing";
            }
            return Integer.toString(state);
        }
    }
}

The lines we’ve highlighted are:

1

New classes that must be imported to add a Listener for the telephone call state.

2

Adds a definition for the Listener.

3

Connects to Android’s telephone call manager.

4

Assigns our extended Listener class (defined at item 5) to the variable defined in item 2.

5

Code from Example 15-1, defining our Listener.

Running this application results in output to the log window in Eclipse that should look something like this:

11-19 01:47:03.704: INFO/telephony-example(159): State changed: Idle
11-19 01:47:04.774: INFO/telephony-example(159): State changed: Off hook

Android Telephony Internals

The 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.

Layers of telephony packages
Figure 15-1. Layers of telephony packages

Inter-Process Communication and AIDL in the android.internal.telephony Package

Many of the internal packages use the remote methods feature discussed in Remote Methods and AIDL. 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);
}

The android.internal.telephony Package

This 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.

The android.internal.telephony.gsm Package

Many 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.

Exploring Android Telephony Internals

A 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.

Android and VoIP

You may have come to the end of this description of Android telephony surprised, and perhaps disappointed, to find no mention of Voice over IP (VoIP). After all, GoogleTalk supports voice calls from PC to PC. Why was this capability omitted from the core telephony functionality of Android?

Android was not designed to treat VoIP calls and mobile calls similarly or, from a programmer’s perspective, through the same APIs. What you see described in this chapter is an abstraction for mobile telephony, not telephony in general. AT commands that are nearly universal in mobile telephony—and that are not used outside mobile telephony—pervade the APIs described here all the way up to the PhoneApp application. The inter-process interfaces are designed around capabilities of mobile telephony, mobile messaging, and mobile data.

As a result, designers of VoIP technologies for Android are left with some design decisions. The current direction treats VoIP as a separate application and makes it possible in the future to provide a very high-level integration with other parts of the system—for example, supporting the ACTION_CALL call in Intent objects. This development would give the user a choice between Android’s built-in mobile telephony and an add-on for VoIP telephony.

A deeper integration of mobile telephony and VoIP can be implemented in Android, but it would require extending the functionality of PhoneApp to encompass both IP and conventional mobile telephony, while providing a compatible interface to applications written to Android’s TelephonyManager API.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
35.171.45.182