Xtr126 / XtMapper

Advanced keyboard and mouse input mapping tool
https://xtr126.github.io/XtMapper-docs
GNU General Public License v3.0
189 stars 21 forks source link

Any fixes for waydroid? #35

Closed coronavirus6045 closed 12 months ago

coronavirus6045 commented 1 year ago

I have done some workarounds in #9 in the latest version, but i experienced the same errors OP got (libmouse_read.so error.) even i installed the APK from #6 but same problem

There hasn't been an update on #9 since 03/26.

waydroid runs Android in a container, it doesn't have direct access to input devices (evdev). You might need to hotplug input devices (kbd,mouse) for the keymapper to function. I couldn't find any way to get exclusive access to mouse input devices from within Android other than reading from kernel evdev devices.

Have you found another way without exclusive access? Also did you consider "persist.waydroid.uevent" property in waydroid which makes direct access to hotplugged devices.

Are the fixes upstream?

Xtr126 commented 1 year ago

Are the fixes upstream?

Fix to that specific issue is already upstreamed: https://github.com/waydroid/waydroid/pull/826

Also did you consider "persist.waydroid.uevent" property in waydroid which makes direct access to hotplugged devices.

It's up to the user to set that property and use the keymapper. But that's not an ideal solution since the mouse will be locked to Android only then. Linux host wont be able to access the mouse. Maybe it will be feasible in the future when Xtmapper gets the ability to auto pause/resume by detecting game activity. Before that property arrived in this commit https://github.com/waydroid/android_vendor_waydroid/commit/d73294de55d47eff4f27968aa92c5b6ea513eb5a, waydroid had hotplugging by default. I tried with that BOOTCLASSPATH workaround and the keymapper worked fine on waydroid at that time. Directly accessing input devices evdev is possibly the lowest latency method I can use for mouse capture.

Have you found another way without exclusive access?

I was thinking about a way like running a daemon on Linux host side for mouse capture and communicating with the app running in the Android container. Feel free to share any ideas you have.

Xtr126 commented 1 year ago

I tried right now using waydroid Android 13 image. Cannot reproduce that issue on my end. Using this command for activation: adb shell sh /sdcard/Android/data/xtr.keymapper/files/xtMapper.sh (Does not work with sudo waydroid shell on Android 13) On Android 11 image this command works but not adb shell: sudo waydroid shell sh /storage/emulated/0/Android/data/xtr.keymapper/files/xtMapper.sh Replugging USB mouse/keyboard and set that property you mentioned persist.waydroid.uevent for mouse/keyboard to be recognized. After replugging USB mouse have to use arrow keys on keyboard to navigate and press enter key on start button of the app, must be done carefully.

coronavirus6045 commented 1 year ago

might be something unusual in your waydroid session. did you use waydroid-script? i did not replug when trying to make it work before i opened the issue so gonna try it some time

Xtr126 commented 1 year ago

might be something unusual in your waydroid session. did you use waydroid-script? i did not replug when trying to make it work before i opened the issue so gonna try it some time

No modifications to the system image or using waydroid_script. I tested on a fresh install. The adb command doesnt work on Android 11 waydroid image due to a filesystem permission issue specific to waydroid: https://github.com/casualsnek/waydroid_script#granting-full-permission-for-apps-data-hack

coronavirus6045 commented 1 year ago

I reinstalled the android 11 image (fresh install) I activated uevent property, replugged the mouse and keyboard and started the script before opening the app, same issue (libmouse_read.so error) What does libmouse_read.so do or it is maybe the issue. When i replugged the mouse and keyboard after activating the property, i can move the mouse but cannot click and every input on keyboard when alt tabbing off the session is also passed to the container.

I thought of an idea where the "linux host" can apply the property and reconnect the mouse and keyboard when focused to session and the keymapped app (e.g. a mobile game) and disable it when out of session or not in the keymapped app Is this the idea you came up? idk if i repeated your idea.

i'm not a programmer but this idea may be good.

my system runs ubuntu 22.04

Xtr126 commented 1 year ago

I reinstalled the android 11 image (fresh install) I activated uevent property, replugged the mouse and keyboard and started the script before opening the app, same issue (libmouse_read.so error) What does libmouse_read.so do or it is maybe the issue.

