검색결과 리스트
글
안드로이드 Native 코드 분석 : DECLARE_META_INTERFACE()
안드로이드 Binder 부분에 대해 공부를 하시다 보면 다음과 같은 함수를 만나게 되는 경우가 있습니다.
/frameworks/native/include/binder/IServiceManager.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | class IServiceManager : public IInterface { public: DECLARE_META_INTERFACE(ServiceManager); /** * Retrieve an existing service, blocking for a few seconds * if it doesn't yet exist. */ virtual sp<IBinder> getService( const String16& name) const = 0; /** * Retrieve an existing service, non-blocking. */ virtual sp<IBinder> checkService( const String16& name) const = 0; /** * Register a service. */ virtual status_t addService( const String16& name, const sp<IBinder>& service, bool allowIsolated = false) = 0; /** * Return list of all existing services. */ virtual Vector<String16> listServices() = 0; enum { GET_SERVICE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION, CHECK_SERVICE_TRANSACTION, ADD_SERVICE_TRANSACTION, LIST_SERVICES_TRANSACTION, }; }; | cs |
위 함수를 처음 만났을 때 많은 분들께서 처음에는 상당히 의야해 하실 것으로 예상합니다. 사실 저것은 함수가 아니라 #define으로 정의된 매크로 함수입니다.
해당 부분에서 MACRO 함수를 사용하는 이유는 Native의 System Service들의 Binder를 설계하다 보면 각 서비스 별로 바인더를 설계해야 하는 경우가 발생하게 됩니다. 즉, 위에 사용된 매크로 함수는 해당 서비스들의 코드를 작성하기엔 양이 많기 때문에 위와 같은 방법을 사용하여 코드 용량을 줄인 것이라고 이해하셔도 될 듯 합니다.
이와 같은 용도로 IMPLEMENT_META_INTERFACE() 함수도 안드로이드에서는 쓰이고 있습니다. 그렇다면 DECLARE_META_INTERFACE() 함수가 어떻게 선언되어 있는지 살펴보도록 하겠습니다.
/frameworks/native/include/binder/IInterface.h
1 2 3 4 5 6 7 | #define DECLARE_META_INTERFACE(INTERFACE) \ static const android::String16 descriptor; \ static android::sp<I##INTERFACE> asInterface( \ const android::sp<android::IBinder>& obj); \ virtual const android::String16& getInterfaceDescriptor() const; \ I##INTERFACE(); \ virtual ~I##INTERFACE(); \ | cs |
위 Macro 코드가 위 코드에서는 다음과 같이 적용됨을 알 수 있습니다.
/frameworks/native/include/binder/IServiceManager.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | class IServiceManager : public IInterface { public: static const android::String16 descriptor; static android::sp<IServiceManager> asInterface( const android::sp<android::IBinder>& obj); virtual const android::String16& getInterfaceDescriptor() const; IServiceManager(); virtual ~IServiceManager(); /** * Retrieve an existing service, blocking for a few seconds * if it doesn't yet exist. */ virtual sp<IBinder> getService( const String16& name) const = 0; /** * Retrieve an existing service, non-blocking. */ virtual sp<IBinder> checkService( const String16& name) const = 0; /** * Register a service. */ virtual status_t addService( const String16& name, const sp<IBinder>& service, bool allowIsolated = false) = 0; /** * Return list of all existing services. */ virtual Vector<String16> listServices() = 0; enum { GET_SERVICE_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION, CHECK_SERVICE_TRANSACTION, ADD_SERVICE_TRANSACTION, LIST_SERVICES_TRANSACTION, }; }; | cs |
위와 같은 원리로 안드로이드 Binder 관련 MACRO 함수로 IMPLEMENT_META_INTERFACE() 함수가 있습니다. 해당 매크로함수에 대한 정리는 아래 포스팅을 확인해주시기 바랍니다.
'안드로이드 > 프레임워크' 카테고리의 다른 글
| 안드로이드 프레임워크 프로그래밍(15) [Native 단계에서의 Parcel 전송(1)] (0) | 2015.03.30 |
|---|---|
| 안드로이드 프레임워크 프로그래밍(14) [서비스 매니저 생성 및 등록과정] (0) | 2015.03.29 |
| 안드로이드 Native 코드 분석 : IMPLEMENT_META_INTERFACE() (0) | 2015.03.27 |
| 안드로이드 프레임워크 프로그래밍(13) [커널이미지 적용후 부팅화면만 나올 때 대처법] (0) | 2015.03.24 |
| 안드로이드 프레임워크 프로그래밍(12) [IServiceManager 등록과정] (1) | 2015.03.23 |
설정
트랙백
댓글
글
안드로이드 Native 코드 분석 : IMPLEMENT_META_INTERFACE()
안드로이드 프레임워크를 분석하는 과정에서 시스템 서비스와 관련된 부분에 대해 분석을 하다보면 다음과 같은 이름의 함수를 만나보실 수 있을 것입니다.
/frameworks/native/libs/binder/IServiceManager.cpp
IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");
위 함수는 겉으로 보기에는 뭔가 거창한 듯한 함수처럼 보입니다만 사실은 #define으로 정의된 매크로입니다. 이 매크로는 header 파일인 IInterface.h에 선언되어 있음을 확인하실 수 있습니다.
/frameworks/native/include/binder/IInterface.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | #define IMPLEMENT_META_INTERFACE(INTERFACE, NAME) \ const android::String16 I##INTERFACE::descriptor(NAME); \ const android::String16& \ I##INTERFACE::getInterfaceDescriptor() const { \ return I##INTERFACE::descriptor; \ } \ android::sp<I##INTERFACE> I##INTERFACE::asInterface( \ const android::sp<android::IBinder>& obj) \ { \ android::sp<I##INTERFACE> intr; \ if (obj != NULL) { \ intr = static_cast<I##INTERFACE*>( \ obj->queryLocalInterface( \ I##INTERFACE::descriptor).get()); \ if (intr == NULL) { \ intr = new Bp##INTERFACE(obj); \ } \ } \ return intr; \ } \ I##INTERFACE::I##INTERFACE() { } \ I##INTERFACE::~I##INTERFACE() { } \ | cs |
보시는 바와 같이 #define을 통해 정의되어 있는 것을 확인하실 수 있습니다. 이 매크로에서 맨 오른쪽 부분에 BackSlash가 처리되어 있는 것은 해당 매크로 #define이 한 줄에서 끝나지 않고 있음을 의미합니다. 그리고 내용을 확인하시다 보면 다음과 같은 내용이 있습니다.
I##INTERFACELLI##INTERFACE() { }
여기서 '##'이란 해당 기호 앞뒤에 있는 글자를 곧바로 붙여쓰라는 의미로 이해해 주신다면 쉽게 넘어가실 수 있으리라 생각합니다.
INTERFACE가 'ServiceManager', Name이 '"android.os.IServiceManager"'로 정의되었다는 가정하에 Macro의 결과물은 다음과 같이 나타낼 수 있습니다.
/frameworks/native/libs/binder/IServiceManager.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | const android::String16 IServiceManager::descriptor("android.os.IServiceManager"); const android::String16& IServiceManager::getInterfaceDescriptor() const { return IServiceManager::descriptor; } android::sp<IServiceManager> IServiceManager::asInterface( const android::sp<android::IBinder>& obj) { android::sp<IServiceManager> intr; if (obj != NULL) { intr = static_cast<IServiceManager*>( obj->queryLocalInterface( IServiceManager::descriptor).get()); if (intr == NULL) { intr = new BpServiceManager(obj); } } return intr; } IServiceManager::IServiceManager() { } IServiceManager::~IServiceManager() { } | cs |
Macro를 해독하면 다음과 같은 코드가 적용되고 있음을 알 수 있습니다.
이 함수가 어떤 부분에서 중요하다는 의미인지 지금까지 설명드린 것 만으로는 충분히 이해하실 수 없으실 겁니다. 하지만 아래의 코드를 확인해 보신다면 단박에 위 매크로의 용도를 눈치채실 수 있을 겁니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | class BpServiceManager : public BpInterface<IServiceManager> { public: BpServiceManager(const sp<IBinder>& impl) : BpInterface<IServiceManager>(impl) { } .... virtual sp<IBinder> checkService( const String16& name) const { Parcel data, reply; data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor()); data.writeString16(name); remote()->transact(CHECK_SERVICE_TRANSACTION, data, &reply); return reply.readStrongBinder(); } .... } | cs |
처음에는 저 IServiceManager 내에 있는 getInterfaceDescriptor() 함수를 찾아보았는데 전혀 찾아낼 수가 없어서 다른 곳에서 이리저리 찾아봤건만 저렇게 Macro를 통해 구현되어 있다는 것은 꿈에도 생각하지 못했습니다! 참으로 안드로이드의 세계는 알거 같으면서도 어려운 구조로군요.
안드로이드 프레임워크 소스 내에는 위에서 소개드렸던 매크로 외에도 다음과 같이 2종류의 Macro가 존재합니다.
#define DECLARE_META_INTERFACE(INTERFACE)
#define CHECK_INTERFACE(interface, data, reply)
위 두 매크로 또한 제가 위에서 설명드린 바와 같이 해석을 해두신다면 원리를 쉽게 파악하실 수 있을 것입니다!
'안드로이드 > 프레임워크' 카테고리의 다른 글
| 안드로이드 프레임워크 프로그래밍(14) [서비스 매니저 생성 및 등록과정] (0) | 2015.03.29 |
|---|---|
| 안드로이드 Native 코드 분석 : DECLARE_META_INTERFACE() (0) | 2015.03.28 |
| 안드로이드 프레임워크 프로그래밍(13) [커널이미지 적용후 부팅화면만 나올 때 대처법] (0) | 2015.03.24 |
| 안드로이드 프레임워크 프로그래밍(12) [IServiceManager 등록과정] (1) | 2015.03.23 |
| 안드로이드 프레임워크 프로그래밍(11) [JAVA 프레임워크와 Native 프레임워크 연결 원리] (2) | 2015.03.18 |
설정
트랙백
댓글
글
우분투 사용중 안보이거나 깨진 언어가 나올 때 언어 설치방법
우분투가 상당히 매력적인 부분 중 하나라면 다양한 언어를 지원해준다는 점입니다. 심지어 이렇게 한글도 제공하는 환경인 것을 보면 우분투는 이름 그대로 공동체 정신을 담고 있는 것은 아닌가 싶습니다.
우분투를 사용하다가 종종 괴랄하게 등장하는 언어들이 보입니다. 이는 자신의 우분투에 해당 언어가 설치되어 있지 않아 보이지 않는 현상입니다.
위키피디아를 사용하던 중 생전 처음보는 괴랄한 글자들이 보시는 바와 같이 튀어나오고 있습니다. 과연 이 언어는 무엇일까요
잠시 한글위키로 넘어온 후 다른 언어로 된 위키백과 모두 보기를 눌러봅니다.
언어 목록들 중 유독 글자가 깨져서 보이는 것이 하나 보입니다. 써있기로는 Burmese라 되어 있군요,
확인해보니 해당 글은 버마어(미얀마어)였습니다. 이렇게 자신의 우분투 환경에서 존재하지 않는 언어를 확인하셨다면 해당 언어를 찾아 우분투에 설치하도록 합니다.
우분투의 시스템 설정 메뉴로 들어가신 후 언어 지원을 클릭합니다.
다음으로 '언어 설치/제거' 버튼을 눌러줍니다.
설치할 언어들의 목록들이 펼쳐지는 것을 보실 수 있습니다. 우리는 이 곳에서 버마어(미얀마어)를 추가합니다.
자신의 슈퍼유저 암호를 입력하시면 해당 언어의 설치가 시작됩니다.
해당 언어를 설치하신 후 우분투를 리셋하시면 깨져 보이지 않던 언어가 드디어 모습을 드러내게 됩니다.
'공대생의 팁' 카테고리의 다른 글
| 컴퓨터가 대기모드 되자마자 바로 풀릴 때 해결방법 (0) | 2015.04.05 |
|---|---|
| 우분투에서 인터넷창을 통해 윈도 미디어 플레이어 관련 영상 보는 방법 (0) | 2015.04.04 |
| 티스토리 블로그를 반년간 하면서... (0) | 2015.03.12 |
| [VMware] NX / XD is required. The processor must support and it must be enabled in the BIOS. (0) | 2015.02.21 |
| Windows XP에서 DOS 파일 실행시 EMS 문제 해결방법 (0) | 2015.01.26 |