Simulating keypress events on Android

Modern day smart-phones have already begun to migrate from the traditional "a-button-for-every-need" approach to the "huge-display-cum-touchscreen" form-factors. Android phones  are no exception. But, traditional buttons are still reqd. for a few oft used functions (power,back,home,menu etc.) And smart-phones continue to have them alongwith the primary touch-based-UI.

Android-OS provides a very easy method to simulate key/button press/release events via software. You might ask why do we need a software to generate the events when a hardware button is already present on the device. Here's why:
  • During development/testing of the button-drivers itself.
  • To implement automated rigorous tests. ( MonkeyTest? )
  • To implement/interface additional custom software keyboards.
  • Just because we can!
The reason why i am doing it today is REASON NUMBER 4.

Now, the basic goal of this exercise is extremely simple:
Q. How to generate a hardware-button-press event
    WITHOUT actually pressing any key on the device?

Let us first understand what happens when a hardware button is pressed. Here is what happens when you press a button on an Android device:
  1. The h/w button triggers an interrupt.
  2. The ISR of the corresponding driver gets called (in kernel).
  3. In the ISR, the driver generates an input-event.
  4. Android-framework (in userspace) gets the notification of the event.
  5. Android reads the input-event code & type.
  6. Compares it with the proper "keymap/keylayout" file.
  7. The proper button is identified.

To simulate button presses we enter this procedure at STEP3.
Instead of the regular driver generating the input-event, we generate an input-event ourselves using a pre-built userspace binary. This will then be notified to the Android-framework and the rest continues as above.

So now all depends on the the pre-built userspace binary, which is...
[ drum-roll... ]
...Input. (How convenient!) The syntax of input is as follows:
input keyevent <event_code>

Now, before we try to send any keyevent, we need to find out the event-code that maps to the h/w key we want to simulate. The following table summarizes all the supported keycodes in Android:


Additionally we can look up the keylayout (.kl) file on the device. Personally, I find keylayout a misnomer, as we are not talking about different keyboards here, but different mappings of an input-event-value to its functionality.

Anyways you can always find the file in system/usr/keylayout/xyz.kl
NOTE: For each keyboard device xyz, the android.keylayout.xyz system property must be set. If a keylayout file is not specified, Android will default to /system/usr/keylayout/qwerty.kl

Now to generate a event of a specific keycode, we simply execute this on the terminal/serial console:
input keyevent <keycode>

The value of keycode can be any of the integer values from the above table. In case a serial-console is NOT available on your device, you can always run the command via adb as follows:
adb shell input keyevent <keycode>

That's how a hardware-button-press is simulated in software!!



Further Reading:

