car audio: run the audio threads at audio priority so a busy phone doesn't make it skip

This commit is contained in:
Seb3thehacker committed 2026-10-12 01:31:24 -07:00
1 parent b2df84c46b
commit 7d6b9cf578
2 files changed
+10 -1

No files matched your search

@@ -45,7 +45,10 @@ class GearslipRunner(
private lateinit var identityTask: FutureTask<PhoneTls> private lateinit var identityTask: FutureTask<PhoneTls>
/** Sends every message, in order, so no other thread ever blocks on the USB link. See [send]. */ /** Sends every message, in order, so no other thread ever blocks on the USB link. See [send]. */
private val writer = java.util.concurrent.Executors.newSingleThreadExecutor { Thread(it, "gearslip-writer") } private val writer = java.util.concurrent.Executors.newSingleThreadExecutor {
// Sound goes out through here too, so it gets audio's priority: late writes are skips.
Thread({ android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_AUDIO); it.run() }, "gearslip-writer")
}
/** Waits for the certificate only when TLS is first needed; see [run]. */ /** Waits for the certificate only when TLS is first needed; see [run]. */
private val tls: PhoneTls by lazy { identityTask.get() } private val tls: PhoneTls by lazy { identityTask.get() }
@@ -88,6 +91,8 @@ class GearslipRunner(
@Volatile private var lastKeyframeSentAt = 0L @Volatile private var lastKeyframeSentAt = 0L
fun run() { fun run() {
// This thread reads the car's acks; audio waits on them, so it can't be left at the back.
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_AUDIO)
SessionReport.begin() SessionReport.begin()
log.i("--- session starting ---") log.i("--- session starting ---")
SessionStatus.connecting("Connected to the head unit") SessionStatus.connecting("Connected to the head unit")
@@ -16,6 +16,7 @@ import android.media.AudioRecord
import android.media.projection.MediaProjection import android.media.projection.MediaProjection
import android.media.projection.MediaProjectionManager import android.media.projection.MediaProjectionManager
import android.os.IBinder import android.os.IBinder
import android.os.Process
import app.seb3thehacker.gearslip.GearslipLog import app.seb3thehacker.gearslip.GearslipLog
import kotlin.math.abs import kotlin.math.abs
@@ -147,6 +148,9 @@ class AudioCaptureService : Service() {
reading = true reading = true
thread = Thread({ thread = Thread({
// A busy phone (a map app drawing, the video encoder) would otherwise starve this
// loop, and the car hears every late read as a skip.
Process.setThreadPriority(Process.THREAD_PRIORITY_URGENT_AUDIO)
val buffer = ByteArray(CHUNK_BYTES) val buffer = ByteArray(CHUNK_BYTES)
var peak = 0 var peak = 0
var heardAt = System.currentTimeMillis() var heardAt = System.currentTimeMillis()