As the name of the file implies, it is used to read mouse events from /dev/input/eventX. I have been using this image lineage-18.1-20230212 and lineage-18.1-20230729. Didn't have any libmouse_read.so issue. Im using it on arch linux. You could try the Android 13 images that were shared in the waydroid group.

I thought of an idea where the "linux host" can apply the property and reconnect the mouse and keyboard when focused to session and the keymapped app (e.g. a mobile game) and disable it when out of session or not in the keymapped app Is this the idea you came up? idk if i repeated your idea.

Yes, I thought the same except the applying of the property.

coronavirus6045 commented 1 year ago

hello! any progress for the implementation for the idea?

Xtr126 commented 1 year ago

hello! any progress for the implementation for the idea?

I was trying if I can use the same interface that waydroid hwcomposer uses (wl_pointer_events) through the existing named pipes in /dev/input provided to the container. If it succeeds then no need to use uevent property or evdev. It will take some time since these are pretty much undocumented stuff and have to find it out myself.

coronavirus6045 commented 1 year ago

what is wl_pointer_events and hwcomposer and whats the relation with hwcomposer?

Xtr126 commented 1 year ago

what is wl_pointer_events and hwcomposer and whats the relation with hwcomposer?

hwcomposer refers to HWC or Hardware Composer HAL of Android. In waydroid hwcomposer is used to display Android GUI on wayland, receiving input and more. wl_pointer_events is some API or interface that waydroid hwcomposer also seems to use.

selurvedu commented 1 year ago

Hey, a month ago, I managed to make XtMapper detect input events on Waydroid by using a patched getevent binary that I compiled myself. The patch allows getevent to process devices that don't have a driver id and driver version set, which is the case for Waydroid, and is the reason why XtMapper cannot detect any input.

With this patch applied, the input devices got detected by XtMapper as they normally should, but the mouse movement became extremely slow and laggy, the CPU load was constantly at 100%, and the host system (not just Waydroid) was really struggling to be responsive. The slowdown ended as soon as I killed the getevent process and didn't linger on.

I had to exclude wl_pointer_events which was causing that overload. I suspect that the events get generated exceedingly more often than they normally should, and that causes the excessive I/O overhead that drastically slows down the system. This is how I see it, though my guess may be incorrect, as it is unclear to me how this was supposed to work in the first place. If you happen to know more about it, please let me know.

After some trial and error I added a condition to skip the input device if its name is not wl_keyboard_events or wl_tablet_events since these two turned out to be safe, i.e., they don't create any excessive CPU load or cause noticeable lags.

After that, XtMapper started reacting to keyboard input, and I was able to bind some keys. They still didn't trigger any touches, though. As I understand, getevent is a read-only way to receive the input events, and the program needs some other mechanism to send the events (i.e. to emulate touches).

Knowing this, I got myself familiar with how to compile an APK of XtMapper locally and did that, but I didn't patch it as I wasn't quite sure where to begin and what exactly I was looking for. I thought of inserting some debug output here and there to narrow down the possible area of search, but never did that, being busy with something else.

I intended to share my findings after doing that, but since you're trying to figure this out yourself now, I'm sharing this to save you some effort in case you haven't made the same discoveries yet.

The patch and the build scripts are in the attached zip archive: XtMapper-getevent-r0.zip

Of course, running XtMapper shouldn't require any binaries to be replaced, it's a temporary measure to allow fixing the other broken parts. Once they are done, this particular thing about input devices not having the IDs / versions / names should be fixed on Waydroid side as these devices are created by it. getevent is not present in Waydroid Git repos, so I assume it's being pulled directly from LineageOS or AOSP.

P.S. Sorry for not providing a proper Makefile, I simply copy-pasted the one-liners I used for compiling and starting getevent to avoid losing them. Also, I don't have a full-fledged Android build system set up since I don't compile ROMs / system images, so I used the compiler commands directly, hope that's okay.

P.P.S. Regarding this line, I can't remember why I changed it. Remove it if you don't find it useful.

-                        printf("%s: ", device_names[i]);
+                        printf("%s ", device_names[i]);
coronavirus6045 commented 1 year ago

