안드로이드 RIL은 android.telephony 서비스들과 radio h/w간의 추상화된 계층을 제공한다. RIL은 radio agnostic(존재하지만 정확하게 표현하기는 어려운 실체)이며, GSM 기반의 radio들에 대한 지원을 포함하고 있다.
아래의 그림은 안드로이드 전화통화 시스템 구조를 설명한다.
위의 그림에서 Radio Daemon과 Vender RIL은 파트너의 특수성을 가진 사적소유영역에 속하며, 나머지 블록은 안드로이드 영역에 속한다고 할 수 있다.
RIL은 두가지의 기본적인 컴포넌트로 구성된다.
RIL 데몬(Daemon) :
RIL 데몬은 Vender RIL을 초기화하며, 안드로이드 telephony 서비스들로부터의 모든 통신을 프로세스하며, solicited 명령어를 통해 Vender RIL로 콜을 넘긴다.
Vender RIL :
ril.h의 radio 특수성을 포함하는 Vender RIL은 radio h/w와의 모든 통신을 처리하며, unsolicited 명령어들을 통해서 RIL 데몬(rild)에 콜을 넘긴다.
RIL 초기화
안드로이드는 구동시점에 아래에 언급된 순서대로, telephony 스택과 Vender RIL 을 초기화한다.
1. RIL 데몬은 Vender RIL에 제공해야할 초기화 argument와 그것을 사용하기 위한 Vender RIL 라이브러리를 결정하기 위한 rild.lib 경로와 rild.libargs 시스템 속성들을 읽어들인다.
2. RIL 데몬은 Vender RIL 라이브러리를 load(탑재)하며, RIL을 초기화하기 위해 RIL_Init을 호출하며, RIL 함수에 대한 참조를 얻는다.
3. RIL 데몬은 Vender RIL 함수들에 대한 하나의 참조를 제공하는 안드로이드 Telephony 스택상의 RIL_register를 호출한다.
RIL 상호작용
RIL 제어 관련 통신에는 두가지 형식이 존재한다.
Solicited commands : Solicited 명령어들은 전화걸기(DIAL) 과 HANGUP(전화끊기)와 같은 RIL 라이브러리에 의해 만들어 진다. Unsolicited responses : Unsolicited responses는 CALL_STATE_CHNGED(전화 상태 변화)와 NEW_SMS(새 문자 메시지)와 같은 baseband로 부터 만들어 진다.
그리고 아래와 같이 계열들로 묶여질 수 있는 10개 이상의 unsolicited 명령어들이 존재한다.
Network status changed (4)
New SMS notify (3)
New USSD notify (2)
Signal strength or time changed (2)
아래의 다이어그램은 안드로이드에서의 unsolicited call을 설명하고 있다.
RIL 구현하기
특정 radio RIL을 구현하기 위해서는, 라디오 요청을 처리하기 위해 안드로이드에서 요구되는 함수의 집합을 구현하는 공유 라이브러리를 만들어야 한다. 요구되는 함수들은 RIL header (/include/telephony/ril.h)에 정의된다.
안드로이드 radio 인터페이스는 radio-agnostic이며, Vender RIL은 radio를 통해 통신하기 위한 어떤 프로토콜도 사용할 수 있다. 안드로이드는 하나의 참조적 구현형태로써의 Vender RIL을 제공하고 있는데, 그것은 Hayes AT command 집합을 사용하고 있으며, 여러분들은 telephony 테스트를 위한 쉬운 시작과 상업적 Vender RIL 들을 위한 가이드로써 사용할 수 있다. 참조적으로 구현된 RIL 소스 코드는 /commands/reference-ril/ 에서 볼 수 있다.
libril-<companyname>-<RIL version>.so 규약을 사용해서 공유 라이브러리 형태로 여러분의 Vender RIL을 컴파일 해라. 여기에 예로써, libril-acme-124.so가 있다.
libril: 모든 vender RIL 구현은 'libril' 로 시작
<companyname>: 특정 회사의 약어
<RIL version>: RIL 버전 숫자
so: 파일 확장자
RIL_Init
여러분의 Vender RIL은 모든 radio 요청들을 처리할 함수들에 대한 제어를 제공하는 RIL_Init 함수를 정의해야 한다. RIL_Init은 RIL을 초기화하기 위해, 부트시점에서 안드로이드 RIL Daemon에 의해 호출된다.
RIL_RadioFunctions *RIL_Init (RIL_Env* env, int argc, char **argv);
RIL_Init은 radio 함수들에 대한 제어를 포함하는 RIL_RadioFuncions 구조체를 반환해야 한다.
type structure { int RIL_version; RIL_RequestFunc onRequest; RIL_RadioStateRequest onStateRequest; RIL_Supports supports; RIL_Cancel onCancel; RIL_GetVersion getVersion; } RIL_RadioFunctions;
RIL 함수들
ril.h는 아래의 테이블에 설명된 함수들 같은, RIL_UNSOL_STK_CALL_SETUP, RIL_SIM_READY, RIL_SIM_NOT_READY 과 같은 RIL 상태들과 변수들을 정의한다. 더 상세하게는 헤더파일(/device/incldue/telephony/ril.h)을 살펴보길.
RIL Solicited 명령어 요청들.
Vender RIL은 solicited 명령어들을 처리하기 위해 아래의 테이블에 설명된 함수들을 제공해야 한다. RIL solicited 명령어 요청 타입들은 RIL_REQUEST_ 라는 접두사를 가지고 ril.h에 정의된다. 상세하게는 헤더 파일을 체크하길.
이것은 solicited 명령어들에 대한 시작 포인트이며, RIL_REQUST_ 접두사를 가지고 ril.h에 정의된 다양한 RIL solicited 요청 타입들을 제어할 수 있어야 한다.
request 는 RIL_REQUEST_* 중 하나임.
data 는 RIL_REQUST_* 위해 정의된 data에 대한 포인터임.
t 는 RIL_onResponse 에 수반되는 호출에서 사용되어야 함.
datalen 은 caller 소유이며, callee에 의해 수정되거나 free 되어서는 안됨.
RIL_onRequestComplete()에 대한 호출을 통해 완료되어야 함. RIL_onRequestComplete()는 임의의 쓰레드로부터 이 함수의 반환 이전 또는 이후에 호출될 수 있다. 이것은 항상 동일한 쓰레드로부터 호출될 것이며, 그러므로 여기에서 반환이라함은 radio가 다른 명령을 수행할 준비하 되어있음을 의미한다.(이전 명령이 완료여부와 상관없이)
RIL_RadioState (*RIL_RadioStateRequest)();
이 함수는 현재의 radio 상태를 동기적으로 반환해야 한다.
int (*RIL_Supports)(int requestCode);
이 함수는 명시된 RIL_REQUEST 코드가 지원된다면 "1"을 아니라면 "0"을 반환한다.
void (*RIL_Cancel)(RIL_Token t);
이 함수는 멈춰져 있는 요청을 취소시키기 위해 사용된다. 이 함수는 다른 쓰레드, 즉 RIL_RequestFunc 을 호출한 쓰레드가 아닌 쓰레드에 의해 호출된다.
취소시, callee는 요청을 포기하기 위해 최선을 다해야하며, 잠시후 RIL_Errno CALCELLED 를 가지고 RIL_onRequestComplete를 호출한다.
다른 결과들을 가진 이 요청들에 대한 RIL_onRequestComplete에 대한 수반되는 호출들은 묵인되지만, 무시된다.(그것은 취소 요청을 무시하기 위해 유효한 것이다)
RIL_Cancel 호출들은 즉시 반환되어야 하며, 취소를 기다려서는 안된다.
const char * (*RIL_GetVersion) (void);
여러분의 Vender RIL에 대한 버젼 문자열을 반환한다.
Vender RIL은 안드로이드 RIL 데몬에 역으로 통신하기 위해 다음과 같은 callback 메쏘드를 사용한다.
함수명
설명
void RIL_onRequestComplete(RIL_Token t, RIL_Errno e, void *response, size_t responselen);
RIL_RequestFunc 이 호출된 동일한 쓰레드에서 사용자 정의의 callback 함수를 호출한다. 만약 relativeTime 이 명시되었다면, 그것은 callback이 발생해야하는 상대적인 시각을 명시한다. 만약 relativeTime 이 NULL 이거나 0 으로 채워진 구조체에 대한 포인터라면, callback은 최대한 빨리 발생한다.
RIL Unsolicited 명령어들
아래의 테이블에 열거된 함수들은 안드로이드 플랫폼에서 unsolicited 명령어들을 발생시키기 위해 Vendor RIL에 의해 사용되는 call-back 함수들이다. 자세하게는 ril.h 를 보길.
data 는 RIL_UNSOL_RESPONSE_* 를 위해 정의된 data에 대한 포인터임.
data 는 caller 소유이며, callee 에 의해 수정되거나 free 되어서는 안됨.
HiJune
2008-12-04 13:39
와...깔끔한 정리 감사합니다~
들풀
2008-12-04 13:50
하이준님..요즘 자주뵙네요..~홧팅.
ratharn
2008-12-04 14:34
어디서 많이 본거 같다는...RIL의 구조가요..
뭐..비슷한 개념이니 다 똑같겠지요..
정말 깔끔하게 정리 잘하셨네요~
들풀
2008-12-04 14:48
제가 정리한건 아닙니다.
단지 Android PDK의 일부 내용을 번역한 것인데여..
이것을 기준으로 실제 Vendor RIL에 대해서 앞으로 고민해 나가 볼려고 만든 것입니다.
논노
2008-12-04 16:45
^^ 정리 깔끔 하네요.
궁금한게 있는데여.. 현재 r1 에서는 SIM IO 에서 3g 포멧을 지원 안하나요 ? EF 를 읽으려고..get response 를 내려서 받은 data 가 2g 포멧이면 body 를 읽으라는 request 를 내리는데, TLV 로 이루어진 3g 포멧으로 올리면...request 를 할 생각을 안하네요 ㅜㅠ 그래서...3g포멧을 2g로 바꾸는 filter 를 만들어야 할지.... 쩝..
들풀
2008-12-04 17:02
R1을 안드로이드 Release 1이라고 생각한다면, 해당 영역에는 참조하기 위한 ril 만이 존재할뿐,
실제로 작동가능한 ril이라고 생각할 수 없기 때문에 뭐라 말씀 드릴 것이 없을 듯 하구여.
G1을 언급하신 거라면, Vender RIL 형태로 Qualcomm RIL이 구현되어서 탑재되어는 있겠지만,
현재 소스가 오픈된 형태가 아니니깐, 핸드셋제조사와 칩벤더간의 협약에 기초해서 서로 작업을
진행하는 것이니, 칩벤더회사와 이야기를 하는게 당연할듯 합니다.
아마도 kandroid의 성격상, 이곳에서는 Vendor RIL 부분은 논의하기가 힘들듯 합니다.
불타는주작
2009-01-07 10:38
깔끔하네요... 잘 보겠습니다.
정토
2009-04-24 00:05
엄청 깔끔하군요. 관계없는 질문 -> 위의 다이어그램은 무엇으로 그리셨나요? ^^;
들풀
파워포인트로 그렸는걸요..~ㅎ
4/24 01:31
낭만고양
2009-10-07 21:27
역시 안드로이드 쪽의 좋은 자료는 네이버 보다 이곳에 확실히 더 많은 것 같네요.
들풀님 덕분에 열심히 공부하고 있습니다. ^^
소오강호
2009-10-08 13:41
마치 비지오 같은 느낌이 나는 파워포인트 그림이군요... ^^;
bestrok
2010-02-24 09:45
세미나 준비하는데 많은 도움이 되었습니다.
bmhd
2010-02-24 21:33
정말 정리 잘하셨습니다.
미약하나마 위의 설명에 첨부를 하자면 RIL 이라는 것은 Application Process(안드로이드) 와 Radio(Modem) 의 인터페이스를 뜻하는 Radio Interface Layer 입니다. 현재 퀄컴은 Application Process쪽은 ARM11, 모뎀쪽은 ARM9을 사용하고 있으며 RIL로 interface가 이루어집니다.
radio deamon rild는 init.rc 에 정의되어 시스템이 시작하면서 올라갑니다,
그림으로 잘 설명해주셨지만 solicited 과 unsolicited 차이를 간단하게 말씀드리자면 solicited 은 안드로이드에서 command를 보내면 모뎀쪽에서 그에 대한 동작 및 응답을 보내는 것이고, unsolicited 는 모뎀쪽에서 안드로이드 쪽으로 command를 보내는 것입니다.
간단히 전화 거는것은 안드로이드쪽에서 모뎀쪽으로 command를 보내는 것이니 solicited command이고, 전화를 받는 것은 모뎀쪽에서 안드로이드 쪽으로 command를 보내는 것이니 unsolicited command 겠지요 .
이상 주절 주절 적었습니다.