[PATCH v12 0/19] MR10569: wineandroid: rework Android integration and switch to split process model
This series reworks the wineandroid driver and moves it away from the current “Wine inside JVM process” model to a split architecture where the Android activity (UI) and Wine run in separate processes. The existing model relies on running Wine inside the JVM process and interacting with Android through JNI callbacks and APC/unixlib-based dispatch. This approach no longer works reliably on modern Android: - Android 10+ applies seccomp restrictions to app processes, making a number of required syscalls unavailable inside the activity process, while processes started via fork/exec are not subject to the same limitations. - The implementation depends on Wine thread context (TEB), signal handling, and register state assumptions that conflict with the JVM runtime (e.g. segment register usage on x86), requiring fragile workarounds. - Due to sandboxing, it is difficult to reliably debug or even observe all failure modes, and future Android changes are likely to tighten these restrictions further. At the same time, downstream projects such as MiceWine, Winlator, Termux’s Wine environment, GameHub and GameNative already use a model where the UI (activity) and Wine run in separate processes and communicate via IPC, which has proven to work reliably on current Android systems. This series implements that model in wineandroid: - Wine is now started in a separate process via fork/exec instead of running inside the JVM process. - Android-facing code no longer depends on the Wine APC/unixlib execution path and runs on the UI thread where appropriate (e.g. native window registration). - ioctl handling is reworked to remove reliance on Wine thread context, with explicit JNIEnv usage and fd-based reply plumbing. - Environment setup and initialization are moved to the Java side, simplifying the native startup path. - Logging for ioctl paths is routed through Android logcat without depending on a Wine TEB. The changes are split into multiple bisect-safe commits to keep intermediate states functional while migrating the code step by step. With Wine running in a separate process, it is no longer subject to JVM seccomp restrictions, and there are no longer conflicts between JVM and Wine execution contexts (signals, thread state, register usage, etc.). <details> <summary>Old message</summary> wineandroid: move ioctl handling to dedicated Java-only thread Move ioctl handling out of the Wine APC/unixlib execution path into a dedicated Java-only thread without Wine context. On Android 10+ a number of syscalls are restricted inside the activity process via seccomp, while processes started via fork/exec are not subject to the same limitations. Decoupling ioctl handling from the Wine context is required to eventually run this code outside of the activity process. This change introduces a new transport and execution model where ioctl dispatch no longer depends on Wine thread state, preparing for moving the Android backend into a separate process. The refactor is intentionally split into multiple bisect-safe commits to keep intermediate states functional while gradually migrating the dispatch path. Since this is a fairly large chunk of work, I’d like to make sure we’re aligned before continuing. </details> -- v12: wineandroid: split Android driver and Wine into separate processes wineandroid: terminate activity when desktop client disconnects This merge request has too many patches to be relayed via email. Please visit the URL below to see the contents of the merge request. https://gitlab.winehq.org/wine/wine/-/merge_requests/10569
Is there a supported way to allocate or attach a TEB to a thread that was created via pthread_create(), instead of going through Wine’s start_thread() path? From what I can see, start_thread() expects a TEB to be passed to pthread_create(), rather than creating it itself, which doesn’t help for threads that are already running (e.g. created externally or by the JVM). Is there a way to initialize a TEB for such threads so they can use Wine logging, to simplify this logging mess? -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10569#note_136321
Splitting Wine execution to a separate process while keeping the process as a UI portal sounds like an interesting approach, and I'm now wondering if we could generalize it to other platforms... other than that I know almost nothing about wineandroid and absolutely nothing about Android in general, and I will only be of little help here. I don't even know how to build or test it. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10569#note_136326
This approach is unfortunately not just a design preference but more or less required on modern Android. Since newer Android versions started enforcing seccomp restrictions on processes running inside the JVM (activity) context, a number of syscalls used by Wine are no longer available there, and the situation keeps getting stricter with each release. Running Wine in a separate fork/exec process avoids these restrictions and matches what downstream projects have already converged on. I understand that familiarity with Android is important here, but I would also really appreciate feedback on the changes themselves. The series is limited to wineandroid, but it still touches a lot of code there, and as I’m still new to the project, I’m not always confident about what is acceptable or what the preferred patterns are in Wine. Even high-level or structural feedback would be very helpful. As for building and testing, I can share build scripts if that helps. At the moment the setup is somewhat device-dependent: it works for me in an Android 8.1 VM and on a Samsung S24 FE (Android 16), but on a Samsung Tab A9 (also Android 16) it starts without rendering, and I’m still investigating that. To make further progress it would really help to get the current state merged so I don’t have to keep juggling a large patch stack locally. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10569#note_136327
On Thu Apr 16 04:50:34 2026 +0000, Twaik Yont wrote:
Is there a supported way to allocate or attach a TEB to a thread that was created via pthread_create(), instead of going through Wine’s start_thread() path? From what I can see, start_thread() expects a TEB to be passed to pthread_create(), rather than creating it itself, which doesn’t help for threads that are already running (e.g. created externally or by the JVM). Is there a way to initialize a TEB for such threads so they can use Wine logging, to simplify this logging mess? !9579 does this for the macOS main thread, although in !10058 there were concerns about whether the thread needs to be hidden from various APIs
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/10569#note_136440
I understand that familiarity with Android is important here, but I would also really appreciate feedback on the changes themselves. The series is limited to wineandroid, but it still touches a lot of code there, and as I’m still new to the project, I’m not always confident about what is acceptable or what the preferred patterns are in Wine. Even high-level or structural feedback would be very helpful.
In general, although having the big picture and future plans available for reference, we prefer smaller MRs for actual review, so my first advice would be to keep this MR as draft then split this into smaller batches of ~5 patches or less. The smaller the number the easier it will be, assuming the changes are also fairly uncontroversial, to get reviewed and approved. This seems to be the case for the first few changes here at least, although again, I know nothing about Android. From a quick glance over the later changes, I don't see anything obvious either, they seem to be relatively small and well split and isolated from each other, but the larger design changes decisions will probably be up to @julliard to decide. More detailed discussion about later changes also feel a bit pointless, as they may end up changing over time, because of previous changes iterations or just because you might decide to change your mind. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10569#note_136459
On Thu Apr 16 04:50:34 2026 +0000, Brendan Shanks wrote:
!9579 does this for the macOS main thread, although in !10058 there were concerns about whether the thread needs to be hidden from various APIs Looks good, but I am afraid that it may conflict with existing JNI thread context.
-- https://gitlab.winehq.org/wine/wine/-/merge_requests/10569#note_136478
Thanks, I opened the !10683 . -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10569#note_136480
participants (3)
-
Brendan Shanks (@bshanks) -
Rémi Bernon (@rbernon) -
Twaik Yont (@twaik)