where do i place these files?

Xtr126 commented 1 year ago

Hey, a month ago, I managed to make XtMapper detect input events on Waydroid by using a patched [getevent]\

Thanks for your work. I never realized that you could read from wl_keyboard_events in that way, I thought it requires some wayland protocol but that's not the case as you found out.

P.P.S. Regarding this line, I can't remember why I changed it. Remove it if you don't find it useful.

-                        printf("%s: ", device_names[i]);
+                        printf("%s ", device_names[i]);

Yes, that change is required only for older versions of XtMapper that used its own getevent binary instead of system getevent.

With this patch applied, the input devices got detected by XtMapper as they normally should, but the mouse movement became extremely slow and laggy, the CPU load was constantly at 100%, and the host system (not just Waydroid) was really struggling to be responsive. The slowdown ended as soon as I killed the getevent process and didn't linger on.

So, I think, for waydroid we should not use getevent. But write additional native code exclusively for reading from wl_pointer_events and wl_keyboard_events using same API, it should help.

coronavirus6045 commented 1 year ago

So no "linux host" stuff and let the android app read from those?

Xtr126 commented 1 year ago

So no "linux host" stuff and let the android app read from those?

Yes, but it is suitable only for keyboard events. I tried and EVIOCGRAB doesn't work on wl_pointer_events (so mouse cannot be locked). Have to run something on the host for mouse events. But waydroid hwcomposer can capture mouse events from it https://github.com/waydroid/android_hardware_waydroid/commit/a50dbb4752b279b4afe63460fac06603512e7c98

coronavirus6045 commented 1 year ago

whats eviocgrab

Xtr126 commented 1 year ago

whats eviocgrab

EVIOCGRAB which is defined in input.h header file of the Linux kernel userland API.

Xtr126 commented 1 year ago

Turns out that I can use IWaydroidWindow .setPointerCapture(..) for pointer lock (found out from the patch). But this won’t prevent Android inputflinger from receiving events. Must figure out a way to not let android receive mouse events, maybe by restarting inputflinger.

selurvedu commented 1 year ago

I never realized that you could read from wl_keyboard_events in that way, I thought it requires some wayland protocol but that's not the case as you found out.

Glad I could help.

So, I think, for waydroid we should not use getevent. But write additional native code exclusively for reading from wl_pointer_events and wl_keyboard_events using same API, it should help.

Good idea!

Xtr126 commented 1 year ago

Never mind, trying to restart inputflinger causes whole android system to "soft reboot" so that's also not a solution for now. In the meantime, I'll look into linux based solutions like wev (wayland event viewer) that use the wayland socket. Since the waydroid container has access to wayland socket.

coronavirus6045 commented 1 year ago

why do you want to stop inputflinger from recieving. is it to prevent conflict

Xtr126 commented 1 year ago

why do you want to stop inputflinger from recieving. is it to prevent conflict

Yes, as it was reported in #13. When mouse cursor moves, ongoing touch events are cancelled/ignored.

selurvedu commented 1 year ago

Yes, as it was reported in #13. When mouse cursor moves, ongoing touch events are cancelled/ignored.

