2013. 12. 30. 21:10ㆍPrograming/Android / Java
Binder를 사용하는데 굳이 Binder의 동작에 대해 알 필요는 없다. 그러나 Binder에 대해 정확히 알면 활용면에서도 그렇고 디버깅에서도 많은 도움이 된다. 그리고 세상에 알아서 나쁜 지식은 없다. 관련된 함수를 모두 분석하진 않겠다. 오히려 더 어렵게 느껴질 뿐이다. 어떤 역할을 하는지 알면 필요할 때 찾아보면 될 것이다.
Binder는 service_manager와 함께 시작된다. service_manager의 main함수를 살펴보자. binder_open()함수를 통해서 "/dev/binder"를 open하고 binder_loop()함수를 실행하는데, 이 때 인자로 binder_state 포인터 변수와 BINDER_SERVICE_MANAGER를 넘긴다. 이것은 필요에 따라 실행되는 프로세스가 아닌, 안드로이드 부팅과 함께 실행되어 종료될때까지 동작한다.
int main(int argc, char **argv)
BINDER_SERVICE_MANAGER는 다음과 같이 정의되어있다.
/* the one magic object */
#define BINDER_SERVICE_MANAGER ((void*) 0)
binder_loop()함수에서는 무한루프에서 ioctl()함수와 binder_parse()함수를 호출한다. 뭐 ioctl()함수로 메시지를 가져오고 binder_parse()함수로 parsing한 후 적절한 동작을 수행할 것이다.
void binder_loop(struct binder_state *bs, binder_handler func)
{
int res;
struct binder_write_read bwr;
unsigned readbuf[32];
bwr.write_size = 0;
bwr.write_consumed = 0;
bwr.write_buffer = 0;
readbuf[0] = BC_ENTER_LOOPER;
binder_write(bs, readbuf, sizeof(unsigned));
for (;;) {
bwr.read_size = sizeof(readbuf);
bwr.read_consumed = 0;
bwr.read_buffer = (unsigned) readbuf;
res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
if (res < 0) {
LOGE("binder_loop: ioctl failed (%s)\n", strerror(errno));
break;
}
res = binder_parse(bs, 0, readbuf, bwr.read_consumed, func);
if (res == 0) {
LOGE("binder_loop: unexpected reply?!\n");
break;
}
if (res < 0) {
LOGE("binder_loop: io error %d %s\n", res, strerror(errno));
break;
}
}
}
그럼 어떻게 메시지가 Binder device driver로 보내지는지, 그리고 parsing한 후 보내야할 프로세스로 메시지를 보내는지를 알아보자.
Binder 통신을 하기 전에 먼저 메시지를 수신할 프로세스는 자신을 service_manager에 등록해야한다. service_manager가 알지도 못하는 프로세스로 메시지를 보낼 순 없으니 말이다. service_manager에 등록하기 위해서 IServiceManager의 인스턴스를 얻어야 하는데 이때 사용하는 함수가 defaultServiceManager()이다.
sp<IServiceManager> defaultServiceManager()
{
if (gDefaultServiceManager != NULL) return gDefaultServiceManager;
{
AutoMutex _l(gDefaultServiceManagerLock);
if (gDefaultServiceManager == NULL) {
gDefaultServiceManager = interface_cast<IServiceManager>(
ProcessState::self()->getContextObject(NULL));
}
}
return gDefaultServiceManager;
}
IServiceManager 인스턴스를 통해서 addService()함수를 이용하여 프로세스를 등록한다. 이제 메시지를 수신할 프로세스를 service_manager에 등록했으니 메시지가 있으면 프로세스의 onTransact()함수를 호출할 것이다. 그럼 메시지를 보내는 것은 어떻게 될까. addService()가 있으니 반대로 getService()함수가 있다. getService 함수로 메시지를 수신할 프로세스의 Binder 인스턴스를 획득하고 transact()함수를 호출한다.
'Programing > Android / Java' 카테고리의 다른 글
안드로이드 Surface View (0) | 2013.12.30 |
---|---|
안드로이드 바인더(Android Binder)가 탄생하기 까지 (0) | 2013.12.30 |
안드로이드 채팅 형식 List View Layout (0) | 2013.12.30 |
안드로이드 - 내 어플에서 통화 걸기 (Make Call) (0) | 2013.12.30 |
안드로이드 - 내 어플에서 통화 종료 시키기 (End Call) (0) | 2013.12.30 |