android: fix stem double-press hang-up and add head gestures master toggle#584
Open
ntsour wants to merge 3 commits intokavishdevar:mainfrom
Open
android: fix stem double-press hang-up and add head gestures master toggle#584ntsour wants to merge 3 commits intokavishdevar:mainfrom
ntsour wants to merge 3 commits intokavishdevar:mainfrom
Conversation
Replace the single "Head Gestures" master toggle with two independent feature
toggles in the Head Tracking screen:
* Answer/decline incoming calls (nod = answer, shake = decline)
* Mute/unmute during a call (shake = mute, nod = unmute)
The two behaviors operate in different call phases (ringing vs. active) and
never overlap, so they are exposed as separate prefs (head_gestures_answer_call
and head_gestures_mute_call) rather than a single switch.
Additional gesture-related polish:
* Stem-press toggleMicMute now plays the same confirm_yes/confirm_no tones
used for head gestures (audible mute/unmute feedback over the AirPods).
* New MUTE_CALL StemAction so a stem press can be mapped to mute toggling.
* Periodic 15-second low-volume "still muted" reminder while the mic is muted
during a call, cancelled automatically on unmute or call end.
* Active-call gesture loop now mutes/unmutes directionally (shake mutes, nod
unmutes) instead of toggling, fixing the case where the gesture detector
re-fires the same direction during a missed restart.
* Restart bug fix in GestureDetector: callback is now invoked AFTER
stopDetection() so a callback that re-arms detection doesn't hit
isRunning=true and silently no-op.
* Removed per-movement "blip" sounds on every head turn; only the final
confirmation tone is played.
* Stale-state fix in testHeadGestures(): force a stop before re-arming so
isRunning=true left over from a previous test no longer breaks the next.
* Threshold tuning for the gesture detector to reduce accidental triggers.
Teams on Android does not register VoIP calls with the Telecom framework,
so InCallService.setMuted() cannot drive its in-app mute UI. Instead, watch
Teams' ongoing-call notification and fire the cached Mute/Unmute action
PendingIntent — Teams reacts as if the user had tapped the action in the
notification, which keeps the in-app mute icon in sync with the OS mute set
by hardware controls (stem press, head gesture).
* New TeamsNotifListener service (BIND_NOTIFICATION_LISTENER_SERVICE) that
caches the latest Mute and Unmute actions from notifications posted by
com.microsoft.teams (and a couple of related package variants).
* AirPodsService.toggleMicMute() and the active-call gesture loop now also
call TeamsNotifListener.setMuted() alongside AudioManager.setMicrophoneMute,
so Teams' UI follows the OS state.
* Notification access permission is requested from the initial setup screen,
matching the existing permission cards. The "Ask for regular permissions"
button now also opens the system Notification access settings if not yet
granted.
The user must enable LibrePods in Settings → Apps → Notification access for
the sync to work; without it the call is a no-op and OS-level mute still
applies, just without Teams' UI updating.
…oggle
Three related improvements to call handling and head gesture control:
1. Fix stem double-press not ending VoIP calls (Teams, etc.)
- Force both single and double press to be reported to the app during
any active call. Previously only the mute-press type was customized,
leaving end-call to the firmware's native HFP CHUP — which telephony
handles fine but Teams and other non-Telecom VoIP apps ignore.
- handleCallStemPress() now routes the end-call press to rejectCall(),
which tries TelecomManager, then Teams' own notification Hang Up
action, then falls back to HEADSETHOOK for other VoIP apps.
2. Teams call hang-up via notification action
- TeamsNotifListener now also caches the Hang Up PendingIntent from
Teams' ongoing-call notification (keywords: hang, end call, colgar,
raccrocher, auflegen, finalizar).
- hangUp() fires it so Teams reacts as if the user tapped the button
in the notification, keeping its in-app UI in sync.
3. Global head gestures master toggle (head_gestures_enabled pref)
- New master switch in the Head Tracking screen that disables all head
gesture features at once (answer/decline + mute/unmute).
- Sub-toggles are grayed out when the master is off.
- ServiceConfig, ViewModel, and the settings screen summary all respect
the new pref. Android 9 fallback disables it along with the others.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ca19dfa to
66b536d
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Three related improvements to call handling and head gesture control (stacked on top of #580 and #581):
Fix stem double-press not ending VoIP calls — During a call, both single and double press are now forced customized so the app intercepts them. The end-call press is routed to
rejectCall(), which triesTelecomManager.endCall(), then Teams' own notification Hang Up action, then falls back toHEADSETHOOKfor other VoIP apps. Previously the firmware handled end-call natively via HFP CHUP — which telephony handles fine but Teams and other non-Telecom VoIP apps ignore.Teams call hang-up via notification action —
TeamsNotifListenernow also caches the Hang UpPendingIntentfrom Teams' ongoing-call notification.hangUp()fires it so Teams reacts as if the user tapped the button in its notification, keeping the in-app UI in sync. Requires Notification access to be granted to LibrePods.Global head gestures master toggle — New
head_gestures_enabledpref exposed as a master switch at the top of the Head Tracking screen. Disables all head gesture features at once (answer/decline + mute/unmute). Sub-toggles are grayed out when the master is off. The settings screen summary,ServiceConfig, and the ViewModel all respect the new pref. Android 9 fallback disables it along with the others.Test plan
TeamsNotifListener: Cached actions from com.microsoft.teams: mute=…, hangUp=…appears in logcat when a Teams call starts