입력

Android 입력 HAL 아이콘

Android 입력 하위 시스템은 명목상으로 시스템의 여러 레이어를 통과하는 이벤트 파이프라인으로 구성됩니다.

입력 파이프라인

실제 입력 기기는 최하위 레이어에서 키 누름 및 터치 접점과 같은 상태 변화를 나타내는 신호를 생성합니다. 기기 펌웨어는 이러한 신호를 인코딩하여 전송하며, 이때 USB HID 보고서를 시스템에 전송하거나 I2C 버스에 관한 인터럽트를 생성하는 등의 방식을 사용합니다.

이어서 신호는 Linux 커널의 기기 드라이버에 의해 디코딩됩니다. Linux 커널은 다수의 일반적인 주변기기, 특히 HID 프로토콜을 준수하는 기기를 위한 드라이버를 제공합니다. 하지만 OEM은 터치스크린과 같은 하위 수준의 시스템에 밀접하게 통합되는 내장형 기기의 맞춤 드라이버를 자주 제공해야 합니다.

입력 기기 드라이버는 Linux 입력 프로토콜을 통해 기기별 신호를 일반적인 이벤트 형식으로 변환해야 합니다. Linux 입력 프로토콜은 linux/input.h 커널 헤더 파일의 표준적인 이벤트 유형 및 코드 집합을 정의합니다. 이렇게 하면 커널 외부의 구성요소는 실제 스캔 코드, HID 사용, I2C 메시지, GPIO 핀 등의 세세한 부분에 신경쓰지 않아도 됩니다.

이어서 Android EventHub 구성요소는 각 입력 기기에 연결된 evdev 드라이버를 열어 커널의 입력 이벤트를 읽습니다. 그러면 Android InputReader 구성요소는 기기 클래스에 따라 입력 이벤트를 디코딩하고 Android 입력 스트림을 생성합니다. 이러한 과정의 일부로, Linux 입력 프로토콜 이벤트 코드는 입력 기기 구성, 키보드 레이아웃 파일 및 다양한 매핑 테이블에 따라 Android 이벤트 코드로 변환됩니다.

마지막으로 InputReader는 입력 이벤트를 InputDispatcher로 전송하며, 여기에서 이벤트가 적절한 창으로 전달됩니다.

컨트롤 포인트

입력 파이프라인에는 입력 기기 동작 제어에 영향을 미치는 여러 단계가 있습니다.

드라이버 및 펌웨어 구성

입력 기기 드라이버는 종종 레지스터에서 매개변수를 설정하거나 펌웨어 자체를 업로드하여 입력 기기의 동작을 구성합니다. 특히 이러한 매개변수를 조정하거나 펌웨어를 수정하여 원하는 정확성과 응답성을 제공하고 노이즈를 억제하는 과정이 보정 프로세스의 대부분을 차지하는 터치스크린 등의 내장형 기기에서는 이러한 구성이 더 자주 이루어집니다.

드라이버 구성 옵션은 커널 보드 서포트 패키지(BSP)의 모듈 매개변수로 지정되는 경우가 많으므로 동일한 드라이버가 여러 다양한 하드웨어 구현을 지원할 수 있습니다.

이 문서에서는 드라이버 또는 펌웨어 구성을 설명하며, 일반적인 기기 보정에 대한 지침을 제공합니다.

보드 구성 속성

커널 보드 서포트 패키지(BSP)는 Android InputReader 구성요소에서 사용하는 SysFS를 통해 보드 구성 속성을 내보낼 수 있습니다(예: 터치스크린에 가상 키를 배치).

다양한 기기에서 보드 구성 속성을 사용하는 방식에 대해 자세히 알아보려면 기기 클래스 섹션을 참고하세요.

리소스 오버레이

몇몇 입력 동작은 config.xml의 리소스 오버레이를 통해 구성됩니다(예: lid 스위치 작동).

다음은 몇 가지 예입니다.

  • config_lidKeyboardAccessibility: lid 스위치를 작동하여 하드웨어 키보드를 액세스 가능하도록 할지 아니면 숨길지를 지정합니다.

  • config_lidNavigationAccessibility: lid 스위치를 작동하여 트랙패드를 액세스 가능하도록 할지 아니면 숨길지를 지정합니다.

  • config_longPressOnPowerBehavior: 사용자가 전원 버튼을 길게 눌렀을 때 발생해야 하는 결과를 지정합니다.

  • config_lidOpenRotation: 화면 방향에 대한 lid 스위치의 효과를 지정합니다.

