Skip to content

Commit 23d04ce

Browse files
NookGL4plus: use persistent root shell for warmth to avoid per-call su overhead
Spawning a new `su` process per setWarmth call and blocking on waitFor() could cause sluggish slider response when the user makes rapid changes. Keep a single long-lived root shell open and pipe echo commands through it. The shell is (re)started on demand if it has exited. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent d48454f commit 23d04ce

1 file changed

Lines changed: 38 additions & 11 deletions

File tree

app/src/main/java/org/koreader/launcher/device/lights/NookGL4plusController.kt

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@ import android.app.Activity
44
import android.provider.Settings
55
import android.util.Log
66
import org.koreader.launcher.device.LightsInterface
7+
import java.io.PrintWriter
78

89
/* Controller for Nook Glowlight 4 Plus (bnrv1300) on Android 8.1.
910
* Brightness via Settings.System (SELinux blocks direct sysfs writes from the app process).
10-
* Warmth via 'su -c echo' to sysfs color file (SELinux blocks direct ioctl from the app process).
11+
* Warmth via a persistent root shell to avoid per-call su process overhead during slider use.
1112
* see https://github.com/koreader/koreader/issues/14574
1213
*/
1314
class NookGL4plusController : LightsInterface {
@@ -21,6 +22,40 @@ class NookGL4plusController : LightsInterface {
2122
}
2223

2324
private var currentWarmth: Int? = null
25+
private var suProcess: Process? = null
26+
private var suWriter: PrintWriter? = null
27+
28+
@Synchronized
29+
private fun runRoot(cmd: String): Boolean {
30+
if (!isShellAlive()) {
31+
try {
32+
suProcess = Runtime.getRuntime().exec("su")
33+
suWriter = PrintWriter(suProcess!!.outputStream, true)
34+
} catch (e: Exception) {
35+
Log.w(TAG, "failed to start root shell: $e")
36+
return false
37+
}
38+
}
39+
return try {
40+
suWriter!!.println(cmd)
41+
true
42+
} catch (e: Exception) {
43+
Log.w(TAG, "runRoot write failed: $e")
44+
suProcess = null
45+
suWriter = null
46+
false
47+
}
48+
}
49+
50+
private fun isShellAlive(): Boolean {
51+
val p = suProcess ?: return false
52+
return try {
53+
p.exitValue()
54+
false
55+
} catch (e: IllegalThreadStateException) {
56+
true
57+
}
58+
}
2459

2560
override fun getPlatform(): String = "nook"
2661
override fun hasFallback(): Boolean = false
@@ -64,16 +99,8 @@ class NookGL4plusController : LightsInterface {
6499
return
65100
}
66101
Log.v(TAG, "Setting warmth to $warmth of $WARMTH_MAX")
67-
try {
68-
val process = Runtime.getRuntime().exec(arrayOf("su", "-c", "echo $warmth > $COLOR_FILE"))
69-
val exitCode = process.waitFor()
70-
if (exitCode == 0) {
71-
currentWarmth = warmth
72-
} else {
73-
Log.w(TAG, "su failed (exit $exitCode)")
74-
}
75-
} catch (e: Exception) {
76-
Log.w(TAG, "setWarmth: $e")
102+
if (runRoot("echo $warmth > $COLOR_FILE")) {
103+
currentWarmth = warmth
77104
}
78105
}
79106

0 commit comments

Comments
 (0)