Author Topic: remapping the Cosmo keyboard's Fn and Alt shortcuts for fun and productivity  (Read 3584 times)

Ninji

  • Newbie
  • *
  • Posts: 32
    • View Profile
I've been using my Cosmo for a few days now and something that's irked me a lot has been the inability to customise the Fn mappings. Some keys like Fn+S and Fn+Z have nothing mapped to them at all, and others like Fn+F are mapped to actions that I rarely need - not enough to justify a keyboard shortcut, anyway. And, Alt is forcibly mapped to the Planet App Bar which I would much rather replace with something more interesting.

There are two sets of mappings. The first is used for plain old character inputs, mostly the stuff on the number row and the right hand of the keyboard: |#\€<>[]{}+-=_@;:` and Home/PgUp/PgDn/End. I haven't messed with these myself just yet, but this thread in the Gemini subforum says they are specified through .kcm files contained in the Planet Keyboard app.

The second one, more interesting to myself, defines the handling of the Alt key (toggling the Planet AppBar) and all the Fn shortcuts with special actions: screenshot, mute, volume, brightness, home, app switcher, etc. This is part of Planet's modifications to Android itself. First, a bit of technical background.

--

On the Cosmo ROM these are handled in com.android.server.policy.PhoneWindowManager; specifically in the interceptKeyBeforeQueueing method (original AOSP code). If you want to look at this yourself you can use adb to pull /system/framework from your Cosmo and examine the services package (I used vdexExtractor's deodex script to get .dex files out of everything, and then jadx and Ghidra to analyse services.dex).

Planet's interceptKeyBeforeQueueing is hard to follow (jadx fails to decompile it, so I had to use Ghidra), but here is a summary of the interesting bits:
- redirects Volume Up/Volume Down (fingerprint sensor buttons) to accept or reject an incoming call iff the Cosmo is closed
- detects keycode 0x8D (F11) as the Cosmo having been closed
- detects keycode 0x8E (F12) as the Cosmo having been opened
- *on Cosmo open, jumps to the Home Screen and/or opens the AppBar depending on what is configured in Cosmo Settings
- detects keycode 0x131, and sends the CoDi command 0x1f,1 iff the Cosmo is closed
- detects Volume Up/Volume Down, keycodes 0xf9-0xfd and 0x12c-0x30, and sends them to the CoDi with command 0x15
- **detects Back and closes AppBar if it was opened with Alt
- detects Alt key-up and opens AppBar
- **detects Esc, Left/Up/Right/Down and Enter and redirects them to AppBar if it was opened with Alt
- **detects Fn, hijacks the press and sets a flag
- **redirects all keys pressed while Fn is held to the fnAction method (entirely a Planet addition, not in AOSP)
- handles Call/EndCall buttons (not sure if Cosmo uses this or if it's a holdover from generic Mediatek modifications to Android)
- toggles Caps Lock light
- *on Cosmo close, broadcasts com.iwrist.action.HALLCLOSE, notifies Planet VoiceAssistant, sends CoDi command 5,0, sleeps PowerManager
- *on Cosmo open, broadcasts com.iwrist.action.HALLOPEN, notifies Planet VoiceAssistant, sends CoDi command 5,1, wakes up PowerManager
- detects USB port connections using special keys F14-F17

--

So how does this help us?

We can probably use EdXposed to write a module that hooks interceptKeyBeforeQueueing and fnAction, and replaces how specific keys are handled. This gives us full control but requires more effort (I will probably do this myself over the coming days -- if I do, it will be open sourced on GitHub) and of course also requires rooting.

There is another way though. Note that some of the things above are marked with * and **. The Cosmo (at least, in the out-of-the-box Android 9 build) allows these to be disabled -- without root!

The ones marked with * can be disabled using the following shell command (e.g. via adb shell): settings put system AEON_HALL_TEST 1. Use 0 instead of 1 to revert to normal.
This is slightly interesting but not practical -- it stops the Cosmo from locking on close (and unlocking on open), and stops the CoDi from changing states. Instead of these behaviours, the OS broadcasts com.eastaeon.action.HALLCLOSE on close and com.eastaeon.action.HALLOPEN on open.

For keymapping, the far more interesting command is: settings put system AEON_KEY_TEST 1 which disables the ones marked with **. Use 0 instead of 1 to revert to normal.

With this in play, Fn is now freed up and regular Android applications can detect it! I'm currently using Key Mapper (F-Droid, Play Store) to map Fn+stuff to the actions I want, both replicating the stock Cosmo actions like home and screenshot, and also adding new ones.

Unfortunately, this trick does not allow the Alt key to be replaced (unless someone can think of a crafty way to let us supply our own com.Pripla.Floating package exposing a com.Pripla.Floating.FloatingWindow service, without Android complaining about it having the same package ID as the Planet AppBar which is a system app). Still, it's a start and already exposes lots more possibilities.

spook

  • Jr. Member
  • **
  • Posts: 89
    • View Profile
remapping the Cosmo keyboard's Fn and Alt shortcuts for fun and productivity
« Reply #1 on: December 30, 2019, 08:56:08 pm »
Wow - do you ever sleep Ninji???

This is very interesting. On a (not really) related topic. I wonder if this:

*on Cosmo close, broadcasts com.iwrist.action.HALLCLOSE, notifies Planet VoiceAssistant, sends CoDi command 5,0, sleeps PowerManager

is why the Cosmo doesn't seem to be able to deep sleep. I've found - on mine at least - that my Cosmo never enters deep sleep. The wake lock that seems to be preventing this is the Kernal (not very helpful). I assumed that the COD needs the Cosmo to be always awake to communicate. But having said this, your finding seem to indicate that when the Cosmo is closed, it tells PowerManager to "sleep". Does this mesn that PowerManager is no possibly longer able to put the device into deep sleep I wonder?