blob: d05e3f2a8c97236d4250d99584d27c44ab5c746a [file] [log] [blame]
This document explains how keyboard emulation works in the Android emulator.
Short version: it's not pretty.
Guest system view of input keys:
The goldfish events virtual device (see GOLDFISH-VIRTUAL-HARDWARE.TXT) is used
to send keyboard-related events to the kernel. More specifically:
- Each virtual 'keydown' is sent as a single (EV_KEY, <keycode>, 1) tuple.
- Each virtual 'keyup' is sent as a single (EV_KEY, <keycode>, 0) tuple.
Where <keycode> is a 9-bit Linux hardware keycode, as defined in
The guest Android system receives Linux keycodes from the kernel, and
translates them into Unicode values through a 'charmap file'. This file
acts as a map from (base key code + modifiers) -> unicode point.
An emulated system image normally contains a single charmap named 'qwerty2',
whose content is duplicated under android/skin/charmap.c (see this file for
It's possible to load an alternative charmap in the emulator with the
'-charmap <file>' option, where <file> points to an Android charmap file
(which typically end in .kcm). This feature has very rarely been used though.
The source file above also contains a function that can perform a reverse
mapping operation: given a Unicode value, generate the sequence of key strokes
for the corresponding 'keydown' or 'keyup' event, if possible.
This operation is not always possible, for example, 'qwerty2' doesn't contain
any entry that allows one to generate an accented letter like 'é'. This is a
*fundamental* limitation of keyboard emulation as it currently is implemented.
Android emulator UI keyboard handling:
When SDL 1.x is being used, it generates SDL_KEYDOWN and SDK_KEYUP events from
user keypresses, these contain three important fields:
keycode: A hardware-agnostic scancode, just like Linux keycodes but with
different values.
mod: A bitmask of activie modifier keys (e.g. Shift, Ctrl, Meta).
unicode: The corresponding Unicode value, if available, or 0. Note that
this is only properly populated on KEYDOWN events, it is always
0 on KEYUP one, due to the way SDL 1.x is implemented.
With SDL 2.x, things are a bit different though, because the |unicode| field
is no longer part of SDK_KEYDOWN/KEYUP events. Instead, there is a new event
type SDL_TEXTINPUT that contains a _list_ of Unicode points (to accomodate
for complex Input Method Engines). These events typically appear after
When the UI receives a SDL_KEYDOWN event, it must decide what to do with it,
1) It must check whether this is one of the UI keyboard shortcuts
(e.g. Ctrl-F11 to switch to the previous layout), that must _not_
be passed to the guest system. And handle them.
2) It must rotate DPad / Arrow events based on the layout orientation,
because that's what the guest system expects (due to long historical
3) It must reverse-map the Unicode value into Linux keycodes using the
current charmap.
When SDL 1.x is used, the |unicode| field from the SDL_KEYDOWN event
can be used directly, for SDL 2.x, the SDL_KEYDOWN event must be ignored,
and the SDL_TEXTINPUT event must be used instead.
To better match both models, the UI event handling uses a model similar to
SDL 2.x, where:
- SDL 2.x events are directly mapped to kEventKeyUp, kEventKeyDown and
kEventTextInput as defined in android/skin/event.h
- SDL 1.x events are translated into the corresponding kEventXXX values,
and kEventTextInput events are synthetized automatically from the
|unicode| field of SDL_KEYDOWN events.
Android emulator keyboard shortcuts:
Key presses used to control the emulator UI directly, i.e. those that are not
passed to the guest, are defined in what is called a 'keyset' file. The default
one is hard-coded in the emulator binary. Look inside android/skin/keyset.c
for details.
It is possible to use an alternative one with the '-keyset <file>' option.
The file format is text-based, where each line must have the following format:
<command> <key-list>
Where <command> is the name of an internal UI command (e.g. TOGGLE_FULLSCREEN),
and <key-list> is a comma-separated list of key combination
(e.g. 'Alt-Enter').
See android/skin/keyset.c for more details on the parser. This feature is
very rarely used.
Android emulator 'raw' keyboard mode:
As a special exception, pressing Ctrl-K at runtime will switch the emulator
into 'raw' keyboard mode. Note that this specific sequence is hard-coded in
the emulator.
Raw mode is used for debugging. It skips the reverse charmap operation and
sends host keycodes directly to the kernel, which typically never gives
the results a typical would expect. It may be removed in the future.