1. 용어

  • 서비스 인터페이스(IAudioFlinger)

서비스 인터페이스는 Framework 데이터 송신을 위해 사용하는 여러 클래스 stub, proxy, binder 등의 클래스를 하나의 form으로 묶는 역할을 진행하는 인터페이스이다.

 

  • 서비스 proxy(BpAudioFlinger)

Proxy 서비스를 호출하는 프로세스 쪽에 존재하는 클래스로 실제 RPC 데이터와 코드를 만들어서 서비스를 요청하는 곳이다.

Framework통신 에서 proxy 최종적인 동작은 사용자 입장에서 Process A 에서 존재하지 않는 Process B 서비스를 사용할 해당 서비스를 Process B 아닌 Process A proxy 위치하는 것처럼 느끼고 사용할 있게 하는 것이다.

 

  • 서비스 stub(BnAudioFlinger)

서비스 stub 위의 예시와 같이 process A 에서 process B 서비스를 사용할 process B입장에서 RPC 데이터와 코드를 받고 실제 해당 서비스 함수를 호출하는 영역이다.

 

  • BpBinder(IPC Binder)

IPC 동작을 수행하기 위한 Binder 클래스이다.

 

  • 서비스(AUdioFlinger)

실제 서비스 함수이다. Stub에서 호출되면 실제 서비스 동작을 진행한다.

 

2. 동작

Framework 동작은 Java단에서의 동작과 C++ Native단에서의 동작이 다른데 이전에 기본적으로 Process A 에서 Process B 서비스를 사용하는 Framework 동작에 대해 설명한다.

해당 내용은 이전 포스팅했던 Binder 내용과 비슷하며 해당 내용을 이해한다면 쉽게 이해할 있다.

 

 

  • 서비스 클라이언트

위는 Process A에서 Process B 서비스를 사용하는 동작을 구조화 그림이다. 여기서 Process A 서비스 클라이언트 Process B 서비스 서버로 명시된다.

기본적으로 서비스 클라이언트에서 사용자가 서비스를 사용하면 가장 먼저 Proxy 해당 서비스를 요청한다.

 

BpFooService(Proxy)에서는 사용하고자 하는 서비스를 얻기 위해 RPC 데이터를 만들게 된다. RPC 코드(어떤 서비스 사용하겠다), RPC 데이터(인자)

Proxy 만든 RPC 포맷을 BpBinder 객체를 생성하여 전달한다.

 

BpBinder객체는 transact()함수를 통해 Proxy로부터 전달받은 RPC 데이터를 IPC 포맷으로 변환한다. 이는 프로세스간 데이터를 주고받기 위함이다. (IPC 실제 데이터를 주고받는 공간으로 클라이언트와 서버가 RPC영역은 Proxy, Stub으로 다르지만 IPC영역은 데이터 송수신을 위해 같은 포맷을 사용한다.)

 

IPCThreadState Binder Driver 통해서 실제적으로 IPC 통신을 진행하는 역할을 수행하는 객체이다.

여기서 Binder Driver에서 데이터를 주고받기 위한 버퍼 공간을 Parcel라고 한다. Parcel 여러 자료형뿐 아니라 파일 주소 등을 저장하는 버퍼로 사용될 있다.

 

  • 서비스 서버

서비스 서버는 IPCThreadState 통해서 IPC통신을 수행하고 클라이언트가 원하는 서비스 정보를 얻어온다. 그리고 BBinder parcel 통해 얻어온 데이터를 전달한다.

 

BBinder 객체는 transact()함수를 통해서 IPC 포맷으로 전달받은 데이터를 RPC 코드와 RPC data RPC포맷으로 변환한다.

BnFooService는 서비스 stub으로써 BBinder 의해 변환된 RPC 정보를 바탕으로 클라이언트가 요청하고자 하는 서비스를 실제적으로 호출한다.

 

서비스 동작 값이 반환되면 과정을 반대로 진행해서 값을 클라이언트에게 전달해줄 있다.

 

3. Native Framework

Native java단의 Framework 서비스 매니저 동작이 다른데 java단에서는 Service Manager 동작하지만 native에서는 Context Manager 상시 동작하여 매니저 역할을 진행한다.

 

Context Manager 안드로이드에서 가장 먼저 동작하는 서비스로 idx 0번의 서비스 이다.

Context Manager 역할은 native 서비스를 바인더 드라이버에 등록하고 사용자가 native 서비스를 사용하고자 해당 서비스를 찾아주는 역할을 수행한다.

 

1) Context Manager 초기화

가장 먼저 Context Manager사용을 위해 초기화 과정이 진행된다.

초기화 과정은 가장 먼저 ProcessState 인스턴스 객체를 생성해서 바인더 드라이버를 open한다. 이후 Binder 접근을 위해 BpBinder 객체를 생성하고 바인더 드라이버의 idx 0번에 연결한다.

Context Manager 안드로이드 OS 번째 서비스로 항상 바인더 드라이버에 idx=0으로 저장된다.

 

이후 Context Manager에서 바인더 RPC 통신을 진행하기위해서 RPC 객체를 생성하는데 해당 객체가 바로 BpServiceManager 객체이다. RPC객체는 실제 데이터 송수신을 위한 IPC객체와의 연결이 필요하므로 Context Manager IPC역할을 하는 BpBinder 연결된다.

 

2) 서비스 등록

서비스를 사용하기 위해서는 우선 바인더 드라이버에 서비스 등록이 진행되야한다.

서비스 등록을 진행하기 위해 BpServiceManager(Context Manager RPC 객체) addService() 멤버함수를 호출한다.

BpServiceManager 실제 서비스 등록을 위해 IPC BpBinder(Context Manager IPC 객체) 해당 내용을 전달한다.

Binder Driver 통해 Context Manager 해당 내용을 전달받은 mmap 통해 메모리를 할당하고 Binder Driver 새로운 서비스를 등록한다. 그리고 Context Manager 내부에 관리하는 서비스를 하나 추가해준다.

 

3) 서비스 사용

서비스 사용하는 방법은 먼저 사용하고자 하는 서비스를 호출하기 위해 BpServiceManager getService함수를 호출한다.

등록과 마찬가지로 BpBinder 통해 IPC통신을 진행하고 Context Manager 바인더 드라이버에서 해당 서비스를 찾아 전달해준다.

 

Context Manager 초기화 이후 지속적으로 반복문을 통해 동작하고 있으며 addService, getService 같이 커맨드가 들어오면 분기를 통해 해당 동작을 수행한다.

 

 

Ref

참고문헌 : 인사이드 안드로이드, 송형주 외 4인 저, 위키북스, 2010

https://elecs.tistory.com/91?category=630880 [늦깎이 공대생의 좌충우돌 이야기]

https://dev-ahn.tistory.com/90

 

+ Recent posts