Today I will talk about how the interaction with the modem in the Android OS is arranged. This article describes the structure of the components of the Android operating system responsible for network communication over packet data transmission protocols - GPRS, EDGE, 3G, etc.
This article contains a large amount of theory, the practice will be in the
second article.
Air Interface Layer Description
Consider the so-called radio interface layer, from English - Radio Interface Layer. In the Android OS, it represents an abstract layer between the telephony service (android.telephony) and the modem.

Figure 1. Air interface layer.
In Figure 1, the radio interface layer is highlighted in red, which includes:
- java radio interface layer;
- Ril demon;
- event planner;
- RIL manufacturer.
The components of the radio interface layer perform the following tasks:
The radio interface Java layer (RIL Java) sends requests to the RIL daemon via the local Linux socket / dev / socket / rild. Java RIL sources are located in the /telephony/java/com/android/internal/telephony/gsm/RIL.java file.
The RIL daemon loads and initializes the producer and event scheduler RIL. The source code for the RIL daemon is located in the / hardware / ril / rild / directory.
Event Scheduler processes the requested and unsolicited commands. It is an intermediary between Java RIL and the manufacturer RIL. The event scheduler source codes are located in the / hardware / ril / libril / directory.
The manufacturer’s RIL initializes the modem, interacts directly with the modem. The manufacturer’s RIL is a dynamic library developed by the modem manufacturer. The development template is located in the / hardware / ril / reference-ril / directory. The most popular manufacturers of modems for mobile devices today are Intel and Qualcomm, and the source codes of libraries are not available.
')
The internal structure of the RIL demon
Figure 2 shows the internal structure of the RIL daemon. The task of the RIL daemon is to initialize the air interface layer when the OS starts. After examining a small amount of the RIL daemon code, you can see that it performs its work according to the following algorithm:
1. From the system settings, reads the path to the manufacturer’s RIL (rild.libpath) and system properties that are used by the manufacturer’s RIL.
2. Loads the manufacturer's RIL and starts the event loop in the event scheduler.
3. Calls the RIL_Init function to initialize and get references to the manufacturer’s RIL functions.
4. Calls the RIL_register function to register the event scheduler for references to the manufacturer’s RIL functions.

Figure 2. The internal structure of the RIL daemon.
There are two types of interaction between the components of a radio interface layer:
solicited (solicited) and
unsolicited (unsolicited) commands. The requested commands are initiated by the telephony service, for example, an outgoing call, the establishment of an Internet connection. Unsolicited commands are initiated by the modem, for example, an incoming SMS message, an incoming call.
Communication between the telephony service and the event planner
The interaction between Java RIL and the event scheduler takes place via the local Linux socket
/ dev / socket / rild . Each request to the library level is recorded in an instance of the
com.android.internal.telephony.RILRequest class, to save information about the request, until a response is received from the underlying layers of the radio interface.
Request parameters are written to the parcel structure, and the request itself is sent to the
com.android.internal.telephony.RIL.RILSender class. The format of the request is shown in the figure below:

The
com.android.internal.telephony.RIL.RILReceiver class listens on a local Linux socket, awaiting responses from the event scheduler. RILReceiver receives two types of responses: the requested and unsolicited. Their format is presented in the figures below.

Figure 4. The format of the requested response.