각 구성 옵션에 대한 자세한 내용은 frameworks/base/core/res/res/values/config.xml 내 문서를 참조하세요.

키 맵

키 맵은 Android EventHubInputReader 구성요소에 의해 사용되며, 이 경우 키, 조이스틱 버튼 및 조이스틱 축과 관련하여 Linux 이벤트 코드에서 Android 이벤트 코드로 매핑을 구성하는 데 목적이 있습니다. 매핑은 기기나 언어에 종속될 수 있습니다.

다양한 기기에서 키 맵을 사용하는 방식에 관해 자세히 알아보려면 기기 클래스 섹션을 참고하세요.

입력 기기 구성 파일

입력 기기 구성 파일은 Android EventHubInputReader 구성요소에 의해 사용되며, 이 경우 터치 크기 정보가 보고되는 방식과 같은 특수한 기기 특성을 구성하는 데 목적이 있습니다.

다양한 기기에서 입력 기기 구성 맵을 사용하는 방식에 대해 자세히 알아보려면 기기 클래스 섹션을 참조하세요.

HID 사용 및 이벤트 코드

키보드의 키, 게임 컨트롤러의 버튼, 조이스틱 축 또는 기타 컨트롤을 지칭하기 위해 사용되는 여러 다양한 식별자가 존재하는 경우가 많습니다. 식별자 간의 관계가 항상 동일한 것은 아닙니다. 관계는 여러 매핑 테이블에 종속되며, 일부는 고정되고 일부는 기기 특성, 기기 드라이버, 현재 언어, 시스템 구성, 사용자 환경설정 및 기타 요인에 따라 다를 수 있습니다.

실제 스캔 코드

실제 스캔 코드는 각 키, 버튼 또는 기타 컨트롤에 연결되는 기기별 식별자입니다. 실제 스캔 코드는 기기마다 다른 경우가 많습니다. 따라서 펌웨어 또는 기기 드라이버에서 이러한 스캔 코드를 HID 사용 또는 Linux 키 코드와 같은 표준 식별자에 매핑해야 합니다.

스캔 코드는 주로 키보드와 관련이 있습니다. 다른 기기는 보통 하위 수준에서 통신하며, 이때 GPIO 핀, I2C 메시지 또는 기타 수단을 사용합니다. 따라서 소프트웨어 스택의 상위 레이어는 현재 상황을 파악하기 위해 기기 드라이버에 의존합니다.

HID 사용

HID 사용은 키보드 키, 조이스틱 축, 마우스 버튼 또는 터치 접점과 같은 컨트롤의 상태를 보고하는 데 사용되는 표준 식별자입니다. 대부분의 USB 및 블루투스 입력 기기는 HID 사양을 준수합니다. 따라서 시스템이 이러한 기기와 일정한 방식으로 상호작용할 수 있습니다.

Android 프레임워크는 HID 사용 코드를 Linux 키 코드 및 기타 식별자로 변환하기 위해 Linux 커널 HID 드라이버에 의존합니다. 따라서 HID 사용은 주로 주변기기 제조업체와 관련이 있습니다.

Linux 키 코드

Linux 키 코드는 키 또는 버튼의 표준 식별자입니다. Linux 키 코드는 linux/input.h 헤더 파일에서 접두어 KEY_ 또는 BTN_으로 시작되는 상수를 사용하여 정의됩니다. Linux 커널 입력 드라이버는 실제 스캔 코드, HID 사용 및 기타 기기별 신호를 Linux 키 코드로 변환하고 관련 정보를 EV_KEY 이벤트의 일부로 제공하는 역할을 합니다.

간혹 Android API는 키에 연결된 Linux 키 코드를 '스캔 코드'로 지칭합니다. 이는 엄밀히 말하면 잘못되었지만 API에서 Linux 키 코드와 Android 키 코드를 구분하는 데에는 도움이 됩니다.

Linux 상대축 또는 절대축 코드