Interesting, I thought this was a bug in Mantis (which I currently use while XtMapper isn't working yet).

Xtr126 commented 1 year ago

As seamlessly supporting pointer capture is not possible in waydroid at the moment, only keyboard can be supported for now.

Xtr126 commented 1 year ago

Update: Work is ongoing in https://github.com/Xtr126/wayland-getevent to create a static binary that can be run in the waydroid container.

LFRon commented 1 year ago

Update: Work is ongoing in https://github.com/Xtr126/XtMapper/tree/wayland to create a static binary that can be run in the waydroid container.

Hello,bros.Could XtMapper support Magisk-Delta?Waydroid could install Magisk-Delta through Waydroid-Script or you can put magisk files into Overlay by yourself.But when I run the XtMapper and give root access through Magisk-Delta,It tells me Don't have root access through KernelSU.Could mogul fixed it?Thanks!

Xtr126 commented 1 year ago

Hello,bros.Could XtMapper support Magisk-Delta?Waydroid could install Magisk-Delta through Waydroid-Script or you can put magisk files into Overlay by yourself.But when I run the XtMapper and give root access through Magisk-Delta,It tells me Don't have root access through KernelSU.Could mogul fixed it?Thanks!

Magisk should work when you grant root access to XtMapper. Xtmapper doesn't use anything specific to kernelSU. And you can activate XtMapper on waydroid without magisk or kernelSU by any of these two commands: sudo waydroid shell sh /storage/emulated/0/Android/data/xtr.keymapper/files/xtMapper.sh adb shell sh /sdcard/Android/data/xtr.keymapper/files/xtMapper.sh For now, ignore the "root access not found" alert dialog if it appears even if you already granted root access.

Xtr126 commented 1 year ago

Now, XtMapper works perfectly fine with waydroid using the wayland client to grab input events.

coronavirus6045 commented 1 year ago

did you test it in the 2.0 release

coronavirus6045 commented 1 year ago

When I was attempting to build "wayland-getevent", I get this: make: pkg-config: No such file or directory make: pkg-config: No such file or directory client-header /stable/xdg-shell/xdg-shell.xml xdg-shell-client-protocol.h make: client-header: No such file or directory make: *** [Makefile:14: xdg-shell-client-protocol.h] Error 127

and do i have to build the client from "dev" branch?

and how do i get the latest apk from https://github.com/Xtr126/XtMapper/actions

Xtr126 commented 1 year ago

did you test it in the 2.0 release

No, 2.0 release doesnt have support for wayland client.

When I was attempting to build "wayland-getevent", I get this: make: pkg-config: No such file or directory make: pkg-config: No such file or directory client-header /stable/xdg-shell/xdg-shell.xml xdg-shell-client-protocol.h make: client-header: No such file or directory make: *** [Makefile:14: xdg-shell-client-protocol.h] Error 127

You must have the dependencies installed before building: sudo apt install wayland-protocols libwayland-client0 libwayland-dev

and do i have to build the client from "dev" branch?

There is no client in dev branch, only in that repo.

and how do i get the latest apk from https://github.com/Xtr126/XtMapper/actions

By clicking on latest workflow run and downloading "Debug APK" from artifacts section. You must be logged in to github to download artifacts

selurvedu commented 1 year ago

and how do i get the latest apk from https://github.com/Xtr126/XtMapper/actions

https://nightly.link/Xtr126/XtMapper/workflows/android/dev?preview

coronavirus6045 commented 1 year ago

i did sudo apt install wayland-protocols libwayland-client0 libwayland-dev and still same error when doing the make command

coronavirus6045 commented 1 year ago

can you give me a precompiled binary?

coronavirus6045 commented 1 year ago

never mind i was able to compile it install pkgconf and libxkbcommon-dev

coronavirus6045 commented 1 year ago

did instructions for wayland client installation and activating the script got me this:

09-04 11:50:06.934 5857 5857 D AndroidRuntime: >>>>>> START com.android.internal.os.RuntimeInit uid 0 <<<<<< 09-04 11:50:06.936 5857 5857 I AndroidRuntime: Using default boot image 09-04 11:50:06.936 5857 5857 I AndroidRuntime: Leaving lock profiling enabled 09-04 11:50:06.937 5857 5857 I app_process: Core platform API reporting enabled, enforcing=false 09-04 11:50:06.983 5857 5857 D app_process: Time zone APEX ICU file found: /apex/com.android.tzdata/etc/icu/icu_tzdata.dat 09-04 11:50:06.984 5857 5857 D app_process: I18n APEX ICU file found: /apex/com.android.i18n/etc/icu/icudt66l.dat 09-04 11:50:06.986 5857 5857 W app_process: Unexpected CPU variant for X86 using defaults: x86_64 09-04 11:50:07.065 5857 5857 W app_process: JNI RegisterNativeMethods: attempt to register 0 native methods for android.media.AudioAttributes 09-04 11:50:07.067 5857 5857 D AndroidRuntime: Calling main entry xtr.keymapper.server.RemoteService 09-04 11:50:07.069 5857 5857 E AndroidRuntime: ERROR: could not find method xtr.keymapper.server.RemoteService.main(String[]) 09-04 11:50:07.069 5857 5857 D AndroidRuntime: Shutting down VM 09-04 11:50:07.069 5857 5857 E AndroidRuntime: FATAL EXCEPTION: main 09-04 11:50:07.069 5857 5857 E AndroidRuntime: PID: 5857 09-04 11:50:07.069 5857 5857 E AndroidRuntime: java.lang.UnsatisfiedLinkError: dlopen failed: library "libmouse_read.so" not found 09-04 11:50:07.069 5857 5857 E AndroidRuntime: at java.lang.Runtime.loadLibrary0(Runtime.java:1087) 09-04 11:50:07.069 5857 5857 E AndroidRuntime: at java.lang.Runtime.loadLibrary0(Runtime.java:1008) 09-04 11:50:07.069 5857 5857 E AndroidRuntime: at java.lang.System.loadLibrary(System.java:1664) 09-04 11:50:07.069 5857 5857 E AndroidRuntime: at xtr.keymapper.server.RemoteService.<clinit>(RemoteService.java:154) 09-04 11:50:07.069 5857 5857 E AndroidRuntime: at com.android.internal.os.RuntimeInit.nativeFinishInit(Native Method) 09-04 11:50:07.069 5857 5857 E AndroidRuntime: at com.android.internal.os.RuntimeInit.main(RuntimeInit.java:399) 09-04 11:50:07.070 5857 5857 E AndroidRuntime: Error reporting crash 09-04 11:50:07.070 5857 5857 E AndroidRuntime: java.lang.RuntimeException: Bad file descriptor 09-04 11:50:07.070 5857 5857 E AndroidRuntime: at android.os.BinderProxy.transactNative(Native Method) 09-04 11:50:07.070 5857 5857 E AndroidRuntime: at android.os.BinderProxy.transact(BinderProxy.java:550) 09-04 11:50:07.070 5857 5857 E AndroidRuntime: at android.os.IServiceManager$Stub$Proxy.checkService(IServiceManager.java:348) 09-04 11:50:07.070 5857 5857 E AndroidRuntime: at android.os.ServiceManagerProxy.getService(ServiceManagerNative.java:63) 09-04 11:50:07.070 5857 5857 E AndroidRuntime: at android.os.ServiceManager.rawGetService(ServiceManager.java:306) 09-04 11:50:07.070 5857 5857 E AndroidRuntime: at android.os.ServiceManager.getService(ServiceManager.java:134) 09-04 11:50:07.070 5857 5857 E AndroidRuntime: at android.app.ActivityManager$1.create(ActivityManager.java:4558) 09-04 11:50:07.070 5857 5857 E AndroidRuntime: at android.app.ActivityManager$1.create(ActivityManager.java:4555) 09-04 11:50:07.070 5857 5857 E AndroidRuntime: at android.util.Singleton.get(Singleton.java:43) 09-04 11:50:07.070 5857 5857 E AndroidRuntime: at android.app.ActivityManager.getService(ActivityManager.java:4546) 09-04 11:50:07.070 5857 5857 E AndroidRuntime: at com.android.internal.os.RuntimeInit$KillApplicationHandler.uncaughtException(RuntimeInit.java:158) 09-04 11:50:07.070 5857 5857 E AndroidRuntime: at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1073) 09-04 11:50:07.070 5857 5857 E AndroidRuntime: at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:1068) 09-04 11:50:07.070 5857 5857 E AndroidRuntime: at java.lang.Thread.dispatchUncaughtException(Thread.java:2203) 09-04 11:50:07.070 5857 5857 I Process : Sending signal. PID: 5857 SIG: 9

