[BUG] [FP6] Network MMI Command Failure for Call Forwarding due to Modem/RIL Firmware Issues
### Bug Report: Network MMI Command Failure for Call Forwarding due to Modem/RIL Firmware Issues
**Device Information:**
* **Device Model:** Fairphone 6
* **OS Version:** e/OS v3.4-a15-20260114569178-official-FP6
* **Carrier:** Tello
* **SIM Type:** eSIM
( ALSO WITH
* **Carrier:** TMobile
* **SIM Type:** physical SIM
)
**Summary:**
Network MMI commands for call forwarding (e.g., `**61*<number>#`) consistently fail on the FP6.
A generic "Call forwarding connection problem or invalid MMI code." error is returend.
The failure appears to be rooted in the FP6 modem firmware and the e/OS(Lineage?)-specific RIL (Radio Interface Layer) implementation.
Leads to failed network state reporting & inability to process standard telephony service requests.
**Expected Behavior:**
Network MMI commands should be processed successfully by the network.
Phone should display confirmation msg indicating the call forwarding settings have been updated.
Call forwarding should be set, verifiable at phone and carrier.
**Impact:**
Unable to set/manage call forwarding settings using standard MMI codes.
**Conclusion:**
MMI cmd failure is a direct consequence of low-level firmware and RIL implementation bugs on the FP6.
These prevent modem from:
(1) correctly processing standard telephony requests
(2) accurately reporting network state information to Android OS
The MMI command failure is a direct consequence of deep-seated firmware and RIL implementation bugs on the device. These issues prevent the modem from:
1. Correctly processing standard telephony requests.
2. Accurately reporting network state information to the Android operating system.
A f/w update from Fairphone appears required to resolve these device-side issues.
**Steps to Reproduce:**
(1) set config
configure device
```
WiFi: OFF
```
and SIM as:
```
WiFi Scanning: OFF
WiFi Calling: OFF
Preferred Network: 4G
4G Calling / VoLTE: ON
Carrier Video Calling: ON
Allow 2G: OFF
```
(2) confirn config
check @ MMI code
```
-> *#*#4636#*#*
Phone Number: 1XXXXXXXXXX {CARRIER:, UICC:1XXXXXXXXXX, IMS: +1XXXXXXXXXX}
Data Network Type: LTE
Data Raw Registration State: HOME
Override Network Type: LTE_CA
Voice Service: In Service
Voice Network Type: LTE
Voice Raw Registration State: HOME
Preferred Network Type: LTE/WCDMA
-> IMS Status:
IMS Registration: Registered
Voice over LTE: Available
Voice over WiFi: Unavailable
Video Calling: Unavailable
UT Interface: Unavailable
$ adb shell "\
getprop ro.build.version.release; \
getprop ro.build.version.sdk; \
getprop ro.build.id; \
getprop ro.build.fingerprint; \
getprop ro.build.version.security_patch; \
getprop ro.product.manufacturer; \
getprop ro.product.model \
"
15
35
BP1A.250505.005
Fairphone/FP6/FP6:15/FP6.QREL.15.162.0/VS1V:user/release-keys
2026-01-01
Fairphone
Fairphone 6
$ adb shell getprop | grep -Ei "e.os|lineage|build.version.incremental"
[ro.bootimage.build.version.incremental]: [1768386585]
[ro.build.flavor]: [lineage_FP6-user]
[ro.build.version.base_os]: []
[ro.build.version.incremental]: [1768386585]
[ro.lineage.build.version]: [3.4]
[ro.lineage.device]: [FP6]
[ro.lineage.display.version]: [3.4-a15-20260114569178-official-FP6]
[ro.lineage.releasetype]: [official]
[ro.lineage.version]: [3.4-a15-20260114569178-official-FP6]
[ro.odm.build.version.incremental]: [1768386585]
[ro.product.bootimage.name]: [lineage_FP6]
[ro.product.build.version.incremental]: [1768386585]
[ro.product.name]: [lineage_FP6]
[ro.product.odm.name]: [lineage_FP6]
[ro.product.product.name]: [lineage_FP6]
[ro.product.system.name]: [lineage_FP6]
[ro.product.system_dlkm.name]: [lineage_FP6]
[ro.product.system_ext.name]: [lineage_FP6]
[ro.product.vendor.name]: [lineage_FP6]
[ro.product.vendor_dlkm.name]: [lineage_FP6]
[ro.system.build.version.incremental]: [1768386585]
[ro.system_dlkm.build.version.incremental]: [1768386585]
[ro.system_ext.build.version.incremental]: [1768386585]
[ro.vendor.build.version.incremental]: [1768386585]
[ro.vendor_dlkm.build.version.incremental]: [1768386585]
```
(3) Open Phone app. Dial an MMI code for call forwarding,
```
**61*1ZZZZZZZZZZ#
```
(4) Observe MMI fail error:
"Call forwarding connection problem or invalid MMI code."
the device's response.
**Log Detail**
with config as above,
from exec of `**61*1ZZZZZZZZZZ#` to appearance of error,
output:
```
adb logcat -b all -s GsmCdmaPhone GsmMmiCode RILJ RILC Telephony MMIDialogActivity Telecom CallManager QtiOemHookAidl QcrilMsgTunnelIfaceManager | grep -E -i -C 5 "GsmMmiCode|SET_CALL_FORWARD|MODEM_ERR|Telecom.*DIALED_MMI|MMIDialogActivity.*onMMIComplete|Unsupported unsolicited response code 1028" | grep -Ev "DisplayBase::CommitThread|commit_sys_config_file"
01-26 10:34:12.972 3271 3440 D RILJ : [UNSL]< UNSOL_RESPONSE_NETWORK_STATE_CHANGED [PHONE1]
01-26 10:34:12.976 3271 3271 D RILJ : [4323]> OPERATOR [PHONE1]
01-26 10:34:12.978 3271 3271 D RILJ : [4324]> QUERY_NETWORK_SELECTION_MODE [PHONE1]
01-26 10:34:12.979 3271 3440 D RILJ : Unsol response received; Sending ack to ril.cpp [PHONE1]
--
01-26 10:34:16.065 3271 3315 D RILJ : Unsol response received; Sending ack to ril.cpp [PHONE1]
01-26 10:34:16.065 3271 3315 D RILJ : [UNSL]< UNSOL_LCE_INFO_RECV [{mType=0, mDownlinkCapacityKbps=-1, mUplinkCapacityKbps=75}, {mType=1, mDownlinkCapacityKbps=0, mUplinkCapacityKbps=0}] [PHONE1]
01-26 10:34:16.066 3271 3271 D GsmCdmaPhone: [1] updateLinkCapacityEstimate: lce list=[{mType=0, mDownlinkCapacityKbps=-1, mUplinkCapacityKbps=75}, {mType=1, mDownlinkCapacityKbps=0, mUplinkCapacityKbps=0}]
01-26 10:34:18.335 3254 3289 D QtiOemHookAidl: oemHookRawIndication length=21
01-26 10:34:18.336 3254 3254 D QcrilMsgTunnelIfaceManager: handleMessage what = 0
01-26 10:34:18.336 1758 2300 E RILC : Unsupported unsolicited response code 1028
01-26 10:34:18.351 3271 3315 D RILJ : Unsol response received; Sending ack to ril.cpp [PHONE1]
01-26 10:34:18.351 3271 3315 D RILJ : [UNSL]< UNSOL_RESPONSE_NETWORK_STATE_CHANGED [PHONE1]
01-26 10:34:18.355 3271 3271 D RILJ : [4331]> OPERATOR [PHONE1]
01-26 10:34:18.357 3271 3622 D RILJ : [4332]> DATA_REGISTRATION_STATE [PHONE1]
01-26 10:34:18.357 3271 3622 D RILJ : getDataRegistrationState: overrideHalVersion=null [PHONE1]
--
01-26 10:34:40.122 3271 3271 I Telephony: placeOutgoingConnection isEmergency=false
01-26 10:34:40.123 3271 3271 I GsmCdmaPhone: [1] dial; isEmergency=false (based on all phones)
01-26 10:34:40.126 3271 3271 I GsmCdmaPhone: [1] useImsForCall=true, useOnlyDialedSimEccList=false, isEmergency=false, useImsForEmergency=false, useImsForUt=false, isUt=true, isSuppServiceCode=true, isPotentialUssdCode=false, isWpsCall=false, allowWpsOverIms=true, imsPhone=Handler (com.android.internal.telephony.imsphone.ImsPhone) {59f97e1}, imsPhone.isVoiceOverCellularImsEnabled()=true, imsPhone.isVowifiEnabled()=false, imsPhone.isVideoEnabled()=false, imsPhone.getServiceState().getState()=0
01-26 10:34:40.129 3271 3271 D GsmCdmaPhone: [1] Trying (non-IMS) CS call
01-26 10:34:40.129 3271 3271 I Telephony: GsmConnection: registerForCallEvents; phone=Handler (com.android.internal.telephony.GsmCdmaPhone) {fae3c4}
01-26 10:34:40.129 3271 3271 D GsmCdmaPhone: [1] dialInternal: dialing w/ mmi 'GsmMmiCode {State=PENDING action=** sc=61 sia=[****] poundString=[****]}'...
01-26 10:34:40.129 3271 3271 D GsmMmiCode: processCode: is CF
01-26 10:34:40.129 3271 3271 D GsmMmiCode: processCode: is CF setCallForward
01-26 10:34:40.131 3271 3271 D RILJ : [4338]> SET_CALL_FORWARD action = 3 cfReason = 2 serviceClass = 0 timeSeconds = 0 [PHONE1]
01-26 10:34:40.131 3271 3271 D Telephony: placeOutgoingConnection, phone.dial returned null
01-26 10:34:40.131 3271 3271 D Telephony: dialed MMI code
01-26 10:34:40.131 3271 3271 D Telephony: subId: 5
01-26 10:34:40.139 3271 3271 V Telephony: onStateChanged, state: DISCONNECTED
01-26 10:34:40.139 3271 3271 V Telephony: close
01-26 10:34:40.148 2222 4418 I Telecom : PhoneAccountRegistrar: getSimCallManager: SimCallManager for subId 5 queried, returning: null: (...->CS.crCo->H.CS.crCo->H.CS.crCo.pICR)->CSW.hCCC(cap/cast)@E-E-M7w
01-26 10:34:40.148 2222 4418 I Telecom : Call: handleCreateConnectionFailure; callid=TC@48, disconnectCause=DisconnectCause [ Code: (OTHER) Label: () Description: () Reason: (Connection is null, DIALED_MMI) Tone: (27) TelephonyCause: 39/-1 ImsReasonInfo: null]: (...->CS.crCo->H.CS.crCo->H.CS.crCo.pICR)->CSW.hCCC(cap/cast)@E-E-M7w
01-26 10:34:40.148 2222 4418 I Telecom : ConnectionServiceWrapper: Call count decrement 0, com.android.phone/com.android.services.telephony.TelephonyConnectionService: (...->CS.crCo->H.CS.crCo->H.CS.crCo.pICR)->CSW.hCCC(cap/cast)@E-E-M7w
01-26 10:34:40.148 2222 4418 I Telecom : ConnectionServiceWrapper: Service unbound ComponentInfo{com.android.phone/com.android.services.telephony.TelephonyConnectionService}, from unbind.: (...->CS.crCo->H.CS.crCo->H.CS.crCo.pICR)->CSW.hCCC(cap/cast)@E-E-M7w
01-26 10:34:40.149 3271 3271 D GsmCdmaPhone: [1] Event BarringInfoChanged Received
01-26 10:34:40.150 2222 4418 I Telecom : CallsManager: handleConnectionServiceDeath: service [ConnectionServiceWrapper componentName=ComponentInfo{com.android.phone/com.android.services.telephony.TelephonyConnectionService}] died: (...->CS.crCo->H.CS.crCo->H.CS.crCo.pICR)->CSW.hCCC(cap/cast)@E-E-M7w
01-26 10:34:40.151 2222 3344 I Telecom : ConnectionServiceFocusManager: updateConnectionServiceFocus connSvr = null: (...->CS.crCo->H.CS.crCo->H.CS.crCo.pICR)->CSW.hCCC->CSFM.oCSD(cap/cast)@E-E-M7w
01-26 10:34:40.151 2222 3344 I Telecom : ConnectionServiceFocusManager: updateConnectionServiceFocus connSvr = null: (...->CS.crCo->H.CS.crCo->H.CS.crCo.pICR)->CSW.hCCC->CSFM.oCSD(cap/cast)@E-E-M7w
01-26 10:34:40.151 2222 3344 I Telecom : ConnectionServiceFocusManager: updateCurrentFocusCall: mCurrentFocus is null: (...->CS.crCo->H.CS.crCo->H.CS.crCo.pICR)->CSW.hCCC->CSFM.oCSD(cap/cast)@E-E-M7w
01-26 10:34:40.152 2222 4418 I Telecom : CallsManager: markCallAsDisconnected: call=[Call id=TC@48, state=CONNECTING, tpac=ComponentInfo{com.android.phone/com.android.services.telephony.TelephonyConnectionService}, 5, UserHandle{0}, cmgr=ComponentInfo{com.android.phone/com.android.services.telephony.TelephonyConnectionService}, 5, UserHandle{0}, handle=tel:*****************, vidst=A, childs(0), has_parent(false), cap=[], prop=[]], voip=false; disconnectCause=DisconnectCause [ Code: (OTHER) Label: () Description: () Reason: (Connection is null, DIALED_MMI) Tone: (27) TelephonyCause: 39/-1 ImsReasonInfo: null]: (...->CS.crCo->H.CS.crCo->H.CS.crCo.pICR)->CSW.hCCC(cap/cast)@E-E-M7w
01-26 10:34:40.152 2222 4418 I Telecom : CallAnomalyWatchdog: onCreateConnectionFailed: call=[Call id=TC@48, state=CONNECTING, tpac=ComponentInfo{com.android.phone/com.android.services.telephony.TelephonyConnectionService}, 5, UserHandle{0}, cmgr=ComponentInfo{com.android.phone/com.android.services.telephony.TelephonyConnectionService}, 5, UserHandle{0}, handle=tel:*****************, vidst=A, childs(0), has_parent(false), cap=[], prop=[]], voip=false: (...->CS.crCo->H.CS.crCo->H.CS.crCo.pICR)->CSW.hCCC(cap/cast)@E-E-M7w
01-26 10:34:40.152 2222 4418 I Telecom : CallsManager: setCallState CONNECTING -> DISCONNECTED, call: [Call id=TC@48, state=CONNECTING, tpac=ComponentInfo{com.android.phone/com.android.services.telephony.TelephonyConnectionService}, 5, UserHandle{0}, cmgr=ComponentInfo{com.android.phone/com.android.services.telephony.TelephonyConnectionService}, 5, UserHandle{0}, handle=tel:*****************, vidst=A, childs(0), has_parent(false), cap=[], prop=[]], voip=false: (...->CS.crCo->H.CS.crCo->H.CS.crCo.pICR)->CSW.hCCC(cap/cast)@E-E-M7w
01-26 10:34:40.152 2222 4418 I Telecom : Event: RecordEntry TC@48: SET_DISCONNECTED, disconnected set explicitly> DisconnectCause [ Code: (OTHER) Label: () Description: () Reason: (Connection is null, DIALED_MMI) Tone: (27) TelephonyCause: 39/-1 ImsReasonInfo: null]: (...->CS.crCo->H.CS.crCo->H.CS.crCo.pICR)->CSW.hCCC(cap/cast)@E-E-M7w
01-26 10:34:40.152 2222 4418 I Telecom : CallsManager: onFailedOutgoingCall for call [Call id=TC@48, state=DISCONNECTED, tpac=ComponentInfo{com.android.phone/com.android.services.telephony.TelephonyConnectionService}, 5, UserHandle{0}, cmgr=ComponentInfo{com.android.phone/com.android.services.telephony.TelephonyConnectionService}, 5, UserHandle{0}, handle=tel:*****************, vidst=A, childs(0), has_parent(false), cap=[], prop=[]], voip=false: (...->CS.crCo->H.CS.crCo->H.CS.crCo.pICR)->CSW.hCCC(cap/cast)@E-E-M7w
01-26 10:34:40.152 2222 4418 I Telecom : CallsManager: markCallAsRemoved; callid=TC@48, immediate.: (...->CS.crCo->H.CS.crCo->H.CS.crCo.pICR)->CSW.hCCC(cap/cast)@E-E-M7w
^C
$
```
**LogAnalysis**
(1) **MMI cmd init**
`GsmCdmaPhone` service correctly identifies the dialed string as a call forwarding MMI code and initiates processing.
```
01-26 10:34:40.129 D GsmCdmaPhone: [1] dialInternal: dialing w/ mmi 'GsmMmiCode {State=PENDING action=** sc=61 sia=[****] poundString=[****]}'...
01-26 10:34:40.129 D GsmMmiCode: processCode: is CF setCallForward
```
(2) **RIL cmd send**
Android telephony framework sends `SET_CALL_FORWARD` req to RIL for modem processing
```
01-26 10:34:40.131 D RILJ : [4338]> SET_CALL_FORWARD action = 3 cfReason = 2 serviceClass = 0 timeSeconds = 0 [PHONE1]
```
(3) **Connection FAIL (Telecom Layer)**
`Telecom` service ( call mgmt & MMI cmds) reports immediate connection failure for MMI cmd
```
01-26 10:34:40.148 I Telecom : Call: handleCreateConnectionFailure; callid=TC@48, disconnectCause=DisconnectCause [ Code: (OTHER) Label: () Description: () Reason: (Connection is null, DIALED_MMI) Tone: (27) TelephonyCause: 39/-1 ImsReasonInfo: null]
```
(4) **Modem Err**: after long delay (~ 15-60 secs), RIL receives generic error code from modem in response to `SET_CALL_FORWARD` req
```
01-26 10:34:40.152 I Telecom : CallsManager: markCallAsDisconnected: call=[Call id=TC@48, state=CONNECTING, tpac=ComponentInfo{com.android.phone/com.android.services.telephony.TelephonyConnectionService}, 5, UserHandle{0}, cmgr=ComponentInfo{com.android.phone/com.android.services.telephony.TelephonyConnectionService}, 5, UserHandle{0}, handle=tel:*****************, vidst=A, childs(0), has_parent(false), cap=[], prop=[]], voip=false; disconnectCause=DisconnectCause [ Code: (OTHER) Label: () Description: () Reason: (Connection is null, DIALED_MMI) Tone: (27) TelephonyCause: 39/-1 ImsReasonInfo: null]
```
(5) **MMI State --> FAILED**:
`GsmMmiCode` obj transitions to `FAILED` state; MMI dialog is dismissed
```
01-26 10:34:40.152 I Telecom : CallsManager: setCallState CONNECTING -> DISCONNECTED, call: [Call id=TC@48, state=CONNECTING, tpac=ComponentInfo{com.android.phone/com.android.services.telephony.TelephonyConnectionService}, 5, UserHandle{0}, cmgr=ComponentInfo{com.android.phone/com.android.services.telephony.TelephonyConnectionService}, 5, UserHandle{0}, handle=tel:*****************, vidst=A, childs(0), has_parent(false), cap=[], prop=[]], voip=false: (...->CS.crCo->H.CS.crCo->H.CS.crCo.pICR)->CSW.hCCC(cap/cast)@E-E-M7w
```
**Root Cause Analysis**
The problem _appears_ to be **device-side** -- that there's a functional flaw in modem fw and the e/OS(Lineage)-specific RIL
(1) **Immediate Telecom Layer Disconnect**:
Telecom` service immediately reports connection FAIL for the MMI cmd
```
disconnectCause=DisconnectCause [ Code: (OTHER) ... Reason: (Connection is null, DIALED_MMI) Tone: (27) TelephonyCause: 39/-1 ImsReasonInfo: null]
```
the MMI cmd fails high in the Android telephony stack.
possibly(?) due to inability to establish the underlying connection with the network for suplementary svcs, preventing RIL req from being fully processed or responded to by the modem
(2) ***Unsupported Unsolicited RIL Responses (`code 1028`)**:
error
```
E RILC: Unsupported unsolicited response code 1028
```
reappears/recurs.
looks like modem sends proprietary(?) msgs that the FP6's RIL is not programmed to handle
if so, that's a comm mismatch between modem f/w and the RIL.
maybe a factor in the `Telecom` layer's failure to establish stable connect for the MMI cmds
(3) **NOTE: Prior `Invalid PhysicalChannelConfig`**
This specific error is *not* present in the log above, since this run is an LTE-only test config.
BUT,
in a prior run, with `5G preferred config` the FP6 modem fell back to `GSM (2G)` due to network instability.
modem f/w incorrectly reported the _GSM_ Cell ID (e.g., `cid: 2571`) in a field intended for _LTE/5G_ Physical Cell IDs (PCI, valid range 0-1007), leading to an `IllegalArgumentException` reported by the framework and a corrupt phone internal network state.
switching to current LTE-only config avoids/mitigates the issue ... but suggests deeper data mapping bug between modem & RIL firmware.
**Affected Components/Libraries:**
(1) **Modem Firmware**
running on the FP6's baseband processor
it's directly responsible for the `MODEM_ERR 40` and the incorrect reporting of cell IDs.
(2)
**e/OS Radio Interface Layer (RIL) / Hardware Abstraction Layer (HAL)**
likely Qualcomm RIL -- given `QtiOemHookAidl` and `QcrilMsgTunnelIfaceManager` logs.
it translates between the Android & modem.
responsible for incorrectly passing GSM Cell IDs as LTE/5G PCIs and for not handling proprietary unsolicited responses from the modem
(3)
**`com.android.phone` application/service**
correctly *inits* the MMI cmd, the receives/processes error responses from lower RIL/modem layers which leading to the observed FAIL
Yes, /com.android.services.telephony is a framework component that is directly involved in surfacing this bug. It is part of the broader com.android.phone
issue