Linux 상대축 또는 절대축 코드는 축에 따른 상대적 움직임 또는 절대 위치를 보고하기 위한 표준 식별자입니다(X 축을 따라 발생하는 마우스의 상대적 움직임 또는 X 축을 따라 발생하는 조이스틱의 절대 위치). Linux 축 코드는 linux/input.h 헤더 파일에서 접두어 REL_ 또는 ABS_로 시작하는 상수를 사용하여 정의됩니다. Linux 커널 입력 드라이버는 HID 사용 및 기타 기기별 신호를 Linux 축 코드로 변환하고 관련 정보를 EV_RELEV_ABS 이벤트의 일부로 제공하는 역할을 합니다.

Linux 스위치 코드

Linux 스위치 코드는 lid 스위치와 같은 기기의 스위치 상태를 보고하기 위한 표준 식별자입니다. Linux 스위치 코드는 linux/input.h 헤더 파일에서 접두어 SW_로 시작하는 상수를 사용하여 정의됩니다. Linux 커널 입력 드라이버는 스위치 상태 변화를 EV_SW 이벤트로 보고합니다.

일반적으로 Android 애플리케이션은 스위치의 이벤트를 수신하지 않지만 시스템에서는 다양한 기기별 기능을 제어하기 위해 이러한 이벤트를 내부적으로 사용할 수 있습니다.

Android 키 코드

Android 키 코드는 'HOME'과 같은 특정 키를 나타내기 위해 Android API에서 정의되는 표준 식별자입니다. Android 키 코드는 android.view.KeyEvent 클래스에 의해 접두어 KEYCODE_로 시작되는 상수로 정의됩니다.

키 레이아웃은 Linux 키 코드가 Android 키 코드에 매핑되는 방식을 정의합니다. 키보드 모델, 언어, 국가, 레이아웃 또는 특수 기능에 따라 다양한 키 레이아웃이 사용될 수 있습니다.

Android 키 코드 조합은 기기, 그리고 언어별 키 문자 맵을 사용하는 문자 코드로 변환됩니다. 예를 들어 KEYCODE_SHIFTKEYCODE_A로 식별된 두 개의 키를 함께 누르면 시스템은 키 문자 맵의 조합을 조회하여 대문자 'A'를 찾은 다음 현재 포커스가 맞춰진 텍스트 위젯에 삽입합니다.

Android 축 코드

Android 축 코드는 특정 기기 축을 나타내기 위해 Android API에서 정의되는 표준 식별자입니다. Android 축 코드는 android.view.MotionEvent 클래스에 의해 접두어 AXIS_로 시작하는 상수로 정의됩니다.

키 레이아웃은 Linux 축 코드가 Android 축 코드에 매핑되는 방식을 지정합니다. 기기 모델, 언어, 국가, 레이아웃 또는 특수 기능에 따라 다양한 키 레이아웃이 사용될 수 있습니다.

Android 메타 상태

Android 메타 상태는 어떤 특수키가 눌렸는지를 나타내기 위해 Android API에서 정의되는 표준 식별자입니다. Android 메타 상태는 android.view.KeyEvent 클래스에 의해 접두어 META_로 시작하는 상수로 정의됩니다.

현재 메타 상태는 KEYCODE_SHIFT_LEFT와 같은 특수키가 언제 눌렸거나 해제되었는지, 언제 적절한 메타 상태 플래그를 설정하거나 재설정하는지를 모니터링하는 Android InputReader 구성요소에 의해 결정됩니다.

특수키와 메타 상태의 관계는 하드코딩되지만 키 레이아웃은 특수키 자체가 매핑되어 메타 상태에 영향을 미치는 방식을 변경할 수 있습니다.

Android 버튼 상태

Android 버튼 상태는 마우스나 스타일러스의 어떤 버튼이 눌렸는지를 나타내기 위해 Android API에서 정의되는 표준 식별자입니다. Android 버튼 상태는 android.view.MotionEvent 클래스에 의해 접두어 BUTTON_으로 시작하는 상수로 정의됩니다.

현재 버튼 상태는 마우스 또는 스타일러스의 버튼이 언제 눌렸거나 해제되었는지, 언제 적절한 버튼 상태 플래그를 설정하거나 재설정하는지를 모니터링하는 Android InputReader 구성요소에 의해 결정됩니다.

버튼과 버튼 상태의 관계는 하드코딩됩니다.

추가 자료

  1. Linux 입력 이벤트 코드
  2. Linux 멀티터치 프로토콜
  3. Linux 입력 드라이버
  4. Linux 강제 피드백
  5. HID 정보(HID 사용 테이블 포함)