I’ve been working with ChatGPT to solve the problem of not having call audio after connecting a phone call. Since I am on the free ChatGPT program the program keeps cutting my time off and telling me I can start again in 5-7 hours. Rather than start a new chat that I have found to limit the AI’s memory of what has taken place previously, I have had to wait, sometime over night, to continue so that the AI would not loose the details of the chat. The AI is still working towards a solution but, I am afraid of loosing this chat completely before a final solution could be reached so I asked it to summarize what it had discovered so far in order to preserve a history in call all is lost. Here is the AI summary to date:
Moto g-2026 (nevada) — /e/OS 4.4 GSI Call-Audio Problem
Device
- Motorola Moto g-2026 / nevada / XT2613-1
- MediaTek MT6835
- T-Mobile SIM
- Dynamic-partition device
/e/OS 4.4 Android 16 GSI
- GSI:
eOS-4.4-a16-2026.09.30-microG-gsi.img
- Android 16 / SDK 36
- Build:
BP2A.250805.005
/e/OS was clean-flashed with userdata erased.
What works
The phone boots normally and the cellular network works.
- T-Mobile SIM is recognized.
- Correct phone number is displayed.
- Outgoing calls connect.
- Incoming calls connect.
- Ringtone works.
- Normal media/video/web audio works.
- Microphone permissions have been checked.
- Audio volumes have been checked.
The problem is specifically cellular call audio:
- Once a cellular call connects, neither side can hear the other.
- Earpiece produces no call audio.
- Speakerphone also produces no call audio.
The same Moto hardware/vendor stack previously worked correctly with the user’s LineageOS GSI. With LineageOS, both outgoing and incoming calls had working two-way call audio.
Therefore this does not appear to be a basic modem, SIM, speaker, microphone, or carrier problem.
Important finding: the vendor audio policy is not the problem
/e/OS is using:
/vendor/etc/audio_policy_configuration.xml
The policy contains the expected Motorola telephony audio definitions.
In particular:
Voice Call In = AUDIO_DEVICE_IN_TELEPHONY_RX
- It supports 8/16/32/44.1/48 kHz.
- Earpiece, Speaker, wired, USB and BT SCO routes all include
Voice Call In.
voice tx also uses Voice Call In.
The live dump shows:
Config source: /vendor/etc/audio_policy_configuration.xml
and the Voice Call In definition is present.
The relevant routes are also present:
- Earpiece ← Voice Call In
- Speaker ← Voice Call In
- Wired outputs ← Voice Call In
- BT SCO ← Voice Call In
- voice tx ← Voice Call In
The /e/OS vendor policy files were also compared against the Motorola stock vendor files and found to be byte-for-byte identical.
Therefore changing the Motorola vendor audio_policy_configuration.xml is probably not the solution.
Actual failure
During an active cellular call, Android AudioPolicyManager selects the Motorola telephony RX hardware bridge:
selectBestRxSinkDevicesForCall() ... using HW Bridge
Immediately afterward it crashes with:
connectAudioSourceToSink: a swOutput shall always be associated
audioserver then aborts/restarts.
The important Android source assertion is effectively:
sp<SwAudioOutputDescriptor> swOutput =
sourceDesc->swOutput().promote();
ALOG_ASSERT(swOutput != nullptr,
"%s: a swOutput shall always be associated",
__func__);
The failing object is therefore the SourceClientDescriptor representing the telephony RX source. Its swOutput weak reference is null when AudioPolicyManager tries to promote it.
This is a framework AudioPolicyManager problem, not simply a missing audio route.
Framework libraries investigated
The two most relevant /system/lib64 libraries are:
/system/lib64/libaudiopolicymanagerdefault.so
/e/OS:
- size: 735,256 bytes
- SHA256:
96af43edf1913688ac23c7a4f812f5bb2b69dae1e0f538bfa3b97097450395d2
Lineage:
- size: 735,040 bytes
- SHA256:
0bef7245bed893a7fc0d3045eb4ced8bc945c54f2f495bfed08407c3a45de192
/system/lib64/libaudiopolicycomponents.so
/e/OS:
- size: 689,536 bytes
- SHA256:
2e7c17c9638b83a6f86df1109463f2a6653e8c9f7533777c7a80a691837f0901
Lineage:
- size: 706,040 bytes
- SHA256:
2b6e3cc69fe334efe8c21fb8d1e6c4bb78d498f34f49b525dba74991bf87924
These are therefore the first framework libraries I would investigate for replacement or rebuilding.
However, the investigation has NOT yet proven that simply copying the Lineage versions into /e/OS is safe. The libraries are from different framework builds, so the C++ ABI/vtables and surrounding framework components must match.
Important binary comparison
The actual connectAudioSourceToSink() code in /e/OS and Lineage is essentially the same at the point where it promotes SourceClientDescriptor::swOutput.
Both contain the expected setSwOutput() operation.
Therefore the problem is not simply:
“/e/OS forgot to call setSwOutput().”
Instead, the /e/OS object reaches the assertion with a null swOutput, while the equivalent Lineage path does not.
This points toward an AudioPolicyManager/framework object-lifecycle or ABI difference, rather than a missing XML route.
Particularly interesting difference
A real structural difference was found in startSource().
Lineage performs an indirect virtual call through an object/vtable slot at:
[x23,#216]
while /e/OS performs the corresponding call through:
[x23,#200]
Specifically:
Lineage
ldr x8, [x23,#216]
mov x0,x22
mov w1,#9
mov w2,wzr
blr x8
/e/OS
ldr x8, [x23,#200]
mov x0,x22
mov w1,#9
mov w2,wzr
blr x8
This is a genuine structural difference and not merely a relocated address.
The exact virtual functions represented by those slots have not yet been identified because the stripped binaries do not retain usable vtable symbols.
This difference is potentially important because startSource() is directly involved in establishing the source/output relationship before connectAudioSourceToSink() reaches the fatal swOutput assertion.
Other relevant framework libraries
The /e/OS framework currently contains:
/system/lib64/libaudiopolicy.so
/system/lib64/libaudiopolicycomponents.so
/system/lib64/libaudiopolicyengineconfigurable.so
/system/lib64/libaudiopolicyenginedefault.so
/system/lib64/libaudiopolicymanagerdefault.so
Because AudioPolicyManager, AudioPolicy components, policy engine and their C++ classes interact through shared objects, replacing only one library may create an ABI/vtable mismatch.
Therefore, if building a corrected /e/OS GSI, I would investigate the complete AudioPolicy framework set, rather than blindly replacing one .so.
The most obvious comparison/replacement candidates are:
libaudiopolicymanagerdefault.so
libaudiopolicycomponents.so
libaudiopolicy.so
libaudiopolicyengineconfigurable.so
libaudiopolicyenginedefault.so
The first two are the strongest suspects based on the binary investigation so far.
What should NOT need changing
The Motorola vendor audio policy should probably be retained.
In particular, do NOT start by replacing:
/vendor/etc/audio_policy_configuration.xml
/vendor/etc/audio_policy.conf
The /e/OS copies were compared against the Motorola stock vendor copies and are identical.
The vendor configuration already contains the necessary:
Voice Call In
AUDIO_DEVICE_IN_TELEPHONY_RX
voip_rx
voice tx
Telephony Tx
and the necessary routes.
Most likely explanation
The current evidence points to a compatibility problem between the Android 16 /e/OS framework AudioPolicy implementation and the Motorola vendor audio HAL/policy behavior.
The Motorola vendor side is exposing a telephony RX hardware bridge.
/e/OS recognizes that bridge and selects:
using HW Bridge
but the /e/OS AudioPolicyManager subsequently reaches:
connectAudioSourceToSink()
with a SourceClientDescriptor whose swOutput weak reference is null.
That triggers Android’s fatal assertion:
a swOutput shall always be associated
and kills audioserver.
The result is exactly what the user experiences: the cellular call itself remains connected, but the call-audio path cannot be established.
Recommended development direction
Rather than modifying the Motorola vendor audio configuration, compare the /e/OS AudioPolicy framework against the working LineageOS framework.
Priority:
libaudiopolicymanagerdefault.so
libaudiopolicycomponents.so
- The remaining
libaudiopolicy*.so libraries as a matched set if necessary.
The goal should be to identify the framework implementation that correctly establishes the SourceClientDescriptor → SwAudioOutputDescriptor association for AUDIO_DEVICE_IN_TELEPHONY_RX.
If the Lineage AudioPolicy implementation is compatible with the /e/OS Android base, the Lineage versions may provide a working reference or possibly a replacement. But this should be checked for framework/ABI compatibility before simply copying them into the GSI.
Bottom line
The phone’s T-Mobile connection works.
The modem/call connection works.
The Motorola vendor audio policy contains the correct telephony routes.
The failure occurs inside Android framework AudioPolicyManager when it tries to create the telephony RX audio connection.
The strongest current target for fixing the GSI is therefore the framework AudioPolicy implementation, especially:
libaudiopolicymanagerdefault.so
libaudiopolicycomponents.so
with the other libaudiopolicy*.so files considered as a matched framework group.
The key error to search for in any future test/build is:
connectAudioSourceToSink: a swOutput shall always be associated
and the preceding:
selectBestRxSinkDevicesForCall() ... using HW Bridge
A successful fix should allow the Motorola telephony RX hardware bridge to be connected without SourceClientDescriptor::swOutput() being null, preventing the audioserver crash and restoring cellular call audio.