Figure 5. The format of the unsolicited response.
The implementation of the manufacturer's RIL
To implement a manufacturer’s RIL, a modem manufacturer develops a dynamic library that implements many of the functions that the Android operating system needs to handle requests addressed to a modem. Its name is determined by the following agreement: libril- <company name> - <version RIL> .so
The header file /include/telephony/ril.h contains:
- description of a set of structures, for example: RIL_RadioState, RIL_Data_Call_Response;
- function prototypes, for example: RIL_Init, RIL_onRequestComplete;
- numeric definitions for the requested and unsolicited commands, for example: # define RIL_REQUEST_SETUP_DATA_CALL 27.
The radio interface layer is hardware independent and the manufacturer’s RIL can use any protocol to communicate with the modem. As a rule, many standardized Hayes AT-commands are used, however, some modem manufacturers supplement the standard set of AT-commands with their own extensions.
To manage the requested commands, the modem manufacturer must implement a set of functions, the prototypes of which are described below. The request types of the requested commands are defined in the ril.h header file with the prefix RIL_REQUEST_.
void (*RIL_RequestFunc)(int request,void *data, size_t datalen,RIL_Token t)
this is the function of processing the requested commands. It is this one that processes the requested commands, which are defined in the ril.h header file and begin with the prefix RIL_REQUEST_. RIL_RadioState (*RIL_RadioStateRequest)()
This function returns the current state of the modem. int (*RIL_Supports)(int requestCode)
the function returns 1 if the given request code is supported, and 0 otherwise. void (*RIL_Cancel)(RIL_Token t)
This function is used to indicate that a pending request will be canceled. Called in a separate thread, different from the one in which the RIL_RequestFunc function is called. const char * (*RIL_GetVersion) (void)
returns the manufacturer’s RIL version.
Manufacturer RIL uses the following callbacks to communicate with the RIL daemon:
void RIL_onRequestComplete(RIL_Token t, RIL_Errno e, void *response, size_t responselen)
reports that the requested command has been processed. void RIL_requestTimedCallback (RIL_TimedCallback callback, void *param, const struct timeval *relativeTime)
the function is responsible for the time interval, which you need to call back.
The callback function that is used by the RIL manufacturer to run unsolicited commands should be as follows:
void RIL_onUnsolicitedResponse(int unsolResponse, const void *data, size_t datalen);
Requested commands
There are 61 requested commands. They can be grouped as follows:
- work with SIM card, I / O and unique device identifier (11);
- call status and call handling (16);
- network status (4);
- network settings (12);
- SMS messages (3);
- connection via packet data protocols (4);
- power and restart (2);
- additional services (5);
- manufacturer definitions and support (4).
Figure 6 illustrates the sequence of calls at different levels of the radio interface layer upon receipt of the requested “establish an Internet connection” command:
1. Java RIL calls RILSender.handleMessage () and sends an event planner via the local Linux socket / dev / socket / rild with grouped arguments.
2. Event Scheduler calls listenCallback (), processCommandCallback (), proccessCommandBuffer () sequentially, preprocesses data and calls dispatch (Request code)
3. In the manufacturer’s RIL, the OnRequest () function is called, in which the request code (SETUP_DATA_CALL) determines what action should be taken in the future. The manufacturer's RIL sends the sequence of AT commands corresponding to the request to the modem and accepts the answers to them. Ends processing the request code with a call to the OnRequestComplete () function. If necessary, sends a response to the event scheduler.
4. The event scheduler processes the response from the manufacturer's RIL and calls the response (Request code) function and sends the Java RIL response.
5. Java RIL accepts the response using the RILReceiver.run () method.

Figure 6. Requested command.
Unsolicited commands
There are 11 unsolicited commands, grouped as follows:
- network status change (4);
- incoming SMS message (3);
- Incoming USSD notification (2);
- change signal strength or time (2).

Figure 7. Unsolicited command.
Figure 7 illustrates the sequence of calls at different levels of the air interface layer when an unsolicited “incoming SMS message” command is received:
1. The AT-response comes from the modem, the manufacturer's RIL reads it and calls the handler for the corresponding function. Manufacturer RIL prepares data for sending it to the event planner. Ends processing by calling OnUnsolicitedResponse ().
2. The event scheduler processes the data that came with the response, sends the RIL Java response via the local Linux socket / dev / socket / rild.
3. Java RIL accepts the response using RILReceiver.run ().
In the next article I plan to talk about how to write my program to interact directly with the modem and what can be achieved in this way.
When writing the article were used:
1. Android source codes
android.googlesource.com2.
dpsm.wordpress.com/2010/09/01/smart-phones-are-still-phones3.
www.netmite.com/android/mydroid/development/pdk/docs/telephony.html4.
www.slideshare.net/ssusere3af56/android-radio-layer-interface