coronavirus6045 commented 1 year ago

and wl_registry@2: error 0: invalid version for global wl_seat (16): have 5, wanted 7

coronavirus6045 commented 1 year ago

and clicking start in latest debug app crashes

Xtr126 commented 1 year ago

and wl_registry@2: error 0: invalid version for global wl_seat (16): have 5, wanted 7

Thanks for reporting, I fixed the wl_seat issue. (I use kwin_wayland and didn't got that error). But still no idea on how to fix the libmouse_read.so issue, as I never encounter it.

and clicking start in latest debug app crashes

Also fixed now.

coronavirus6045 commented 1 year ago

have you found a way to fix the libmouse_read.so issue. i might try ttesting on arch to see if the issue exists but can you do a fresh install of ubuntu (maybe the lts) and try doing the activation on that system?

coronavirus6045 commented 1 year ago

Latest wayland-getevent repo failed to build cc \ -g -std=c11 \ -o client client.c xdg-shell-client-protocol.h pointer-constraints-unstable-v1-client-protocol.h relative-pointer-unstable-v1-client-protocol.h xdg-shell-protocol.c pointer-constraints-protocol.c relative-pointer-protocol.c \ ./libwayland-client.a ./libffi.a ./libxkbcommon.a -static /usr/bin/ld: ./libwayland-client.a(wayland-client.c.o): in function `wl_display_connect': /home/hp/Desktop/wayland-getevent/build/wayland-1.22.0/build/../src/wayland-client.c:1287: undefined reference to `__isoc23_strtol' /usr/bin/ld: ./libwayland-client.a(connection.c.o): in function `atoi': /usr/include/stdlib.h:483: undefined reference to `__isoc23_strtol' /usr/bin/ld: ./libffi.a(tramp.o): in function `ffi_tramp_get_libffi': tramp.c:(.text+0x320): undefined reference to `__isoc23_sscanf' /usr/bin/ld: ./libxkbcommon.a(src_context.c.o): in function `log_level': /home/hp/Desktop/wayland-getevent/build/libxkbcommon-xkbcommon-1.5.0/build/../src/context.c:247: undefined reference to `__isoc23_strtol' /usr/bin/ld: ./libxkbcommon.a(src_context.c.o): in function `log_verbosity': /home/hp/Desktop/wayland-getevent/build/libxkbcommon-xkbcommon-1.5.0/build/../src/context.c:270: undefined reference to `__isoc23_strtol' /usr/bin/ld: ./libxkbcommon.a(src_xkbcomp_scanner.c.o): in function `number': /home/hp/Desktop/wayland-getevent/build/libxkbcommon-xkbcommon-1.5.0/build/../src/xkbcomp/scanner.c:51: undefined reference to `__isoc23_strtoul' /usr/bin/ld: /home/hp/Desktop/wayland-getevent/build/libxkbcommon-xkbcommon-1.5.0/build/../src/xkbcomp/scanner.c:57: undefined reference to `__isoc23_strtoul' collect2: error: ld returned 1 exit status make: *** [Makefile:32: all] Error 1

Xtr126 commented 12 months ago

have you found a way to fix the libmouse_read.so issue. i might try ttesting on arch to see if the issue exists but can you do a fresh install of ubuntu (maybe the lts) and try doing the activation on that system?

I will try it on Ubuntu and fedora

Latest wayland-getevent repo failed to build

Github actions can build it successfully on Ubuntu : https://github.com/Xtr126/wayland-getevent/actions/runs/6243675100

You can download the artifact for the client binary.

Xtr126 commented 12 months ago

have you found a way to fix the libmouse_read.so issue. i might try ttesting on arch to see if the issue exists but can you do a fresh install of ubuntu (maybe the lts) and try doing the activation on that system?

I tested Ubuntu and experienced the same issue. But as it works fine on other distros (Arch Linux), I believe it is Ubuntu fault and not going to waste time on it for now.

Xtr126 commented 12 months ago

Alright so I found a fix https://github.com/Xtr126/XtMapper/commit/df9af2a041944c074032819fdec434ec556df5de it will be fixed for Ubuntu in next release. Ubuntu being weird as always. Thanks for reporting it.

coronavirus6045 commented 12 months ago

images

coronavirus6045 commented 12 months ago

yeah it works on my ubuntu system, time to try out some games

minor inconveniences: "enable keymapping for this app" also i have to switch between overlay window and waydroid

Xtr126 commented 12 months ago

yeah it works on my ubuntu system, time to try out some games

minor inconveniences: "enable keymapping for this app" also i have to switch between overlay window and waydroid

Try again with latest APK. Later I'll figure out a way for it to interact with the service so that the window can be hidden when not required.

coronavirus6045 commented 11 months ago

can you make the input receiving while editing keymap profile on the waydroid window and not the keymap wayland window