Skip to content

Fix Onyx Boox black screen on wake by not using SurfaceView#579

Merged
Frenzie merged 1 commit into
koreader:masterfrom
msk:fix/boox-needsview
Feb 9, 2026
Merged

Fix Onyx Boox black screen on wake by not using SurfaceView#579
Frenzie merged 1 commit into
koreader:masterfrom
msk:fix/boox-needsview

Conversation

@msk

@msk msk commented Feb 9, 2026

Copy link
Copy Markdown
Contributor

On some Onyx Boox devices (confirmed on Palma 2), the SurfaceView surface is not recreated after the rapid RESUME/PAUSE/STOP activity cycling that the Boox system performs on wake. This leaves android.app.window permanently nil, causing a black screen. The app is still running and responding to touch; it just can't render because ANativeWindow_lock has no window to lock.

The SurfaceView with setZOrderOnTop(true) and PixelFormat.TRANSPARENT was introduced for NGL4/Tolino devices. The Onyx Qualcomm EPD API (View.refreshScreen) does not require a SurfaceView; when needsView is false, einkUpdate() already falls back to the DecorView content view. Setting needsView()=false makes Onyx devices use NativeActivity's default DecorView surface, which follows the standard activity lifecycle and correctly survives the Boox wake sequence.

This fixes koreader/koreader#12445.

Diagnostics that led to this fix

Lifecycle event logging on the Boox Palma 2 revealed that after sleep/wake, INIT_WINDOW never fires when using a SurfaceView:

  1. PAUSE → TERM_WINDOW(nil) → STOP → LOST_FOCUS
  2. START → RESUME → PAUSE → RESUME → PAUSE → STOP → START → RESUME → GAINED_FOCUS(nil)

With needsView()=false (DecorView surface), INIT_WINDOW fires correctly:

  1. PAUSE → TERM_WINDOW(nil) → STOP → LOST_FOCUS
  2. START → RESUME → PAUSE → RESUME → INIT_WINDOW(valid) → PAUSE → TERM_WINDOW(nil) → STOP → START → RESUME → INIT_WINDOW(valid) → GAINED_FOCUS(valid)

Test on Boox Palma 2

See koreader/koreader#12445 (comment) for the reproduction steps.

  • Before this fix: font size change → sleep → wake causes black screen
  • After this fix: font size change → sleep → wake no longer causes black screen

This change is Reviewable

On some Onyx Boox devices (confirmed on Palma 2), the SurfaceView
surface is not recreated after the rapid RESUME/PAUSE/STOP activity
cycling that the Boox system performs on wake. This leaves
android.app.window permanently nil, causing a black screen.

The SurfaceView with setZOrderOnTop(true) and PixelFormat.TRANSPARENT
was introduced for NGL4/Tolino devices. The Onyx Qualcomm EPD API
(View.refreshScreen) does not require a SurfaceView — when needsView is
false, einkUpdate() already falls back to the DecorView content view.
Setting needsView()=false makes Onyx devices use NativeActivity's
default DecorView surface, which follows the standard activity lifecycle
and correctly survives the Boox wake sequence.
@Frenzie Frenzie requested a review from hugleo February 9, 2026 18:34
@hugleo

hugleo commented Feb 9, 2026

Copy link
Copy Markdown
Contributor

Last time I tested, my device also worked with needsView = false, and if I remember correctly, I don’t recall any Onyx device that required this feature. I think you can go ahead with that and if someone complains we can create a specific driver just for that device.

@hugleo hugleo requested review from hugleo and removed request for hugleo February 9, 2026 19:09

@hugleo hugleo left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@Frenzie Frenzie merged commit 3e149d8 into koreader:master Feb 9, 2026
3 checks passed
@BrendanL79

Copy link
Copy Markdown

Congratulations, @msk !! This one's been bugging me for a LONG time.

benoit-pierre pushed a commit to benoit-pierre/koreader that referenced this pull request Feb 10, 2026
…/android-luajit-launcher#579)

On some Onyx Boox devices (confirmed on Palma 2), the SurfaceView
surface is not recreated after the rapid RESUME/PAUSE/STOP activity
cycling that the Boox system performs on wake. This leaves
android.app.window permanently nil, causing a black screen.

The SurfaceView with setZOrderOnTop(true) and PixelFormat.TRANSPARENT
was introduced for NGL4/Tolino devices. The Onyx Qualcomm EPD API
(View.refreshScreen) does not require a SurfaceView — when needsView is
false, einkUpdate() already falls back to the DecorView content view.
Setting needsView()=false makes Onyx devices use NativeActivity's
default DecorView surface, which follows the standard activity lifecycle
and correctly survives the Boox wake sequence.
@msk msk deleted the fix/boox-needsview branch February 13, 2026 17:39
@Tukks

Tukks commented Mar 3, 2026

Copy link
Copy Markdown
Contributor

So with this fix, we can revert this PR then #562
And try to had back
DeviceInfo.Id.ONYX_GO7,

In app/src/main/java/org/koreader/launcher/device/EPDFactory.kt

@Frenzie

Frenzie commented Mar 3, 2026

Copy link
Copy Markdown
Member

Are you able to try it yourself? I realize setting up the whole environment including Android can be slightly challenging.

@Tukks

Tukks commented Mar 4, 2026

Copy link
Copy Markdown
Contributor

@Frenzie I will try to build it and test on the boox directly

@Tukks

Tukks commented Mar 4, 2026

Copy link
Copy Markdown
Contributor

@Frenzie I can't manage to build the android version on a Mac M4 :/
If someone is willing to do it, I can test it.

@Tukks

Tukks commented Mar 4, 2026

Copy link
Copy Markdown
Contributor

I managed to build the APK.
After the test, everything is working fine. the PR is here #584

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.

[onyx boox]: black screen when starting KR or resuming from sleep

5 participants