Browse Source

Keep call headset hotplug automatic after selecting speaker manually

master
evgeny 4 days ago
parent
commit
29b01237aa
  1. 17
      tools/chatgui-android/app/src/main/java/com/utun/chat/data/CallAudioRouter.kt
  2. 5
      tools/chatgui-android/app/src/main/java/com/utun/chat/data/RadioAudioEngine.kt

17
tools/chatgui-android/app/src/main/java/com/utun/chat/data/CallAudioRouter.kt

@ -52,8 +52,7 @@ class CallAudioRouter {
/** Куда откатываться при потере гарнитуры (звонок — EARPIECE, рация — SPEAKER). */ /** Куда откатываться при потере гарнитуры (звонок — EARPIECE, рация — SPEAKER). */
@Volatile var fallbackRoute = AudioRoute.EARPIECE @Volatile var fallbackRoute = AudioRoute.EARPIECE
/** Автоматически следовать за гарнитурой: появилась → HEADSET, исчезла → fallbackRoute. /** Следовать за подключением/отключением гарнитуры. Ручной выбор действует до следующего изменения доступности. */
* Ручной setRoute() сбрасывает в false. */
@Volatile var autoHeadset = false @Volatile var autoHeadset = false
private set private set
@ -143,7 +142,7 @@ class CallAudioRouter {
applyRoute(desiredRoute) applyRoute(desiredRoute)
val applyMs = SystemClock.elapsedRealtime() - stageAt val applyMs = SystemClock.elapsedRealtime() - stageAt
stageAt = SystemClock.elapsedRealtime() stageAt = SystemClock.elapsedRealtime()
refresh() refresh(forceAuto = true)
val refreshMs = SystemClock.elapsedRealtime() - stageAt val refreshMs = SystemClock.elapsedRealtime() - stageAt
LogManager.addLog("INFO", "CallAudioRouter", LogManager.addLog("INFO", "CallAudioRouter",
"started totalMs=${SystemClock.elapsedRealtime() - startedAt} callbackMs=$callbackMs btProfileMs=$btProfileMs " + "started totalMs=${SystemClock.elapsedRealtime() - startedAt} callbackMs=$callbackMs btProfileMs=$btProfileMs " +
@ -178,12 +177,12 @@ class CallAudioRouter {
LogManager.addLog("WARN", "CallAudioRouter", "setRoute HEADSET rejected: no headset available") LogManager.addLog("WARN", "CallAudioRouter", "setRoute HEADSET rejected: no headset available")
return return
} }
if (!automatic) autoHeadset = false
val preferenceChanged = preferWiredHeadset != preferWired val preferenceChanged = preferWiredHeadset != preferWired
preferWiredHeadset = preferWired preferWiredHeadset = preferWired
if (desiredRoute == r && route == r && !preferenceChanged) return if (desiredRoute == r && route == r && !preferenceChanged) return
desiredRoute = r desiredRoute = r
preferredRoute = r preferredRoute = r
if (!automatic && r != AudioRoute.HEADSET) fallbackRoute = r
applyRoute(r) applyRoute(r)
LogManager.addLog("INFO", "CallAudioRouter", "requested route=$r actual=$route headsetAvailable=$headsetAvailable automatic=$automatic") LogManager.addLog("INFO", "CallAudioRouter", "requested route=$r actual=$route headsetAvailable=$headsetAvailable automatic=$automatic")
if (telecom == null) onChanged?.invoke(route, headsetAvailable) if (telecom == null) onChanged?.invoke(route, headsetAvailable)
@ -195,7 +194,7 @@ class CallAudioRouter {
LogManager.addLog("INFO", "CallAudioRouter", "preferredRoute -> $r") LogManager.addLog("INFO", "CallAudioRouter", "preferredRoute -> $r")
} }
/** Включить/выключить автоследование за гарнитурой (рация включает, звонок — нет). */ /** Включить/выключить автоследование; reapply немедленно применяет авторежим к текущим устройствам. */
fun setAutoHeadset(enabled: Boolean) { fun setAutoHeadset(enabled: Boolean) {
val resetPreference = enabled && preferWiredHeadset val resetPreference = enabled && preferWiredHeadset
autoHeadset = enabled autoHeadset = enabled
@ -208,7 +207,7 @@ class CallAudioRouter {
fun reapply() { fun reapply() {
if (!started) return if (!started) return
devices = am.getDevices(AudioManager.GET_DEVICES_ALL) devices = am.getDevices(AudioManager.GET_DEVICES_ALL)
refresh() refresh(forceAuto = true)
} }
/* ── применение маршрута ── */ /* ── применение маршрута ── */
@ -341,7 +340,7 @@ class CallAudioRouter {
refresh() refresh()
} }
private fun refresh() { private fun refresh(forceAuto: Boolean = false) {
val now = isHeadsetConnected() val now = isHeadsetConnected()
val prev = headsetAvailable val prev = headsetAvailable
headsetAvailable = now headsetAvailable = now
@ -349,14 +348,14 @@ class CallAudioRouter {
LogManager.addLog("INFO", "CallAudioRouter", "headsetAvailable -> $now") LogManager.addLog("INFO", "CallAudioRouter", "headsetAvailable -> $now")
} }
/* авторежим: маршрут следует за гарнитурой */ /* авторежим: маршрут следует за гарнитурой */
if (autoHeadset) { if (autoHeadset && (forceAuto || now != prev)) {
val want = if (now) AudioRoute.HEADSET else fallbackRoute val want = if (now) AudioRoute.HEADSET else fallbackRoute
if (desiredRoute != want) { if (desiredRoute != want) {
desiredRoute = want desiredRoute = want
applyRoute(want) applyRoute(want)
LogManager.addLog("INFO", "CallAudioRouter", "auto route -> $want") LogManager.addLog("INFO", "CallAudioRouter", "auto route -> $want")
} }
} else { } else if (!autoHeadset) {
/* гарнитуру отключили — откатываемся на fallback-маршрут */ /* гарнитуру отключили — откатываемся на fallback-маршрут */
if (!now && desiredRoute == AudioRoute.HEADSET) { if (!now && desiredRoute == AudioRoute.HEADSET) {
desiredRoute = fallbackRoute desiredRoute = fallbackRoute

5
tools/chatgui-android/app/src/main/java/com/utun/chat/data/RadioAudioEngine.kt

@ -131,7 +131,10 @@ class RadioAudioEngine {
fun headsetAvailable(): Boolean = router.headsetAvailable fun headsetAvailable(): Boolean = router.headsetAvailable
/** Ручной выбор выхода (отключает автоследование за гарнитурой). */ /** Ручной выбор выхода (отключает автоследование за гарнитурой). */
fun setRoute(r: AudioRoute, preferWired: Boolean = false) = router.setRoute(r, preferWired) fun setRoute(r: AudioRoute, preferWired: Boolean = false) {
router.setAutoHeadset(false)
router.setRoute(r, preferWired)
}
/** Начать прослушивание канала (переключатель рации вкл). /** Начать прослушивание канала (переключатель рации вкл).
* Тяжёлая инициализация аудио выполняется на io-потоке, не блокируя main. */ * Тяжёлая инициализация аудио выполняется на io-потоке, не блокируя main. */

Loading…
Cancel
Save