리눅스 & 안드로이드2016. 1. 22. 13:41

Input Device의 input event를 App.에서 직접 받아 볼 필요가 있어, NDK로 epoll을 이용해 구현 했던 내용을 정리 해 본다.

epoll 관련 설명은 The Event Poll Interface를 참고 하였다.


우선, device driver file의 fd를 사용해야 하기 때문에, 해당 device file을 열 수 있는 권한을 App.이 가지고 있어야 한다. (예를 들면 App.이 system 권한을 가지고 있어야 한다.)

아래 예제 소스 각각의 특징에 대해서, 간략하게만 정리 해 둔다. 구현 했던 걸, 생각나는 대로 다시 정리한 것이라서, 그대로 copy & paste 하면 제대로 빌드가 되지 않을 수는 있겠으나, 전체적인 맥락은 유효하니 나중에 필요할 때 다시 볼 수 있을 것으로 믿는다.ㅎㅎ


[Header]

  • epoll이나 device driver 파일을 열고나면, 열린 file descriptor를 복사한다는거 자체가 적절하지 않으므로, 복사/대입을 막아 두었다.
  • epoll로 이벤트를 받고 처리하기위해 thread를 하나 만들었으며, 전달 받은 이벤트를 container에 저장 해 두고 사용하기 위해서 mutex를 하나 두었다.
  • JNI에서 instance를 생성하고 사용해야 하므로, 간단하게 constructor에서 모든 초기화를 마치고, destructor에서 file descriptor등을 닫도록 처리 했다.


[Source]

  • threadHandler에서는 epoll_wait으로 이벤트를 무한정 대기한다.(timeout 시간을 지정할 수도 있음)
  • 정상적으로 이벤트를 받은 경우, epoll_wait이 이벤트의 개수를 반환한다. 이 개수 만큼, 대상 file descriptor를 통해 이벤트 데이터를 읽어 들인다.
  • 오류를 검사하고, input_event 구조체를 통해 이벤트 데이터를 활용한다.


[JNI interface for JAVA]

  • App.에서 JAVA로 호출하게 될 native 함수 정의이다.
  • native도 복사/대입 금지를 하도록 되어 있으므로, JAVA interface도 singleton으로 구현하는 것이 적절하다고 판단 되므로, static으로 선언!
  • native instance의 pointer를 JAVA instance에서 보관하고 활용하는 방식으로 구현되어 있으므로, native interface를 추가하고 활용하기 위해서는, long 타입의 native instance pointer를 전달하는 것이 필요하다.
※ 참고로 native library를 동적으로 로드하기 위해 아래 코드가 JAVA layer에 추가되어 있어야 함.

static {
System.loadLibrary("epoll_sample");
}


[JNI interface for C/C++]

  • App.이 native 초기화를 진행하면, native instance를 생성하면서 초기화를 진행하고, 문제가 없으면 instance pointer를 반환한다.
  • 현재는 device driver 파일경로를 직접 표시 했는데, android property 등의 환경변수나 다른 입력을 통해 전달 받도록 할 수 있겠다.


[Android.mk]

  • 일반적인 NDK makefile이며, C++11을 사용하기위해 -std=c++11을 추가함. (Application.mk에서와 중복되어 있다)


[Application.mk]

  • GCC 4.9와 STL 사용을 위해 명시적으로 추가 해 두었다.
  • platform이 32bit/64bit ABI를 사용하므로 두 종류 모두 빌드 할 수 있도록, armeabi-v7a, arm64-v8a를 추가 했다.


※ NDK로는 아무 문제없이 빌드가 되는데, Android platform에 추가해서 빌드를 해 보니 STL header(string 등등)의 path를 기본적으로 찾지 못했고, prebuilt에 포함된 NDK v9을 이용해 빌드 하면 컴파일은 가능하지만, arm64-v8a binary link를 진행하면서 unsupported ELF machine number 183 에러가 발생하였다. 구글링을 통해 google group이나 stack overflow의 글들을 찾아 보고, 적용해 볼만한건 다 해 봤지만 빌드가 되지 않았다.

해결 방법을 아시는 분은 덧글로 알려주시면 감사하겠습니다. (__)


Posted by 세월의돌