Search code examples
androidxposed

Android 4.4 get hardware key ids (which are actually available on the device)


I'm working on an Xposed Module which uses hardware buttons (like Power, Volume Up, etc) to initiate some actions. I'd like to add a "Settings" UI so the user can chose which button he want's to use.

So far, I found several possible solutions but none of them will fit the bill for me. For example, the following all return true:

boolean hasMenuKey = ViewConfiguration.get(context).hasPermanentMenuKey();
boolean hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK);
boolean hasVolumeUpKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_VOLUME_UP);

However, the device actually doesn't have any volume key at all. By logging the hardware keys, I found out that the "volume" key is actually KEYCODE_F1. So checking deviceHasKey() is unreliable and I can't count on it.

Is there another solution for checking which hardware keys are available which actually works like you would expect? Or even better, is there a way to get a complete list of all available buttons?

Also could somebody explain why deviceHasKey() returns true for the volume keys (_UP, _DOWN, _MUTE) while there is no single volume button at all? I think it must have something to do with the KeyCharacterMap of the device which might be poorly implemented due to the fact that the device is a cheap china device.

My third question is: is there a way to distinguish between buttons which work when the device is asleep (Power, Volume, F1 in my case) and buttons which doesn't (like Menu, Back, Home, which are all touch buttons below the display (not software buttons IN the display) instead of pressable buttons)?

Any hint is highly appreciated :)

Thank you in advance

-----UPDATE------

As suggested by Burak Day, here's the result of adb shell getevent -lp:

add device 1: /dev/input/event0
  name:     "mtk-kpd"
  events:
    KEY (0001): KEY_HOME              KEY_END               KEY_VOLUMEDOWN        KEY_VOLUMEUP         
                KEY_POWER             KEY_MENU              KEY_BACK              KEY_HP               
                KEY_CAMERA            KEY_SEND             
  input props:
    <none>
add device 2: /dev/input/event4
  name:     "mtk-tpd-kpd"
  events:
    KEY (0001): KEY_MENU              KEY_BACK              KEY_HOMEPAGE         
  input props:
    <none>
could not get driver version for /dev/input/mouse0, Not a typewriter
add device 3: /dev/input/event3
  name:     "mtk-tpd"
  events:
    KEY (0001): KEY_MENU              KEY_BACK              KEY_HOMEPAGE          BTN_TOUCH            
    ABS (0003): ABS_X                 : value 0, min 0, max 240, fuzz 0, flat 0, resolution 240
                ABS_Y                 : value 0, min 0, max 240, fuzz 0, flat 0, resolution 240
                ABS_PRESSURE          : value 0, min 0, max 255, fuzz 0, flat 0, resolution 0
                ABS_MT_TOUCH_MAJOR    : value 0, min 0, max 100, fuzz 0, flat 0, resolution 0
                ABS_MT_TOUCH_MINOR    : value 0, min 0, max 100, fuzz 0, flat 0, resolution 0
                ABS_MT_POSITION_X     : value 0, min 0, max 240, fuzz 0, flat 0, resolution 0
                ABS_MT_POSITION_Y     : value 0, min 0, max 240, fuzz 0, flat 0, resolution 0
                ABS_MT_TRACKING_ID    : value 0, min 0, max 0, fuzz 0, flat 0, resolution 0
  input props:
    INPUT_PROP_DIRECT
add device 4: /dev/input/event2
  name:     "hwmdata"
  events:
    REL (0002): REL_Y                
  input props:
    <none>
add device 5: /dev/input/event1
  name:     "ACCDET"
  events:
    KEY (0001): KEY_VOLUMEDOWN        KEY_VOLUMEUP          KEY_HANGEUL           KEY_NEXTSONG         
                KEY_PLAYPAUSE         KEY_PREVIOUSSONG      KEY_STOPCD            KEY_SEND             
  input props:
    <none>
could not get driver version for /dev/input/mice, Not a typewriter

As you can see, the device thinks that there are buttons available and after talking to the manufacturer, we found out that they could add more buttons to the device (if we would order a certain amount and pay a few thousand dollars extra). But still, in the current variation, the buttons don't exist.

My guess is, that the device uses a modular board/processor/driver where you can solder buttons to it or just leave them blank but the software doesn't know if a button is soldered on the board or not.

How am I supposed to know if a button is physically available? I want to make my module as generic as possible so that it might run on other devices in the future without explicitly changing the code. Also I don't want to show possible buttons to the user if they are not really existing.

Another thing is that I still need a way to differ between buttons which are available when the device is asleep (Power, Volume) and the ones which are not (Menu, Home, Back, all of them are touch buttons and if the display is powered off, they are powered off too).

----UPDATE 2----

I checked the raw hex value of the keys of the event0 device. Then I translated them using the "mtk-kpd.kl" character map. Then I used the respective KeyEvent ids to check if the device returns true for all of them:

Log.d(Constants.LOG_TAG, "Home:" + KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_HOME));
Log.d(Constants.LOG_TAG, "END:" + KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_ENDCALL));
Log.d(Constants.LOG_TAG, "Volume Up:" + KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_VOLUME_UP));
Log.d(Constants.LOG_TAG, "Volume Down:" + KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_VOLUME_DOWN));

Log.d(Constants.LOG_TAG, "POWER:" + KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_POWER));
Log.d(Constants.LOG_TAG, "Menu:" + KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_MENU));
Log.d(Constants.LOG_TAG, "Back:" + KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK));
Log.d(Constants.LOG_TAG, "HP:" + KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_FOCUS));

Log.d(Constants.LOG_TAG, "CAMERA:" + KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_CAMERA));
Log.d(Constants.LOG_TAG, "Send:" + KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_CALL));

And yes, they all return true...


Solution

  • I came to the conclusion that there is no reliable way to find out which hardware buttons are available if the manufacturer of the device did a poor job.

    In my case, it is that the hardware/software is capable of having several buttons. However, the device actually has only a few buttons soldered on the logic board.

    There is no way to identify if a button is actually soldered onto the board at App level.