Brief introduction of android telephony framework, detailed analyze of RIL (radio interface layer), and some examples for doing telephony thing in a low layer
1. Android RIL - Radio Interface Layer
Lifu Zhang
Elektrobit Wireless(2011)
Android RIL - Radio Interface Layer
1 / 35
2. Outline
1 Android Telephony
Big Picture
Porting Work
Interacton between Framework and Local Service
Ril Initilize
2 Vender RIL
Example I: Signal Strength
Example II: Voice Call
Experiences when IMPL telephony features
3 Data Connection
4 Reference
Android RIL - Radio Interface Layer
2 / 35
3. Terms
RIL Daemon: The RIL daemon initializes the Vendor RIL, processes
all communication from Android telephony services, and dispatches
calls to the Vendor RIL as solicited commands.
Vendor RIL: The radio-speciïŹc Vendor RIL of ril.h that processes all
communication with radio hardware and dispatches calls to the RIL
Daemon (rild) through unsolicited commands.
Android RIL - Radio Interface Layer
3 / 35
4. Architechture of Android Telephony
The telephony is based on these items, layout layer by layer
Android Services, activities, call settings
Service âismsâ
Dialer application
Other Telephony settings and operations
The com.android.internal.phone interface
PhoneFactory, PhoneProxy, CDMAPhone, GSMPhone
RIL.java
ril-daemon
vender ril
Android RIL - Radio Interface Layer
4 / 35
6. Files in System
Binary:
Source:
/system/framework/
com.android.telephony
framework.jar
com.android.internal.telephony
/system/bin/rild
com.android.phone
/system/lib/libril.so
hardware/ril
/system/lib/lib(vender)-ril.so
Android RIL - Radio Interface Layer
6 / 35
7. Our Job: libxxx-ril.so vender ril
The C Programming Language
Control the modem, by whatever means (using tty now)
Translate requests and data between framework and modem
Android RIL - Radio Interface Layer
7 / 35
9. Requests and Response - Async IPC
They are async, you donât
have to response it
immediately.
All requests and response is
handled by the RIL.java,
then dispatched to upper
framework
The ril daemon will use some
C++ code disamble the
Parcel, and pass void * data
to vender ril
Android RIL - Radio Interface Layer
9 / 35
10. The Requests
requests is comming from the framework, packed as Parcel, trasfered
on local socket, dispatched by rild, and handled by vender ril.
request id: What do you want to do
request token: just a token, using when response it
request data: e.g. when sending sms, you have to specify address,
text in the data
Android RIL - Radio Interface Layer
10 / 35
11. The Response
the response is generated by vender ril, packed as Parcel, transfered
on local socket, dispatched by CommandInterface, and handled by
those who register its handler.
id: same as the requests id
error id: success or something wrong
data: data is in format specify by the request, and if no data
needed, it would be âNULLâ
special: Some response is not to a request, we call they unsolicited
responses.
Android RIL - Radio Interface Layer
11 / 35
13. Init Code I - Load RIL Library
dlHandle = dlopen ( rilLibPath , RTLD_NOW ) ;
if ( dlHandle == NULL ) {
fprintf ( stderr , " dlopen failed : % s n " , dlerror () ) ;
exit ( -1) ;
}
R I L _ s t ar t Ev e nt Lo o p () ;
rilInit = ( const R I L_ Ra d io F un ct i on s *(*) ( const struct RIL_Env * , int , char
**) )
dlsym ( dlHandle , " RIL_Init " ) ;
if ( rilInit == NULL ) {
fprintf ( stderr , " RIL_Init not defined or exported in % s n " , rilLibPath ) ;
exit ( -1) ;
}
// .. omitted code ..
funcs = rilInit (& s_rilEnv , argc , rilArgv ) ;
RIL_register ( funcs ) ;
done :
while (1) {
// sleep ( U I N T 3 2 _ M A X ) seems to return i m m e d i a t e l y on bionic
sleep (0 x00ffffff ) ;
}
Android RIL - Radio Interface Layer
13 / 35
14. Init Code II - Wait for device ready
for (;;) {
fd = -1;
while ( fd < 0) {
if ( s_port > 0) {
fd = s o c k e t _ l o o p b a c k _ c l i e n t ( s_port , SOCK_STREAM ) ;
} else if ( s_device_socket ) {
if (! strcmp ( s_device_path , " / dev / socket / qemud " ) ) {
/* .. CODE OMITTED .. Qemu - specific control socket */
}
else
fd = s o ck e t _ l o c a l _c l i e n t ( s_device_path ,
A NDR OI D_ SO CK ET _N AM ESP AC E_ FI LE SY ST EM ,
SOCK_STREAM ) ;
} else if ( s_device_path != NULL ) {
fd = open ( s_device_path , O_RDWR ) ;
if ( fd >= 0 && i sS e ri al P or t De vi c e ( s_device_path ) ) {
/* set serial port acting in raw mode , CODE OMITTED .. */
tcsetattr ( fd , TCSANOW , & ios ) ;
}
}
if ( fd < 0) {
sleep (10) ;
}
}
s_closed = 0;
ret = at_open ( fd , onUnsolicited ) ;
R I L _ r e q u e s t T i m e d C a l l b a c k ( initializeCallback , NULL , & TIMEVAL_0 ) ;
// Give i n i t i a l i z e C a l l b a c k a chance to dispatched , since
// we don ât p r e s e n t l y have a c a n c e l l a t i o n m e c h a n i s m
sleep (1) ;
waitForClose () ;
}
Android RIL - Radio Interface Layer
14 / 35
15. The Vender RIL
In this sections, weâll have some examples about how the vender ril
works.
The Vender RIL and RIL Daemon is interact with
RIL RadioFunctions and RIL Env facility.
The Vender RIL is the very part of system that handle radio
operations.
Android RIL - Radio Interface Layer
15 / 35
16. The RIL Enviroment and RIL Radio Functions
typedef void (* RIL_RequestFunc ) ( int request , void * data ,
size_t datalen , RIL_Token t ) ;
typedef RIL_RadioState (* R I L _ R a d i o S t a t e R e q u e s t ) () ;
typedef int (* RIL_Supports ) ( int requestCode ) ;
typedef void (* RIL_Cancel ) ( RIL_Token t ) ;
typedef void (* R IL_T ime dCa llb ack ) ( void * param ) ;
typedef const char * (* RIL_GetVersion ) ( void ) ;
typedef struct {
int version ;
R IL _R equestFunc onRequest ;
R I L _ R a d i o S t a t e R e q u e s t onStateRequest ;
RIL_Supports supports ;
RIL_Cancel onCancel ;
RIL_ GetVersion getVersion ;
} R I L _ R a d io Fu n ct i on s ;
struct RIL_Env {
void (* On Req ues tCo mple te ) ( RIL_Token t , RIL_Errno e ,
void * response , size_t responselen ) ;
void (* O n U n s o l i c i t e d R e s p o n s e ) ( int unsolResponse ,
const void * data ,
size_t datalen ) ;
void (* R e q u e s t T i m e d C a l l b a c k ) ( R IL_ Tim edCa llb ack callback ,
void * param ,
const struct timeval * relativeTime ) ;
};
Android RIL - Radio Interface Layer
16 / 35
17. NOTES
functions in RIL Env is used by vender ril, and RIL RadioFunctions
is used by rild
The vender rilementation is in the same process space as ril-daemon
onComplete is re-enterable, (will block by a mutex if called by
multi-thread in same time)
Android RIL - Radio Interface Layer
17 / 35
18. Operation to the modem
Android RIL - Radio Interface Layer
18 / 35
19. Summary: Threads in rild process space
rild main thread: parse argc, argv, open ril library, create event loop,
some timed call back is run in this thread.
rild event loop: handle requests from upper layer, and call
OnRequests of vender ril.
vender reader loop: read data comming from modem, packed as
response/unsol response.
Android RIL - Radio Interface Layer
19 / 35
20. Example I: Signal Strength Query/Report
The framework may query current signal strength(case I), and
when modem detect a signal change, ril should report this
event(case II).
For Case I: For Case II:
Send âAT+CSQâ command The reader loop recieve
â+CSQxxxxâ
Waiting for response
Parse the at command string
Parse response, pack data into pack data into
RIL CDMA SignalStrength RIL CDMA SignalStrength
OnRequestComplete OnUnsolicitedResponse
Android RIL - Radio Interface Layer
20 / 35
21. Example I: Signal Strength Report - Code
static void onUnsolicited ( const char *s , const char * sms_pdu )
{
// this is the function called when r e a d e r l o o p found an unsol modem command
// .. omitted code ..
} else if ( strStartsWith (s , " ^ HRSSILVL : " ) ) {
// handle signals here
onHrssiChanged ( s ) ;
}
// .. omitted code ..
}
static void onHrssiChanged ( const char * s )
{
int sigStrength ;
int err ;
char * membak = strdup ( s ) ;
char * ln = membak ;
R I L _ S i gn a lS t re ng t h sigsth ;
R I L _ S i gn a lS t re ng t h * sth = & sigsth ;
err = at_tok_start (& ln ) ;
if ( err ) goto error ;
err = at_tok_nextint (& ln , & sigStrength ) ;
if ( err ) goto error ;
h w _ c o n v e r t S i g n a l S t r e n g h ( sigStrength , sth ) ; // will do data c o n v e r t i o n
R I L _ o n U n s o l i c i t e d R e s p o n s e ( RIL_UNSOL_SIGNAL_STRENGTH , sth , sizeof (* sth ) ) ;
free ( membak ) ;
return ;
error :
free ( membak ) ;
LOGE ( " Unsol Signal Strength command error : % s " , s ) ;
return ;
}
Android RIL - Radio Interface Layer
21 / 35
22. Example I: Signal Strength Query - Code
R IL _S i gn a l S t r e ng t h sth ;
int err = h w _ g e t S i g n a l S t r e n g t h (& sth ) ;
if (! err ) {
R I L _ o n R e q u e s t C o m p l e t e (t , RIL_E_SUCCESS , & sth , sizeof ( sth ) )
;
} else {
R I L _ o n R e q u e s t C o m p l e t e (t , RIL_E_GENERIC_FAILURE , NULL , 0) ;
}
SS query int h w _ g e t S i g n a l S t r e n g t h ( R IL _ S i g na lS t r e n g t h * sth )
{
int err = 0;
For Huawei ATResponse * p_response ;
modem err = a t _ s e n d _ c o m m a n d _ s i n g l e l i n e ( " AT ^ HDRCSQ " , " ^ HDRCSQ " , &
p_response ) ;
char * line = p_response - > p_intermediates - > line ;
with do {
int hwhdr ;
adaptation if ( err < 0 || p_response - > success == 0) break ;
err = at_tok_start (& line ) ;
if ( err ) break ;
err = at _tok_nex tint (& line , & hwhdr ) ;
if ( err ) break ;
h w _ c o n v e r t S i g n a l S t r e n g h ( hwhdr , sth ) ;
} while (0) ;
at_res po ns e_ free ( p_response ) ;
return err ;
}
Android RIL - Radio Interface Layer
22 / 35
23. Dial a Number
When the java framework wanna dial a number, it will send a
request to rild:
ID : RIL REQUEST DIAL (value=10, int)
Data: RIL Dial :{
address: char *, the address weâll dialing, e.g. 13xxxxxxxx
clir: int, loop TS27.007 7.7 +CLIR, I donât know whatâs this.
uusInfo: RIL UUS Info *, NULL or Pointer to User-User Signaling
Information
}
Android RIL - Radio Interface Layer
23 / 35
24. What Shall I Do? Make the Call!
p_dial = ( RIL_Dial *) data ;
switch ( p_dial - > clir ) {
case 1: clir = " I " ; break ; /* i n v o c a t i o n */
case 2: clir = " i " ; break ; /* s u p p r e s s i o n */
default :
case 0: clir = " " ; break ; /* s u b s c r i p t i o n default */
}
ret = sendDialCommand ( p_dial - > address , clir ) ;
R I L _ o n R e q u e s t C o m p l e t e (t , ( RIL_Errno ) ret , NULL , 0) ;
static int sendDialCommand ( const char * number , const char * clir )
{
int ret ;
if ( isInCall () ) { // forbide call in call o p e r a t i o n
ret = R I L _ E _ G E N E R I C _ F A I L U R E ;
} else { /* Not in call , us AT + CDV */
char * cmd ;
asprintf (& cmd , " AT + CDV % s % s ; " , number , clir ) ;
ret = at_send_command ( cmd , NULL ) ;
free ( cmd ) ;
}
if ( ret ) {
return R I L _ E _ G E N E R I C _ F A I L U R E ;
} else {
return RIL_E_SUCCESS ;
}
}
Android RIL - Radio Interface Layer
24 / 35
25. Whatâs Your Call Status?
RIL_Call ** hw_getValidCalls ( void )
{
// .. omited code ..
err = a t _ s e n d _ c o m m a n d _ m u l t i l i n e ( " AT + CLCC " , " + CLCC : " , & p_response ) ;
// .. omited code ..
atline = p_response - > p_intermediates ;
while ( atline != NULL ) {
err = r i l c a l lF r o m C l c c L in e ( p_callbuf , atline - > line ) ;
if (! err ) {
RIL_Call * curCall ;
curCall = ( typeof ( curCall ) ) malloc ( sizeof (* curCall ) ) ;
memcpy ( curCall , p_callbuf , sizeof (* p_callbuf ) ) ;
pp_calls [ nValidCalls ] = curCall ;
++ nValidCalls ;
} else {
ebDebug ( " failed to parse one clcc line " ) ;
}
atline = atline - > p_next ;
}
// .. omitted code ..
}
pp_calls = hw_getValidCalls () ;
// .. omitted code ..
R I L _ o n R e q u e s t C o m p l e t e (t , RIL_E_SUCCESS , pp_calls ,
nValidCalls * sizeof (* pp_calls ) ) ;
// .. omitted code ..
Android RIL - Radio Interface Layer
25 / 35
26. Incoming Transmission
When the call state changed, i.e., under these situation: ring,
dialing, connectiong established, or hang-up, the ril damon should
simply give a âCALL STATE CHANGEDâ unsol response.
else if ( strStartsWith (s , " + CRING : " )
|| strStartsWith (s , " RING " )
|| strStartsWith (s , " NO CARRIER " )
|| strStartsWith (s , " + CCWA " )
|| strStartsWith (s , " ^ ORIG " )
|| strStartsWith (s , " ^ CONN " )
|| strStartsWith (s , " ^ CEND " )
) {
RIL_onUnsolicitedResponse (
R IL _ U N SO L _ RE S P ON S E _C A L L _S T A TE _ C HA N G ED ,
NULL , 0) ;
if ( strStartsWith (s , " ^ CONN " ) ) {
onCallStart () ;
} else if ( strStartsWith (s , " ^ CEND " ) ) {
onCallEnd () ;
} else if ( strStartsWith (s , " + CRING : " ) || strStartsWith (s , " RING " ) ) {
R I L _ o n U n s o l i c i t e d R e s p o n s e ( RIL_UNSOL_CALL_RING , &
s_StandardSingalInfo , sizeof ( s _ S t a n d a r d S i n g a l I n f o ) ) ;
}
Android RIL - Radio Interface Layer
26 / 35
27. Expansion: 3rd Party Voice Call(CDMA)
Always, we will make call with multiple persons, this kind of action
in CDMA/EVDO is little bit diïŹerent between GSM/WCDMA.
There is a action named âFLASHâ:
If the ïŹash command come without params, itâll hang the current
call.
If the ïŹash come with a phone number, itâll connected to that
phone.(and hold other calls)
If the ïŹash come without params, and there is holding calls, it will
rejoin them, and make a 3rd party call.
Android RIL - Radio Interface Layer
27 / 35
28. Expansion: 3rd Party Voice Call(CDMA),
Implements
The hw ïŹash(const char *) method will send ïŹash command to
modem.
static void cdmaFlash ( void * param )
{
int err ;
err = hw_flash ( " " ) ;
}
static void requestCdmaFlash ( void * data , size_t datalen , RIL_Token t )
{
int err ;
const char * flashstr = ( const char *) data ;
err = hw_flash ( flashstr ) ;
if ( err ) {
goto error ;
}
static const struct timeval FlashWait = {5 , 0};
R I L _ r e q u e s t T i m e d C a l l b a c k ( cdmaFlash , NULL , & FlashWait ) ;
// .. omitted code ..
}
Android RIL - Radio Interface Layer
28 / 35
29. SMS
Android java framework will pack all sms text as pdu byte array,
and will take over the long sms partition work.
The vender ril has to do:
Translate pdu to the format modem could regconize.
Pack the text data from modem to ril pdu format.
Handle the storage/deletion work for sms on sim/ruim card
Android RIL - Radio Interface Layer
29 / 35
30. Call Forward and Call Waiting
Opensource android CDMA Telephony framework doesnât surpport
these action.
Itâs simple to add impl code to java framework and settings app
refer to gsm system.
For China Telecom, you have to make cvoice calls with special
number to register these service.
Android RIL - Radio Interface Layer
30 / 35
31. Main Flow for Data Connection
Android RIL - Radio Interface Layer
31 / 35
32. CDMA Data conn Establish
Android RIL - Radio Interface Layer
32 / 35
33. GSM Data conn Establish
Android RIL - Radio Interface Layer
33 / 35
34. NOTES
A modem always have two channel to operate, when established a
ppp link, one channel will be hold for ppp.
pppd will create interface, set dns/ip or dhcp them.
Android RIL - Radio Interface Layer
34 / 35