27 comments :

  1. Awesome! Are there any way to detect foreground App to send accurate key events?

    ReplyDelete
  2. Have no problem using KEYCODE_CALL but no luck to hang-up with KEYCODE_ENDCALL.

    ReplyDelete
  3. @sj314 KEYCODE_ENDCALL CANNOT be intercepted by apps. Also since it is handled lower than the input queue, injecting it via adb may not work as expected.

    More info here:
    http://groups.google.com/group/android-platform/browse_thread/thread/c6e2de4b0cdbecd7/21b7cf4ee06a7005

    ReplyDelete
  4. Is there a way to send a key press event for long press (The one that generally opens a context menu)

    ReplyDelete
  5. @tagmaster Any character/string literals can be sent directly using "input text" command.

    For example to send a colon,

    adb shell input text ":"

    ReplyDelete
  6. Hi,

    still sending a text string with spaces is not supported.

    Or at least not on my device
    adb shell input text "a b c"
    Will only print 'a' to the device screen

    Workarounds are not so hard, just split the text on spaces and do 'adb shell input key SPACE' but it would be more convenient to have the adb to accept strings with spaces in them from the beginning

    Cheers Johan

    ReplyDelete
  7. Can i simulate the power on event when the battery is off? I want my phone to power on as soon as a charger is connected . My specific requirement will not allow me to press power on button to start the android phone . Can any one has any idea whether this can be done? Iphone automatically starts itself if battery is drained off and put to charge . I want similar functionality in android phone. Please let me know if this is possible at all or not? Can we actually simulate power on button event when phone is off completely?Is it through alarm interrupt?if yes then details please.
    Thanks in advance.

    ReplyDelete
    Replies
    1. Short answer: No.

      Long answer: The technique described in the above post requires Android to be booted-up on the device and adb setup properly between the device and the host-machine. Powering-on the device when charger is connected depends on how the bootloader is configured on it. When powered-off and connected to a charger, most Android devices just start charging and do NOT power-on until the power button is explicitly pressed.

      Delete
  8. The keylayout table you listed is working fine, but I tried to search for it on the system and didn't find it under /system/usr/keylayout in any "*.kl" file their. For example in your able the power keycode is 26 which is working on my device, but the power keycode in all my "*.kl" files are 116. I am confused.

    ReplyDelete
    Replies
    1. Here is the complete list of paths on the device where keylayout files can be stored.

      Also the various paths listed in the above link are in order of priority. i.e. the system starts scanning for a .kl file in the path at the top of the list and continues down the list.

      The first relevant .kl file found is used by the device.

      Multiple .kl files can exist on a device. This is usually done to handle different input-devices like external-keyboards & joysticks. The input-device can generally be identified by the names of the .kl files.

      Irrelevant keycodes can be listed in some .kl files. For example a joystick's .kl file could contain a (possibly wrong) keymap for the "power" button. Such codes do NOT affect the system behaviour as long as that particular input-device never generates that keycode.

      It also could be done intentionally to provide similar functionality from multiple interfaces. For example, a particular button on the joystick can be configured to act as a power button for the Android device.

      One can verify any .kl file using the Validate Keymaps tool (available as part of Android source code).

      Delete
  9. This works great when I use terminal emulator, but when I log in via ssh or telnet and issue the same command (i.e. input keyevent 82), I get a "Segmentation Fault" error.

    Anyway to run this with ssh and have the gui on the screen respond?

    Thanks!

    ReplyDelete
    Replies
    1. Not being able to run system commands is a common problem with various ssh servers on Android. It looks like its an issue with one or more environment vars not being setup properly which leads to missing lib and a seg-fault. You might want to run a trace on ssh from where you are trying to access the android device. Also the logs of the ssh-server on the Android device ought to be of help...

      Delete
    2. I did some more digging and found out that the version of su that I was using was causing the problem. It is the su that ships with the mk802 (which is what I am using). I downloaded Superuser from the market, and replaced the current su with it. Now it seems to be working, but it is a little slow. You don't happen to know of a way to speed it up do you?

      Delete
    3. Splendid job! :) Among other things, one way to speed-up ssh is switching to RSA keys which are almost 4times faster(for validation) than DSA.

      Delete
    4. Hi erocm123,
      How did you replace "su"?
      I have tried replacing the su file but executing su I do not get the su prompt.
      Can you provide the steps?
      Thanks!!

      Delete
  10. can anybody tell me that if i want to do any action on long click then it is possible using adb shell ? yes then how ? because i had try out to find out but get only by click event . please help me .

    ReplyDelete
  11. Thank you , helped me a lot :)

    ReplyDelete
  12. is there a way to do the "opposite"

    to hook a touch action to a hardware button, for instance

    (I have first person shooters on tables because you cant aim and fire correctly)

    in a game I press the screen to shoot which should be converted to a event, If I can attach that event to a button I'll be able to do the action with the button instead of the screen

    the same way as if I attach a game controller to the tablet.

    is that possible?

    ReplyDelete
  13. This works great! However , how can I use this to simuulate the screenshot capturing ? For capturing screenshot , *simultaneous* keypresses of volume down and power key are needed.

    ReplyDelete
  14. i want to change the device date . changing date by 7 day ahead . i used intent function am start -a android.intent.action.MAIN -n com.android.settings/.DateTimeSettings
    Now i can go ahead by 7 day by input keyevent to change the date .

    ReplyDelete
    Replies
    1. *now i want to go ahead by 7 days by input keyevent to change the date

      Delete
    2. One can use the keyevents 19/20/21/22 (up/down/left/right) and 66(enter) to navigate the UI elements. The following sequence of keyevents does the trick for me on my N1 running CyanogenMod7.2(gingerbread):-

      adb shell

      input keyevent 20
      input keyevent 20
      input keyevent 66
      (down,down,enter to select "set-date" option)
      input keyevent 22
      input keyevent 19
      (move focus to "+" over day)
      input keyevent 66
      input keyevent 19
      input keyevent 66
      input keyevent 19
      input keyevent 66
      input keyevent 19
      input keyevent 66
      input keyevent 19
      input keyevent 66
      input keyevent 19
      input keyevent 66
      input keyevent 19
      input keyevent 66
      (7 times "enter". "Up" to refocus onto "+")
      input keyevent 20
      input keyevent 20
      input keyevent 20
      input keyevent 66
      (move focus "down" to "Set" button and "enter")

      This might have to change depending on your device and any UI modifications based on the ROM you are running. For example if "Set Date" option is further down in the list, then additional "keyevent 20"s will be required to navigate all the way down.

      A simpler method for rooted devices would be to run the following command to set the required time and date.

      date -s yyyyMMdd.hhmmss

      Delete
  15. How do I delete say a list of characters for example.

    The quick brown fox.

    I could from the end of sentence execute the following command 20 times. But that executes rather slowly and it also seems superflous. Is there a execute multiple times command to make it simpler ?

    input keyevent 67
    input keyevent 67
    input keyevent 67
    input keyevent 67
    input keyevent 67
    input keyevent 67
    input keyevent 67
    input keyevent 67
    input keyevent 67
    input keyevent 67
    input keyevent 67
    input keyevent 67
    input keyevent 67
    input keyevent 67
    input keyevent 67
    input keyevent 67
    input keyevent 67
    input keyevent 67
    input keyevent 67
    input keyevent 67

    ReplyDelete
  16. Use shell scripts! ;-)

    Either enter the entire set of adb commands in a shell-script on the host-PC and run it.

    OR

    Create a shell-script on the Android-device with all the "input keyevent keycode" commands and run this script on the Android-device via "adb shell script-name".

    ReplyDelete
  17. Thanks mate
    this was useful

    ReplyDelete
  18. Hi ,

    I want to simulate Recent Apps icon on my Android device, can u guys pls let me know how to do it ....

    Thanks in Advance......

    ReplyDelete