Android Telephony, RIL & Modem
This page walks the whole cellular stack on an Android phone, from a tap in an app down to radio waves: the telephony framework, the Radio Interface Layer (RIL), the Radio HAL, the vendor RIL daemon, the modem interface and the 3GPP protocols inside the modem. It also covers SIM/eSIM, how a mobile data connection really moves packets, and the evidence-first debugging method and cause codes that telephony interviews test most.
- Six layers: apps → Telecom/Telephony framework (mostly in
com.android.phone) → RIL Java (RIL.java) → Radio HAL (IRadio*) → vendor daemon (qcrild/ MTK rild) → modem firmware → air interface. - RIL traffic is asynchronous: solicited requests carry a serial number and complete on a response callback; unsolicited indications are modem-initiated events fanned out to registrants.
- Since Android 13 the Radio HAL is stable AIDL, split by domain (network, data, voice, sim, modem, messaging, ims, config); older devices use HIDL
radio@1.0–1.6. - Below the HAL, Qualcomm uses QMI over the IPC router (QRTR), MediaTek uses CCCI channels with MIPC/AT; user-plane packets use
rmnet+IPA (Qualcomm) orccmni(MediaTek). - Key framework owners:
ServiceStateTracker(registration),DataNetworkController(data calls, replacedDcTracker),SubscriptionManagerServiceandUiccController(SIMs),CarrierConfigManager(per-carrier behaviour). - Debug in order: chipset and log family → RF environment → modem health (SSR,
md1exception,serviceDied) → protocol cause codes at the exact timestamp → framework stack → hypotheses with supporting and contradicting evidence.
The big picture: app to antenna
Android telephony is a stack of six layers. You should be able to draw it in about a minute and, more importantly, say what mechanism crosses each boundary: Binder, plain Java calls, a HAL interface, a vendor IPC protocol, or radio frequency (RF). Almost every interview question in this area is a request to trace something through this stack.
Think of an international shipping company. Customers (apps) walk into a front office (the framework) that speaks their language. The front office hands a standard shipping form (a RIL request with a tracking number) to a customs broker (the Radio HAL contract), who passes it to a local freight agent (the vendor RIL daemon) who speaks the port's own dialect (QMI or AT) to the ship's captain (the modem). The captain follows international maritime law (3GPP) to cross the ocean (the air interface). Each hand-off has its own paperwork, and when a parcel goes missing you check each desk's logbook in order.
+----------------------------------------------------------------------+
| APPS: Dialer, Messaging, Settings, carrier apps |
| TelephonyManager, SubscriptionManager, SmsManager, TelecomManager |
+----------------------------------------------------------------------+
| Binder (AIDL): ITelephony, ISub, ITelecomService ...
+----------------------------------------------------------------------+
| FRAMEWORK: Telecom (system_server) + Telephony (com.android.phone) |
| Phone/GsmCdmaPhone, ServiceStateTracker, DataNetworkController, |
| SubscriptionManagerService, UiccController, TelephonyRegistry, |
| CarrierConfigLoader, ImsPhone |
+----------------------------------------------------------------------+
| in-process Java calls, Message/Handler
+----------------------------------------------------------------------+
| RIL JAVA (RILJ): RIL.java, RILRequest, RadioResponse, RadioIndication|
+----------------------------------------------------------------------+
| Stable AIDL Binder (Android 13+) or HIDL HwBinder (legacy)
+----------------------------------------------------------------------+
| RADIO HAL: IRadioNetwork/Data/Voice/Sim/Modem/Messaging/Ims/Config |
| + matching *Response and *Indication interfaces |
+----------------------------------------------------------------------+
| vendor process boundary
+----------------------------------------------------------------------+
| VENDOR RIL DAEMON: Qualcomm qcrild (QCRIL) / MediaTek rild (Rfx/Rmm) |
+----------------------------------------------------------------------+
| QMI over QRTR/GLINK/SMEM (QC), MIPC/AT over CCCI (MTK), PCIe/MHI
+----------------------------------------------------------------------+
| MODEM FIRMWARE (baseband): NAS, RRC, PDCP, RLC, MAC, PHY |
+----------------------------------------------------------------------+
| RF over the Uu air interface
eNB (LTE) / gNB (5G NR) ──▶ core network (EPC / 5GC) ──▶ internet / IMS
| Boundary | Mechanism | Example |
|---|---|---|
| App → framework | Binder (AIDL) via a manager class | TelephonyManager → ITelephony → PhoneInterfaceManager |
| Framework → RIL Java | Plain Java calls, Message/Handler callbacks | ServiceStateTracker → mCi.getVoiceRegistrationState(msg) |
| RIL Java → HAL | Binder (stable AIDL) or HwBinder (HIDL); async request / response / indication | IRadioNetwork.getVoiceRegistrationState(serial) |
| HAL → vendor daemon | Same process: the daemon is the HAL server | qcrild implements IRadioNetwork |
| Vendor daemon → modem | QMI (Qualcomm), MIPC/AT over CCCI (MediaTek), AT (generic) | QMI NAS "get serving system", AT+CEREG? |
| Modem → network | RF over Uu using 3GPP protocols | RRC, NAS attach/registration |
Two processes you must know
system_server
Hosts Telecom (TelecomService, CallsManager), ConnectivityService, TelephonyRegistry (the telephony event bus) and the network-stack glue. Telecom knows about calls and audio, not about radios.
com.android.phone
The persistent telephony process (packages/services/Telephony). Hosts PhoneInterfaceManager (the ITelephony server), the Phone objects, RIL, CarrierConfigLoader and IMS glue. If it crashes the whole radio stack restarts; the system respawns it because it is persistent.
Where the source lives
| Path | What it contains |
|---|---|
frameworks/base/telephony | Public SDK: TelephonyManager, SubscriptionManager, ServiceState, SignalStrength, CarrierConfigManager, IMS APIs |
frameworks/opt/telephony | Internal telephony: Phone, GsmCdmaPhone, RIL, ServiceStateTracker, DataNetworkController, UICC classes, SMS dispatchers |
packages/services/Telephony | The com.android.phone app: PhoneInterfaceManager, TelephonyConnectionService, CarrierConfigLoader |
packages/services/Telecomm | Telecom: TelecomService, CallsManager, PhoneAccountRegistrar |
hardware/interfaces/radio/aidl | Radio HAL AIDL definitions (android.hardware.radio.*) |
hardware/ril | Legacy libril, rild and the emulator reference-ril |
The telephony framework
The framework turns radio events into Android state (service state, signal bars, call state) and turns app requests into radio commands. It is built from long-lived objects, each owned by one thread's Handler/Looper, that talk to each other with Messages and RegistrantLists.
Picture an airport control tower. One controller watches the radar (ServiceStateTracker watching registration), one assigns gates (DataNetworkController assigning data connections), one checks passports (UICC and subscription classes), and a public-address system announces changes to everyone waiting (TelephonyRegistry notifying apps). A rulebook per airline (CarrierConfig) tells each controller how that airline wants things done. The Phone object is the tower itself: one tower per runway, just as there is one Phone per SIM slot.
Telecom vs Telephony
Telecom (call routing)
TelecomService/TelecomManager: the call switchboard; knows nothing about radios.- Works in terms of
PhoneAccount(one per SIM or VoIP app) andConnection. ConnectionService: implemented by Telephony (TelephonyConnectionService) and by third-party VoIP apps.InCallService: implemented by the Dialer UI to render calls; Telecom also manages audio routing.
Telephony (radio ownership)
- Owns the modem: registration, signal, data connections, SIM, SMS, supplementary services.
- Lives in
com.android.phone; exposesITelephony,ISub,ISmsto apps. - For calls it plugs into Telecom as a
ConnectionService. - Path:
TelecomManager.placeCall()→TelephonyConnectionService→Phone.dial().
Core classes
| Class | Responsibility |
|---|---|
PhoneFactory | At boot, creates one RIL and one Phone per logical modem/SIM slot, plus shared singletons (UiccController, PhoneSwitcher, subscription service). |
Phone (abstract) → GsmCdmaPhone | The per-slot phone. Owns its trackers, handles dial/hang-up, USSD and supplementary services, and holds a CommandsInterface (the RIL). |
ImsPhone, ImsPhoneCallTracker | A shadow phone for IMS calls. GsmCdmaPhone delegates VoLTE/VoNR/Wi-Fi calling to it when IMS is registered. |
GsmCdmaCallTracker | Circuit-switched call state; polls getCurrentCalls after callStateChanged indications. |
ServiceStateTracker (SST) | Registration state, operator, RAT, roaming, signal strength, NITZ time, radio power. |
DataNetworkController | Data connections (Android 13+); see the data section. |
SubscriptionManagerService | Source of truth for subscriptions and default voice/SMS/data subscription (Android 14+, was SubscriptionController). |
UiccController | SIM card tree and SIM state; see the SIM section. |
DefaultPhoneNotifier | Pushes state from Phone objects into TelephonyRegistry. |
TelephonyRegistry | Central publish/subscribe service in system_server; apps register TelephonyCallback (formerly PhoneStateListener). |
CarrierConfigManager / CarrierConfigLoader | Per-carrier feature flags and values. |
PhoneSwitcher | Decides which logical modem serves data (the preferred data modem) and activates the right per-phone network factory; handles temporary data switching. |
DeviceStateMonitor | Tells the modem about screen, charging and tethering state so it can filter indications and save power (setIndicationFilter, signal reporting criteria). |
SmsDispatchersController | Routes SMS over IMS (ImsSmsDispatcher) or CS (GsmSMSDispatcher). |
EmergencyNumberTracker | Merges emergency numbers from modem, SIM, database and carrier config. |
NetworkTypeController / DisplayInfoController | Compute TelephonyDisplayInfo (for example showing "5G" while registered on LTE with an NR secondary cell in NSA). |
ServiceStateTracker in detail
SST answers "am I in service, on what network, with what technology?" It consumes unsolicited networkStateChanged, signal strength and NITZ indications, and then polls the modem because the indication itself carries no details.
- Indication The modem sends
IRadioNetworkIndication.networkStateChanged(legacy:RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED). - pollState() SST fires four requests in parallel:
getOperator,getVoiceRegistrationState,getDataRegistrationState,getNetworkSelectionMode. - Build a new ServiceState When all replies arrive, SST combines them into a new
ServiceStatewith oneNetworkRegistrationInfoper domain (CS/PS) and transport (WWAN/WLAN). - Apply policy Roaming overrides from carrier config, out-of-service hysteresis, operator-name (SPN/PLMN) display rules, emergency-only detection.
- Notify
DefaultPhoneNotifier→TelephonyRegistry→ every registeredTelephonyCallback.ServiceStateListener, plus theACTION_SERVICE_STATEbroadcast. Status-bar icons update.
| ServiceState field | Meaning |
|---|---|
getState() | STATE_IN_SERVICE, STATE_OUT_OF_SERVICE, STATE_EMERGENCY_ONLY, STATE_POWER_OFF (voice domain) |
getDataRegistrationState() | The same states for the packet (data) domain; voice and data can differ |
NetworkRegistrationInfo | Per domain/transport: registration state, access network technology (LTE, NR...), cell identity, reject cause, available services |
| Operator names/numeric | Long/short alpha name and MCC+MNC of the registered PLMN |
| Roaming | Voice/data roaming type (domestic, international), possibly overridden by carrier config |
| NR state | For NSA: whether NR is restricted, not restricted or connected; drives the 5G icon |
Modem registration states reported to SST include REG_HOME, REG_ROAMING, NOT_REG_MT_SEARCHING_OP, NOT_REG_MT_NOT_SEARCHING_OP, REG_DENIED (with a reject cause) and UNKNOWN, plus "emergency calls allowed" variants. REG_DENIED with a cause is the first thing to look for in a "no service" bug.
getState() (voice) can be STATE_OUT_OF_SERVICE while getDataRegistrationState() is STATE_IN_SERVICE: the LTE icon and mobile data work, but CS calls fail and IMS is not registered. Combined-attach reject EMM #18 ("CS domain not available") is a typical cause. Always read both domains, plus IMS registration, before saying the phone is "in service" for voice.Signal strength, radio power and NITZ
- Signal
SignalStrengthholds per-RAT values (CellSignalStrengthLte: RSRP, RSRQ, RSSNR;CellSignalStrengthNr: SS-RSRP, SS-RSRQ, SS-SINR). Bars come from carrier-configurable thresholds. The framework sets reporting criteria (setSignalStrengthReportingCriteria) so the modem only reports when a threshold is crossed, which saves power. Rough LTE field estimates (not 3GPP pass/fail limits; carriers remap them to bars): RSRP greater than about -80 dBm is excellent, -80 to -100 dBm is usable, below about -110 dBm is cell-edge / poor; RSRQ above about -10 dB is strong and below about -20 dB is poor; SINR above about 20 dB is excellent and below 0 dB is poor. - Radio power Airplane mode, SIM power-down and radio-off all end in
IRadioModem.setRadioPower. The radio state isRADIO_OFF,RADIO_ONorRADIO_UNAVAILABLE(HAL or modem not ready). - NITZ Network Identity and Time Zone: the network sends time and zone;
NitzStateMachinefeeds Android's time and time-zone detectors.
TelephonyRegistry and CarrierConfig
TelephonyRegistry
The telephony event bus in system_server. Apps register a TelephonyCallback with the listener interfaces they need (service state, signal strengths, call state, data connection state, display info). Many callbacks need permissions such as READ_PHONE_STATE or location, and the registry filters data accordingly.
CarrierConfigManager
A per-subscription bundle of keys such as "VoLTE available", IMS APN, emergency numbers, roaming rules, signal thresholds, data retry rules. CarrierConfigLoader merges platform defaults, the carrier-config app's values for the identified carrier (by carrier ID / MCC-MNC), and a privileged carrier app's CarrierService. It broadcasts ACTION_CARRIER_CONFIG_CHANGED when the bundle changes (SIM swap, SIM loaded, config update).
Carrier identification
CarrierResolver maps the SIM (MCC-MNC, GID1, SPN, ICCID prefix, IMSI prefix) to an Android carrier ID from the carrier database. Carrier config, APNs and IMS behaviour key off this ID, so a wrong carrier ID causes many downstream symptoms.
RadioConfig
The multi-SIM configuration HAL (IRadioConfig): SIM slot mapping, phone capability (how many logical modems, DSDS vs DSDA), switching between single and dual SIM, and setPreferredDataModem.
networkStateChanged → SST.pollState() (four requests) → new ServiceState → DefaultPhoneNotifier → TelephonyRegistry → TelephonyCallbacks and broadcast. Naming this chain signals real framework depth.DataNetworkController not DcTracker; SubscriptionManagerService not SubscriptionController; TelephonyCallback not PhoneStateListener) and whether you can explain the threading model: each tracker is a Handler on a looper, so state changes are serialized without locks, and a blocking call on the phone main thread causes an ANR in com.android.phone.SIM, eSIM and subscriptions
The SIM (technically the UICC, Universal Integrated Circuit Card) is a small secure computer that holds the subscriber identity (IMSI), the secret key used for authentication, and operator files. Android models it as a tree of objects and maps each active SIM profile to a subscription with a stable subscription ID.
A SIM is like a passport. The card itself (UICC) is the booklet, the applications on it (USIM, ISIM) are the individual visa pages, and the files inside (IMSI, ICCID, forbidden networks) are the stamps. An eSIM is a passport printer built into the phone: new passports (profiles) are downloaded from the issuing office (SM-DP+) rather than handed over physically. The subscription ID is the traveller record the airline (Android) keeps for each passport, so it does not have to reread the booklet every time.
The UICC object tree
UiccController (singleton, listens to IRadioSim status indications)
└── UiccSlot (physical or eUICC slot; card present / absent)
└── UiccCard / UiccPort (one card; eUICC cards may expose several ports)
└── UiccProfile (the active profile; exposes aggregated SIM state)
├── UiccCardApplication USIM → SIMRecords (IMSI, MSISDN, SPN, PLMN lists)
├── UiccCardApplication ISIM → IsimUiccRecords (IMPI, IMPU, domain)
└── UiccCardApplication CSIM/RUIM → RuimRecords (CDMA, legacy)
Each application reads files through an IccFileHandler → RIL iccIoForApp → modem → card APDUs
SIM states
| State | Meaning |
|---|---|
ABSENT | No card detected in the slot |
PIN_REQUIRED / PUK_REQUIRED | User must enter PIN, or PUK after too many wrong PINs |
NETWORK_LOCKED | Device is carrier-locked and this SIM is not allowed (subsidy lock / personalization) |
NOT_READY | Card present but not yet initialized (or radio off) |
READY | Applications are usable; files may still be loading |
LOADED | Internal state: all records (IMSI, ICCID, etc.) have been read; subscriptions and carrier config are finalized after this |
CARD_IO_ERROR | Electrical or protocol failure talking to the card |
CARD_RESTRICTED / PERM_DISABLED | Card restricted by carrier policy or permanently blocked |
Important elementary files (EFs)
| File | Contents | Why it matters |
|---|---|---|
| EF_ICCID (2FE2) | Card serial number | Identifies the card; used to create/find the subscription record |
| EF_IMSI (6F07) | International Mobile Subscriber Identity (MCC + MNC + MSIN) | Home network, authentication identity |
| EF_AD | Administrative data, including MNC length (2 or 3 digits) | Wrong MNC length gives a wrong MCC-MNC and wrong APNs/config |
| EF_SPN | Service provider name and display rules | Operator name on the status bar |
| EF_MSISDN | Own phone number (often empty) | Why getLine1Number() is unreliable |
| EF_PLMNwAcT / EF_OPLMNwAcT / EF_EHPLMN | Preferred and equivalent home networks with access technology | Network selection and roaming priority |
| EF_FPLMN | Forbidden PLMN list | Networks added after rejects such as EMM #11; a common "cannot register" culprit |
| EF_IMPI / EF_IMPU (ISIM) | IMS private and public identities | IMS registration; derived from IMSI if no ISIM |
SIM access uses APDUs (smart-card command/response units). SIM Toolkit (STK) proactive commands arrive as indications and are handled by CatService. A simRefresh indication tells the framework that files changed (for example after an over-the-air SIM update) so records must be reread.
Carrier privileges
An app whose signing certificate is listed in the UICC access-rule applet (ARA-M / ARF) is treated as a carrier-privileged app for that subscription. TelephonyManager.hasCarrierPrivileges() is the check. Privileged apps can use APIs that ordinary apps cannot: open UICC logical channels (iccOpenLogicalChannel, iccTransmitApduLogicalChannel), manage some APN and IMS provisioning, and call other carrier-only telephony methods. This is not the same as being a privileged system app, and it is not the same as holding READ_PHONE_STATE. A missing or stale access rule on the SIM is a common reason a carrier app "works on the operator's reference phone but not on ours".
Subscriptions and IDs
| Identifier | What it is | Stable? |
|---|---|---|
| Slot index | Physical/logical SIM slot (0, 1) | Fixed by hardware |
| Phone ID | Index of the Phone object / logical modem | Usually equals the logical slot |
| Subscription ID (subId) | Row in the subscription database for one SIM profile (keyed by ICCID) | Stable for a given SIM; new ID for a new SIM; INVALID_SUBSCRIPTION_ID (-1) when none |
| Carrier ID | Android's canonical carrier identity | Stable across devices |
SubscriptionManagerService owns the database and the defaults: default data subscription (DDS), default voice and default SMS subscription. Apps use SubscriptionManager and TelephonyManager.createForSubscriptionId(subId) to target one SIM.
Multi-SIM: DSDS vs DSDA
DSDS (Dual SIM Dual Standby)
- One RF chain shared between two SIMs; both registered and pageable, but only one can be in an active call or high-rate data at a time.
- The modem time-shares the radio ("tune-away") to listen to the other SIM's paging.
- A call on the non-DDS SIM suspends data on the DDS unless the device supports temporary data switching.
DSDA (Dual SIM Dual Active)
- Two RF chains (or enough RF resources) so both SIMs can be active at once.
- Data on one SIM continues during a call on the other.
- Costs more hardware and power; advertised through
PhoneCapabilityinIRadioConfig.
Temporary data switch: when a voice call starts on the non-DDS SIM, PhoneSwitcher can move data to that SIM (calls IRadioConfig.setPreferredDataModem) for the call's duration, then switch back. Newer releases also support automatic data switching to the other SIM when the DDS has poor service, controlled by user setting and carrier policy.
eSIM basics
- eUICC: an embedded, soldered UICC that can store several operator profiles. Identified by its EID.
- ISD-R: the on-card security domain that manages profiles; the device talks to it over a logical channel.
- LPA (Local Profile Assistant): the on-device component (an app implementing
EuiccService) that downloads, enables, disables and deletes profiles. Apps useEuiccManager. - SM-DP+: the operator-side server that prepares and delivers encrypted profiles; SM-DS is a discovery server. An activation code (often a QR code) points the LPA to the SM-DP+.
- The GSMA Remote SIM Provisioning specs (consumer: SGP.21/SGP.22; IoT: SGP.31/SGP.32) define the flow. Android 13+ supports Multiple Enabled Profiles (MEP), so one eUICC can host two active profiles for dual-SIM on eSIM only.
- Wearables use eSIM because there is no room for a tray; number sharing (one number on phone and watch) is a carrier feature. See Wear OS.
User scans QR (activation code)
└── LPA app (EuiccService) ── HTTPS (ES9+) ──▶ SM-DP+ (mutual authentication, profile binding)
│ downloads encrypted Bound Profile Package
└── APDUs over logical channel (ES10) ──▶ eUICC ISD-R ──▶ installs profile
Enable profile → card refresh → UiccController sees new ICCID → new subId → carrier config → registration
OnSubscriptionsChangedListener) and carrier config changes.simStatusChanged indication → getIccCardStatus → UiccController builds the tree → PIN check → records load (ICCID, IMSI, EF_AD) → state LOADED → subscription created/updated → carrier ID resolved → carrier config loaded → APNs and IMS configured → modem registers with the home PLMN.Data framework: APNs and DataNetworkController
A mobile data connection is called a PDN connection on LTE and a PDU session on 5G. Each one is set up against an APN (Access Point Name; called DNN on 5G) that tells the core network which gateway and service to use. The framework decides when to bring connections up or down; the modem does the actual signalling.
An APN is like a named entrance to a large building: the main entrance for visitors (internet), a staff entrance (IMS), a delivery dock (MMS) and a side door for guests you bring along (tethering/DUN). DataNetworkController is the receptionist who opens an entrance only when someone actually needs it (a network request), checks whether that visitor is allowed today (data enabled, roaming policy, the right SIM), and closes it again when nobody is using it.
APN types
| APN type | Used for | Notes |
|---|---|---|
default | General internet | Usually the initial attach APN on LTE |
ims | IMS signalling and media (VoLTE, VoNR, SMS over IMS) | Often IPv6; never used for app internet traffic; stays up even with mobile data off |
mms | Multimedia messages | Brought up on demand, works with mobile data off on many carriers |
supl | Assisted GPS | Location assistance |
dun | Tethering | Some carriers require a separate DUN APN for hotspot traffic |
emergency | Emergency IMS calls | Can be set up without a valid subscription |
xcap, fota, cbs, ia, enterprise | Supplementary-service config, firmware updates, cell broadcast, initial attach, enterprise slices | Carrier-specific |
APN definitions come from the device APN database (apns-conf.xml → telephony provider, content://telephony/carriers), filtered by carrier ID / MCC-MNC, and can be edited by the user or a carrier app. Each becomes a DataProfile. The framework sends the initial attach APN (setInitialAttachApn) and the full profile list (setDataProfile) to the modem.
DcTracker → DataNetworkController
Before Android 13
DcTrackerper transport,ApnContextper APN type,DataConnectionstate machine per connection.- Logic spread across several interacting state machines; many races during bring-up/teardown and handover.
Android 13 and later
DataNetworkController(one per phone) evaluates every network request against every rule.DataNetwork= one active connection (its own state machine);DataProfileManagerpicks profiles;DataRetryManagerhandles retries and throttling;DataSettingsManagertracks user data/roaming settings;AccessNetworksManagerdecides cellular vs Wi-Fi (IWLAN) transport.- Request-driven with explicit "data evaluation" reasons, which makes decisions easy to log and debug.
How a data call is brought up
- Network request An app or the system asks
ConnectivityServicefor a network with capabilities (for exampleINTERNET, orIMS, orMMS). - Routing to telephony The telephony network factory (
TelephonyNetworkFactory, activated on the preferred data phone byPhoneSwitcher) passes it toDataNetworkController. - Evaluation Checks: SIM loaded, in service on PS domain, data enabled (user/policy/carrier), roaming allowed, correct DDS, not throttled, no conflicting call on DSDS, radio on.
- Profile choice
DataProfileManagerpicks theDataProfile(APN) that satisfies the capabilities. - Setup
DataNetworkcallsRIL.setupDataCall()→IRadioData.setupDataCall(serial, accessNetwork, dataProfile, roamingAllowed, reason, addresses, dnses, pduSessionId, sliceInfo, matchAllRuleAllowed). - Modem signalling The modem sends an ESM PDN Connectivity Request (LTE) or 5GSM PDU Session Establishment Request (5G).
- Response
SetupDataCallResultreturns a cause (DataFailCause), interface name (rmnet_data0/ccmni0), addresses, DNS, gateways, MTU, P-CSCF addresses, and optionally QoS and slice information. - Network agent
DataNetworkcreates aTelephonyNetworkAgent,netdconfigures the interface and routes, andConnectivityServicecallsonAvailable(Network)on the requesting app. - Teardown When no request needs it,
deactivateDataCall. The modem can also drop it and report throughdataCallListChanged.
Retry and throttling
- Failed setups are retried by
DataRetryManageraccording to carrier-config retry rules (per cause, with back-off intervals). - The network can impose back-off through T3396 (per-APN, after an ESM reject such as #26 insufficient resources) or T3346 (mobility-management congestion). The modem reports the suggested retry time in the response; the framework must honour it.
- Permanent failures (for example #27 unknown APN, #33 not subscribed) should stop automatic retries until something changes (new APN, SIM, or settings).
IRadioData.setDataThrottlinglets the framework ask the modem to reduce throughput (for example for thermal mitigation).
DataNetworkController, DataNetwork, DataProfile, the setupDataCall response fields (cause, ifname, IP, DNS, MTU, P-CSCF) and the retry rules. Mention that the framework decides when while the modem decides how.RIL: the Radio Interface Layer
The RIL is the translator between the Java framework and the vendor radio software. On the framework side it is RIL.java (usually called RILJ), which implements CommandsInterface; there is one instance per logical modem/SIM slot. Its job is to turn method calls into HAL requests, match responses back to the caller, deliver unsolicited events, keep the device awake while requests are pending, and recover when the vendor side dies.
RILJ works like a restaurant's order desk. Every order gets a ticket number (the serial) and is pinned to a board (the request list). The kitchen (the modem) calls out "ticket 42 ready" (a solicited response) and the desk hands the dish to whoever ordered it. The kitchen can also shout news nobody asked for, such as "we are out of fish" (an unsolicited indication), and the desk announces it to everyone who subscribed. While tickets are open the desk keeps the lights on (the wakelock). If the kitchen catches fire (the HAL dies), the desk tells every waiting customer "order cancelled" (RADIO_NOT_AVAILABLE) and waits for the kitchen to reopen.
Solicited vs unsolicited
Solicited (request/response)
- Framework-initiated:
dial,setupDataCall,getSignalStrength,setRadioPower. - Each gets a
RILRequestwith a unique serial, stored inmRequestList. - The answer arrives later on the matching
IRadio*Responsecallback carryingRadioResponseInfo{type, serial, error}. - Holds the RILJ wakelock while outstanding.
Unsolicited (indication)
- Modem-initiated: network state changed, signal strength, incoming call/SMS, NITZ, SIM status, data call list changed, modem reset.
- Arrives on
IRadio*Indication;RadioIndicationconverts it and notifies aRegistrantList. - No serial and no request tracking; just fan-out.
- Some indications require an acknowledgement so the vendor can release its own wakelock.
Solicited request lifecycle
// Simplified from frameworks/opt/telephony RIL.java
RILRequest rr = obtainRequest(RIL_REQUEST_SETUP_DATA_CALL, result, mRILDefaultWorkSource);
// RILRequest.obtain(): take from pool, assign mSerial (atomic counter),
// store the caller's result Message
// acquireWakeLock(rr, FOR_WAKELOCK): mWakeLockCount++ (acquire on 0 -> 1),
// post a WAKE_LOCK_TIMEOUT message
// mRequestList.append(rr.mSerial, rr)
riljLog(rr.serialString() + "> " + RILUtils.requestToString(rr.mRequest));
dataProxy.setupDataCall(rr.mSerial, accessNetwork, dataProfile, ...); // HAL call, returns at once
... modem works; seconds may pass ...
// Vendor calls back on IRadioDataResponse.setupDataCallResponse(info, result)
RILRequest rr = mRil.processResponse(HAL_SERVICE_DATA, info);
// findAndRemoveRequestFromList(info.serial)
// if info.type == SOLICITED_ACK_EXP: send ack, switch to ack wakelock
if (rr != null) {
if (info.error == RadioError.NONE) sendMessageResponse(rr.mResult, result);
mRil.processResponseDone(rr, info, result); // logs "<", completes rr.onError/onReceived,
// decrementWakeLock(rr), rr.release() back to pool
}
Key RIL types
| Type | Role |
|---|---|
CommandsInterface | The abstract radio API the framework programs against; RIL implements it (test code uses SimulatedCommands). |
RIL | One per slot; holds HAL proxies, request list, wakelocks, death recipients. |
RILRequest | Pooled object: serial, request ID, result Message, work source, start time. |
RadioServiceProxy (per domain) | Client-side handle to one HAL service: RadioNetworkProxy, RadioDataProxy, RadioVoiceProxy, RadioSimProxy, RadioModemProxy, RadioMessagingProxy, RadioImsProxy. Hides AIDL vs HIDL differences. |
*Response classes | Framework-side Binder servers the vendor calls for solicited replies (NetworkResponse, DataResponse...). |
*Indication classes | Framework-side servers for unsolicited events (NetworkIndication, DataIndication...). |
RegistrantList / Registrant | How framework objects subscribe to events (for example registerForNetworkStateChanged). |
AsyncResult | Wrapper placed in Message.obj carrying result or exception back to the caller. |
CommandException | Exception type mapped from RadioError (for example RADIO_NOT_AVAILABLE, GENERIC_FAILURE). |
Wakelocks and acknowledgements
- RIL holds a partial wakelock (tag
*telephony-radio*) while any solicited request is outstanding, so the application processor (AP) does not suspend mid-request. It is not reference-counted by PowerManager; RIL keeps its ownmWakeLockCount, acquiring on 0→1 and releasing on return to 0. - A timeout (
WAKE_LOCK_TIMEOUT, configurable) releases the lock if the modem never answers, so a lost response cannot pin the CPU awake forever. - A second short ack wakelock covers the acknowledgement protocol: if the vendor returns
SOLICITED_ACK("received, still working"), RIL can drop the main wakelock; for indications of typeUNSOLICITED_ACK_EXP, RIL briefly holds the ack wakelock and callsresponseAcknowledgement()so the vendor can release its own wakelock. - Every request carries a
WorkSourceso battery stats blame the right app.
Reading RILJ logs
RILJ : [0342]> SETUP_DATA_CALL,reason=NORMAL,accessNetwork=EUTRAN,dataProfile=... [PHONE0]
RILJ : [0342]< SETUP_DATA_CALL DataCallResponse: { cause=NONE ifname=rmnet_data1
addresses=[10.x.x.x/32, 2001:db8::/64] dnses=[...] mtuV4=1500 mtuV6=1500 ... } [PHONE0]
RILJ : [UNSL]< UNSOL_RESPONSE_NETWORK_STATE_CHANGED [PHONE0]
RILJ : [0343]> VOICE_REGISTRATION_STATE [PHONE0]
RILJ : [0343]< VOICE_REGISTRATION_STATE error: RADIO_NOT_AVAILABLE [PHONE0]
RILJ : [0344]> SETUP_DATA_CALL ... (no matching "<" line = response never came)
The number in brackets is the serial; > is a request, < a response, [UNSL] an indication. A request with no matching response line points below the RIL (vendor daemon or modem). [PHONE0]/[PHONE1] tells you the slot.
Death and recovery
- Link to death RIL registers a death recipient on every HAL service binder.
- serviceDied() If the vendor process dies, the callback fires for each affected service.
- Flush RIL completes every pending
RILRequestwithRADIO_NOT_AVAILABLE, clears the request list, releases wakelocks and resets the proxies. - Radio state The framework sees radio state
UNAVAILABLE; service state and data calls are torn down. - Reconnect RIL waits for the HAL service to be registered again, re-sends response/indication callbacks (
setResponseFunctions) and the framework resynchronizes (SIM status, radio power, data profiles).
serviceDied is not the same as a modem crash. HAL death means the vendor daemon process restarted. A modem crash is Qualcomm SSR (subsystem restart) or a MediaTek md1 exception. One can cause the other (a modem crash often makes the daemon restart, and a daemon bug can trigger a modem reset), so compare timestamps to decide the direction.Legacy native RIL (before Treble)
Older devices ran AOSP rild, which loaded a vendor library (librilvendor.so) through RIL_Init. Framework requests arrived over a Unix socket as parcels; libril dispatched them to the vendor's onRequest, and the vendor answered with RIL_onRequestComplete or pushed events with RIL_onUnsolicitedResponse. The request IDs (RIL_REQUEST_DIAL, RIL_UNSOL_RESPONSE_NEW_SMS...) still appear in logs and in RILConstants. HIDL (Android 8) replaced the socket with HwBinder; AIDL (Android 13) replaced HIDL.
ServiceStateTracker, and how to read [serial]>/< log pairs. A strong answer also mentions that RIL is per slot and that all callbacks land on the phone process's handler threads.Radio HAL (AIDL) and the vendor RIL daemon
The Radio HAL is the stable contract between AOSP and the chipset vendor. AOSP defines the interfaces and calls them; the vendor implements them inside its RIL daemon. Because the contract is versioned and frozen, Google can update the framework without the vendor rebuilding its radio stack (the Project Treble idea).
The Radio HAL is like a standard electrical socket. Appliance makers (AOSP) build plugs to the standard, and each power company (Qualcomm, MediaTek) wires its grid differently behind the wall. As long as both honour the socket shape and voltage (the frozen AIDL interface), any appliance works in any house. The AIDL split into IRadioNetwork, IRadioData and so on is like having separate sockets for lights, the oven and the washing machine, so each can be upgraded without rewiring the whole house.
Three interface families per domain
IRadioX: requests the framework calls (implemented by the vendor). Every method takes aserialand returns immediately (oneway).IRadioXResponse: solicited replies (implemented by the framework, called by the vendor), each carryingRadioResponseInfo.IRadioXIndication: unsolicited events (implemented by the framework, called by the vendor).
At startup RIL calls setResponseFunctions(response, indication) on each service to hand its callback binders to the vendor, so Binder runs in both directions.
RIL (client) vendor rild (server for IRadioVoice)
|-- IRadioVoice.dial(serial=42, dialInfo) --------->| returns immediately (oneway)
| |-- QMI VOICE dial / ATD --> modem
|<-- IRadioVoiceResponse.dialResponse(info{serial=42, error=NONE}) --| reverse Binder call
| RadioResponse matches serial 42, completes RILRequest |
| |<-- modem: call state change
|<-- IRadioVoiceIndication.callStateChanged(type) ---| unsolicited
| GsmCdmaCallTracker.pollCallsWhenSafe() -> getCurrentCalls(serial=43) ...
The AIDL modules
Interface (package android.hardware.radio.*) | Example requests | Example indications |
|---|---|---|
IRadioConfig (instance /default) | getSimSlotsStatus, getPhoneCapability, setPreferredDataModem, setNumOfLiveModems, setSimSlotsMapping | simSlotsStatusChanged |
IRadioModem | setRadioPower, getModemActivityInfo, getImei/getDeviceIdentity, getBasebandVersion, requestShutdown, nvResetConfig | radioStateChanged, modemReset, rilConnected, hardwareConfigChanged |
IRadioNetwork | getVoiceRegistrationState, getDataRegistrationState, getOperator, getSignalStrength, getCellInfoList, setAllowedNetworkTypesBitmap, setNetworkSelectionModeManual, startNetworkScan, setSignalStrengthReportingCriteria, setIndicationFilter | networkStateChanged, currentSignalStrength, nitzTimeReceived, cellInfoList, currentPhysicalChannelConfigs, barringInfoChanged, registrationFailed |
IRadioData | setupDataCall, deactivateDataCall, getDataCallList, setInitialAttachApn, setDataProfile, setDataAllowed, setDataThrottling, startKeepalive, allocatePduSessionId, getSlicingConfig | dataCallListChanged, pcoData, unthrottleApn, keepaliveStatus, slicingConfigChanged |
IRadioVoice | dial, emergencyDial, hangup, acceptCall, getCurrentCalls, sendDtmf, getClir/setCallForward | callStateChanged, callRing, srvccStateNotify, currentEmergencyNumberList |
IRadioSim | getIccCardStatus, supplyIccPinForApp, iccIoForApp, getImsiForApp, iccOpenLogicalChannel, iccTransmitApduLogicalChannel, setSimCardPower, sendEnvelope (STK) | simStatusChanged, simRefresh, stkProactiveCommand, carrierInfoForImsiEncryption |
IRadioMessaging | sendSms, sendImsSms, acknowledgeLastIncomingGsmSms, writeSmsToSim, setGsmBroadcastConfig, getSmscAddress | newSms, newSmsOnSim, newBroadcastSms, simSmsStorageFull |
IRadioIms (Android 14+) | setSrvccCallInfo, updateImsRegistrationInfo, startImsTraffic/stopImsTraffic, triggerEpsFallback, sendAnbrQuery | onConnectionSetupFailure, notifyAnbr, triggerImsDeregistration |
Per-slot services are registered as android.hardware.radio.network.IRadioNetwork/slot1, .../slot2 and so on; IRadioConfig is a single /default instance. IRadioIms exists because on modern designs the IMS stack may run on the AP (vendor ImsService) while the modem still needs to know about IMS traffic for access barring, SRVCC and EPS fallback.
HIDL vs stable AIDL
| HIDL (Android 8 to 12) | Stable AIDL (Android 13+) | |
|---|---|---|
| Package | android.hardware.radio@1.0 … @1.6 | android.hardware.radio.network, .data, .voice, .sim, .modem, .messaging, .ims, .config |
| Shape | One monolithic IRadio growing by inheritance (@1.1::IRadio extends @1.0::IRadio) | Split by domain; each module versioned independently |
| Transport | HwBinder via hwservicemanager | Regular Binder via servicemanager |
| Evolution | New minor version per change; clients check getHalVersion and fall back | Frozen versions; new methods added in a new version; framework checks the interface version |
| Mental model | Identical: async request with serial, response callback, indication callback | |
RIL.java supports both at runtime: each RadioServiceProxy wraps either an AIDL or a HIDL handle, and RIL tracks the HAL version per service so it can reply REQUEST_NOT_SUPPORTED for methods the vendor does not implement.
How the HAL is found at boot
- Declaration The vendor's VINTF manifest fragment declares, for example,
android.hardware.radio.data.IRadioData/slot1with a version. - Compatibility The framework compatibility matrix lists which versions it accepts; a mismatch fails the VTS/compatibility check.
- Start
initstarts the vendor daemon from its.rcfile (or on demand for lazy HALs throughctl.interface_start). - Register The daemon registers each service with
servicemanager. - Bind RIL calls
ServiceManager.waitForDeclaredService(...), gets the binder, links to death and callssetResponseFunctions.
init service entry provides it, you see init: Could not find '...IRadio.../slot1' for ctl.interface_start and the framework's proxy stays null forever (logs full of serviceProxy == null). It looks like a dead modem but is a build/packaging bug. Declared is not the same as running.Vendor implementations
| Layer | Qualcomm | MediaTek |
|---|---|---|
| HAL server process | qcrild (QCRIL), often one instance per slot; vendor extensions under vendor.qti.hardware.radio.* | MTK RIL daemon (mtkfusionrild on many platforms); extensions under vendor.mediatek.hardware.* |
| Internal structure | Modules per domain (VoiceModule, NasModule, DataModule...), qcril_qmi_* | Rfx framework (RfxController, Rmc*/Rmm* handlers, URC handlers) |
| IPC to modem | QMI clients over QRTR (IPC router) | MIPC (MTK IPC) and AT channels over CCCI |
| Data path netdevs | rmnet_data0..N over rmnet_ipa0 or rmnet_mhi0 | ccmni0..N |
| IMS stack | Vendor ImsService + modem IMS (QMI IMSA/IMS) | Vendor ImsService + MIPC IMS |
| Log tags | QCRIL, QMI_*, qcril_qmi_* | Rfx*, Rmm*, MipcVsClient, AT>/AT< |
| Modem logs | QXDM / QCAT via DIAG | MTKLogger modem log, decoded with ELT / Catcher |
Everything from Dialer down to RIL.java is the same AOSP code on both vendors; divergence starts at the HAL implementation. OEMs may add hooks above the HAL (extended phone or call-tracker classes), which is why stack traces sometimes show OEM class names inside the phone process.
REQUEST_NOT_SUPPORTED), and "How does RIL find the HAL?" (VINTF declaration, servicemanager, waitForDeclaredService). Mentioning the lazy-HAL trap shows real bring-up experience. See also Binder IPC & AIDL.The modem and AP interface
The modem (baseband) is a separate processor, usually a DSP cluster inside the same SoC (Qualcomm MPSS on a Hexagon core; MediaTek MD1) or a separate chip connected by PCIe. It runs its own real-time OS and the full 3GPP stack. The application processor (AP) running Android talks to it on two separate paths: a control path for commands and events, and a data path for IP packets.
Think of a ship's bridge and engine room. The bridge (AP) sends orders through a speaking tube (the control channel: QMI or AT messages), while fuel and cargo move through a separate wide pipe (the data path: shared-memory rings moved by DMA hardware). The speaking tube carries short, structured messages in a fixed vocabulary; the pipe carries bulk goods with no conversation at all. Mixing the two would slow both down, which is exactly why the phone keeps control and user plane separate.
APPLICATION PROCESSOR (Android) MODEM +-----------------------------------------+ +------------------------------+ | vendor RIL daemon (qcrild / MTK rild) | | modem RTOS | | QMI clients / MIPC / AT | | QMI services / AT parser | +-------------------+---------------------+ | NAS / RRC / PDCP / RLC / | | kernel: QRTR sockets (QC) or | | MAC / PHY | | /dev/ccci_* char devices (MTK) | <===> | | | transport: GLINK / SMD over SMEM, |control| | | or MHI over PCIe | | | +-----------------------------------------+ | | | net: rmnet_data* over rmnet_ipa0/mhi | <===> | user-plane buffers | | (QMAP mux + aggregation, IPA HW) | data | | | ccmni* over CCCI/DPMAIF (MTK) | | | +-----------------------------------------+ +------------------------------+ shared DDR memory regions, doorbell interrupts, SMMU-protected DMA
QMI (Qualcomm MSM Interface)
- A service-oriented, binary request/response/indication protocol between AP clients and modem services. Messages are TLV (type-length-value) encoded, identified by service ID, message ID and a transaction ID.
- Transport: the IPC router, exposed in upstream Linux as QRTR (
AF_QIPCRTRsockets), running over GLINK/SMD on shared memory for on-chip modems, or over MHI (Modem Host Interface) on PCIe for external modems. Older stacks used theqmuxddaemon. - Conceptually mirrors the HAL: a HAL request usually maps to one or more QMI requests; QMI indications become HAL indications.
| QMI service | Purpose | HAL counterpart |
|---|---|---|
| NAS | Network access: registration, system selection, signal, cell info, network scan | IRadioNetwork |
| WDS | Wireless Data Service: start/stop network (PDN/PDU), packet data status, profiles | IRadioData |
| DSD | Data System Determination: preferred data system, which RAT carries data | IRadioData / IRadioConfig |
| VOICE | CS calls, supplementary services, USSD | IRadioVoice |
| UIM | SIM card access, APDUs, PIN, refresh | IRadioSim |
| CAT | SIM Toolkit (card application toolkit) | IRadioSim STK methods |
| WMS | Wireless Messaging Service: SMS send/receive, cell broadcast | IRadioMessaging |
| DMS | Device management: IMEI, firmware version, operating mode (online/low power) | IRadioModem |
| IMSA / IMSS | IMS application status and settings | IRadioIms, vendor IMS |
| PDC | Persistent Device Configuration: modem carrier configuration (MBN files) selection | Vendor extension |
| PBM, QoS, DFS | Phonebook, QoS flows, data filter service | Various |
AT commands
- Text commands defined by 3GPP TS 27.007 (general and network) and TS 27.005 (SMS). Common on external USB/M.2 modems and IoT modules, and used internally by MediaTek alongside MIPC.
- Responses end with
OKorERROR/+CME ERROR: n; unsolicited result codes (URCs) such as+CREG:orRINGarrive at any time.
| Command | Purpose |
|---|---|
AT+CFUN=1 / =0 / =4 | Full functionality / minimum / radio off (airplane) |
AT+COPS?, AT+COPS=1,2,"310260" | Query operator; manual network selection |
AT+CREG? / AT+CGREG? / AT+CEREG? / AT+C5GREG? | CS / GPRS / EPS / 5GS registration status |
AT+CGDCONT=1,"IPV4V6","internet" | Define a PDP/PDN context (APN) |
AT+CGACT=1,1 | Activate the context |
AT+CSQ, AT+CESQ | Signal quality |
AT+CPIN?, AT+CIMI, AT+CGSN | SIM PIN state, IMSI, IMEI |
ATD<number>;, ATA, ATH, AT+CLCC | Dial voice call, answer, hang up, list current calls |
AT+CMGS, AT+CMGF | Send SMS, select text/PDU mode |
MediaTek: CCCI, MIPC and ccmni
- CCCI (Cross Core Communication Interface) is MediaTek's kernel driver for AP-modem communication. It exposes channels as character devices (
/dev/ccci_*) for control, AT/MIPC, logging and file system services, plus network devices for data. - Userspace helpers include
ccci_mdinit(modem boot/init and monitoring) andccci_fsd(serves modem file-system requests such as NV data from the AP side). - MIPC is MTK's structured IPC protocol replacing much raw AT traffic; logs still often show
AT>/AT<pairs. - ccmni interfaces carry user-plane packets; a hardware data mover (for example CLDMA on older chips, DPMAIF on newer ones) moves packets between AP memory and the modem.
- Modem crashes are reported as md1 exception /
MD_EEthrough CCCI and the AEE exception framework, with a modem memory dump.
Shared memory, interrupts and security
- AP and modem share carved-out DDR regions (SMEM on Qualcomm). Messages are written into ring buffers; a doorbell interrupt tells the other side to read.
- DMA from the modem is restricted by the SMMU/IOMMU and memory firewalls (Qualcomm xPU), so a compromised modem cannot read arbitrary AP memory.
- The modem firmware is loaded and authenticated by the AP at boot: on Qualcomm the kernel's remote-processor driver (historically PIL, today
remoteprocwithqcom_q6v5_mss/_pas) loads the images from the modem partition, and TrustZone verifies signatures before the modem runs.
NV items, EFS and modem configuration
- NV items / EFS: the modem's persistent store for RF calibration, IMEI (protected), band settings, feature flags and certificates. Corruption can leave the device without radio; IMEI and calibration are specially protected.
- MBN / carrier configuration: Qualcomm modems load a carrier-specific configuration package (MBN) selected by PDC based on the SIM, setting modem-side behaviour (bands, IMS, timers). MediaTek has equivalent modem carrier configurations. Framework CarrierConfig and modem configuration must agree, or features like VoLTE break.
Modem crash and restart (SSR)
- Fault The modem hits a fatal error (assert, "err_fatal"), its watchdog expires, or the AP requests a restart.
- Notify The kernel remote-processor / subsystem-restart framework is notified; if enabled, a ramdump of modem memory is collected.
- Tear down clients Registered notifiers (rmnet/IPA data path, QRTR, RIL daemon, IMS) are told the modem went down; data interfaces go down and pending requests fail.
- Reload Firmware is reloaded and restarted; the modem re-initializes.
- Recover upward The RIL daemon reports radio state
UNAVAILABLEthen back, may send amodemResetindication with a reason string; the framework re-reads SIM status, re-registers, and re-establishes data and IMS.
User-visible effect: a few seconds of "no service", dropped calls, lost data connections. MediaTek follows the same idea with an md1 exception, CCCI notification and modem reset.
ccmni and md1 exceptions. Everyone asks why control and data paths are separate.3GPP protocol layers inside the modem
These layers run in modem firmware, but telephony engineers must be conversant because cause codes and logs come from them. The stack is split into the Non-Access Stratum (NAS), which talks end to end to the core network, and the Access Stratum (AS), which talks only to the base station.
Sending a legal document by courier: NAS is the letter between you and the government office (the core network) that the courier never reads. RRC is your arrangement with the local courier branch (the base station): when to pick up, which van, which route. PDCP seals and stamps the envelope (encryption, compression). RLC splits a large parcel into boxes and re-sends lost ones. MAC is the dispatcher deciding which van leaves when and quickly redoing botched hand-offs (HARQ). PHY is the road and the van itself.
CONTROL PLANE USER PLANE +------------------+ +------------------+ | NAS (EMM/ESM, | UE <-> MME/AMF | IP packets | UE <-> P-GW/UPF | 5GMM/5GSM) | +------------------+ +------------------+ | SDAP (5G only) | QoS flow -> DRB mapping | RRC | UE <-> eNB/gNB +------------------+ +------------------+ | PDCP | | PDCP | +------------------+ +------------------+ | RLC | | RLC | +------------------+ +------------------+ | MAC | | MAC | +------------------+ +------------------+ | PHY | | PHY | +------------------+ +------------------+ Signalling radio bearers (SRB0/1/2) Data radio bearers (DRBs)
| Layer | Peer | Main jobs |
|---|---|---|
| NAS | MME (LTE) / AMF + SMF (5G) | Mobility management (attach/registration, tracking area update, authentication, NAS security, detach) and session management (PDN connectivity / PDU sessions). LTE: EMM + ESM. 5G: 5GMM + 5GSM. Reject causes originate here. |
| RRC | eNB / gNB | Radio connection setup, reconfiguration and release; system information broadcast; measurement configuration and reports; handover commands; AS security; SRB/DRB setup. States: RRC_IDLE, RRC_CONNECTED, and on NR RRC_INACTIVE. |
| SDAP (5G) | gNB | Maps QoS flows (QFI) to data radio bearers. |
| PDCP | eNB / gNB | Ciphering, integrity protection, header compression (ROHC, vital for VoLTE), in-order delivery, duplicate detection; split-bearer routing in dual connectivity. |
| RLC | eNB / gNB | Segmentation and reassembly; ARQ retransmission. Modes: TM (transparent), UM (unacknowledged, used for voice), AM (acknowledged, used for data and signalling). |
| MAC | eNB / gNB | Scheduling, multiplexing logical channels onto transport channels, HARQ fast retransmission, random access, timing advance, buffer status reports, DRX. |
| PHY | eNB / gNB | Channel coding (turbo for LTE data; LDPC and polar for NR), modulation (QPSK to 256/1024-QAM), OFDM, MIMO and beamforming, reference-signal measurements (RSRP/RSRQ/SINR). |
HARQ (MAC)
- Fast, within milliseconds; several parallel stop-and-wait processes.
- Soft combining: failed copies are kept and combined with the retransmission.
- Fixes the vast majority of radio errors.
ARQ (RLC AM)
- Slower, status-report driven.
- Backstop for residual errors HARQ misses.
- Too many RLC retransmissions is one trigger of radio link failure.
RRC states and procedures
- RRC_IDLE: no radio connection; the UE does cell selection/reselection and listens for paging at DRX occasions. Lowest power.
- RRC_CONNECTED: dedicated resources; the network controls mobility via handover.
- RRC_INACTIVE (NR): context kept in the network and UE, radio released; resume is much faster than a fresh setup. Saves power and signalling.
- Key procedures: RRC connection setup (LTE
RRCConnectionRequest/Setup/SetupComplete; NRRRCSetupRequest/RRCSetup/RRCSetupComplete), Security Mode Command, RRC Reconfiguration (adds bearers, measurements, handover), RRC Release (optionally with redirection), re-establishment after failure. - RLF (Radio Link Failure): declared on T310 expiry after out-of-sync indications, maximum RLC retransmissions, or random-access problems; the UE tries RRC re-establishment, otherwise it goes idle.
Mobility and power saving
- Idle mode: PLMN selection, cell selection (S-criterion) and reselection by priority and thresholds, paging reception, tracking-area updates.
- Connected mode: measurement events A1–A6 (intra-RAT: serving better/worse than threshold, neighbour better than serving...), B1/B2 (inter-RAT); handover over X2/Xn directly between base stations or via the core (S1/N2); conditional handover (CHO) where the UE executes a pre-prepared handover when conditions are met.
- DRX / eDRX: the UE sleeps between paging or PDCCH monitoring occasions; eDRX stretches cycles to seconds or minutes for IoT and wearables at the cost of reachability latency.
- PSM (Power Saving Mode): the UE stays registered but unreachable for long periods (timers T3324/T3412 extended); used by IoT devices.
From boot to "in service": registration and attach
Before a phone can call or use data it must find a network, prove who it is, and register. On LTE this is the Attach procedure (which also creates the first data connection); on 5G it is Registration (with data connections set up separately as PDU sessions). This section ties the framework, RIL, SIM and 3GPP pieces together into one timeline.
Checking into a hotel. You pick a hotel you are allowed to use (PLMN selection), walk to the front desk (RRC connection), show your passport and answer a security question only you can answer (authentication with the SIM's secret key), agree on a private code for the room safe (NAS security), and get your key card and room number (attach accept, IP address). Moving to another wing tells the desk where you are (tracking area update), and checking out is a detach.
Boot to in service: the Android timeline
- Phone process starts
PhoneFactory.makeDefaultPhones()createsRILandGsmCdmaPhoneper slot; RIL binds to the Radio HAL services and registers callbacks. - rilConnected / radio state The vendor daemon reports readiness; radio state moves from
UNAVAILABLEtoOFF. - SIM
UiccControllercallsgetIccCardStatus; the card tree is built, PIN checked, records loaded; subscription and carrier config are finalized. - Radio on Unless airplane mode is on, SST calls
setRadioPower(true). The framework also sends allowed network types, initial attach APN and data profiles. - Modem registers PLMN search → cell selection → RRC connection → NAS Attach / Registration (below).
- Framework sees service
networkStateChanged→pollState()→STATE_IN_SERVICE→ notifications. - Data and IMS
DataNetworkControllersets up internet and IMS data connections; the vendorImsServiceperforms IMS registration; the VoLTE/VoNR indicator appears.
PLMN and cell selection
- Automatic mode order: last registered PLMN → home PLMN / equivalent home (EHPLMN) → user-controlled list (EF_PLMNwAcT) → operator-controlled list (EF_OPLMNwAcT) → other PLMNs by signal quality. Forbidden PLMNs (EF_FPLMN) are skipped.
- Manual mode: the user picks from a network scan (
startNetworkScan→setNetworkSelectionModeManual). - The modem camps on a suitable cell (S-criterion satisfied, not barred, PLMN allowed, tracking area not forbidden). If only a non-allowed network is available it camps in "limited service" for emergency calls (
STATE_EMERGENCY_ONLY). - Allowed RATs come from
setAllowedNetworkTypesBitmap(combination of user preference, carrier restrictions, power/thermal reasons).
LTE Attach
UE eNB MME HSS / S-GW / P-GW |-- RRCConnectionRequest -->| | | |<-- RRCConnectionSetup ----| | | |-- RRCConnectionSetupComplete [NAS: Attach Request + PDN Connectivity Request] -->| | |-- Initial UE Message ->| | |<================ NAS Authentication Request (RAND, AUTN) ====|<-- auth vectors -| | USIM runs AKA: checks AUTN (network is genuine), computes RES | |================= NAS Authentication Response (RES) ========>| | |<================ NAS Security Mode Command / Complete =====>| | | | |-- Update Location ----->| HSS | | |-- Create Session ------>| S-GW/P-GW (IP allocated) |<-- AS Security Mode Command / Complete, UE Capability Enquiry --| | |<-- RRCConnectionReconfiguration [NAS: Attach Accept + Activate Default EPS Bearer Context Request] --| |-- RRCConnectionReconfigurationComplete -->| | | |-- [NAS: Attach Complete + Activate Default EPS Bearer Context Accept] ------>| | Registered (EMM-REGISTERED), default bearer up, IP address assigned |
Because LTE attach always creates a default bearer, an LTE phone is "always on IP". The APN used is the initial attach APN the framework pushed (or one the network chooses). If the default bearer is rejected, attach fails with an ESM cause wrapped in an EMM reject.
5G Registration and PDU sessions
- UE sends Registration Request (types: initial, mobility update, periodic, emergency) with a concealed identity SUCI (the encrypted form of the permanent SUPI/IMSI).
- Authentication: 5G-AKA or EAP-AKA' via AUSF/UDM; then NAS security mode.
- Registration Accept carries the temporary identity (5G-GUTI), registration area (TAI list), allowed NSSAI (slices) and timers; UE replies Registration Complete.
- Data is a separate step: PDU Session Establishment with the SMF, selecting a DNN (APN) and slice (S-NSSAI); the UPF is the user-plane gateway.
Staying registered
| Procedure / timer | Purpose |
|---|---|
| Tracking Area Update (TAU) / mobility registration | UE entered a tracking area outside its list |
| Periodic TAU (T3412) / periodic registration (T3512) | Tell the network the UE is still alive; expiry without update makes the network implicitly detach the UE |
| T3410 (attach), T3430 (TAU), T3411/T3402 (retry) | Attach/TAU supervision and back-off; typical 3GPP defaults T3410/T3430 = 15 s, T3411 = 10 s; after five failed attempts the UE waits T3402 (typical default 12 minutes) |
| T3346 | Mobility-management back-off sent by a congested network; UE must not retry until expiry |
| T3396 | Session-management back-off for a specific APN |
| T3417 | Service request supervision (idle to connected for signalling or data); typical 3GPP default 5 s |
| Detach / deregistration | Power off, airplane mode, SIM removal, or network-initiated (with a cause) |
CS services on LTE: CSFB and combined attach
On LTE networks without VoLTE, the UE does a combined EPS/IMSI attach so the MSC knows about it. For a call it performs CS Fallback (CSFB): it leaves LTE for 2G/3G, places the CS call, then returns. On the air interface the marker is a NAS EXTENDED SERVICE REQUEST followed by RRC release with redirection (or PS handover / cell change order). The framework only sees a normal CS dial plus a RAT change in ServiceStateTracker. There is no AOSP class named CsFallbackHelper; some vendor trees add extra helper log tags that are not in AOSP. Combined-attach rejects with EMM #18 ("CS domain not available") push devices to rely on IMS for voice. The AOSP IMS-to-CS redial path is covered in CS & IMS Call Flows.
NAS states, paging, TAU and radio mobility
After attach, interviewers expect you to separate registration state (am I known to the core?) from connection state (is there a signalling path right now?) and from RRC state (is the radio up?). Mixing those three is the usual stumble. This section also covers the high-frequency procedures that move a UE between those states: paging and Service Request, Tracking Area Update, access barring, AKA failure types, and intra-LTE X2 handover.
Hotel check-in versus actually being in the lobby. After you check in you are a registered guest (EMM-REGISTERED / 5GMM-REGISTERED) even when you are asleep in your room (ECM-IDLE / RRC_IDLE). A wake-up call (paging) makes you walk to the desk (Service Request) and you become reachable in the lobby (ECM-CONNECTED / RRC_CONNECTED). Changing wings without telling the desk is a Tracking Area Update. A fire alarm that blocks the stairs is access barring. The night clerk checking your passport again is AKA; a bad stamp is MAC failure, a clock that is out of date is sync failure.
EMM, ECM, 5GMM and CM states
| Family | States you must name | What they mean |
|---|---|---|
| EMM (LTE NAS registration) | EMM-DEREGISTERED, EMM-REGISTERED-INITIATED, EMM-REGISTERED, plus procedure states such as TAU-INITIATED and SERVICE-REQUEST-INITIATED | Whether the MME has a context for this UE. You can stay EMM-REGISTERED for hours while the radio is idle. |
| ECM / EMM connection (LTE) | ECM-IDLE (also called EMM-IDLE) and ECM-CONNECTED (EMM-CONNECTED) | Whether a NAS signalling connection exists. Idle = pageable, no SRB; connected = NAS can be sent immediately. |
| 5GMM (5G NAS) | 5GMM-DEREGISTERED, 5GMM-REGISTERED-INITIATED, 5GMM-REGISTERED, plus SERVICE-REQUEST-INITIATED | Same idea as EMM, toward the AMF. 5G also has a connected-with-RRC_INACTIVE flavour: NAS context kept, radio released. |
| CM / MM (CS domain) | MM-IDLE vs MM-CONNECTED; Call Control states Null → Call initiated → MO proceeding → Call delivered → Active | CS mobility and the 24.008 call-control state machine used on 2G/3G (and after CSFB). |
| RRC (radio) | RRC_IDLE, RRC_CONNECTED, and on NR RRC_INACTIVE | The access-stratum view. ECM-IDLE almost always means RRC_IDLE; ECM-CONNECTED means RRC_CONNECTED. |
Paging and Service Request (idle to connected)
Downlink data, an incoming IMS INVITE, or an MT CS/CSFB call all start the same way if the UE is idle: the network pages, the UE brings up RRC, then it sends a NAS Service Request so the core can restore the user plane.
UE (ECM-IDLE / RRC_IDLE) eNB MME / S-GW | listens at DRX paging occasions | | |<----------- Paging (S-TMSI) ------------| (from MME paging) | |-- RRCConnectionRequest (mt-Access) ---->| | |<-- RRCConnectionSetup ------------------| | |-- RRCConnectionSetupComplete [NAS: Service Request] ---------------->| |<-- Security / RRC reconfiguration [user-plane bearers restored] -----| | ECM-CONNECTED, RRC_CONNECTED; downlink data or INVITE / CS SETUP | MO data or signalling while idle uses the same Service Request, with establishment cause mo-Data or mo-Signalling instead of mt-Access. CSFB uses EXTENDED SERVICE REQUEST rather than a plain Service Request. T3417 supervises the Service Request (typical 3GPP default 5 s).
On Android you see this as a networkStateChanged plus a brief radio-connected period, then (for MT IMS) notifyIncomingCall, or (for MT CS) callStateChanged. If paging never arrives, the callee never rings even though the device looks in service.
Tracking Area Update
- Normal / TA-change TAU: the UE camps on a cell whose TAI is not in the last TAI list from Attach/TAU Accept.
- Periodic TAU: T3412 expires (typical default 54 minutes). If the UE never updates, the MME implicitly detaches it (EMM #10).
- Other common triggers: load balancing, recovery after a failed Service Request, and some capability or bearer changes.
- Ladder: RRC setup (if idle) → NAS Tracking Area Update Request → (possible auth / security) → TAU Accept (new TAI list, maybe new GUTI) → TAU Complete. T3430 supervises the request (typical default 15 s).
- 5G equivalent: mobility or periodic Registration Update; T3512 is the periodic timer (typical default 54 minutes).
Access barring and UAC
The network can stop UEs from starting traffic even when RF looks fine. LTE uses AC barring / SSAC (separate flags for MMTEL voice and video) in system information. 5G uses Unified Access Control (UAC): each access attempt has an access category (for example emergency, MMTEL voice, MO data) and an access identity; the gNB broadcasts barring parameters per category. That is why the modem must be told when IMS traffic starts (IRadioIms.startImsTraffic): it applies the right category before it tries RRC. On Android, IRadioNetworkIndication.barringInfoChanged and getBarringInfo surface this to the framework; a "VoLTE registered but INVITE never leaves" bug is often barring, not SIP.
LTE AKA: MAC failure vs sync failure
The network sends RAND and AUTN. The USIM checks AUTN in two steps:
- MAC check first. If the message-authentication code is wrong, the UE sends AUTHENTICATION FAILURE with cause MAC failure. That usually means the wrong key (wrong SIM, cloned IMSI, or the HSS vector does not match this USIM). The network does not recover by retrying the same vector.
- Sequence-number check next. If the MAC is good but SQN is outside the acceptable window, the UE sends AUTHENTICATION FAILURE with cause synch failure and an AUTS token. The HSS resynchronises SQN and the network retries with a fresh vector. This is a recoverable desync, not a "bad SIM".
Do not treat every AKA failure as "illegal UE". MAC failure and sync failure are different next steps. After a successful RES match, NAS Security Mode Command activates the derived keys.
X2 handover (intra-LTE sketch)
UE Source eNB Target eNB MME / S-GW |-- meas config ---->| | | |-- A3 (neighbour better than serving) ----------------->| | | |-- X2 HANDOVER REQUEST ------------->| | | |<-- X2 HANDOVER REQUEST ACK ---------| (prepared RRC) | |<-- RRC Reconfiguration (handover command) --------------| | | sync + RACH to target, RRC Reconfiguration Complete ->| | | | |-- Path Switch ------>| | | SN status / data forward |<-- Path Switch Ack --| | |<-- UE context release --------------| | | still EMM-REGISTERED; RRC stays CONNECTED on the new cell |
X2 is eNB-to-eNB. If there is no X2, the same move goes over S1 through the MME (slower). NR uses Xn between gNBs, or N2 through the AMF. Interviewers want the idea: prepare on the target, command the UE, path-switch the user plane, then release the source. Conditional handover (CHO) pre-loads that command and lets the UE execute it when a condition is met.
startImsTraffic exists.IMS, 5G and call flows at a glance
Voice on modern networks is carried by IMS (IP Multimedia Subsystem): a SIP session with RTP media over a dedicated IP bearer. 5G adds a new core and radio. Both have their own detailed pages; this section gives the overview a RIL/modem engineer needs and shows where they touch the stack described here.
Old circuit-switched voice is like a private phone line wired between two houses for the duration of a call. IMS voice is like a video-call app that runs over a reserved, high-priority lane of the internet: the app (SIP) sets up the call and the voice travels as packets (RTP) in that priority lane (the QCI 1 / 5QI 1 bearer). 5G is a new motorway and a new traffic-control centre; if the new motorway has no voice lane yet, the call is diverted to the older LTE road (EPS fallback).
IMS in the Android stack
- A vendor or carrier
ImsServiceis bound byImsResolverper slot and providesMmTelFeature(voice, video, SMS over IMS) andRcsFeature. GsmCdmaPhonedelegates calls toImsPhone/ImsPhoneCallTrackerwhen IMS is registered; otherwise it uses the CS path throughGsmCdmaCallTrackerandIRadioVoice.- IMS needs the IMS PDN (brought up by
DataNetworkController) and a P-CSCF address (from PCO in thesetupDataCallresponse, or DHCP). - Registration: SIP
REGISTER→401 Unauthorizedwith an AKA challenge (computed by ISIM/USIM) → re-REGISTER →200 OK. - Bearers: QCI 5 for SIP signalling (default bearer on IMS APN), QCI 1 guaranteed-bit-rate bearer for voice, QCI 2 for video; 5G uses 5QI 5 and 5QI 1 QoS flows.
- Continuity: SRVCC moves an active VoLTE call to CS when LTE coverage ends; EPS fallback moves a call setup from 5G SA to LTE when VoNR is not available; Wi-Fi calling uses an ePDG tunnel and can hand over to and from cellular.
VoLTE MO call (condensed): UE ── INVITE (SDP offer) ──▶ P-CSCF ──▶ S-CSCF ──▶ ... ──▶ callee ◀── 100 Trying ◀── 183 Session Progress (SDP answer, preconditions) ; P-CSCF typically starts dedicated QCI 1 setup from the SDP answer (around 183, not strictly at PRACK) ── PRACK ──▶ ── UPDATE (preconditions met) ──▶ ; ◀── 200 OK ◀── 180 Ringing ; ◀── 200 OK (INVITE) ; ── ACK ──▶ ═══ RTP/RTCP voice on QCI 1 ═══ ; hang up: BYE / 200 OK
5G essentials that touch RIL and the framework
| 5G concept | Where you see it in Android |
|---|---|
| NSA (EN-DC): LTE anchor plus NR secondary cell group | Data registration shows LTE; currentPhysicalChannelConfigs and NR state drive TelephonyDisplayInfo to show a 5G icon |
| SA: NR with the 5G core | Registration RAT = NR; required for VoNR, slicing, RRC_INACTIVE |
| PDU sessions and QoS flows | setupDataCall with pduSessionId, QoS sessions in the response, URSP-based traffic routing |
| Network slicing (S-NSSAI) | SliceInfo in data profiles, getSlicingConfig, enterprise network capabilities |
| VoNR / EPS fallback | IRadioIms.triggerEpsFallback, IMS registration over NR, RAT change to LTE during call setup |
| Allowed network types | setAllowedNetworkTypesBitmap including NR; carrier config can disable SA or NSA |
Call flows through the stack
CS / IMS outgoing call through every process boundary:
Dialer ──Binder──▶ TelecomService / CallsManager [system_server]
──bind──▶ TelephonyConnectionService.onCreateOutgoingConnection [com.android.phone]
──▶ GsmCdmaPhone.dial() (domain selection: IMS or CS)
IMS: ImsPhone ─▶ ImsPhoneCallTracker ─▶ ImsService/MmTelFeature ─▶ SIP INVITE
CS : GsmCdmaCallTracker ─▶ RIL.dial ─▶ IRadioVoice.dial(serial) ─▶ rild
─▶ QMI VOICE dial (Qualcomm) / ATD or MIPC (MediaTek) ─▶ modem CC/MM signalling
state flows back: callStateChanged ─▶ getCurrentCalls ─▶ Connection ─▶ Telecom ─▶ InCallService UI
The data plane: APN, PDN, rmnet, routing and tethering
A "data call" has two halves that people often confuse. The control plane negotiates the bearer: which APN, which IP addresses, which QoS. The user plane is the highway the IP packets drive on afterwards; on modern SoCs it is hardware-accelerated and mostly bypasses the CPU.
Opening a data connection is like a city approving a new toll road: lots of paperwork once (control plane: RIL, QMI WDS, NAS PDN signalling), after which the road exists with a name (the rmnet_data1 interface) and an address. Traffic then flows without any more paperwork, and automatic toll gates (the IPA hardware) let cars through without a human cashier (the CPU) waking up for each one.
Step 1: control plane (set up the pipe)
App / ConnectivityService Telephony (phone process) Modem | NetworkRequest(INTERNET) ------> | | | | DataNetworkController picks | | | DataProfile (APN), checks data | | | enabled / roaming / DDS / throttling | | | RIL.setupDataCall -------------------> | QMI WDS start network | | | NAS: PDN / PDU activation | | <--------- SetupDataCallResult -------- | (cause, ifname, addrs, | | | dns, gw, mtu, pcscf) | | DataNetwork + TelephonyNetworkAgent; | | | netd: bring up rmnet_data1, add | | | addresses, per-network routing table | | <--- onAvailable(Network) ------- | | | (sockets bind to this Network) |
Step 2: user plane (the packet's journey)
App socket write() │ syscall Kernel TCP/UDP/IP stack │ routing: ip rule (fwmark carries netId / UID) ──▶ per-network table ──▶ dev rmnet_data1 │ netfilter / eBPF: per-UID firewall, data saver, accounting, tethering NAT rmnet_data1 (logical netdev, one per PDN) │ rmnet driver adds QMAP header (mux ID = which PDN), aggregates packets, flow control rmnet_ipa0 (on-chip) or rmnet_mhi0 (PCIe modem) MediaTek: ccmni1 over CCCI / DPMAIF │ IPA hardware: DMA through SMMU, header processing, filtering, NAT, aggregation Modem: PDCP (cipher, ROHC) ─▶ RLC ─▶ MAC (schedule, HARQ) ─▶ PHY │ RF over Uu eNB / gNB ─▶ S-GW/P-GW or UPF ─▶ internet (downlink is the exact reverse)
| Piece | Side | Role |
|---|---|---|
ConnectivityService / netd | AP framework / native | Network selection, default network, routes, per-UID rules, DNS |
DataNetworkController | AP telephony | Decides and manages PDN/PDU bring-up and teardown |
| RIL / Radio HAL | AP ↔ vendor | setupDataCall, SetupDataCallResult, dataCallListChanged |
rmnet / QMAP | AP kernel | Logical netdevs, multiplexing several PDNs onto one link, aggregation, flow control |
| IPA (Qualcomm) / DPMAIF (MediaTek) | SoC hardware | User-plane offload between AP memory and the modem |
| QMI WDS / MIPC data | Modem control | Start/stop network, packet data status |
| PDCP … PHY | Modem firmware | 3GPP user-plane processing |
IP routing on Android
- Each
Networkgets its own routing table (named after the interface, for examplermnet_data1).ip ruleentries select the table using a fwmark that encodes the network ID, set on sockets bynetdbased on the app's default network or explicitNetwork.bindSocket(). - This is how IMS traffic uses the IMS PDN while apps use the internet PDN, and how an app can use cellular while Wi-Fi is the default.
- Useful commands:
ip addr,ip rule,ip route show table all,dumpsys connectivity.
IPv4, IPv6 and 464XLAT
- PDN types: IPv4, IPv6 or IPv4v6. The network may restrict (ESM #50 "IPv4 only allowed", #51 "IPv6 only allowed").
- IPv6 on cellular gets a /64 prefix via router advertisement after the PDN is up; the modem-provided interface identifier forms the address.
- On IPv6-only networks, Android runs clatd (464XLAT): a
v4-rmnet_data1interface translates app IPv4 traffic to IPv6, with NAT64 in the network.
Multiple PDNs and MTU
- Each APN (internet, IMS, MMS, DUN) is a separate PDN with its own interface, addresses and bearer.
- MTU comes from the network in the data call response (or PCO). A wrong MTU causes fragmentation or silent "black-hole" drops of large packets: pages half-load, TLS handshakes hang. A classic symptom is "small pings work, large downloads stall".
- Flow control: the modem signals the kernel to pause and resume uplink so the radio buffer is not overrun.
Tethering
- The Tethering module (a Mainline module) sets up the hotspot/USB/Bluetooth interface, DHCP, and NAT from the tethered clients to the upstream cellular network.
- Some carriers require a DUN APN for tethered traffic, so tethering may bring up a separate PDN; carrier config controls this and whether tethering is allowed at all (entitlement checks).
- Forwarding can be offloaded: Qualcomm IPA through the tethering offload HAL, or eBPF-based forwarding in the kernel on newer releases, so the CPU does not touch every packet.
Why hardware offload matters
Copying every packet through the CPU at hundreds of megabits per second would keep big cores awake and burn battery, and would cap throughput. With IPA-style offload, the AP sets up the path once and then can sleep while packets move by DMA; interrupts are coalesced and packets aggregated. This is a central power topic for phones and wearables (see Power, Thermal & Battery).
rmnet/QMAP and are DMA-offloaded by the IPA straight to the modem, so the CPU mostly sleeps."socket.write() to the air, explain why there is hardware offload, what QMAP multiplexing is, how Android routes per network (fwmark, per-network tables), what happens on IPv6-only networks, and how MTU problems show up. End-to-end tracing across many subsystems is covered in Trace a Path Through the Android Stack. The cellular packet path in depth is Android Data Call.System-design concepts in Android telephony
Telephony is a real-time, multi-actor, partly unreliable distributed system inside one device: several processes and processors, an external network that can refuse or delay you, and hardware that can crash and restart. The patterns it uses map directly onto generic system-design vocabulary, which lets you answer design questions with concrete, real examples.
A phone's telephony stack is like a small airline operations centre. Flights (requests) are tracked by number, gate changes are announced to everyone subscribed, each desk handles one thing at a time from its own queue, a supervisor restarts a desk that stops responding, and when the airport is congested the tower tells planes to hold for a set time before trying again. Every one of these practices has a direct counterpart in RIL serials, RegistrantLists, Handlers, death recipients and NAS back-off timers.
| Pattern | Where in telephony | General system-design equivalent |
|---|---|---|
| Layering + stable interfaces | App → framework → RIL → HAL → vendor; frozen AIDL versions | Decoupling and independent evolution; versioned API contracts |
| Async request/response with correlation IDs | RIL serials matched to IRadio*Response | Non-blocking RPC; request IDs in message systems |
| Publish/subscribe (observer) | RegistrantList, TelephonyRegistry, TelephonyCallback | Event bus; decouples producers from many consumers |
| Single-threaded event loop | Handler/Looper per component | Actor model; serializes state changes without locks |
| Explicit state machines | StateMachine base class; DataNetwork, call trackers | Deterministic handling of complex transitions |
| Failure detection + recovery | HAL death recipients, request flush, persistent-process respawn, modem SSR | Health checks, supervisors, circuit breakers |
| Back-off / throttling | NAS timers T3346/T3396/T3402, DataRetryManager | Congestion control; exponential back-off with jitter |
| Caching with invalidation | CarrierConfig, cached ServiceState, SIM records, subscription DB | Cache plus invalidation on SIM swap / config change |
| Rate limiting / coalescing | Signal reporting criteria, indication filters, SST poll coalescing | Debounce/coalesce to protect consumers from event storms |
| Resource arbitration | DDS, temporary data switch, DSDS RF sharing | Scheduling a scarce shared resource fairly and safely |
| Power-aware design | RIL wakelock with timeout, IPA offload, DRX, indication filtering on screen off | Batching, letting hardware sleep; energy as a first-class constraint |
| Layered configuration / feature flags | AOSP defaults → carrier config app → carrier service → overrides | Config hierarchy, staged rollout, kill switches |
Design prompt: multi-SIM data-switch arbiter
"Design the component that decides which SIM carries internet data on a dual-SIM phone."
- Inputs: user DDS choice, active call on the non-DDS SIM, foreground app needs, roaming/cost policy, signal quality and service state per subscription, carrier restrictions.
- State machine with hysteresis to avoid flapping; debounce switch triggers; minimum dwell time.
- Atomic switch: tear down the old PDN and bring up the new one without leaking a stale default network; make "set preferred data modem" idempotent.
- Failure handling: if the new subscription fails to get data within a timeout, roll back to the previous one (transactional switch).
- Observability: switch latency, failure rate, flap count, time on each SIM.
Design prompt: resilient RIL to modem channel
"Make the framework survive a flaky or crashing radio HAL."
- Death recipient on each HAL service; on death, fail all in-flight requests with
RADIO_NOT_AVAILABLEso no caller hangs. - Timeouts on every solicited request, plus a wakelock timeout, so a lost response can neither deadlock a state machine nor pin power.
- Idempotent re-initialization on HAL restart (re-send profiles, radio power, indication filters); bounded retry with back-off.
- Never crash the persistent process on a transient failure or on a telemetry path; catch, recover, log.
- Back-pressure: cap outstanding requests, coalesce duplicate polls.
Design prompt: carrier-config delivery
"Deliver per-carrier settings to millions of devices, overridable per SIM."
- Layered config: platform defaults → carrier bundle keyed by carrier ID → server-pushed override → runtime cache.
- Invalidation on SIM swap, roaming change, OTA; versioned so devices detect staleness.
- Safe rollout: staged percentage, kill switch, rollback; validate keys and types before applying.
Design prompt: telephony metrics and modem-log pipeline
"Collect call-drop and registration-failure KPIs (and modem logs) from a device fleet."
- On device: bounded ring buffer, local aggregation and sampling instead of shipping every event, privacy scrubbing (no IMSI, phone numbers or precise location).
- Upload in batches on Wi-Fi and charging; back-off on failure; triggered full modem-log capture only for targeted cohorts.
- Server: partition by build, region, carrier and chipset; compare against a baseline to tell a real regression from a handful of noisy devices.
Debugging playbook
Telephony bugs cross many layers and two processors, and the first obvious explanation is often wrong. The method below is evidence-first: establish the environment, check modem health, find protocol cause codes at the exact timestamp, then read framework evidence, and only then conclude with a stated confidence.
Debugging telephony is like investigating a road accident. First check the weather and road conditions (RF environment), then whether the car's engine failed (modem health), then read the black box's recorded error codes at the exact second (NAS/SIP causes), then interview the drivers (framework logs). A detective who blames the engine before checking the black box will often convict the wrong suspect, just as blaming the modem for a SIP 403 does.
The toolbox
| Tool / command | What it shows |
|---|---|
adb logcat -b radio | RILJ requests/responses, telephony framework, vendor RIL logs |
adb logcat -b main -b system -b crash | IMS service, Telecom, crashes in the phone process |
adb shell dumpsys activity service com.android.phone/.TelephonyDebugService | The big telephony dump: per-phone RIL state, SST, data networks, retry state, UICC, recent local logs |
adb shell dumpsys telephony.registry | Last notified service state, signal, call state, data state per subscription |
adb shell dumpsys isub | Subscriptions, DDS and default voice/SMS |
adb shell dumpsys carrier_config | Effective carrier config per subscription |
adb shell dumpsys connectivity, dumpsys netd | Networks, capabilities, default network, validation, routes |
adb shell ip addr, ip rule, ip route show table all | Interfaces (rmnet/ccmni), addresses, per-network routing |
adb shell cmd phone ... | Telephony shell commands (IMS, carrier config overrides, data, test modes; exact subcommands vary by release) |
adb shell svc data enable|disable | Toggle mobile data |
adb shell cmd connectivity airplane-mode enable|disable | Toggle airplane mode |
Dialer code *#*#4636#*#* | Testing menu: phone info, preferred network type, radio power, signal, ping |
adb bugreport | Everything above plus kernel log, ANR traces, tombstones, dumpsys of all services |
| QXDM / QCAT (Qualcomm) | Modem logs over DIAG: over-the-air RRC/NAS messages, F3 debug messages, events, packet logs |
| MTKLogger + ELT / Catcher (MediaTek) | Modem logs, over-the-air signalling, modem exception info |
Wireshark / tcpdump -i rmnet_data1 | IP traffic, SIP/RTP for IMS, DNS, TCP issues |
| Perfetto / battery stats | Wakelocks (*telephony-radio*), modem activity, power attribution |
Mandatory first check
- Chipset and log family MediaTek (
mipc,md1,ccci,Rfx) or Qualcomm (qcril,QMI,subsys/remoteproc,DIAG)? This decides which keywords and tools apply. - Environment Is the device in usable RF? RSRP/RSRQ/SINR, serving PLMN, roaming, SIM state, airplane-mode transitions, user actions around the event.
- Modem health Any reset near the event? Qualcomm SSR/ramdump, MediaTek
md1exception, RILserviceDied, radio stateUNAVAILABLE, phone-process restart.
Decision priorities (apply in order)
| # | Layer | What to extract |
|---|---|---|
| 1 | Chipset + environment + modem health | The first check; gate everything on it |
| 2 | Protocol cause codes | NAS EMM/ESM/5GMM/5GSM, RRC reject/release, SIP 4xx/5xx/6xx, RIL errors, DataFailCause, timestamp-aligned to the symptom |
| 3 | Framework stack evidence | ServiceStateTracker, DataNetworkController, ImsPhoneCallTracker, UiccController logs around the window |
| 4 | Modem / RF evidence | Serving cell, RSRP/RSRQ trend, PLMN, NAS timers (T3346/T3396/T3417), handover and reselection |
| 5 | ANR / tombstone / watchdog | Correlate process death or hangs with the radio event |
| 6 | Historical similarity | Prior cases are a hint, never proof; current logs win |
Hypothesis and evidence matrix
List every plausible hypothesis with evidence for and against before concluding. This prevents confirmation bias.
| Hypothesis | Supporting evidence | Contradicting evidence |
|---|---|---|
| Modem fault / SSR | md1 exception or SSR near the window, serviceDied, phone restart | No reset markers; modem answered requests normally throughout |
| Network reject | EMM/ESM/5GMM/SIP cause at the exact timestamp | Successful attach/registration at the same time |
| UE / framework bug | Clear exception or wrong state in phone, IMS or carrier app | No app exception; radio shows a network reject |
| SIM / provisioning | ABSENT, UICC reset, IMSI read failure, wrong carrier ID | Card LOADED, IMSI present, correct carrier config |
| RF / coverage | RSRP below about -115 dBm sustained, repeated searching, RLF | Strong RF yet the symptom persists |
Contradiction-detection rules
- SIP error + healthy modem → IMS/operator/provisioning layer, not the modem.
- NAS cause + modem reset → the reset may be a consequence of the reject handling (or unrelated); compare timestamps.
- Stack deadlock + no radio evidence → app-side ANR; route to ANR analysis.
- Strong RF + persistent failure → suspect IMS, provisioning or configuration, not coverage.
- One slot fails on dual-SIM → slot- or subscription-specific, not a platform-wide bug.
- Reproduces on only one build → code regression; diff against a known-good build.
Symptom-driven checklists
No service
Radio power on? SIM LOADED? Allowed network types sane? Registration state REG_DENIED with a reject cause? PLMN in forbidden list? Manual selection stuck on a missing network? Modem logs: cell search results, RRC failures, NAS rejects.
No data
Data enabled and DDS correct? PS domain registered? setupDataCall sent and what DataFailCause came back? Retry/throttle state (T3396)? Interface up with an IP? Routes and DNS? Network validation failing (captive portal, DNS, MTU)?
No SIM
simStatusChanged received? getIccCardStatus result (absent, error, restricted)? Card power (setSimCardPower)? UICC reset or CARD_IO_ERROR in modem logs? Hot-swap detection? Slot mapping on multi-SIM?
Call drop
Modem reset near the drop? SIP BYE with reason or ImsReasonInfo? RRC release or RLF? RSRP/RSRQ trend? SRVCC or EPS fallback attempted and failed? CS disconnect cause (for example 16 normal, 17 busy, 41 temporary failure)?
Useful log markers
| Marker | Meaning |
|---|---|
RILJ: [nnnn]> without [nnnn]< | Request never answered: vendor daemon or modem is stuck |
serviceDied, RADIO_NOT_AVAILABLE | HAL process died or radio unavailable |
subsystem restart / remoteproc crash / ramdump | Qualcomm modem SSR |
md1 exception, MD_EE, ccci reset | MediaTek modem exception |
SST: pollStateDone, REG_DENIED, reject cause | Registration outcome in the framework |
DataNetwork: ... setup failed cause=, DataRetryManager | Data call failure and retry decision |
ImsPhoneCallTracker: onCallTerminated reason= | IMS call end reason (maps SIP code) |
GsmCdmaCallTracker: onDisconnect cause= | CS call disconnect cause |
AT> / AT<, MipcVsClient | MediaTek modem command traffic |
QCRIL_*, QMI_* result/indication | Qualcomm modem command traffic |
Worked case study A: fatal RIL wakelock crash
Symptom: the persistent com.android.phone process dies repeatedly. The crash-reporting tool labelled it with a vendor IWLAN service package, because that package shares the phone process and happened to be last in the process's package list.
FATAL EXCEPTION: main Process: com.android.phone
java.lang.IllegalArgumentException: Wakelock.mLock is already dead.
at android.os.PowerManager$WakeLock.acquire(...)
at com.android.internal.telephony.RIL.acquireWakeLock(RIL.java)
at com.android.internal.telephony.RIL.obtainRequest(RIL.java)
at com.android.internal.telephony.RIL.getModemActivityInfo(RIL.java)
at <OEM modem-activity telemetry manager>.poll(...)
at com.android.phone.PhoneInterfaceManager$MainThreadHandler.handleMessage(...)
Caused by: android.os.RemoteException
at com.android.server.power.PowerManagerService$WakeLock.linkToDeath(...)
| Step | Finding |
|---|---|
| Real owner | The shared com.android.phone process, not the IWLAN package the label named. |
| Root cause | A periodic modem-activity poll calls RIL.acquireWakeLock(); the wakelock's internal binder token is already dead, so PowerManagerService rejects the acquire and the exception is thrown on the main thread, killing the persistent process. |
| Ruled out | Modem SSR: the modem answered the previous activity-info request seconds earlier, and there were no SSR or md1 markers. |
| Fix | In RIL, catch the dead-token failure, recreate the wakelock (new binder token), reset mWakeLockCount and retry once; also guard the telemetry poll so telemetry can never crash the persistent process. |
| Lesson | The crash label was misleading. Reading the stack (owner = phone process, path = RIL wakelock) and checking modem health produced the correct root cause and a minimal, safe fix. |
Worked case study B: "no radio" that is not a modem fault
Symptom: thousands of serviceProxy == null lines from an IMS radio adapter and "modem disabled" messages; it looks as if the modem is down.
| Step | Finding |
|---|---|
| Real cause | Broken lazy AIDL HAL start-up: init: Could not find '...IRadioExData/slot1' for ctl.interface_start. The VINTF manifest declares a vendor radio extension HAL but init has no service for it, so the proxy never binds. |
| Symptom vs cause | The repeated null-proxy logs are a symptom; "modem disabled" is the IMS adapter giving up on the null proxy, not a baseband crash. |
| Ruled out | Modem reset: no md1 exception, no SSR, no serviceDied; the other HAL services were present and working. |
| Scale lesson | A large fleet on the same build but only a handful of reports means a narrow trigger or sub-build difference, not a deterministic fleet-wide bug. Do not over-generalize from a few logs. |
logcat -b radio for RIL, QXDM/ELT for over-the-air, Wireshark for SIP, dumpsys for final state).Cause-code cheat sheets
Cause codes are the single most valuable debugging evidence: they say who refused what and why. NAS codes come from the core network (3GPP TS 24.301 for LTE, TS 24.501 for 5G), SIP codes from the IMS network (RFC 3261), RIL errors from the vendor HAL, and call-control causes from CS signalling (TS 24.008). Android surfaces data causes as DataFailCause constants whose values usually equal the 3GPP numbers.
Cause codes are like the reason codes on a rejected bank transaction: "insufficient funds", "card expired" and "suspected fraud" each send you to a different fix. A reject number from the network tells you whether to look at the subscription, the APN, the roaming agreement or congestion, just as a decline code tells a cashier whether to try another card or call the bank.
NAS EMM (LTE mobility) reject causes
| # | Meaning | Typical interpretation |
|---|---|---|
| 3 | Illegal UE | Authentication failed / SIM not accepted; USIM treated as invalid until power cycle |
| 6 | Illegal ME | Device (IMEI) blocked, for example blacklisted |
| 7 | EPS services not allowed | Subscription has no LTE service |
| 8 | EPS and non-EPS services not allowed | No service at all for this subscription |
| 9 | UE identity cannot be derived by the network | Network lost the UE context; UE re-attaches with IMSI |
| 10 | Implicitly detached | Network detached the UE (for example missed periodic TAU) |
| 11 | PLMN not allowed | No agreement with this network; PLMN added to EF_FPLMN |
| 12 | Tracking area not allowed | TA stored on the forbidden-TA list for regional provision of service; same PLMN still usable in other TAs |
| 13 | Roaming not allowed in this tracking area | TA stored on the forbidden-TA list for roaming; not added to EF_FPLMN |
| 14 | EPS services not allowed in this PLMN | LTE not allowed on this network (2G/3G may be); added to the "forbidden PLMNs for GPRS service" list, not EF_FPLMN |
| 15 | No suitable cells in tracking area | TA stored on the forbidden-TA list for regional provision of service; try another TA of the same PLMN |
| 18 | CS domain not available | Combined attach: no CS; device must rely on IMS for voice |
| 22 | Congestion | Usually with T3346 back-off |
| 25 | Not authorized for this CSG | Closed subscriber group (femtocell) restriction |
| 40 | No EPS bearer context activated | Network has no default bearer for the UE; re-attach |
NAS ESM (LTE session / PDN) causes
| # | Meaning | Typical interpretation |
|---|---|---|
| 8 | Operator determined barring | Subscriber barred from this service by the operator |
| 26 | Insufficient resources | Network overload; often comes with T3396 back-off |
| 27 | Missing or unknown APN | Wrong APN name in the profile; fix APN configuration |
| 28 | Unknown PDN type | Requested IP type not recognized |
| 29 | User authentication failed | APN username/password (PAP/CHAP) rejected |
| 30 | Request rejected by serving/PDN gateway | Gateway refused the connection |
| 31 | Request rejected, unspecified | Generic; needs network-side logs |
| 32 | Service option not supported | Network does not support the request |
| 33 | Requested service option not subscribed | Subscription lacks this APN (for example tethering APN) |
| 36 | Regular deactivation | Normal teardown |
| 38 | Network failure | Core-network problem |
| 50 | PDN type IPv4 only allowed | Retry as IPv4 |
| 51 | PDN type IPv6 only allowed | Retry as IPv6 (464XLAT for IPv4 apps) |
| 54 | PDN connection does not exist | State mismatch between UE and network |
| 55 | Multiple PDN connections for a given APN not allowed | Duplicate connection to the same APN |
| 65 | Maximum number of EPS bearers reached | Too many bearers |
5GSM mirrors many of these (for example #27 missing or unknown DNN, #26 insufficient resources, #33 not subscribed).
5GMM (5G mobility) reject causes
| # | Meaning |
|---|---|
| 3 | Illegal UE |
| 6 | Illegal ME |
| 7 | 5GS services not allowed |
| 11 | PLMN not allowed |
| 12 | Tracking area not allowed |
| 13 | Roaming not allowed in this tracking area |
| 15 | No suitable cells in tracking area |
| 22 | Congestion |
| 27 | N1 mode not allowed (5G NAS not allowed; use LTE) |
| 62 | No network slices available |
| 111 | Protocol error, unspecified |
SIP response codes (IMS)
| Code | Meaning / typical cause |
|---|---|
| 100 / 180 / 183 | Trying / Ringing / Session Progress (provisional, normal) |
| 401 / 407 | Unauthorized / proxy auth required: AKA challenge (a normal registration step) |
| 403 | Forbidden: provisioning, subscription or registration not allowed |
| 404 | Not found: bad URI or number |
| 408 | Request timeout: no answer from the network |
| 480 | Temporarily unavailable (callee not registered or not reachable) |
| 486 | Busy here |
| 487 | Request terminated (caller cancelled) |
| 488 | Not acceptable here: codec/SDP mismatch |
| 500 | Server internal error |
| 503 | Service unavailable: congestion or overload (may include Retry-After) |
| 504 | Server timeout |
| 603 | Decline |
RIL errors and NAS timers
| Token | Meaning |
|---|---|
NONE | Success |
RADIO_NOT_AVAILABLE | HAL/modem down or restarting; request cannot be served |
REQUEST_NOT_SUPPORTED | HAL version or vendor does not implement the method |
GENERIC_FAILURE | Catch-all modem failure |
INVALID_ARGUMENTS | Bad parameters from the framework |
INVALID_STATE | Request not valid in the current modem state |
SIM_ABSENT, SIM_PIN2, SIM_PUK2, PASSWORD_INCORRECT | SIM-related failures |
MODEM_ERR, INTERNAL_ERR, SYSTEM_ERR, NO_MEMORY | Modem or vendor-daemon internal problems |
OEM_ERROR_* | Vendor-specific |
T3346 | NAS mobility back-off (congestion) before retrying attach/registration; value assigned by the network |
T3396 | Per-APN back-off after an ESM reject; value assigned by the network |
T3402 | Long back-off after five failed attach/TAU attempts (typical 3GPP default 12 minutes) |
T3410 | Attach supervision: wait for Attach Accept (typical 3GPP default 15 s) |
T3411 | Short retry after a failed attach/TAU (typical 3GPP default 10 s) |
T3412 | Periodic TAU (typical 3GPP default 54 min if the network does not assign another value) |
T3417 | Service Request supervision (typical 3GPP default 5 s) |
T3430 | TAU supervision: wait for TAU Accept (typical 3GPP default 15 s) |
T3512 | Periodic 5G registration update (typical 3GPP default 54 min if the network does not assign another value) |
CS call-control disconnect causes (TS 24.008)
| # | Meaning |
|---|---|
| 1 | Unassigned (unallocated) number |
| 16 | Normal call clearing |
| 17 | User busy |
| 18 | No user responding |
| 19 | No answer from user (alerted) |
| 21 | Call rejected |
| 31 | Normal, unspecified |
| 34 | No circuit/channel available |
| 38 | Network out of order |
| 41 | Temporary failure |
| 47 | Resources unavailable, unspecified |
| 68 | ACM equal to or greater than ACMmax (credit limit) |
Quick revision
- Stack: apps → Telecom (
system_server) + Telephony (com.android.phone) →RIL.java→ Radio HAL → vendor daemon → modem → Uu air interface. - Telecom routes calls with
PhoneAccount/ConnectionService/InCallService; Telephony owns the radio and plugs in asTelephonyConnectionService. PhoneFactorycreates oneRILand oneGsmCdmaPhoneper slot;ImsPhonehandles IMS calls when registered.ServiceStateTrackerreacts tonetworkStateChangedby polling operator, voice reg, data reg and selection mode, then notifies viaTelephonyRegistry.DataNetworkController(Android 13+) replacedDcTracker/DataConnection/ApnContext;DataNetwork= one connection,DataProfile= APN.SubscriptionManagerService(Android 14+) replacedSubscriptionControllerand owns DDS and default voice/SMS subscriptions.- UICC tree:
UiccController→UiccSlot→UiccCard/UiccPort→UiccProfile→ applications (USIM, ISIM) → records. CarrierConfigLoadermerges platform defaults, carrier-config app values by carrier ID and carrier-app overrides; broadcastsACTION_CARRIER_CONFIG_CHANGED.- Solicited = request with serial + response callback + wakelock; unsolicited = indication fanned out through
RegistrantList. - RILJ log:
[serial]>request,[serial]<response,[UNSL]<indication; a missing response means the problem is below RIL. - RIL holds the
*telephony-radio*partial wakelock with its own count and a timeout; an ack wakelock covers the acknowledgement protocol. - On HAL death, RIL fails every pending request with
RADIO_NOT_AVAILABLE, resets proxies and reconnects when the service returns. serviceDied(vendor process died) is not the same as modem SSR /md1exception (baseband crashed); timestamps decide cause and effect.- Radio HAL: HIDL
radio@1.0–1.6monolithicIRadio→ stable AIDL (Android 13) split into Network, Data, Voice, Sim, Modem, Messaging, Ims, Config. - Each HAL domain has request, Response and Indication interfaces;
setResponseFunctionshands callback binders to the vendor. - HAL discovery: VINTF declaration →
initstarts daemon → registers withservicemanager→ RILwaitForDeclaredService; declared-but-not-started gives a permanent null proxy. - Qualcomm:
qcrild→ QMI (NAS, WDS, VOICE, UIM, WMS, DMS, IMSA...) over QRTR on GLINK/SMEM or MHI/PCIe. - MediaTek: rild (Rfx/Rmm) → MIPC/AT over CCCI; data on
ccmni; crashes aremd1exceptions. - AT commands (TS 27.007/27.005):
+CFUN,+COPS,+CEREG,+CGDCONT,+CGACT,ATD. - NAS (EMM/ESM, 5GMM/5GSM) talks to the core; RRC, PDCP, RLC, MAC, PHY talk to the base station; SDAP maps QoS flows in 5G.
- PDCP = ciphering, integrity, ROHC; RLC = segmentation + ARQ; MAC = scheduling + HARQ; PHY = coding, modulation, MIMO.
- RRC states: IDLE, CONNECTED, and INACTIVE on NR; RLF triggers include T310 expiry, max RLC retransmissions, random-access failure.
- LTE attach creates a default bearer (always-on IP); 5G registration and PDU session establishment are separate steps.
- Authentication is AKA using the SIM's secret key; 5G hides the IMSI as SUCI.
- Control plane sets up the PDN/PDU and returns ifname, IP, DNS, MTU, P-CSCF; user plane uses
rmnet_data*+ QMAP + IPA offload so the CPU can sleep. - Android routes per network with fwmark and per-network routing tables; IPv6-only networks use clatd (464XLAT).
- The IMS PDN stays up with mobile data off; QCI 5 carries SIP, QCI 1 carries voice (QCI 1 is typically started from the SDP answer around 183, not strictly at PRACK).
- DSDS shares one RF chain; DSDA runs both SIMs concurrently;
PhoneSwitcher+setPreferredDataModemimplement data switching. - eSIM: eUICC (EID) + ISD-R + LPA (
EuiccService) + SM-DP+; Android 13+ supports multiple enabled profiles. - Debug order: chipset/log family → RF environment → modem health → cause codes at timestamp → framework evidence → hypothesis matrix.
- Key causes: EMM #11 PLMN not allowed (adds EF_FPLMN), EMM #13/#15 forbid a tracking area (not the whole PLMN), ESM #27 unknown APN, ESM #33 not subscribed, SIP 403 forbidden, SIP 488 codec mismatch.
- EMM-REGISTERED is not the same as ECM-CONNECTED: a camped LTE phone is usually registered and idle until paging or a Service Request (T3417).
- Typical 3GPP NAS timer defaults: T3410/T3430 15 s, T3411 10 s, T3412/T3512 54 min, T3417 5 s, T3402 12 min (network can override).
- AKA MAC failure means the AUTN is not for this USIM; sync failure (AUTS) is an SQN desync the HSS can recover.
- X2 handover: source prepares target, UE gets RRC handover command, target path-switches through the MME, source releases.
- Carrier privileges come from the UICC access-rule applet, checked by
hasCarrierPrivileges(); they are not ordinary app permissions. - Voice can be OOS while data is in service on LTE-only without IMS; read both
ServiceStatedomains plus IMS registration. - Back-off timers T3346 (mobility congestion), T3396 (per APN) and T3402 (after repeated failures) must be honoured.
- Big telephony dump:
dumpsys activity service com.android.phone/.TelephonyDebugService; alsotelephony.registry,isub,carrier_config.
Glossary
- 5GMM / 5GSM
- 5G mobility management and session management; the NAS protocols for registration and PDU sessions.
- AKA
- Authentication and Key Agreement; challenge-response using the secret key in the USIM/ISIM, which also authenticates the network.
- AMF / SMF / UPF
- 5G core functions for mobility, session management and the user-plane gateway.
- AP
- Application processor: the CPU cluster running Android, as opposed to the modem.
- APN / DNN
- Access Point Name (LTE) / Data Network Name (5G): names the gateway and service for a data connection.
- ARQ / HARQ
- Automatic Repeat reQuest in RLC (reliable, slower) and Hybrid ARQ in MAC (fast, with soft combining).
- AT commands
- Text modem commands standardized in 3GPP TS 27.007 and 27.005.
- AUTS
- Resynchronisation token the USIM returns on AKA sync failure so the HSS can realign SQN.
- Carrier ID
- Android's canonical identifier for a carrier, resolved from SIM attributes by
CarrierResolver. - Carrier privileges
- UICC-granted rights for an app whose signing certificate is listed in the SIM access-rule applet; checked with
hasCarrierPrivileges(). - CarrierConfig
- Per-subscription bundle of carrier-specific settings exposed by
CarrierConfigManager. - CCCI
- Cross Core Communication Interface: MediaTek's kernel framework for AP to modem channels.
- ccmni
- MediaTek cellular network interfaces carrying user-plane IP traffic.
- CSFB
- Circuit-Switched Fallback: leaving LTE for 2G/3G to make a CS voice call.
- DataNetworkController
- Android 13+ framework class managing all data connections of one phone.
- DDS
- Default Data Subscription: the SIM that carries internet data on a multi-SIM phone.
- DSDS / DSDA
- Dual SIM Dual Standby (shared radio) / Dual SIM Dual Active (both SIMs active at once).
- ECM
- EPS Connection Management: ECM-IDLE (no NAS signalling connection) versus ECM-CONNECTED (NAS connection up). Distinct from EMM registration state.
- EMM / ESM
- EPS Mobility Management and EPS Session Management: the LTE NAS protocols.
- EN-DC
- E-UTRA NR Dual Connectivity: 5G NSA with an LTE anchor and NR secondary cell group.
- eUICC / EID
- Embedded UICC that stores downloadable profiles, and its unique identifier.
- GLINK / SMD / SMEM
- Qualcomm shared-memory transports and memory region used between processors.
- ICCID
- Integrated Circuit Card Identifier: the SIM card serial number.
- IMS
- IP Multimedia Subsystem: SIP-based core network for VoLTE, VoNR, Wi-Fi calling and RCS.
- IMSI / SUPI / SUCI
- Permanent subscriber identity (IMSI; SUPI in 5G) and its concealed 5G form (SUCI).
- IPA
- Qualcomm IP Accelerator: hardware that moves user-plane packets between AP memory and the modem.
- IRadio*
- Radio HAL interfaces (Network, Data, Voice, Sim, Modem, Messaging, Ims, Config) with Response and Indication partners.
- LPA
- Local Profile Assistant: on-device component that downloads and manages eSIM profiles.
- MHI
- Modem Host Interface: Qualcomm protocol for talking to a modem over PCIe.
- MIPC
- MediaTek's structured IPC protocol between the RIL daemon and the modem.
- MTU
- Maximum Transmission Unit: largest IP packet size on a link; provided by the network for cellular.
- NAS
- Non-Access Stratum: signalling between UE and core network, carried transparently by the radio.
- NITZ
- Network Identity and Time Zone: time, zone and network name sent by the network.
- NV / EFS
- Modem non-volatile items and embedded file system for calibration, IMEI and configuration.
- P-CSCF
- Proxy Call Session Control Function: the IMS entry point, learned via PCO or DHCP.
- PCO
- Protocol Configuration Options: extra parameters (DNS, P-CSCF, MTU) exchanged during PDN/PDU setup.
- PDCP
- Packet Data Convergence Protocol: ciphering, integrity, header compression, reordering.
- PDN connection / PDU session
- A data connection to an APN/DNN in LTE / 5G, with its own IP address and bearers or QoS flows.
- PLMN
- Public Land Mobile Network: an operator network identified by MCC + MNC.
- QCI / 5QI
- QoS class identifiers in LTE / 5G (1 = conversational voice, 5 = IMS signalling).
- QMAP
- Qualcomm multiplexing protocol that carries several PDNs over one data link with aggregation.
- QMI
- Qualcomm MSM Interface: service-based binary protocol between AP clients and modem services.
- QRTR
- Qualcomm IPC router: kernel socket family (
AF_QIPCRTR) that transports QMI messages. - QXDM / QCAT
- Qualcomm tools to capture and decode modem logs over the DIAG interface.
- RadioResponseInfo
- Header on every HAL response: type (solicited or solicited-ack), serial and error.
- RAT
- Radio Access Technology: GSM, UMTS, LTE, NR and so on.
- RIL / RILJ
- Radio Interface Layer; RILJ is the Java side (
RIL.java) in the framework. - rild
- The vendor RIL daemon implementing the Radio HAL (for example
qcrild). - RLC
- Radio Link Control: segmentation, reassembly and ARQ in TM, UM or AM mode.
- RLF
- Radio Link Failure: loss of the radio connection, followed by re-establishment or idle.
- rmnet
- Qualcomm cellular data network interfaces (
rmnet_data0..N), one per PDN. - RRC
- Radio Resource Control: sets up, reconfigures and releases the radio connection.
- RSRP / RSRQ / SINR
- Reference signal received power, quality, and signal-to-interference-plus-noise ratio.
- Service Request
- NAS procedure that takes an idle UE to connected so the core can restore the user plane after paging or for MO data.
- ServiceStateTracker
- Framework class that tracks registration, operator, RAT, roaming and signal.
- SM-DP+
- Subscription Manager Data Preparation: server that prepares and delivers eSIM profiles.
- SRVCC
- Single Radio Voice Call Continuity: hands an active VoLTE call over to CS.
- SSR
- Subsystem Restart: Qualcomm mechanism to crash-dump and restart the modem without rebooting the phone.
- TAU
- Tracking Area Update: NAS procedure when the UE enters a new TA or when periodic timer T3412 expires.
- TelephonyRegistry
- System service that publishes telephony state to registered
TelephonyCallbacks. - UAC
- Unified Access Control (5G): barring of access attempts by category and identity; LTE used AC barring / SSAC.
- UICC / USIM / ISIM
- The smart card and its 3GPP and IMS applications.
- VINTF
- Vendor Interface object: manifests and compatibility matrices that declare which HALs a device provides.
- X2 / Xn
- Direct interface between neighbour base stations used for intra-RAT handover (X2 on LTE, Xn on NR).
Interview questions
Fundamentals
Describe the Android telephony stack from app to antenna.
Apps use public managers such as TelephonyManager, SubscriptionManager and TelecomManager, which call over Binder into the framework. Telecom in system_server routes calls; the Telephony framework in the persistent com.android.phone process owns the radio (GsmCdmaPhone, ServiceStateTracker, DataNetworkController, UICC and subscription classes). The framework calls RIL.java, which sends asynchronous requests over the Radio HAL (IRadio*, stable AIDL since Android 13) to the vendor RIL daemon. The daemon talks to the modem over QMI (Qualcomm) or MIPC/AT over CCCI (MediaTek), and the modem runs the 3GPP stack over the air to the base station.
What is the difference between Telecom and Telephony?
Telecom is the call-routing and audio layer: it manages PhoneAccounts, Call objects, ConnectionServices and InCallServices, and it does not know anything about radios. Telephony owns the cellular modem: registration, SIM, data, SMS and cellular calls. Telephony plugs into Telecom as a ConnectionService (TelephonyConnectionService), just as a VoIP app can. Telecom runs in system_server; Telephony mostly runs in com.android.phone.
What is the RIL?
The Radio Interface Layer is the bridge between the Android telephony framework and the vendor radio software. On the framework side, RIL.java (RILJ) implements CommandsInterface, converts method calls into Radio HAL requests with serial numbers, matches responses, dispatches unsolicited indications to subscribers, holds a wakelock while requests are pending and handles HAL death. On the vendor side, the RIL daemon implements the HAL and talks to the modem.
What is the difference between RILJ and rild?
RILJ is the Java RIL inside the telephony framework (RIL.java in the phone process). rild is the native vendor daemon (for example qcrild on Qualcomm) that implements the Radio HAL server side and converts HAL calls into modem messages (QMI, MIPC or AT). They communicate over the Radio HAL Binder interface: RILJ is the client for requests and the server for responses and indications.
What are solicited and unsolicited RIL messages?
Solicited messages are framework-initiated requests, such as dial or setupDataCall. Each gets a unique serial, is tracked in RIL's request list, holds the RIL wakelock and completes when the vendor calls the matching IRadio*Response method. Unsolicited messages are modem-initiated events, such as network state change, signal strength, incoming call or new SMS, delivered on IRadio*Indication; RIL converts them and notifies all registrants. Solicited needs correlation and tracking; unsolicited is simple fan-out.
Why does every RIL request carry a serial number?
The HAL is asynchronous: a request returns immediately and the result arrives later on a separate callback, possibly after other requests have completed. The serial lets RIL find the pending RILRequest in its request list, deliver the result to the right caller's Message, release the wakelock reference and log the request/response pair. It is the same idea as a correlation ID in any asynchronous messaging system.
What is the Radio HAL and why does it exist?
The Radio HAL is the stable, versioned interface between AOSP's telephony framework and the chipset vendor's radio implementation. AOSP defines and calls it; vendors implement it. Because it is frozen and versioned (Project Treble), Google can update the framework without vendors rebuilding their radio stack, and vendors can change their modem internals without touching the framework. Since Android 13 it is stable AIDL; earlier it was HIDL.
Name the stable AIDL Radio HAL modules.
IRadioConfig (multi-SIM configuration, slot mapping, preferred data modem), IRadioModem (radio power, modem info, activity), IRadioNetwork (registration, signal, cell info, network selection), IRadioData (data calls, profiles, throttling), IRadioVoice (CS calls and supplementary services), IRadioSim (SIM status, file and APDU access, STK), IRadioMessaging (SMS and cell broadcast) and IRadioIms (IMS-related modem coordination, Android 14+). Each has a matching *Response and *Indication interface.
What is com.android.phone and why is it important?
It is the persistent telephony process built from packages/services/Telephony. It hosts PhoneInterfaceManager (the ITelephony Binder service), the Phone objects, RIL, the subscription and carrier-config services, and IMS glue. Because it is persistent, the system restarts it if it dies, but a crash drops calls, data and registration state for a few seconds, so it is effectively a single point of failure for telephony.
What does ServiceStateTracker do?
ServiceStateTracker tracks whether the phone is in service and on what network: voice and data registration state, operator name and MCC-MNC, radio technology, roaming, signal strength, NITZ time and radio power. It reacts to unsolicited network-state indications by polling the modem, builds a new ServiceState, applies carrier policies and notifies listeners through TelephonyRegistry. It is the first place to look in "no service" or "wrong network" bugs.
What is TelephonyRegistry?
It is a system service in system_server that acts as a publish/subscribe bus for telephony state. The phone process pushes state (service state, signal strength, call state, data connection state, display info) through DefaultPhoneNotifier, and apps receive it by registering a TelephonyCallback (the replacement for PhoneStateListener) via TelephonyManager.registerTelephonyCallback. It enforces permissions and location restrictions before delivering sensitive data.
What is an APN?
An Access Point Name tells the core network which gateway and service a data connection should use, such as internet, ims or mms. Each APN has a type (default, ims, mms, dun, supl, emergency...), protocol (IPv4, IPv6, IPv4v6), optional authentication and other attributes. On 5G the equivalent is the DNN. The device's APN list comes from the APN database filtered by carrier, and each entry becomes a DataProfile in the framework.
What is the difference between a PDN connection and a PDU session?
Both are data connections to a named network (APN/DNN) with an IP address. A PDN connection is the LTE/EPC term, made of a default EPS bearer plus optional dedicated bearers with QCI-based QoS, anchored at the P-GW. A PDU session is the 5G core term, with QoS flows identified by QFI inside the session, anchored at the UPF and managed by the SMF; it can also be tied to a network slice. From Android's point of view both are set up with setupDataCall.
What is the UICC, and what are USIM and ISIM?
The UICC is the smart card itself (physical or embedded). It hosts applications: the USIM holds the 3GPP subscription (IMSI, keys for AKA, network lists) and the ISIM holds IMS identities (IMPI, IMPU, home domain). Android models the card with UiccController, UiccCard, UiccProfile and UiccCardApplication, with SIMRecords and IsimUiccRecords holding the parsed files.
What is the difference between IMSI, ICCID and IMEI?
The IMSI identifies the subscriber (MCC + MNC + subscriber number) and lives on the SIM; it is used for registration and authentication. The ICCID is the serial number of the SIM card or eSIM profile, used by Android to identify subscriptions. The IMEI identifies the device hardware and is stored in the modem's protected memory; networks can block a device by IMEI (EMM #6 Illegal ME).
What is DDS?
DDS is the Default Data Subscription: on a multi-SIM phone, the subscription that carries internet data. It is stored by SubscriptionManagerService and applied by PhoneSwitcher, which tells the modem which logical modem is the preferred data modem (IRadioConfig.setPreferredDataModem) and activates that phone's network factory. Voice and SMS have their own defaults.
What is an eSIM and how is a profile installed?
An eSIM is an embedded UICC (eUICC) soldered onto the board that can store several operator profiles. The user scans an activation code; the on-device LPA (an app implementing EuiccService, driven through EuiccManager) contacts the operator's SM-DP+ server, performs mutual authentication, downloads the encrypted profile package and installs it into the eUICC via APDUs to the ISD-R. Enabling the profile triggers a card refresh; Android sees a new ICCID, creates a subscription and loads carrier config.
What is QMI?
QMI (Qualcomm MSM Interface) is Qualcomm's binary, TLV-encoded request/response/indication protocol between AP-side clients and modem services. Services include NAS (network access), WDS (data), VOICE, UIM (SIM), WMS (SMS), DMS (device management) and IMS services. It runs over the IPC router (QRTR) on shared memory transports or PCIe/MHI. qcrild translates Radio HAL calls into QMI messages.
What are AT commands and where are they still used?
AT commands are text commands for modems standardized by 3GPP TS 27.007 and 27.005, for example AT+CFUN (radio power), AT+COPS (operator selection), AT+CEREG? (LTE registration), AT+CGDCONT (define APN context) and ATD (dial). They are common on external USB/M.2 modems and IoT modules, in emulator reference RIL, and inside MediaTek stacks alongside MIPC. Qualcomm phones use QMI instead.
What are the main 3GPP protocol layers and what does each do?
NAS handles mobility and session management with the core network (attach/registration, authentication, PDN/PDU sessions). RRC controls the radio connection with the base station (setup, reconfiguration, measurements, handover, release). PDCP does ciphering, integrity and header compression; RLC does segmentation and ARQ; MAC does scheduling, multiplexing and HARQ; PHY does coding, modulation and MIMO. 5G adds SDAP to map QoS flows to radio bearers.
What are RRC_IDLE, RRC_CONNECTED and RRC_INACTIVE?
In RRC_IDLE the UE has no radio connection, performs cell reselection itself and listens for paging, using the least power. In RRC_CONNECTED it has dedicated radio resources and the network controls mobility with handovers. RRC_INACTIVE, introduced in NR, keeps the UE context stored in both UE and network while releasing radio resources, so the UE can resume quickly with less signalling and power than a fresh connection.
What is the difference between LTE Attach and 5G Registration?
LTE Attach registers the UE with the MME and always sets up a default EPS bearer, so the UE gets an IP address as part of attach. 5G Registration registers with the AMF and does not create a data connection; PDU sessions are established separately with the SMF. 5G registration also has explicit types (initial, mobility, periodic, emergency) and uses a concealed identity (SUCI) instead of sending the IMSI in clear.
What are rmnet and ccmni interfaces?
They are the Linux network interfaces that carry cellular user-plane IP traffic. On Qualcomm, rmnet_data0..N are logical interfaces (one per active PDN) multiplexed with QMAP over a physical link such as rmnet_ipa0 (on-chip, IPA hardware) or rmnet_mhi0 (PCIe modem). On MediaTek, ccmni0..N play the same role over CCCI and a hardware data mover. The interface name comes back in the setupDataCall response.
What is CarrierConfig used for?
CarrierConfigManager provides a per-subscription bundle of carrier-specific settings: whether VoLTE, VoWiFi or VoNR are available, IMS and emergency behaviour, roaming rules, signal thresholds, data retry rules, APN-related settings, UI options and more. CarrierConfigLoader merges platform defaults, values for the identified carrier from the carrier-config app, and overrides from a privileged carrier app. Components listen to ACTION_CARRIER_CONFIG_CHANGED and re-read values when the SIM or config changes.
Which basic tools do you use to debug telephony on Android?
adb logcat -b radiofor RIL and telephony logs.dumpsys telephony.registry,dumpsys isub,dumpsys carrier_configand theTelephonyDebugServicedump for state.dumpsys connectivity,ip addr,ip routefor data.- QXDM/QCAT (Qualcomm) or MTKLogger with ELT/Catcher (MediaTek) for modem over-the-air logs.
- Wireshark/tcpdump for SIP and IP traffic, and a full
bugreportfor everything together.
What is the difference between EMM-REGISTERED and ECM-IDLE?
EMM-REGISTERED means the MME has a context for the UE (it is "in service" at NAS). ECM-IDLE means there is no NAS signalling connection right now: the radio is in RRC_IDLE and the UE is only pageable. A normal camped LTE phone is EMM-REGISTERED and ECM-IDLE until it is paged or it sends a Service Request. 5G uses the same split (5GMM-REGISTERED vs 5GMM-IDLE). Do not say "registered" when you mean "RRC connected".
What rough RSRP, RSRQ and SINR ranges do you treat as good or bad?
These are field estimates, not 3GPP pass/fail limits, and carriers remap them to bars. For LTE RSRP, above about -80 dBm is excellent, -80 to -100 dBm is typically usable, and below about -110 dBm is cell-edge or poor. RSRQ above about -10 dB is strong and below about -20 dB is poor. SINR above about 20 dB is excellent and below 0 dB is poor. Always pair the number with a trend and with whether the symptom persists on strong RF.
Going deeper
Walk through the lifecycle of a solicited RIL request.
- A framework component calls a
CommandsInterfacemethod with a resultMessage. RIL.obtainRequest()takes a pooledRILRequest, assigns a serial, acquires the RIL wakelock reference and adds it tomRequestList.- RIL logs
[serial]> REQUESTand calls the HAL proxy method, which returns immediately. - Later the vendor calls the matching
*Responsemethod withRadioResponseInfo. processResponsefinds and removes the request by serial;processResponseDonesends the result or aCommandExceptionto the caller's handler, logs[serial]<, decrements the wakelock count and releases the request object.
How does an unsolicited network-state change reach apps?
The vendor calls IRadioNetworkIndication.networkStateChanged. RIL's NetworkIndication logs [UNSL]< and notifies the RegistrantList for network state. ServiceStateTracker receives the message and runs pollState(), sending getOperator, getVoiceRegistrationState, getDataRegistrationState and getNetworkSelectionMode. When all four responses arrive, it builds a new ServiceState, applies policy, and DefaultPhoneNotifier pushes it to TelephonyRegistry, which calls every registered ServiceStateListener and sends the service-state broadcast.
What replaced DcTracker, and why?
Android 13 introduced DataNetworkController with DataNetwork (one connection), DataProfileManager, DataRetryManager, DataSettingsManager and AccessNetworksManager. It replaced DcTracker, ApnContext and DataConnection, whose interacting state machines spread logic across many places and caused races during bring-up, teardown and handover. The new design is request-driven: every network request is evaluated against explicit rules with logged reasons, which is easier to reason about and debug.
What fields come back in a setupDataCall response and why do they matter?
SetupDataCallResult includes the cause (DataFailCause, 0 on success), suggested retry delay, connection ID, link status, PDN/PDU type, interface name (rmnet_data1, ccmni1), IP addresses, DNS servers, gateways, P-CSCF addresses, IPv4/IPv6 MTU, and optionally QoS sessions, traffic descriptors and slice info. The framework uses them to configure the netdev and routes, to feed P-CSCF addresses to IMS, to decide retries, and to set MTU. Wrong or missing values here explain many "connected but no traffic" bugs.
Why does RIL hold a wakelock, and what are the risks?
While a solicited request is outstanding, the AP must not suspend, or the response (and the caller's state machine) could be delayed indefinitely. RIL holds a partial wakelock tagged *telephony-radio*, counting references itself and releasing when the count returns to zero. Risks: if a response is lost, the wakelock would pin the CPU and drain the battery, so there is a timeout; if the count gets out of sync, the lock can leak or be released early; and exceptions in acquire/release on the main thread can crash the persistent phone process.
What is the acknowledgement mechanism in the Radio HAL?
Responses carry a type: SOLICITED, SOLICITED_ACK or SOLICITED_ACK_EXP. A SOLICITED_ACK means the vendor received the request and is still working, so RIL can release its long wakelock early. Indications can be UNSOLICITED or UNSOLICITED_ACK_EXP; for the latter RIL takes a short ack wakelock and calls responseAcknowledgement() so the vendor can release the wakelock it held while delivering the event. It lets each side keep the device awake only as long as needed.
What happens in RIL when the Radio HAL service dies?
RIL has registered a death recipient on each HAL service binder, so serviceDied() is called. It then completes every pending RILRequest with RADIO_NOT_AVAILABLE so callers do not hang, clears the request list, releases wakelocks and resets the proxies. The radio state becomes unavailable, so service state and data calls drop. When the vendor daemon restarts and re-registers, RIL reconnects, re-sends its response/indication callbacks, and the framework resynchronizes SIM status, radio power and data profiles.
What changed in the Radio HAL between HIDL and AIDL?
HIDL used android.hardware.radio@1.0 to @1.6, a single monolithic IRadio extended by inheritance for each minor version, over HwBinder and hwservicemanager. Stable AIDL (Android 13) splits the HAL into domain modules (Network, Data, Voice, Sim, Modem, Messaging, Ims, Config), each versioned independently, using regular Binder and servicemanager. The asynchronous request/response/indication model is unchanged. RIL.java supports both through per-domain RadioServiceProxy wrappers and per-service version checks.
How does the framework find and connect to the Radio HAL at boot?
The vendor VINTF manifest declares the HAL instances (for example android.hardware.radio.network.IRadioNetwork/slot1), and the framework compatibility matrix states which versions it accepts. init starts the vendor daemon (or starts it lazily on demand), and the daemon registers each service with servicemanager. RIL calls ServiceManager.waitForDeclaredService, wraps the binder in a proxy, links to death and calls setResponseFunctions to hand over its callback objects. The vendor then sends rilConnected and radio state updates.
Explain the UICC object model in the framework.
UiccController is a singleton that listens for SIM status indications and calls getIccCardStatus. It owns UiccSlots (physical or eUICC slots); each slot has a UiccCard (with UiccPorts on multi-profile eUICCs), which has a UiccProfile representing the active profile and its aggregated state. The profile contains UiccCardApplications (USIM, ISIM, CSIM), each with a records object (SIMRecords, IsimUiccRecords) that reads files through an IccFileHandler using iccIoForApp.
What happens between SIM insertion and first network registration?
- The modem detects the card and sends
simStatusChanged. UiccControllercallsgetIccCardStatusand builds the card tree.- PIN state is checked; if needed the user enters the PIN.
- Records load: ICCID, IMSI, EF_AD (MNC length), SPN, PLMN lists; state becomes
LOADED. - The subscription is created or updated, the carrier ID is resolved and carrier config is loaded.
- The framework sends allowed network types, initial attach APN and data profiles; the modem performs PLMN selection and attach/registration; SST reports in service.
What is the difference between slot index, phone ID and subscription ID?
Slot index is the physical or logical SIM slot. Phone ID is the index of the Phone object and logical modem, usually equal to the logical slot. Subscription ID is a database row in the subscription service for one SIM profile, keyed by ICCID; it stays the same for that SIM across reboots and slots and changes when a different SIM is used. APIs that take a subId must not assume it equals the slot, and code must handle INVALID_SUBSCRIPTION_ID when no SIM is present.
Explain DSDS vs DSDA and what happens to data during a call on the non-DDS SIM.
DSDS shares one RF chain between two SIMs: both are registered and pageable, but only one can be actively in a call or high-rate data at a time. DSDA has enough RF resources for both to be active simultaneously. On DSDS, a voice call on the non-DDS SIM would normally suspend data on the DDS; with temporary data switching, PhoneSwitcher moves data to the calling SIM (setPreferredDataModem) for the duration of the call and moves it back afterwards. On DSDA, data continues on the DDS during the call.
What is the IMS APN and how is it different from the internet APN?
The IMS APN is a separate PDN/PDU session used only for IMS signalling and media (VoLTE, VoNR, SMS over IMS, sometimes RCS). It is usually IPv6, carries SIP on a QCI 5 default bearer and voice on a QCI 1 dedicated bearer, and provides the P-CSCF addresses. It is never used for app internet traffic and stays up when the user turns mobile data off. The internet APN carries general app traffic and follows the user's data and roaming settings.
What is the difference between the control plane and the user plane for mobile data?
The control plane is signalling that sets up and manages the connection: RIL setupDataCall, QMI WDS or AT +CGACT, and NAS PDN/PDU procedures that return IP addresses, DNS, MTU and QoS. It happens once per connection and is low bandwidth. The user plane is the actual IP packets, flowing socket → kernel IP stack → rmnet/ccmni → hardware offload (IPA or DPMAIF) → modem PDCP/RLC/MAC/PHY → air. They use different paths so bulk traffic does not wait behind signalling and can bypass the CPU.
What does IPA do and why is it important?
IPA (IP Accelerator) is Qualcomm hardware that moves user-plane packets between AP memory and the modem by DMA, doing header processing, filtering, routing, NAT and aggregation without the CPU touching each packet. At high throughput this lets the AP stay in low-power states and avoids the CPU becoming the bottleneck. It also offloads tethering forwarding. It is a frequent integration and power-tuning point.
What is QMAP?
QMAP is Qualcomm's multiplexing and aggregation protocol on the data link between AP and modem. Each packet gets a small header with a mux ID identifying the logical channel, which maps to one rmnet_data interface and one PDN, so several PDNs share one physical link. QMAP also aggregates many packets into one transfer to reduce interrupts and supports flow-control commands and checksum offload.
How does Android route traffic when several networks are up (for example IMS PDN and internet PDN)?
Each network has its own routing table, and ip rule selects the table using a fwmark on each socket that encodes the network ID. netd sets the mark based on the app's default network or an explicit Network.bindSocket()/bindProcessToNetwork. The IMS stack binds to the IMS network, so SIP and RTP go over the IMS interface, while apps use the default network. Per-UID rules also enforce VPNs, data saver and background restrictions.
What does PDCP do, and how is ARQ different from HARQ?
PDCP provides ciphering, integrity protection (mandatory for signalling), ROHC header compression (critical for VoLTE efficiency), in-order delivery and duplicate detection, and routing for split bearers. HARQ in MAC is fast retransmission within milliseconds using soft combining of the failed and retransmitted copies; it fixes most errors. ARQ in RLC acknowledged mode is slower, status-report-driven retransmission that catches the residual errors HARQ misses. HARQ is fast and local; ARQ is the reliable backstop.
What is PLMN selection and what role do SIM files play?
PLMN selection is how the modem chooses which operator network to register on. In automatic mode it tries the last registered PLMN, then the home or equivalent home PLMNs, then the user-controlled and operator-controlled preferred lists from the SIM (EF_PLMNwAcT, EF_OPLMNwAcT), then other networks by signal quality, skipping forbidden PLMNs in EF_FPLMN. In manual mode the user picks from a scan. Wrong SIM files, such as a bad MNC length in EF_AD or a stale forbidden list, cause registration and roaming problems.
What are T3346, T3396 and T3402?
They are NAS back-off timers. T3346 is sent by a congested network with a mobility-management reject (often cause #22) and forbids new attach/registration or service requests until it expires. T3396 is a session-management back-off for a specific APN after an ESM reject such as #26 insufficient resources. T3402 is the longer wait (typical 3GPP default 12 minutes) after five failed attach or TAU attempts. Related supervision timers (typical 3GPP defaults) are T3410 15 s (attach), T3430 15 s (TAU), T3411 10 s (short retry), T3417 5 s (Service Request), and T3412 / T3512 54 min (periodic TAU / 5G registration). The modem and framework must honour them; ignoring them causes signalling storms and can get devices barred.
What is CSFB and when does it happen?
Circuit-Switched Fallback lets an LTE device without VoLTE make and receive voice calls. The device does a combined EPS/IMSI attach so the MSC can page it; for a call it is released or handed over from LTE to 2G/3G, places the CS call there, and returns to LTE afterwards. It adds call-setup delay and interrupts LTE data. With VoLTE widely deployed and 2G/3G shutting down, CSFB is disappearing, but it still appears in roaming and legacy scenarios.
How does a CS outgoing call flow through the stack?
Dialer → TelecomManager.placeCall() → CallsManager picks the SIM's PhoneAccount → Telecom binds TelephonyConnectionService → onCreateOutgoingConnection selects the Phone and domain → GsmCdmaPhone.dial() → GsmCdmaCallTracker → RIL.dial() → IRadioVoice.dial(serial) → vendor daemon → QMI VOICE dial or ATD/MIPC → modem CC/MM signalling. The modem reports progress with callStateChanged; the tracker polls getCurrentCalls and updates the Connection, which Telecom forwards to the InCallService UI.
Walk through a VoLTE call from tapping "call" to RF on air.
Dialer → Telecom selects the PhoneAccount → TelephonyConnectionService → GsmCdmaPhone.dial(), which sees IMS is registered and delegates to ImsPhone → ImsPhoneCallTracker → vendor ImsService/MmTelFeature. The IMS stack sends SIP INVITE with an SDP offer over the IMS PDN (QCI 5): 100 Trying, 183 Session Progress with SDP answer and preconditions. The P-CSCF typically starts the dedicated QCI 1 bearer from that SDP answer (around 183, not strictly at PRACK). PRACK acknowledges the 183, UPDATE signals preconditions met, then 180 Ringing, 200 OK, ACK. RTP voice then flows on the QCI 1 bearer. Underneath, the IMS PDN was set up through RIL and the modem, which runs PDCP (with ROHC), RLC, MAC and PHY over the air.
What is the difference between serviceDied and a modem SSR?
serviceDied means the vendor HAL process (the RIL daemon) died, detected by RIL's Binder death recipient. SSR (Subsystem Restart) on Qualcomm, or an md1 exception on MediaTek, means the modem firmware itself crashed and was restarted, usually with a ramdump. A modem crash often makes the daemon restart too, and a daemon bug can trigger a modem restart, so you check kernel logs for SSR/remoteproc or CCCI markers and compare timestamps to determine which came first.
What is the purpose of DeviceStateMonitor and indication filters?
Unsolicited indications such as signal strength, cell info and data-call updates wake the AP. DeviceStateMonitor tracks screen state, charging, tethering and low-data mode and tells the modem (setIndicationFilter, setSignalStrengthReportingCriteria, link capacity criteria) which indications to send and with what thresholds. With the screen off, only essential events are reported, reducing AP wake-ups. It is a key telephony power optimization.
How is the 5G icon decided in NSA mode?
In NSA the data registration RAT is LTE, because LTE is the anchor. The modem reports whether the LTE cell supports EN-DC and whether an NR secondary cell is connected (NR state and physical channel configs). NetworkTypeController combines this with carrier-config rules (for example show 5G when NR is available but not connected, or only when connected) and produces an override network type in TelephonyDisplayInfo, which the status bar shows as "5G" or "5G+". So the icon is a display decision, not the registration RAT.
What happens when an idle UE is paged for downlink data or an incoming call?
The UE is EMM-REGISTERED but ECM-IDLE / RRC_IDLE and only listens at DRX paging occasions. The MME pages; the UE sends RRC Connection Request (establishment cause mt-Access), then a NAS Service Request in SetupComplete. The network restores the user-plane bearers and the UE becomes ECM-CONNECTED. Downlink IP (including a SIP INVITE) or a CS SETUP can then be delivered. T3417 supervises the Service Request (typical default 5 s). MO data uses the same Service Request with a mobile-originated establishment cause. CSFB uses EXTENDED SERVICE REQUEST instead.
When does a Tracking Area Update happen?
When the UE camps on a cell whose TAI is not in the TAI list from the last Attach or TAU Accept, or when periodic timer T3412 expires (typical default 54 minutes). Other triggers include some recoveries after a failed Service Request and certain capability changes. The UE sends TAU Request (T3430 supervises it, typical default 15 s) and receives TAU Accept with a possibly new TAI list and GUTI. If periodic TAU is missed, the network implicitly detaches the UE (EMM #10). The 5G equivalent is a mobility or periodic Registration Update (T3512).
What is the difference between AKA MAC failure and sync failure?
The USIM checks AUTN in two steps. If the MAC is wrong, the UE returns AUTHENTICATION FAILURE with cause MAC failure: the vector is not for this USIM (wrong key, wrong SIM, or a mismatched HSS vector) and retrying the same vector will not help. If the MAC is good but SQN is outside the window, the UE returns synch failure plus an AUTS token; the HSS resynchronises SQN and the network retries with a fresh vector. Treat them as different bugs: one is identity/key, the other is recoverable sequence desync.
What is UAC / access barring, and why does the modem need IMS traffic awareness?
The network can bar new access attempts even when the cell is camped and RF is fine. LTE uses AC barring and SSAC (separate MMTEL voice/video flags) in system information. 5G uses Unified Access Control: each attempt has an access category (emergency, MMTEL voice, MO data, and so on) and an access identity. The modem must know that IMS voice is starting so it applies the voice category before RRC. That is why IRadioIms.startImsTraffic exists. Android also exposes barringInfoChanged. A registered IMS stack that never sends INVITE is often barred, not a SIP bug.
Advanced
Why is com.android.phone a single point of failure, and how would you harden it?
It hosts PhoneInterfaceManager, all Phone objects, RIL, subscription and carrier-config services and IMS glue, so an uncaught exception on its main looper kills the whole telephony stack; the system respawns it, but calls drop, data resets and shared-process components restart. Hardening:
- Never let telemetry or polling paths throw fatally; catch and recover.
- Defensive recovery in RIL (for example recreate a dead wakelock and retry once).
- Keep blocking work and periodic polling off the main thread.
- Add timeouts on every cross-process call so a stuck vendor cannot cause an ANR.
- Track crash rates per build and add tests for HAL death and restart paths.
Design a resilient RIL to modem channel that survives a flaky HAL.
- Death recipients on every HAL service; on death fail all in-flight requests with
RADIO_NOT_AVAILABLEso no state machine waits forever. - Per-request timeouts and a wakelock timeout, so a lost response cannot deadlock or drain the battery.
- Idempotent re-initialization after restart: re-send response functions, radio power, data profiles, indication filters, and re-read SIM status.
- Bounded retries with exponential back-off; avoid tight reconnect loops.
- Back-pressure: cap outstanding requests, coalesce duplicate polls.
- Observability: metrics for HAL deaths, request latency, timeouts, and the last N requests in a dump for post-mortems.
How does RIL.java support both HIDL and AIDL vendors at runtime?
RIL keeps one RadioServiceProxy per domain (network, data, voice, sim, modem, messaging, ims) plus a config proxy. Each proxy wraps either an AIDL binder or a HIDL IRadio handle, and RIL records the HAL version per service. Request methods check the version: if the method is newer than what the vendor supports, RIL completes the request immediately with REQUEST_NOT_SUPPORTED; otherwise it calls the proxy, which translates framework types to AIDL or HIDL structures (via RILUtils). Responses and indications come back through separate AIDL or HIDL callback classes that converge on the same framework handlers.
Explain Qualcomm's modem boot and where a modem SSR can come from.
At boot the AP kernel's remote-processor driver (historically PIL; now remoteproc with the Qualcomm Q6 drivers) loads modem firmware images from the modem partition into reserved memory; TrustZone authenticates them (on older designs the Modem Boot Authenticator, MBA, verified MPSS) and memory protections (xPU/SMMU) are set, then the Hexagon core is released. An SSR can be triggered by a modem fatal error (err_fatal / assert), a modem watchdog bite, a hung Q6 detected by the AP, or an explicit AP request. Recovery: notify clients (rmnet/IPA, QRTR, RIL daemon, IMS), optionally collect a ramdump, reload and restart firmware, then clients re-initialize and the framework re-registers.
Whiteboard a QMI flow end to end for a data call.
DataNetworkcallsRIL.setupDataCall→IRadioData.setupDataCall(serial, ...).qcrild's data module maps the profile to a modem profile and sends a QMI WDS "start network interface" request (TLVs: profile, APN, IP family, auth) over a QRTR socket.- The modem's WDS service returns an immediate response (accepted, with a packet data handle) and triggers NAS PDN/PDU signalling.
- When the network accepts, the modem sends a WDS "packet service status" indication (connected); the daemon queries runtime settings (IP, DNS, gateway, MTU, P-CSCF).
- The daemon maps the connection to a QMAP mux ID and an
rmnet_datainterface and callssetupDataCallResponse(info{serial}, result). - Later disconnects arrive as WDS status indications, surfaced as
dataCallListChanged.
What is the IRadioIms HAL for, given IMS runs in ImsService?
On many modern designs the IMS stack (SIP, media control) runs on the AP in a vendor ImsService, but the modem still needs IMS context for decisions only it can make. IRadioIms lets the framework tell the modem about IMS registration state (updateImsRegistrationInfo), when IMS traffic of a given type starts and stops (startImsTraffic/stopImsTraffic, used for access barring and connection setup priority), SRVCC call context (setSrvccCallInfo), and to request EPS fallback (triggerEpsFallback). The modem reports connection setup failures and bitrate recommendations (ANBR) back.
How do data retry and throttling work, and how do network timers interact with framework rules?
DataRetryManager applies carrier-config retry rules: per-cause lists of retry intervals, maximum attempts and whether a cause is permanent. The network can override with explicit back-off: the modem returns a suggested retry time (from T3396 or a 5GSM back-off) in the setup response, or indicates throttling per APN; the framework must not retry before it expires, and unthrottleApn indications release it early. Permanent causes (unknown APN, not subscribed) stop retries until conditions change. Handover retries between cellular and IWLAN follow separate rules.
How would you design a multi-SIM data-switch arbiter?
Inputs: user DDS, active call on the non-DDS SIM, per-subscription service state and signal quality, roaming and cost policy, carrier restrictions and user consent for automatic switching. Implement a state machine with hysteresis and minimum dwell time to avoid flapping, and debounce triggers. Make the switch transactional: request the new preferred data modem, bring up data there, validate connectivity, then tear down the old one; roll back on timeout or failure. Keep "set preferred data modem" idempotent. Expose metrics for switch latency, failure rate and flap count. This matches what PhoneSwitcher and automatic data switch do in AOSP.
How does MediaTek's CCCI architecture compare with Qualcomm's QMI/IPA architecture?
Both separate control and data. Qualcomm: control messages are QMI over QRTR (GLINK/SMEM on-chip or MHI on PCIe); data flows through rmnet with QMAP multiplexing and IPA hardware offload; crashes are SSR via remoteproc. MediaTek: the CCCI kernel driver provides character-device channels for MIPC/AT control, logging and modem file-system services (ccci_fsd), with ccci_mdinit managing modem boot; data flows through ccmni interfaces with a hardware data mover (CLDMA/DPMAIF); crashes are md1 exceptions reported through CCCI and AEE. The Android framework and RIL are identical above the HAL.
How does IPv6-only cellular work for IPv4 apps?
If the PDN is IPv6-only (by operator choice or ESM #51), Android starts clatd, the client side of 464XLAT. It creates a v4- interface (for example v4-rmnet_data1) with a private IPv4 address and a default IPv4 route; clatd translates outgoing IPv4 packets to IPv6 using the network's NAT64 prefix (discovered via DNS64 or RA/PREF64), and translates replies back. The operator's NAT64 translates to real IPv4 on the internet. Issues show up as IPv4-literal apps failing when NAT64 prefix discovery fails, or MTU problems because translation adds header overhead.
How can MTU problems appear on cellular and how do you fix them?
The MTU comes from the network in the setup response or PCO; if it is missing, wrong, or the path has lower MTU (tunnels, 464XLAT overhead), large packets are fragmented or silently dropped when ICMP "packet too big" is filtered. Symptoms: small pings and DNS work, but TLS handshakes stall, pages half-load, or uploads hang. Diagnose with ip link, pings with the don't-fragment flag and increasing size, and packet captures. Fix by honouring the network MTU, correcting carrier config or modem defaults, and relying on TCP MSS clamping where appropriate.
What is the role of PhoneSwitcher and TelephonyNetworkFactory?
Each Phone has a network factory that offers cellular networks to ConnectivityService. PhoneSwitcher decides which phone is currently allowed to serve internet requests, based on DDS, active calls, emergency, and automatic data switching. It tells the modem the preferred data modem and activates the matching factory, which forwards network requests to that phone's DataNetworkController. Requests that target a specific subscription (for example MMS on the non-DDS SIM) can be served by the other phone when capacity allows.
How do carrier config, the APN database and modem configuration interact, and what goes wrong?
The framework derives behaviour from carrier config (keyed by carrier ID) and APNs from the telephony provider; the modem has its own carrier configuration (Qualcomm MBN via PDC, MediaTek modem configs) selected from the SIM. The framework pushes the initial attach APN and data profiles to the modem. Problems arise when these disagree: VoLTE enabled in carrier config but disabled in the modem configuration, a wrong carrier ID selecting wrong APNs, or the modem attaching with a stale initial APN. Debug by dumping carrier config, APN list, carrier ID, and the modem's active configuration together.
How does IMS registration depend on the RIL and data framework?
IMS needs the IMS PDN first: DataNetworkController sets it up through setupDataCall, and the response carries P-CSCF addresses (from PCO), IP addresses and the interface. The ImsService binds to that network and sends SIP REGISTER; AKA authentication uses ISIM/USIM access via the SIM HAL. Carrier config enables VoLTE/VoNR and provisioning. Registration state is fed back to the modem via IRadioIms so it can apply barring and voice domain preference. A failure anywhere (no IMS PDN, empty P-CSCF list, SIM auth failure, config disabled) prevents registration.
How do you keep telephony power-efficient?
- Filter unsolicited indications and use signal/link-capacity reporting thresholds when the screen is off (
DeviceStateMonitor). - Hardware offload of the data path (IPA/DPMAIF) and packet aggregation to minimise AP wake-ups.
- Keep RIL wakelocks short with timeouts and the ack protocol.
- Modem-side DRX/eDRX, RRC_INACTIVE and fast dormancy to spend less time connected.
- Avoid periodic polling of modem info from the framework; batch telemetry.
- Measure with battery stats, modem activity info and Perfetto wakelock traces.
What happens when an IMS PDN goes down mid-call?
The QCI 1 dedicated bearer goes with it, so RTP media stops. The modem reports the loss via dataCallListChanged; DataNetworkController tears down the DataNetwork, and the ImsService loses its network and ends the call with a reason such as media or network lost, which ImsPhoneCallTracker maps to a disconnect cause. Recovery depends on the cause: re-establish the IMS PDN and re-register if allowed; if the loss is due to leaving LTE coverage, SRVCC should ideally have moved the call to CS before the PDN dropped.
Explain EPS fallback versus SRVCC.
EPS fallback applies on 5G SA when VoNR is not supported: when an IMS voice call is being set up, the gNB redirects or hands the UE over to LTE so the call proceeds as VoLTE; it happens at call setup and adds some setup delay. SRVCC (Single Radio Voice Call Continuity) moves an already active VoLTE call from LTE (packet-switched IMS) to 2G/3G circuit-switched when leaving LTE coverage, coordinated through the MSC. EPS fallback is NR to LTE at setup; SRVCC is LTE to CS mid-call.
Why might 5G NSA fail to add NR while LTE works fine?
Possible causes: the LTE cell does not advertise EN-DC support or the UE is not configured for it; the B1 measurement threshold is not met or NR measurements are not configured; the UE capability does not include the needed band combination; SCG addition fails at the gNB (bad PSCell configuration, X2 issue between eNB and gNB); repeated SCG failures lead the network to stop adding NR; carrier config or allowed network types disable NR; or thermal/power policy restricts NR. Debug with modem over-the-air logs: RRC reconfiguration with SCG, SCG failure information and its cause.
What is the lazy HAL trap and how would you prevent it?
AIDL HALs can be started on demand: when a client asks for a declared service, servicemanager asks init to start it with ctl.interface_start. If the VINTF manifest declares the service but no .rc service lists that interface, init logs "Could not find ... for ctl.interface_start", the client waits or gets null, and the framework may log null proxies forever, looking like a dead modem. Prevent it with build-time checks that every declared instance has a matching interface line in an init service, VTS tests, and boot-time health checks that alert on missing HAL instances.
How are unsolicited event storms handled?
Storms (for example rapid signal or cell-info changes in poor coverage) can flood the phone process and wake the AP. Mitigations: reporting thresholds and hysteresis configured in the modem, indication filters when the screen is off, rate limits for cell-info requests from apps, coalescing in SST so multiple network-state indications during a pending poll trigger just one more poll, and handler-level de-duplication. On the vendor side, the daemon can merge frequent modem indications before sending them over the HAL.
How would you design a telephony KPI and modem-log collection pipeline for a fleet?
On device: record events (drops, registration failures, setup failures with cause codes) in a bounded ring buffer, aggregate locally, scrub personal data (no IMSI, numbers or precise location), and upload in batches on Wi-Fi and charging with back-off. Allow targeted full modem-log capture only for opted-in cohorts, triggered by specific failures. Server side: partition by build, carrier, region and chipset; compare each build to a baseline with statistical thresholds to separate real regressions from noise; link spikes to top cause codes. Include versioning and kill switches for the collection config.
How does SMS flow from app to network, over CS and over IMS?
SmsManager.sendTextMessage → ISms in the phone process → SmsDispatchersController, which chooses IMS if SMS over IMS is registered and enabled, otherwise CS. IMS path: ImsSmsDispatcher → MmTelFeature → SIP MESSAGE carrying the SMS PDU. CS path: GsmSMSDispatcher → RIL.sendSms → IRadioMessaging.sendSms → modem (QMI WMS or AT+CMGS) → NAS/SGs or CS signalling. Incoming SMS arrive as newSms indications and must be acknowledged with acknowledgeLastIncomingGsmSms, otherwise the network retransmits.
Sketch an intra-LTE X2 handover.
The source eNB configures measurements; the UE reports A3 (neighbour better than serving). The source sends X2 HANDOVER REQUEST; the target admits the UE and returns HANDOVER REQUEST ACK with a prepared RRC container. The source sends RRC Reconfiguration (handover command) to the UE. The UE syncs to the target, does RACH, and sends Reconfiguration Complete. The target asks the MME to path-switch the S-GW user plane, SN status is forwarded, and the source releases the UE context. The UE stays EMM-REGISTERED the whole time. No X2 means the same move over S1 through the MME; NR uses Xn or N2.
What are carrier privileges on Android?
If an app's signing certificate is listed in the UICC access-rule applet (ARA-M / ARF) for that subscription, TelephonyManager.hasCarrierPrivileges() is true and the app can call carrier-only APIs: UICC logical channels, some APN and IMS provisioning, and other privileged telephony methods. It is not the same as a privileged system app and not the same as READ_PHONE_STATE. Debug a "carrier app works on the operator device only" report by dumping privilege state and the SIM access rules, not by chasing a framework permission.
Scenario & debugging
RIL.serviceDied fired in the log. What do you do, and is the modem dead?
Not necessarily. serviceDied means the vendor HAL process died. First check the kernel and vendor logs around the same timestamp for a modem crash: Qualcomm SSR/remoteproc crash and ramdump, or MediaTek md1 exception/CCCI reset. If the modem crashed first, the daemon restart is a consequence and the modem crash signature is the lead. If there is no modem crash, look for a tombstone or native crash of the vendor daemon, an init restart reason, or an ANR/watchdog kill. Then confirm recovery: did RIL reconnect, did the radio come back, and how long was the outage?
IMS registration fails with SIP 403. How do you debug it?
A 403 with a healthy modem points at the IMS, operator or provisioning layer, not RF. Check in order:
- Is the IMS PDN up with IP addresses?
- Were P-CSCF addresses received (PCO or DHCP)?
- Did AKA with ISIM/USIM succeed (the 401 step)?
- Are IMPI/IMPU correct (from ISIM or derived from IMSI)?
- Is VoLTE enabled and provisioned in carrier config and modem configuration for this carrier and region?
- Is the device clock correct?
Capture a SIP trace to read the exact response and any Reason or Warning header, and compare with a working device on the same SIM.
A user reports a silent call drop. What is your triage order?
Start with the first check: chipset/log family, RF environment, modem health. Then: (1) any modem reset or serviceDied near the drop? That is a strong lead; (2) protocol cause at the exact timestamp: SIP BYE with reason, ImsReasonInfo, RRC release or RLF, NAS cause, or CS disconnect cause; (3) RF trend: RSRP/RSRQ/SINR falling (coverage loss) versus strong signal (network or IMS side); (4) was SRVCC or a handover attempted and did it fail? (5) correlate modem, radio and IMS logs by timestamp; (6) list hypotheses with supporting and contradicting evidence and give a confidence level. Avoid blaming the modem when a SIP error with a healthy modem points at IMS.
The phone shows "No service" but other phones on the same network work. How do you investigate?
- Check radio power and airplane mode, SIM state (
LOADED?) and subscription. - Look at SST logs: registration state, especially
REG_DENIEDwith a reject cause. Also compare voice vs dataServiceState(they can disagree). - If denied, interpret the cause: EMM #11 (PLMN not allowed → check EF_FPLMN), #13/#15 (forbidden tracking area, not FPLMN; try other TAs), #7/#8 (subscription), #3/#6 (SIM or IMEI blocked).
- If searching, check allowed network types, band configuration and manual selection mode.
- Pull modem logs for cell search, RRC setup failures and NAS messages.
- Compare IMEI, SIM, build and modem configuration with a working device.
Mobile data shows connected but nothing loads. How do you debug it?
Split control plane from user plane. Confirm the data call is up (DataNetwork connected, interface with IP addresses in ip addr), the default network and validation result in dumpsys connectivity, and routes and DNS. Test: ping an IP address (routing and user plane), then resolve a hostname (DNS), then fetch a large page (MTU). If pings fail, check the modem data path (flow control, IPA or ccmni state, uplink grants in modem logs). If only large transfers fail, suspect MTU. If only DNS fails, check the DNS servers from the setup response. Also check for a captive portal, data saver, per-app restrictions or a VPN capturing traffic.
setupDataCall fails with cause 27. What does that mean and what do you do?
Cause 27 (MISSING_UNKNOWN_APN) is ESM/5GSM "missing or unknown APN/DNN": the network does not recognise the APN the device requested. Check which DataProfile was used, whether the APN list matches the carrier (correct carrier ID and MCC-MNC, correct MNC length from EF_AD), whether a user or carrier app edited the APN, and whether the initial attach APN pushed to the modem is correct. It is a permanent-type failure, so the device should stop retrying until the configuration changes. Fix the APN database or carrier ID mapping.
Data fails repeatedly with cause 26 and then stops retrying for a long time. Is this a bug?
Probably not. ESM #26 is "insufficient resources", often sent by a congested network together with the T3396 back-off timer. The modem passes the back-off to the framework as a suggested retry time, and the device must not retry that APN until it expires (unless the network sends an unthrottle indication or conditions change, such as moving to another PLMN). Verify the retry time in the setup response and DataRetryManager logs. It would be a bug only if the device ignored the timer or kept the throttle after it expired.
Dual SIM: data does not work on SIM 2 after a voice call on SIM 2 (non-DDS) ends. How do you debug it?
- Check DDS and preferred data modem before, during and after the call in
dumpsys isuband the telephony dump. - Check
PhoneSwitcherlogs: was a temporary switch made, and was it reverted correctly? - Check
setPreferredDataModemrequests and responses in the radio log. - Check the data network list per phone and whether internet was set up on the intended SIM.
- Verify initial attach APN and data profiles on the right subscription.
- If voice was IMS, check the IMS PDN state on both SIMs.
- Reproduce with modem logs to see whether the modem received and applied the switch.
Every RIL request returns RADIO_NOT_AVAILABLE after boot. What could be wrong?
The framework cannot talk to a working radio. Check: are the HAL services registered (service list, lshal on HIDL), or is there a lazy-HAL/VINTF mismatch ("Could not find ... for ctl.interface_start")? Did the vendor daemon crash-loop (tombstones, init restarts)? Did the modem fail to boot (firmware load or authentication failure in the kernel log, missing modem partition after an update, remoteproc or CCCI errors)? Is the radio state stuck at unavailable because the daemon never sent rilConnected? Compare with a known-good build to spot packaging changes.
The phone process crashes repeatedly with IllegalArgumentException: Wakelock.mLock is already dead in RIL.acquireWakeLock. How do you analyse and fix it?
First identify the real owner: the stack is in com.android.phone, even if the crash tool labels it with another package sharing that process. The path shows a periodic poll (for example modem activity info) calling RIL.obtainRequest → acquireWakeLock, and PowerManagerService rejecting it because the wakelock's binder token died. Rule out a modem crash by checking that the modem answered recent requests and there are no SSR or md1 markers. Fix: in RIL, catch the failure, recreate the wakelock with a fresh token, reset the count and retry once; guard the polling code; never let a telemetry path throw on the phone main thread.
Logs show thousands of serviceProxy == null and "modem disabled" messages. Is the modem down?
Probably not. Repeated null proxies usually mean a HAL service was never bound. Check the kernel/init log for "Could not find '...' for ctl.interface_start", which indicates the VINTF manifest declares a HAL instance that no init service provides (a lazy HAL packaging bug). Confirm the modem is healthy: no SSR, no md1 exception, no serviceDied, and other HAL services working. The "modem disabled" message is a component giving up on the null proxy, a symptom rather than the cause. Also check how many devices on the build report it: a handful out of many suggests a narrow trigger or sub-build difference.
VoLTE works at home but not while roaming. What do you check?
Check whether the home carrier's config allows VoLTE roaming and whether the roaming partner supports it (IMS roaming agreements, home-routed vs local breakout for the IMS APN). Check the IMS PDN setup while roaming: it may be rejected (ESM #33 or #27) or have no P-CSCF. Check IMS registration responses (403 while roaming). Check voice domain preference and whether the device falls back to CS or CSFB, and whether 2G/3G is still available in that country. Finally confirm the modem configuration is not restricting IMS on visited networks.
The SIM is detected intermittently ("No SIM" flickers). How do you debug?
Look for repeated simStatusChanged indications and card state transitions between present and absent or CARD_IO_ERROR. In modem logs check for UICC resets, voltage-class negotiation failures, or APDU timeouts. Check hardware: SIM tray contacts, detect pin configuration, card power (setSimCardPower), and whether a specific card or all cards are affected. Check whether it correlates with RF activity, temperature or a specific build. On eSIM, check profile enable/disable events and refreshes. Collect logs from several reproductions and compare with a different SIM and device.
After an OTA update, the device registers but IMS never comes up. How do you approach it?
Something changed in the build, so diff against the previous build. Check: carrier ID and carrier config values for VoLTE (did a config key change?), APN database entries for the IMS APN, the vendor ImsService binding (ImsResolver logs; is the package present and bound?), IMS PDN setup result and P-CSCF addresses, the modem configuration (MBN) selected, and IMS registration SIP responses. Also confirm the Radio HAL and IMS HAL versions match what the new framework expects. A regression on one build with the same SIM and network is almost always configuration or packaging.
The signal bars jump between full and zero every few seconds, but calls work. What is going on?
This is likely a reporting or display issue rather than real RF loss. Check the currentSignalStrength indications and values in the radio log: are invalid values (for example "unavailable" sentinels) being reported intermittently, or is the RAT flipping (LTE/NR) with different thresholds? Check the carrier-config signal thresholds and which measurement (RSRP, RSRQ, SS-RSRP) is used for bars. Check signal reporting criteria and hysteresis settings. If values look valid, check SST handling and the status-bar mapping. Compare with modem-side measurements to confirm the real RF is stable.
Battery drain is traced to *telephony-radio* wakelocks. How do you investigate?
Use battery stats and a Perfetto trace to see how long and how often the RIL wakelock is held, and correlate with the radio log. Look for: requests with no response that hold the lock until timeout (vendor or modem stuck); a high rate of requests from a polling component or app (cell info, signal, modem activity) that should be throttled or batched; indication storms because indication filters were not applied on screen off; or a wakelock count leak. The request's WorkSource identifies the app causing it. Fix the source: throttle polling, apply filters, fix the missing responses.
After a modem SSR, data does not recover until reboot. Where do you look?
Trace recovery layer by layer. Kernel: did the modem restart successfully, and did the data path (IPA, rmnet or MHI) re-initialize? RIL: did it see radio unavailable then available, and a modemReset indication? Framework: did DataNetworkController tear down stale data networks and bring up new ones, or is a stale DataNetwork or interface left behind? Retry state: is the APN throttled? Netd: are old routes or interfaces lingering? Often the bug is an SSR notifier client that did not re-register or a stale data call ID reused after restart.
Emergency calls fail on a device without a SIM. What do you check?
Without a SIM the device should camp in limited service on any available network. Check SST for STATE_EMERGENCY_ONLY or out-of-service, and whether cell search finds a suitable cell. Check emergency number detection (EmergencyNumberTracker: modem, database and default numbers like 112/911). Check the domain chosen: CS emergency on 2G/3G if available, or IMS emergency over LTE/NR, which needs an emergency PDN and IMS emergency registration without a subscription; the network must support unauthenticated emergency. Check emergencyDial responses and modem logs for rejects.
An eSIM profile download fails. How do you debug it?
Check the LPA (EuiccService) logs for the step that failed: activation code parsing, HTTPS connection to the SM-DP+ (network, certificates, time), mutual authentication, eligibility checks, or installation on the card. Check device time (certificate validation), connectivity, and whether the SM-DP+ reported an error code (for example profile already used or not released). Check APDU exchanges with the ISD-R via logical channels in the radio log for card-side errors, and eUICC free memory. Compare with another device to separate operator-side issues from device issues.
A new build shows a spike in call drops on one carrier in a few devices. How do you decide whether it is real?
Normalize first: compare the drop rate per call on the new build versus the previous build for the same carrier, region and chipset, with enough volume for statistical confidence. A handful of reports from a very large population may be noise or a narrow trigger. If the rate is significantly higher, break down by drop cause (SIP reason, RRC release, RLF, SRVCC failure), RAT and modem version to find the cluster, then pull full logs from affected devices and diff the builds (framework, IMS, modem configuration). Do not generalize from a few logs, and do not dismiss a consistent cluster.
You are handed a radio log where a request has [0512]> SETUP_DATA_CALL but no matching response. What does it tell you and what next?
The framework sent the request and the vendor never answered, so the problem is below RIL: the vendor daemon is stuck, a QMI/MIPC transaction was lost, or the modem did not respond. Check whether the RIL wakelock timeout fired, whether other requests were answered after it (daemon alive but this path stuck) or not (daemon hung), and whether a modem reset followed. Next collect vendor daemon logs around the serial, a stack dump of the daemon (debuggerd), and modem logs showing whether the WDS/data request reached the modem and whether PDN signalling started.
An app reports it cannot read the phone number from getLine1Number(). Is that a telephony bug?
Usually not. The number comes from EF_MSISDN on the SIM (or carrier-provided sources), which many operators leave empty. The API also requires specific permissions (READ_PHONE_NUMBERS or carrier privileges) and newer releases provide SubscriptionManager.getPhoneNumber with source selection (UICC, carrier, IMS). Check the permissions, the subscription targeted, and whether the SIM actually contains the number. If the number is present on the SIM but not returned, then investigate record loading in SIMRecords.
Voice shows out of service but mobile data works on LTE. What is going on?
Voice and data ServiceState are separate. On an LTE-only cell with no CS domain and no IMS/VoLTE, getState() can be STATE_OUT_OF_SERVICE while getDataRegistrationState() is STATE_IN_SERVICE. Combined-attach reject EMM #18 ("CS domain not available") is a typical cause. useImsForCall() is false if IMS is not registered, so a CS dial fails and the user sees "no voice" even though LTE data and the signal icon look fine. Check both domains, IMS registration, voice-domain preference, and whether the network advertised IMS voice over PS.