Skip to content

Pr 397 background session persistence.#423

Merged
Xnick417x merged 36 commits into
WinNative-Emu:mainfrom
Xnick417x:Pr397
May 21, 2026
Merged

Pr 397 background session persistence.#423
Xnick417x merged 36 commits into
WinNative-Emu:mainfrom
Xnick417x:Pr397

Conversation

@Xnick417x
Copy link
Copy Markdown
Collaborator

Set up wizard doesn't reset upon backgrounding app.
Pause inside container should proceed and not rest container
Pause will only unpause when unpaused.

Juan-Antonio-Doe and others added 30 commits May 10, 2026 20:07
Introduces a reference-counted foreground service to prevent the Android system from reclaiming the app process during active Wine sessions or long-running background tasks, such as component downloads and ImageFS extractions.

Key changes:
- **SessionKeepAliveService**: Created a new foreground service using `FOREGROUND_SERVICE_TYPE_SPECIAL_USE` and `DATA_SYNC`. It manages a notification and a `PARTIAL_WAKE_LOCK` to keep the CPU active when the screen is locked or the app is backgrounded.
- **Process Protection**: Added `setOomScoreAdj` in `ProcessHelper` to lower the kill priority of paused (SIGSTOP'd) Wine processes, preventing the kernel from reaping them during memory pressure.
- **Lifecycle Integration**:
    - Updated `XServerDisplayActivity` to start/stop the service alongside the XServer session and toggle wake locks during pause/resume.
    - Wrapped extraction and download logic in `SetupWizardActivity`, `ContentsFragment`, and `DriversFragment` with keep-alive tags to ensure multi-minute installs complete successfully in the background.
- **Manifest**: Added permissions for `FOREGROUND_SERVICE_SPECIAL_USE`, `WAKE_LOCK`, and defined the new service.
- **Input Handling**: Prevented generic motion and key event dispatching in `XServerDisplayActivity` when the session is paused.

What was missing for it to work seems to have been both the SPECIAL_USE and a CPU wakelock. There’s also a commented-out wifiLock in case someone want to stabilize suspension for online games or ones that need to download assets (and the user wants to turn off the screen or do something else in the meantime).

I’ve also verified that the container actually goes into suspension while the device is locked.

Using this *PowerShell* command to check the status of the processes:
adb shell ps -eA | Select-String -Pattern "wine", "box64", "wfm", "handler"

With the screen on and the container running, the command returns:
------------
u0_a297      19983 19102   10865704  38256 0                   0 S wineserver
u0_a297      19996 19102          0      0 0                   0 Z [wineboot.exe]
u0_a297      20002 19102   16256732  70704 0                   0 S winedevice.exe
u0_a297      20011 19102   16535896  89960 0                   0 S winedevice.exe
u0_a297      20039 19102   16230516  78720 0                   0 S winhandler.exe
u0_a297      20045 19102   16342600 116620 0                   0 S wfm.exe
------------

With the screen off after a few seconds, the command returns:
------------
root          7873     2          0      0 0                   0 I [kworker/u16:0-qmi_msg_handler]
root          9916     2          0      0 0                   0 I [kworker/u16:4-qmi_msg_handler]
u0_a297      19983 19102   10865704  38256 0                   0 T wineserver
u0_a297      19996 19102          0      0 0                   0 Z [wineboot.exe]
u0_a297      20002 19102   16256732  70704 0                   0 T winedevice.exe
u0_a297      20011 19102   16535896  89960 0                   0 T winedevice.exe
u0_a297      20039 19102   16230516  78720 0                   0 T winhandler.exe
u0_a297      20045 19102   16342600 116620 0                   0 T wfm.exe
------------

Which implies that the container should indeed reduce its consumption in sleep mode.
…ton in the DrawerMenu.

- Restored the value of the isPaused boolean inside onResume and updated the drawer accordingly.
- Simplified a duplicated logic in the drawer menu Kotlin class related to the pause/resume button.
…dling

This change removes local notification management from `XServerDisplayActivity` and centralizes it within `SessionKeepAliveService`. It also updates the process resumption logic to better respect the activity's paused state.

Key changes:
- Disabled redundant notification creation and cancellation in `XServerDisplayActivity`.
- Updated `SessionKeepAliveService` to use `XServerDisplayActivity` as the content intent target with `FLAG_ACTIVITY_REORDER_TO_FRONT`.
- Enhanced service notification visibility on the lockscreen and updated its icon and priority. However, if the user has notifications set to "silent" it will still not work.
- Modified `XServerDisplayActivity` to ensure Wine processes only resume when the activity is not paused. User need to resume it manually.
- Properly set the `isPaused` flag in `onPause`.

So, in summary:
- Commented out the notification code in XServerDisplayActivity since its functionality has been replaced by the SessionKeepAliveService notification.
- The container/game now remains paused when returning to the foreground.
- Removed a commented-out line of code in XServerDrawerMenu.kt that I forgot to delete in the previous commit.
Update base string in generateNotificationId() in SessionKeepAliveService.java to match project name. I forgot to change it in the first commit.

Switch javasteam version to the lastest release available. Required to prevent the build process from failing both locally and in GitHub CI.
…better notification feedback

- The service notification is now shown only when:
  - The container is paused, regardless of whether it is in the foreground or background.
  - There is an active download.
- The notification is not shown when:
  - The container is running.
- The notification message has been adjusted to avoid confusion.

 - Previously commented-out code has been removed.

- The service has been reinforced:
  - To ensure it stops when the container activity is destroyed.
  - If starting the service fails, a crash is prevented by attempting to start the foreground service again as a fallback.
XServerDisplayActivity: Removed unused imports related to notifications.
SessionKeepAliveService: Removed a leftover log and commented out an import related to the wifiLock.
…tering inputs.

Fixed a bug inherited from upstream (winlator_bionic or CMOD) where, when the container is paused, if the user continues to provide input, such as moving the cursor with two fingers at the same time, the app crashes with an exception:

ANR in com.winnative.test (com.winnative.test/com.winlator.cmod.runtime.display.XServerDisplayActivity)
Reason: Input dispatching timed out (ca8503b com.winnative.test/com.winlator.cmod.runtime.display.XServerDisplayActivity is not responding. Waited 5001ms for MotionEvent).
- Separate activity pause from manual pause.
- Ensure game remains paused after backgrounding (disables auto-resume).
- Respect PiP mode in backgrounding logic.
- Keep SessionKeepAliveService active whenever a session is open.
- Block inputs correctly during background transitions to prevent ANRs.
- Exclude core Wine processes (wineserver, winhandler, services, etc.) from SIGSTOP to keep the session structurally alive and WinHandler responsive.
- Fix Steam exit watch thread to wait during pause, preventing timeout-induced exits.
- Defer guest process termination exit while backgrounded or paused to prevent OOM-reap from closing the activity.
- Improve OOM protection logging and refine pause-awareness in XServerDisplayActivity.
- Added 'enable_background_session' preference, defaulting to off.
- Linked background session opt-in to the Notification card in Setup Wizard.
- Removed auto-pause and auto-resume logic from XEnvironment and XServerDisplayActivity.
- Ensured manual pause state is persistent across activity lifecycle.
- Added manual Background toggle in Other Settings.
- Ensure SessionKeepAliveService stays active and holds wake lock during manual pause.
- Apply aggressive OOM protection (-1000) to main and Wine processes during active/paused sessions.
- Force render request in XServerSurfaceView.onResume to recover from paused state on unlock.
Uncommented wifiLock acquisition to keep Wi-Fi alive.
@Xnick417x Xnick417x force-pushed the Pr397 branch 2 times, most recently from 958d11c to b355ed3 Compare May 20, 2026 03:06
@Xnick417x Xnick417x merged commit edb2616 into WinNative-Emu:main May 21, 2026
4 checks passed
Xnick417x added a commit to Xnick417x/WinNative that referenced this pull request May 23, 2026
* fix: Implement SessionKeepAliveService for improved process persistence

Introduces a reference-counted foreground service to prevent the Android system from reclaiming the app process during active Wine sessions or long-running background tasks, such as component downloads and ImageFS extractions.

Key changes:
- **SessionKeepAliveService**: Created a new foreground service using `FOREGROUND_SERVICE_TYPE_SPECIAL_USE` and `DATA_SYNC`. It manages a notification and a `PARTIAL_WAKE_LOCK` to keep the CPU active when the screen is locked or the app is backgrounded.
- **Process Protection**: Added `setOomScoreAdj` in `ProcessHelper` to lower the kill priority of paused (SIGSTOP'd) Wine processes, preventing the kernel from reaping them during memory pressure.
- **Lifecycle Integration**:
    - Updated `XServerDisplayActivity` to start/stop the service alongside the XServer session and toggle wake locks during pause/resume.
    - Wrapped extraction and download logic in `SetupWizardActivity`, `ContentsFragment`, and `DriversFragment` with keep-alive tags to ensure multi-minute installs complete successfully in the background.
- **Manifest**: Added permissions for `FOREGROUND_SERVICE_SPECIAL_USE`, `WAKE_LOCK`, and defined the new service.
- **Input Handling**: Prevented generic motion and key event dispatching in `XServerDisplayActivity` when the session is paused.

What was missing for it to work seems to have been both the SPECIAL_USE and a CPU wakelock. There’s also a commented-out wifiLock in case someone want to stabilize suspension for online games or ones that need to download assets (and the user wants to turn off the screen or do something else in the meantime).

I’ve also verified that the container actually goes into suspension while the device is locked.

Using this *PowerShell* command to check the status of the processes:
adb shell ps -eA | Select-String -Pattern "wine", "box64", "wfm", "handler"

With the screen on and the container running, the command returns:
------------
u0_a297      19983 19102   10865704  38256 0                   0 S wineserver
u0_a297      19996 19102          0      0 0                   0 Z [wineboot.exe]
u0_a297      20002 19102   16256732  70704 0                   0 S winedevice.exe
u0_a297      20011 19102   16535896  89960 0                   0 S winedevice.exe
u0_a297      20039 19102   16230516  78720 0                   0 S winhandler.exe
u0_a297      20045 19102   16342600 116620 0                   0 S wfm.exe
------------

With the screen off after a few seconds, the command returns:
------------
root          7873     2          0      0 0                   0 I [kworker/u16:0-qmi_msg_handler]
root          9916     2          0      0 0                   0 I [kworker/u16:4-qmi_msg_handler]
u0_a297      19983 19102   10865704  38256 0                   0 T wineserver
u0_a297      19996 19102          0      0 0                   0 Z [wineboot.exe]
u0_a297      20002 19102   16256732  70704 0                   0 T winedevice.exe
u0_a297      20011 19102   16535896  89960 0                   0 T winedevice.exe
u0_a297      20039 19102   16230516  78720 0                   0 T winhandler.exe
u0_a297      20045 19102   16342600 116620 0                   0 T wfm.exe
------------

Which implies that the container should indeed reduce its consumption in sleep mode.

* fix: Mismatch between the active pause state and the pause/resume button in the DrawerMenu.

- Restored the value of the isPaused boolean inside onResume and updated the drawer accordingly.
- Simplified a duplicated logic in the drawer menu Kotlin class related to the pause/resume button.

* refactor: consolidate notifications and refine activity lifecycle handling

This change removes local notification management from `XServerDisplayActivity` and centralizes it within `SessionKeepAliveService`. It also updates the process resumption logic to better respect the activity's paused state.

Key changes:
- Disabled redundant notification creation and cancellation in `XServerDisplayActivity`.
- Updated `SessionKeepAliveService` to use `XServerDisplayActivity` as the content intent target with `FLAG_ACTIVITY_REORDER_TO_FRONT`.
- Enhanced service notification visibility on the lockscreen and updated its icon and priority. However, if the user has notifications set to "silent" it will still not work.
- Modified `XServerDisplayActivity` to ensure Wine processes only resume when the activity is not paused. User need to resume it manually.
- Properly set the `isPaused` flag in `onPause`.

So, in summary:
- Commented out the notification code in XServerDisplayActivity since its functionality has been replaced by the SessionKeepAliveService notification.
- The container/game now remains paused when returning to the foreground.
- Removed a commented-out line of code in XServerDrawerMenu.kt that I forgot to delete in the previous commit.

* Update base string for NotificationID generator.

Update base string in generateNotificationId() in SessionKeepAliveService.java to match project name. I forgot to change it in the first commit.

Switch javasteam version to the lastest release available. Required to prevent the build process from failing both locally and in GitHub CI.

* runtime: updated session keep-alive and background service logic for better notification feedback

- The service notification is now shown only when:
  - The container is paused, regardless of whether it is in the foreground or background.
  - There is an active download.
- The notification is not shown when:
  - The container is running.
- The notification message has been adjusted to avoid confusion.

 - Previously commented-out code has been removed.

- The service has been reinforced:
  - To ensure it stops when the container activity is destroyed.
  - If starting the service fails, a crash is prevented by attempting to start the foreground service again as a fallback.

* Cleaning: Removed unused imports and a leftover log.

XServerDisplayActivity: Removed unused imports related to notifications.
SessionKeepAliveService: Removed a leftover log and commented out an import related to the wifiLock.

* Fix: App crash when the container is paused and the user continues entering inputs.

Fixed a bug inherited from upstream (winlator_bionic or CMOD) where, when the container is paused, if the user continues to provide input, such as moving the cursor with two fingers at the same time, the app crashes with an exception:

ANR in com.winnative.test (com.winnative.test/com.winlator.cmod.runtime.display.XServerDisplayActivity)
Reason: Input dispatching timed out (ca8503b com.winnative.test/com.winlator.cmod.runtime.display.XServerDisplayActivity is not responding. Waited 5001ms for MotionEvent).

* fix: enforce persistent pause state and refine keep-alive logic

- Separate activity pause from manual pause.
- Ensure game remains paused after backgrounding (disables auto-resume).
- Respect PiP mode in backgrounding logic.
- Keep SessionKeepAliveService active whenever a session is open.
- Block inputs correctly during background transitions to prevent ANRs.

* fix: stabilize pause/resume and prevent premature session closure

- Exclude core Wine processes (wineserver, winhandler, services, etc.) from SIGSTOP to keep the session structurally alive and WinHandler responsive.
- Fix Steam exit watch thread to wait during pause, preventing timeout-induced exits.
- Defer guest process termination exit while backgrounded or paused to prevent OOM-reap from closing the activity.
- Improve OOM protection logging and refine pause-awareness in XServerDisplayActivity.

* fix: robust pause stabilization and watchdog fix

* fix: block input injection during pause to prevent deadlocks and ANRs

* fix: resolve compilation errors and add missing imports

* feat: make background sessions optional and remove auto-pause behavior

- Added 'enable_background_session' preference, defaulting to off.
- Linked background session opt-in to the Notification card in Setup Wizard.
- Removed auto-pause and auto-resume logic from XEnvironment and XServerDisplayActivity.
- Ensured manual pause state is persistent across activity lifecycle.
- Added manual Background toggle in Other Settings.

* fix: resolve black screen and process reaping after phone lock

- Ensure SessionKeepAliveService stays active and holds wake lock during manual pause.
- Apply aggressive OOM protection (-1000) to main and Wine processes during active/paused sessions.
- Force render request in XServerSurfaceView.onResume to recover from paused state on unlock.

* Enable Wi-Fi keep-alive in SessionKeepAliveService

Uncommented wifiLock acquisition to keep Wi-Fi alive.

* Update SessionKeepAliveService.java

* Update SessionKeepAliveService.java

* fix: exclude Steam from SIGSTOP and upgrade WifiLock to prevent timeouts on mobile data

* feat: implement persistent background sessions and re-attachment logic for Steam games

* fix: resolve black screen and input disconnect during session re-attachment

* fix: resolve re-attachment freezes and deadlocks in background sessions

* fix: correct typo in wifiLock release check

---------

Co-authored-by: Juan-Antonio-Doe <jaespinosag@esimurcia.com>
Co-authored-by: John_Doe <91592965+Juan-Antonio-Doe@users.noreply.github.com>
Co-authored-by: MaxsTechReview <maxjividen@gmail.com>
Co-authored-by: xnick417x
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants