Eventhub

[InputDeviceClass::]

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

그 중 이번에는 InputDeviceClass가 무엇이 있고 어떻게 결정되는지 간단하게 확인하려 한다.

1. InputDeviceClass

EventHub.h에 Device 속성들이 정의되어 있다. 보통 Device들 판단하는 기준은 keybit를 가지고 있는지를 check한다.

/*
 * Input device classes.
 */
enum class InputDeviceClass : uint32_t {
    /* The input device is a keyboard or has buttons. */
    KEYBOARD = 0x00000001,
    ...
    /* The input device is external (not built-in). */
    EXTERNAL = 0x80000000,
}

Keyboard가 되기 위한 조건

// See if this is a keyboard.  Ignore everything in the button range except for
// joystick and gamepad buttons which are handled like keyboards for the most part.
    bool haveKeyboardKeys =
            device->keyBitmask.any(0, BTN_MISC) || device->keyBitmask.any(BTN_WHEEL, KEY_MAX + 1);
    bool haveGamepadButtons = device->keyBitmask.any(BTN_MISC, BTN_MOUSE) ||
            device->keyBitmask.any(BTN_JOYSTICK, BTN_DIGI);
    if (haveKeyboardKeys || haveGamepadButtons) {
        device->classes |= InputDeviceClass::KEYBOARD;
    }

Switch가 되기 위한 조건

BitArray swBitmask; //SW_MAX = 0x10사이 값이 있으면 switch

    // Check whether this device has switches.
    for (int i = 0; i <= SW_MAX; i++) {
        if (device->swBitmask.test(i)) {
            device->classes |= InputDeviceClass::SWITCH;
            break;
        }
    }

Gamepad가 되기 위한 조건

아래 scancode 중 하나라도 가지고 있다면 Gamepad

static const int32_t GAMEPAD_KEYCODES[] = {
        AKEYCODE_BUTTON_A,      AKEYCODE_BUTTON_B,      AKEYCODE_BUTTON_C,    //
        AKEYCODE_BUTTON_X,      AKEYCODE_BUTTON_Y,      AKEYCODE_BUTTON_Z,    //
        AKEYCODE_BUTTON_L1,     AKEYCODE_BUTTON_R1,                           //
        AKEYCODE_BUTTON_L2,     AKEYCODE_BUTTON_R2,                           //
        AKEYCODE_BUTTON_THUMBL, AKEYCODE_BUTTON_THUMBR,                       //
        AKEYCODE_BUTTON_START,  AKEYCODE_BUTTON_SELECT, AKEYCODE_BUTTON_MODE, //
};

// See if this device has a gamepad.
for (size_t i = 0; i < sizeof(GAMEPAD_KEYCODES) / sizeof(GAMEPAD_KEYCODES[0]); i++) {
    if (device->hasKeycodeLocked(GAMEPAD_KEYCODES[i])) {
           device->classes |= InputDeviceClass::GAMEPAD;
           break;
        }
    }

DeviceClass에 따른 Mapper 할당

일러한 Device 속성들을 EventHub에서 결정하면 InputDevice.cpp에서 InputDeviceClass에 따라 Mapper를 설정해줌.

void InputDevice::addEventHubDevice(int32_t eventHubId, bool populateMappers) {
    // Switch-like devices.
    if (classes.test(InputDeviceClass::SWITCH)) {
        mappers.push_back(std::make_unique<SwitchInputMapper>(*contextPtr));
    }

    // Scroll wheel-like devices.
    if (classes.test(InputDeviceClass::ROTARY_ENCODER)) {
        mappers.push_back(std::make_unique<RotaryEncoderInputMapper>(*contextPtr));
    }

    // Vibrator-like devices.
    if (classes.test(InputDeviceClass::VIBRATOR)) {
        mappers.push_back(std::make_unique<VibratorInputMapper>(*contextPtr));
    }