- accounts: outbound transport=tls on port 5062.
- config.static: tls_verify no + tls_selfsigned yes (server cert is an
expired Asterisk Private CA; verification disabled for now; mTLS client
cert support planned but not yet enabled).
- Registration over TLS verified working on Galaxy Watch (Android 16).
Note: TLS transport is independent of the self-managed incoming-call UI
path (verified earlier over UDP), so lock-screen answer/decline + audio
carry over unchanged.
- Launch InCallActivity from WearConnectionService.onCreateIncomingConnection
(self-managed telecom context) instead of a background FGS startActivity.
This is the only path Android permits to show UI over a secure lock screen
/ from the background (BAL exemption); a plain FGS startActivity is blocked.
- Register a SELF_MANAGED PhoneAccount (CAPABILITY_SELF_MANAGED only; a
self-managed account must not also be CALL_PROVIDER) and hand inbound calls
to TelecomManager.addNewIncomingCall.
- Answer/Decline routed from the system self-managed Connection back to the
native stack via WearBaresipServiceHelper (deferred ua_answer/ua_hangup).
- Add dedicated InCallActivity (setShowWhenLocked/turnScreenOn) hosting the
InCallScreen; MainActivity no longer owns the call UI.
- Switch SIP transport to UDP:5761 (matches server); keep sipnat=outbound +
natpinhole for NAT traversal.
- Remove dead phoneCall FGS upgrade/downgrade (needed DIALER role; the
self-managed launch path replaces it).
Verified on Galaxy Watch (Android 16, SDK 36): inbound call rings + shows
InCallActivity over the lock screen (pattern lock on) with working two-way
audio; activity dismisses cleanly on hangup.
- NAT-survival account settings (sipnat=outbound;natpinhole=yes) so INVITE
replies are not dropped (was going straight to voicemail).
- Native event_handler emits 'incoming call' (BEVENT_SIPSESS_CONN) carrying
the SIP msg pointer and 'call incoming' (BEVENT_CALL_INCOMING) carrying the
real struct call*; passes ua/call as separate jlong args (no lossy string
parse). uaEvent(String, Long, Long) signature updated.
- Answer flow: ua_accept on 'incoming call' (caller hears ringing) then
ua_answer deferred to the baresip main loop via a one-shot timer
(ua_answer_async) so the UI-thread Answer tap does not crash in sip_treplyf.
- FGS started from Application.onCreate (decoupled from Activity) holding
WifiLock + WakeLock so SIP survives screen-off / task removal.
- Ring: vibration + screen wake + high-priority full-screen-intent
notification; stopRinging() on established/closed + 30s watchdog so the
ring never loops forever on remote hang-up.
- Lock-screen presentation: manifest showWhenLocked/turnScreenOn +
USE_FULL_SCREEN_INTENT permission + InCallScreen launch. (Still unreliable
when fully asleep + backgrounded — tracked in README.)
- wear/README.md: project overview, how answering works, build/install,
known gaps, and roadmap (SIP MESSAGE, contacts, start-at-boot, UI).
Co-Authored-By: Claude <noreply@anthropic.com>
The UDP switch made the watch register over UDP while Asterisk had
cached a TCP Contact (transport=tcp). Asterisk sent the INVITE over
TCP but got no SIP response (not even 100 Trying) -> 6.4s
retransmission timeout -> immediate voicemail.
Revert to TCP so the watch's registration matches Asterisk's cached
contact. With nat=yes now set, the TCP Contact is made public
(78.141.29.181:<port>), so the INVITE arrives over the persistent TCP
socket and baresip's response reaches Asterisk, letting the call ring
the full configured window instead of timing out.
The experiment of calling TelecomManager.addNewIncomingCall() for our
COMPANION PhoneAccount caused Samsung Wear's telecom stack to auto-reject
the incoming WearConnection within ~2s; its onReject() then hung up the
native baresip call, so Asterisk dropped to voicemail immediately instead
of ringing for the configured 25s.
Remove the handoff from the 'call incoming' path. The in-app InCallScreen
+ full-screen-intent notification remain the alert UI. The native call now
stays alive and rings for the full window (verified: no more 2s reject +
re-register cycle).
Switch outbound transport from tcp to udp. With Asterisk peer
nat=yes, Asterisk now sends the INVITE to the public source address
(78.141.29.181:<port>) instead of the watch's private Contact, so
incoming calls traverse the NAT and reach the watch.
Verified: external incoming calls now arrive (uaEvent: incoming call
from external caller logged on the watch).
- Account line now uses 01273961147 (same credential).
- sipnat=outbound + natpinhole=yes + regint=60 keep the NAT
mapping/keep-alive fresh so Asterisk's INVITE (sent to the public
Contact) reaches the watch behind NAT.
Note: sipnat=outbound is ineffective here because the outbound proxy
is the server itself (no edge STUN to learn the watch's public NAT
IP); the actual NAT fix is Asterisk-side (nat=force_rport,comedia on
the peer), which makes Asterisk target the public source address.
- High-importance (IMPORTANCE_MAX) call channel; on incoming call post a
PRIORITY_MAX / CATEGORY_CALL notification with a full-screen intent that
launches the InCallScreen over the watch face.
- MainActivity: setShowWhenLocked/setTurnScreenOn + FLAG_SHOW_WHEN_LOCKED
so the in-call UI presents over the dimmed screen / keyguard.
- Request POST_NOTIFICATIONS at runtime (API 33+ silently drops
notifications without it) alongside RECORD_AUDIO.
- Vibration ring pattern + wake-lock on incoming call; dismiss the
heads-up when the call closes.
Note: on Samsung Galaxy Watch the watch notification manager blocks
alerting for apps not in its allowed-notifications list; the device
setting (Settings > Notifications > App notifications > Baresip Wear)
must be enabled for the heads-up to fire. Foreground/app-open case
verified working (call answered, audio -> onboard speaker).
- AudioRouteManager: route to onboard speaker when no BT headset is
connected, BT SCO when one is; set MODE_IN_COMMUNICATION + focus.
- aaudio: build with AAUDIO_PERFORMANCE_MODE_NONE so Android routing
(speakerphone) is honoured instead of being bypassed by low-latency.
- DialerScreen: restyled to a stock-dialer layout (large number display,
3x4 keypad with sub-letters, green call FAB, backspace, recent chips).
- InCallScreen: added DTMF keypad (sendDigit) for voicemail/IVR.
- WearBaresipService: on incoming call, wake screen + vibrate + bring
activity to foreground so Answer/Decline is visible.
- Fixed dial normalization (bare extension -> full SIP URI with domain)
and the uap parse in uaEvent so defaultUap is set and calls connect.
- config.static: load g711/opus codecs to resolve 488 Not Acceptable Here.
- Telecom scaffold (experiment): PhoneAccount + ConnectionService handed
incoming calls via addNewIncomingCall to test stock Wear dialer pickup.
- Submodule libbaresip-android rebuilt with g711/opus/aaudio changes.
Verified: assembleDebug green, installs and registers on Galaxy Watch,
incoming call event fires and is handled without crashing.
- New :wear application module (Wear Compose, minSdk 30)
- Second JNI lib 'wearbaresip' reusing distribution static libs
- Watch-side service initializes baresip via full init path
(libre_init -> conf_configure -> baresip_init -> ua_init)
- FGS started from MainActivity foreground state with mic type
only (phoneCall requires default-dialer, rejected on watch)
- Runtime-verified: builds, installs, native lib loads and SIP
stack starts on armeabi-v7a Wear OS device