Telephony & Wireless

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.

~120 min read 0 interview questions
In 30 seconds
  • 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) or ccmni (MediaTek).
  • Key framework owners: ServiceStateTracker (registration), DataNetworkController (data calls, replaced DcTracker), SubscriptionManagerService and UiccController (SIMs), CarrierConfigManager (per-carrier behaviour).
  • Debug in order: chipset and log family → RF environment → modem health (SSR, md1 exception, 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.

Analogy

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
BoundaryMechanismExample
App → frameworkBinder (AIDL) via a manager classTelephonyManager → ITelephony → PhoneInterfaceManager
Framework → RIL JavaPlain Java calls, Message/Handler callbacksServiceStateTracker → mCi.getVoiceRegistrationState(msg)
RIL Java → HALBinder (stable AIDL) or HwBinder (HIDL); async request / response / indicationIRadioNetwork.getVoiceRegistrationState(serial)
HAL → vendor daemonSame process: the daemon is the HAL serverqcrild implements IRadioNetwork
Vendor daemon → modemQMI (Qualcomm), MIPC/AT over CCCI (MediaTek), AT (generic)QMI NAS "get serving system", AT+CEREG?
Modem → networkRF over Uu using 3GPP protocolsRRC, 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

PathWhat it contains
frameworks/base/telephonyPublic SDK: TelephonyManager, SubscriptionManager, ServiceState, SignalStrength, CarrierConfigManager, IMS APIs
frameworks/opt/telephonyInternal telephony: Phone, GsmCdmaPhone, RIL, ServiceStateTracker, DataNetworkController, UICC classes, SMS dispatchers
packages/services/TelephonyThe com.android.phone app: PhoneInterfaceManager, TelephonyConnectionService, CarrierConfigLoader
packages/services/TelecommTelecom: TelecomService, CallsManager, PhoneAccountRegistrar
hardware/interfaces/radio/aidlRadio HAL AIDL definitions (android.hardware.radio.*)
hardware/rilLegacy libril, rild and the emulator reference-ril
Interview angle "Draw the Android telephony stack" is often the opening question. A strong answer names one concrete class per layer, states the IPC at every boundary, and points out that everything from the Radio HAL down is vendor-specific while everything above it is AOSP. Bonus: mention that Telecom (calls) and Telephony (radio) are separate and live in different processes.

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.

Analogy

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) and Connection.
  • 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; exposes ITelephony, ISub, ISms to apps.
  • For calls it plugs into Telecom as a ConnectionService.
  • Path: TelecomManager.placeCall() → TelephonyConnectionService → Phone.dial().

Core classes

ClassResponsibility
PhoneFactoryAt boot, creates one RIL and one Phone per logical modem/SIM slot, plus shared singletons (UiccController, PhoneSwitcher, subscription service).
Phone (abstract) → GsmCdmaPhoneThe per-slot phone. Owns its trackers, handles dial/hang-up, USSD and supplementary services, and holds a CommandsInterface (the RIL).
ImsPhone, ImsPhoneCallTrackerA shadow phone for IMS calls. GsmCdmaPhone delegates VoLTE/VoNR/Wi-Fi calling to it when IMS is registered.
GsmCdmaCallTrackerCircuit-switched call state; polls getCurrentCalls after callStateChanged indications.
ServiceStateTracker (SST)Registration state, operator, RAT, roaming, signal strength, NITZ time, radio power.
DataNetworkControllerData connections (Android 13+); see the data section.
SubscriptionManagerServiceSource of truth for subscriptions and default voice/SMS/data subscription (Android 14+, was SubscriptionController).
UiccControllerSIM card tree and SIM state; see the SIM section.
DefaultPhoneNotifierPushes state from Phone objects into TelephonyRegistry.
TelephonyRegistryCentral publish/subscribe service in system_server; apps register TelephonyCallback (formerly PhoneStateListener).
CarrierConfigManager / CarrierConfigLoaderPer-carrier feature flags and values.
PhoneSwitcherDecides which logical modem serves data (the preferred data modem) and activates the right per-phone network factory; handles temporary data switching.
DeviceStateMonitorTells the modem about screen, charging and tethering state so it can filter indications and save power (setIndicationFilter, signal reporting criteria).
SmsDispatchersControllerRoutes SMS over IMS (ImsSmsDispatcher) or CS (GsmSMSDispatcher).
EmergencyNumberTrackerMerges emergency numbers from modem, SIM, database and carrier config.
NetworkTypeController / DisplayInfoControllerCompute 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.

  1. Indication The modem sends IRadioNetworkIndication.networkStateChanged (legacy: RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED).
  2. pollState() SST fires four requests in parallel: getOperator, getVoiceRegistrationState, getDataRegistrationState, getNetworkSelectionMode.
  3. Build a new ServiceState When all replies arrive, SST combines them into a new ServiceState with one NetworkRegistrationInfo per domain (CS/PS) and transport (WWAN/WLAN).
  4. Apply policy Roaming overrides from carrier config, out-of-service hysteresis, operator-name (SPN/PLMN) display rules, emergency-only detection.
  5. Notify DefaultPhoneNotifier → TelephonyRegistry → every registered TelephonyCallback.ServiceStateListener, plus the ACTION_SERVICE_STATE broadcast. Status-bar icons update.
ServiceState fieldMeaning
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
NetworkRegistrationInfoPer domain/transport: registration state, access network technology (LTE, NR...), cell identity, reject cause, available services
Operator names/numericLong/short alpha name and MCC+MNC of the registered PLMN
RoamingVoice/data roaming type (domestic, international), possibly overridden by carrier config
NR stateFor 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.

ServiceState edge case Voice and data domains can disagree. On an LTE-only network with no CS domain and no IMS/VoLTE, 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 SignalStrength holds 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 is RADIO_OFF, RADIO_ON or RADIO_UNAVAILABLE (HAL or modem not ready).
  • NITZ Network Identity and Time Zone: the network sends time and zone; NitzStateMachine feeds 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.

Tip When asked "what happens when service state changes?", say the chain: RIL indication networkStateChanged → SST.pollState() (four requests) → new ServiceState → DefaultPhoneNotifier → TelephonyRegistry → TelephonyCallbacks and broadcast. Naming this chain signals real framework depth.
Interview angle Interviewers probe whether you know the modern class names (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.

Analogy

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

StateMeaning
ABSENTNo card detected in the slot
PIN_REQUIRED / PUK_REQUIREDUser must enter PIN, or PUK after too many wrong PINs
NETWORK_LOCKEDDevice is carrier-locked and this SIM is not allowed (subsidy lock / personalization)
NOT_READYCard present but not yet initialized (or radio off)
READYApplications are usable; files may still be loading
LOADEDInternal state: all records (IMSI, ICCID, etc.) have been read; subscriptions and carrier config are finalized after this
CARD_IO_ERRORElectrical or protocol failure talking to the card
CARD_RESTRICTED / PERM_DISABLEDCard restricted by carrier policy or permanently blocked

Important elementary files (EFs)

FileContentsWhy it matters
EF_ICCID (2FE2)Card serial numberIdentifies the card; used to create/find the subscription record
EF_IMSI (6F07)International Mobile Subscriber Identity (MCC + MNC + MSIN)Home network, authentication identity
EF_ADAdministrative data, including MNC length (2 or 3 digits)Wrong MNC length gives a wrong MCC-MNC and wrong APNs/config
EF_SPNService provider name and display rulesOperator name on the status bar
EF_MSISDNOwn phone number (often empty)Why getLine1Number() is unreliable
EF_PLMNwAcT / EF_OPLMNwAcT / EF_EHPLMNPreferred and equivalent home networks with access technologyNetwork selection and roaming priority
EF_FPLMNForbidden PLMN listNetworks added after rejects such as EMM #11; a common "cannot register" culprit
EF_IMPI / EF_IMPU (ISIM)IMS private and public identitiesIMS 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

IdentifierWhat it isStable?
Slot indexPhysical/logical SIM slot (0, 1)Fixed by hardware
Phone IDIndex of the Phone object / logical modemUsually 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 IDAndroid's canonical carrier identityStable 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 PhoneCapability in IRadioConfig.

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 use EuiccManager.
  • 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
Common pitfall Confusing slot index, phone ID and subscription ID. Code that caches a subId across a SIM swap, or assumes subId equals slot, breaks on dual-SIM and eSIM devices. Always listen for subscription changes (OnSubscriptionsChangedListener) and carrier config changes.
Interview angle Expect "what happens between SIM insertion and the first network registration?" A good answer: card detected → 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.

Analogy

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 typeUsed forNotes
defaultGeneral internetUsually the initial attach APN on LTE
imsIMS signalling and media (VoLTE, VoNR, SMS over IMS)Often IPv6; never used for app internet traffic; stays up even with mobile data off
mmsMultimedia messagesBrought up on demand, works with mobile data off on many carriers
suplAssisted GPSLocation assistance
dunTetheringSome carriers require a separate DUN APN for hotspot traffic
emergencyEmergency IMS callsCan be set up without a valid subscription
xcap, fota, cbs, ia, enterpriseSupplementary-service config, firmware updates, cell broadcast, initial attach, enterprise slicesCarrier-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

  • DcTracker per transport, ApnContext per APN type, DataConnection state 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); DataProfileManager picks profiles; DataRetryManager handles retries and throttling; DataSettingsManager tracks user data/roaming settings; AccessNetworksManager decides 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

  1. Network request An app or the system asks ConnectivityService for a network with capabilities (for example INTERNET, or IMS, or MMS).
  2. Routing to telephony The telephony network factory (TelephonyNetworkFactory, activated on the preferred data phone by PhoneSwitcher) passes it to DataNetworkController.
  3. 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.
  4. Profile choice DataProfileManager picks the DataProfile (APN) that satisfies the capabilities.
  5. Setup DataNetwork calls RIL.setupDataCall() → IRadioData.setupDataCall(serial, accessNetwork, dataProfile, roamingAllowed, reason, addresses, dnses, pduSessionId, sliceInfo, matchAllRuleAllowed).
  6. Modem signalling The modem sends an ESM PDN Connectivity Request (LTE) or 5GSM PDU Session Establishment Request (5G).
  7. Response SetupDataCallResult returns a cause (DataFailCause), interface name (rmnet_data0 / ccmni0), addresses, DNS, gateways, MTU, P-CSCF addresses, and optionally QoS and slice information.
  8. Network agent DataNetwork creates a TelephonyNetworkAgent, netd configures the interface and routes, and ConnectivityService calls onAvailable(Network) on the requesting app.
  9. Teardown When no request needs it, deactivateDataCall. The modem can also drop it and report through dataCallListChanged.

Retry and throttling

  • Failed setups are retried by DataRetryManager according 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.setDataThrottling lets the framework ask the modem to reduce throughput (for example for thermal mitigation).
Common pitfall Assuming "mobile data off" tears down every PDN. The IMS PDN (and often MMS, emergency, and carrier-required APNs) stays up because voice and messaging depend on it. A bug that brings down the IMS PDN with the data toggle breaks VoLTE.
Interview angle Interviewers ask "what replaced DcTracker and why?" and "trace a data request to an interface". Name 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.

Analogy

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 RILRequest with a unique serial, stored in mRequestList.
  • The answer arrives later on the matching IRadio*Response callback carrying RadioResponseInfo{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; RadioIndication converts it and notifies a RegistrantList.
  • 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

TypeRole
CommandsInterfaceThe abstract radio API the framework programs against; RIL implements it (test code uses SimulatedCommands).
RILOne per slot; holds HAL proxies, request list, wakelocks, death recipients.
RILRequestPooled 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 classesFramework-side Binder servers the vendor calls for solicited replies (NetworkResponse, DataResponse...).
*Indication classesFramework-side servers for unsolicited events (NetworkIndication, DataIndication...).
RegistrantList / RegistrantHow framework objects subscribe to events (for example registerForNetworkStateChanged).
AsyncResultWrapper placed in Message.obj carrying result or exception back to the caller.
CommandExceptionException 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 own mWakeLockCount, 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 type UNSOLICITED_ACK_EXP, RIL briefly holds the ack wakelock and calls responseAcknowledgement() so the vendor can release its own wakelock.
  • Every request carries a WorkSource so 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

  1. Link to death RIL registers a death recipient on every HAL service binder.
  2. serviceDied() If the vendor process dies, the callback fires for each affected service.
  3. Flush RIL completes every pending RILRequest with RADIO_NOT_AVAILABLE, clears the request list, releases wakelocks and resets the proxies.
  4. Radio state The framework sees radio state UNAVAILABLE; service state and data calls are torn down.
  5. 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).
Common pitfall 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.

Interview angle For RIL roles, interviewers go deep: why serials exist (correlating async responses), what happens to pending requests on HAL death, why RIL needs a wakelock and what the timeout protects against, how unsolicited events reach 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).

Analogy

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 a serial and returns immediately (oneway).
  • IRadioXResponse: solicited replies (implemented by the framework, called by the vendor), each carrying RadioResponseInfo.
  • 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 requestsExample indications
IRadioConfig (instance /default)getSimSlotsStatus, getPhoneCapability, setPreferredDataModem, setNumOfLiveModems, setSimSlotsMappingsimSlotsStatusChanged
IRadioModemsetRadioPower, getModemActivityInfo, getImei/getDeviceIdentity, getBasebandVersion, requestShutdown, nvResetConfigradioStateChanged, modemReset, rilConnected, hardwareConfigChanged
IRadioNetworkgetVoiceRegistrationState, getDataRegistrationState, getOperator, getSignalStrength, getCellInfoList, setAllowedNetworkTypesBitmap, setNetworkSelectionModeManual, startNetworkScan, setSignalStrengthReportingCriteria, setIndicationFilternetworkStateChanged, currentSignalStrength, nitzTimeReceived, cellInfoList, currentPhysicalChannelConfigs, barringInfoChanged, registrationFailed
IRadioDatasetupDataCall, deactivateDataCall, getDataCallList, setInitialAttachApn, setDataProfile, setDataAllowed, setDataThrottling, startKeepalive, allocatePduSessionId, getSlicingConfigdataCallListChanged, pcoData, unthrottleApn, keepaliveStatus, slicingConfigChanged
IRadioVoicedial, emergencyDial, hangup, acceptCall, getCurrentCalls, sendDtmf, getClir/setCallForwardcallStateChanged, callRing, srvccStateNotify, currentEmergencyNumberList
IRadioSimgetIccCardStatus, supplyIccPinForApp, iccIoForApp, getImsiForApp, iccOpenLogicalChannel, iccTransmitApduLogicalChannel, setSimCardPower, sendEnvelope (STK)simStatusChanged, simRefresh, stkProactiveCommand, carrierInfoForImsiEncryption
IRadioMessagingsendSms, sendImsSms, acknowledgeLastIncomingGsmSms, writeSmsToSim, setGsmBroadcastConfig, getSmscAddressnewSms, newSmsOnSim, newBroadcastSms, simSmsStorageFull
IRadioIms (Android 14+)setSrvccCallInfo, updateImsRegistrationInfo, startImsTraffic/stopImsTraffic, triggerEpsFallback, sendAnbrQueryonConnectionSetupFailure, 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+)
Packageandroid.hardware.radio@1.0 … @1.6android.hardware.radio.network, .data, .voice, .sim, .modem, .messaging, .ims, .config
ShapeOne monolithic IRadio growing by inheritance (@1.1::IRadio extends @1.0::IRadio)Split by domain; each module versioned independently
TransportHwBinder via hwservicemanagerRegular Binder via servicemanager
EvolutionNew minor version per change; clients check getHalVersion and fall backFrozen versions; new methods added in a new version; framework checks the interface version
Mental modelIdentical: 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

  1. Declaration The vendor's VINTF manifest fragment declares, for example, android.hardware.radio.data.IRadioData/slot1 with a version.
  2. Compatibility The framework compatibility matrix lists which versions it accepts; a mismatch fails the VTS/compatibility check.
  3. Start init starts the vendor daemon from its .rc file (or on demand for lazy HALs through ctl.interface_start).
  4. Register The daemon registers each service with servicemanager.
  5. Bind RIL calls ServiceManager.waitForDeclaredService(...), gets the binder, links to death and calls setResponseFunctions.
Common pitfall The "lazy HAL / VINTF" trap. If the VINTF manifest declares a HAL but no 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

LayerQualcommMediaTek
HAL server processqcrild (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 structureModules per domain (VoiceModule, NasModule, DataModule...), qcril_qmi_*Rfx framework (RfxController, Rmc*/Rmm* handlers, URC handlers)
IPC to modemQMI clients over QRTR (IPC router)MIPC (MTK IPC) and AT channels over CCCI
Data path netdevsrmnet_data0..N over rmnet_ipa0 or rmnet_mhi0ccmni0..N
IMS stackVendor ImsService + modem IMS (QMI IMSA/IMS)Vendor ImsService + MIPC IMS
Log tagsQCRIL, QMI_*, qcril_qmi_*Rfx*, Rmm*, MipcVsClient, AT>/AT<
Modem logsQXDM / QCAT via DIAGMTKLogger 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.

Interview angle Expect: "What changed in the Radio HAL in Android 13?", "Why split it?" (clean domain ownership, independent versioning, better tooling, easier partial implementation), "How does the framework know which methods a vendor supports?" (interface version, 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.

Analogy

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_QIPCRTR sockets), 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 the qmuxd daemon.
  • Conceptually mirrors the HAL: a HAL request usually maps to one or more QMI requests; QMI indications become HAL indications.
QMI servicePurposeHAL counterpart
NASNetwork access: registration, system selection, signal, cell info, network scanIRadioNetwork
WDSWireless Data Service: start/stop network (PDN/PDU), packet data status, profilesIRadioData
DSDData System Determination: preferred data system, which RAT carries dataIRadioData / IRadioConfig
VOICECS calls, supplementary services, USSDIRadioVoice
UIMSIM card access, APDUs, PIN, refreshIRadioSim
CATSIM Toolkit (card application toolkit)IRadioSim STK methods
WMSWireless Messaging Service: SMS send/receive, cell broadcastIRadioMessaging
DMSDevice management: IMEI, firmware version, operating mode (online/low power)IRadioModem
IMSA / IMSSIMS application status and settingsIRadioIms, vendor IMS
PDCPersistent Device Configuration: modem carrier configuration (MBN files) selectionVendor extension
PBM, QoS, DFSPhonebook, QoS flows, data filter serviceVarious

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 OK or ERROR/+CME ERROR: n; unsolicited result codes (URCs) such as +CREG: or RING arrive at any time.
CommandPurpose
AT+CFUN=1 / =0 / =4Full 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,1Activate the context
AT+CSQ, AT+CESQSignal quality
AT+CPIN?, AT+CIMI, AT+CGSNSIM PIN state, IMSI, IMEI
ATD<number>;, ATA, ATH, AT+CLCCDial voice call, answer, hang up, list current calls
AT+CMGS, AT+CMGFSend 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) and ccci_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_EE through 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 remoteproc with qcom_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)

  1. Fault The modem hits a fatal error (assert, "err_fatal"), its watchdog expires, or the AP requests a restart.
  2. Notify The kernel remote-processor / subsystem-restart framework is notified; if enabled, a ramdump of modem memory is collected.
  3. 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.
  4. Reload Firmware is reloaded and restarted; the modem re-initializes.
  5. Recover upward The RIL daemon reports radio state UNAVAILABLE then back, may send a modemReset indication 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.

Interview angle Qualcomm-focused loops ask you to whiteboard a QMI flow end to end (HAL request → QCRIL module → QMI client → QRTR → modem service → response/indication), name the main QMI services and explain SSR. MediaTek-focused loops ask about CCCI, 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.

Analogy

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)
LayerPeerMain jobs
NASMME (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.
RRCeNB / gNBRadio 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)gNBMaps QoS flows (QFI) to data radio bearers.
PDCPeNB / gNBCiphering, integrity protection, header compression (ROHC, vital for VoLTE), in-order delivery, duplicate detection; split-bearer routing in dual connectivity.
RLCeNB / gNBSegmentation and reassembly; ARQ retransmission. Modes: TM (transparent), UM (unacknowledged, used for voice), AM (acknowledged, used for data and signalling).
MACeNB / gNBScheduling, multiplexing logical channels onto transport channels, HARQ fast retransmission, random access, timing advance, buffer status reports, DRX.
PHYeNB / gNBChannel 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; NR RRCSetupRequest/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.
Interview angle Typical probes: "What does PDCP do?", "HARQ vs ARQ?", "Where does a NAS reject come from and who sends it?" (the core network, carried transparently by the base station), "What is RRC_INACTIVE for?", "What triggers RLF?". For 5G details (numerology, BWP, beams, slicing) see 5G NR & 5G Core.

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.

Analogy

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

  1. Phone process starts PhoneFactory.makeDefaultPhones() creates RIL and GsmCdmaPhone per slot; RIL binds to the Radio HAL services and registers callbacks.
  2. rilConnected / radio state The vendor daemon reports readiness; radio state moves from UNAVAILABLE to OFF.
  3. SIM UiccController calls getIccCardStatus; the card tree is built, PIN checked, records loaded; subscription and carrier config are finalized.
  4. Radio on Unless airplane mode is on, SST calls setRadioPower(true). The framework also sends allowed network types, initial attach APN and data profiles.
  5. Modem registers PLMN search → cell selection → RRC connection → NAS Attach / Registration (below).
  6. Framework sees service networkStateChanged → pollState() → STATE_IN_SERVICE → notifications.
  7. Data and IMS DataNetworkController sets up internet and IMS data connections; the vendor ImsService performs 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 / timerPurpose
Tracking Area Update (TAU) / mobility registrationUE 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)
T3346Mobility-management back-off sent by a congested network; UE must not retry until expiry
T3396Session-management back-off for a specific APN
T3417Service request supervision (idle to connected for signalling or data); typical 3GPP default 5 s
Detach / deregistrationPower 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.

Common pitfall Treating "no service" as an RF problem by default. Check the reject cause first. EMM #11 (PLMN not allowed) adds that PLMN to EF_FPLMN, so the UE stops trying it even on excellent RF. EMM #13 (roaming not allowed in this tracking area) and #15 (no suitable cells in this tracking area) add the tracking area to a forbidden-TA list, not the FPLMN; the UE can still try other TAs of the same PLMN. 5GMM has matching causes. A leftover forbidden list is a common "cannot register" culprit.
Interview angle "Walk me through what happens from power-on to the signal bars appearing" is a favourite. Cover both halves: Android (PhoneFactory, RIL binding, SIM load, carrier config, radio power, SST polling) and 3GPP (PLMN selection, RRC setup, authentication with the USIM, security, attach accept with default bearer). Knowing the difference between LTE attach and 5G registration plus PDU session scores extra.

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.

Analogy

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

FamilyStates you must nameWhat they mean
EMM (LTE NAS registration)EMM-DEREGISTERED, EMM-REGISTERED-INITIATED, EMM-REGISTERED, plus procedure states such as TAU-INITIATED and SERVICE-REQUEST-INITIATEDWhether 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-INITIATEDSame 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 → ActiveCS 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_INACTIVEThe access-stratum view. ECM-IDLE almost always means RRC_IDLE; ECM-CONNECTED means RRC_CONNECTED.
Interview one-liner "EMM-REGISTERED + ECM-IDLE + RRC_IDLE" is the normal camped-on-LTE phone: in service, data and IMS PDNs exist in the core, but the radio is down until paging or a Service Request.

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:

  1. 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.
  2. 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.

Interview angle A compact answer that scores well: name EMM vs ECM vs RRC, walk paging → Service Request with T3417, say when TAU runs (new TA or T3412), distinguish AKA MAC failure from sync failure, and sketch X2 as prepare / command / path switch. Bonus: UAC is why 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.

Analogy

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 ImsService is bound by ImsResolver per slot and provides MmTelFeature (voice, video, SMS over IMS) and RcsFeature.
  • GsmCdmaPhone delegates calls to ImsPhone / ImsPhoneCallTracker when IMS is registered; otherwise it uses the CS path through GsmCdmaCallTracker and IRadioVoice.
  • IMS needs the IMS PDN (brought up by DataNetworkController) and a P-CSCF address (from PCO in the setupDataCall response, or DHCP).
  • Registration: SIP REGISTER → 401 Unauthorized with 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 conceptWhere you see it in Android
NSA (EN-DC): LTE anchor plus NR secondary cell groupData registration shows LTE; currentPhysicalChannelConfigs and NR state drive TelephonyDisplayInfo to show a 5G icon
SA: NR with the 5G coreRegistration RAT = NR; required for VoNR, slicing, RRC_INACTIVE
PDU sessions and QoS flowssetupDataCall 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 fallbackIRadioIms.triggerEpsFallback, IMS registration over NR, RAT change to LTE during call setup
Allowed network typessetAllowedNetworkTypesBitmap 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
Note Deep dives live elsewhere: IMS registration, SIP/SDP, supplementary services, SRVCC and Wi-Fi calling in IMS, VoLTE & VoWiFi; NSA/SA, 5GC, numerology, beams, slicing in 5G NR & 5G Core; every class for CS, VoLTE, VoNR, incoming calls and CSFB, plus MediaTek vs Qualcomm paths, in CS & IMS Call Flows.
Interview angle Even in a RIL-focused loop you will be asked to trace a VoLTE call from Dialer to RF and to explain IMS registration failures. Show that you know which parts go through RIL (data bearers, IMS status to the modem, CS calls) and which go through the IMS stack (SIP), and that a SIP error with a healthy modem is an IMS/operator problem, not a modem problem.

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.

Analogy

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)
PieceSideRole
ConnectivityService / netdAP framework / nativeNetwork selection, default network, routes, per-UID rules, DNS
DataNetworkControllerAP telephonyDecides and manages PDN/PDU bring-up and teardown
RIL / Radio HALAP ↔ vendorsetupDataCall, SetupDataCallResult, dataCallListChanged
rmnet / QMAPAP kernelLogical netdevs, multiplexing several PDNs onto one link, aggregation, flow control
IPA (Qualcomm) / DPMAIF (MediaTek)SoC hardwareUser-plane offload between AP memory and the modem
QMI WDS / MIPC dataModem controlStart/stop network, packet data status
PDCP … PHYModem firmware3GPP user-plane processing

IP routing on Android

  • Each Network gets its own routing table (named after the interface, for example rmnet_data1). ip rule entries select the table using a fwmark that encodes the network ID, set on sockets by netd based on the app's default network or explicit Network.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_data1 interface 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).

Tip One sentence to remember: "The control plane (RIL → QMI WDS → NAS) negotiates the bearer and returns an interface plus IP; after that, user-plane packets ride rmnet/QMAP and are DMA-offloaded by the IPA straight to the modem, so the CPU mostly sleeps."
Interview angle Interviewers ask you to trace a packet from 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.

Analogy

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.

PatternWhere in telephonyGeneral system-design equivalent
Layering + stable interfacesApp → framework → RIL → HAL → vendor; frozen AIDL versionsDecoupling and independent evolution; versioned API contracts
Async request/response with correlation IDsRIL serials matched to IRadio*ResponseNon-blocking RPC; request IDs in message systems
Publish/subscribe (observer)RegistrantList, TelephonyRegistry, TelephonyCallbackEvent bus; decouples producers from many consumers
Single-threaded event loopHandler/Looper per componentActor model; serializes state changes without locks
Explicit state machinesStateMachine base class; DataNetwork, call trackersDeterministic handling of complex transitions
Failure detection + recoveryHAL death recipients, request flush, persistent-process respawn, modem SSRHealth checks, supervisors, circuit breakers
Back-off / throttlingNAS timers T3346/T3396/T3402, DataRetryManagerCongestion control; exponential back-off with jitter
Caching with invalidationCarrierConfig, cached ServiceState, SIM records, subscription DBCache plus invalidation on SIM swap / config change
Rate limiting / coalescingSignal reporting criteria, indication filters, SST poll coalescingDebounce/coalesce to protect consumers from event storms
Resource arbitrationDDS, temporary data switch, DSDS RF sharingScheduling a scarce shared resource fairly and safely
Power-aware designRIL wakelock with timeout, IPA offload, DRX, indication filtering on screen offBatching, letting hardware sleep; energy as a first-class constraint
Layered configuration / feature flagsAOSP defaults → carrier config app → carrier service → overridesConfig 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_AVAILABLE so 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.
Interview angle In a generic system-design round, anchor ideas in telephony where you can: back-off with network-provided timers, idempotent re-init after HAL death, request correlation with serials, resource arbitration for DDS, and power-aware batching. Interviewers reward concrete, hard-won examples of these concepts. For the general framework see System Design.

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.

Analogy

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 / commandWhat it shows
adb logcat -b radioRILJ requests/responses, telephony framework, vendor RIL logs
adb logcat -b main -b system -b crashIMS service, Telecom, crashes in the phone process
adb shell dumpsys activity service com.android.phone/.TelephonyDebugServiceThe big telephony dump: per-phone RIL state, SST, data networks, retry state, UICC, recent local logs
adb shell dumpsys telephony.registryLast notified service state, signal, call state, data state per subscription
adb shell dumpsys isubSubscriptions, DDS and default voice/SMS
adb shell dumpsys carrier_configEffective carrier config per subscription
adb shell dumpsys connectivity, dumpsys netdNetworks, capabilities, default network, validation, routes
adb shell ip addr, ip rule, ip route show table allInterfaces (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|disableToggle mobile data
adb shell cmd connectivity airplane-mode enable|disableToggle airplane mode
Dialer code *#*#4636#*#*Testing menu: phone info, preferred network type, radio power, signal, ping
adb bugreportEverything 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_data1IP traffic, SIP/RTP for IMS, DNS, TCP issues
Perfetto / battery statsWakelocks (*telephony-radio*), modem activity, power attribution

Mandatory first check

  1. Chipset and log family MediaTek (mipc, md1, ccci, Rfx) or Qualcomm (qcril, QMI, subsys/remoteproc, DIAG)? This decides which keywords and tools apply.
  2. Environment Is the device in usable RF? RSRP/RSRQ/SINR, serving PLMN, roaming, SIM state, airplane-mode transitions, user actions around the event.
  3. Modem health Any reset near the event? Qualcomm SSR/ramdump, MediaTek md1 exception, RIL serviceDied, radio state UNAVAILABLE, phone-process restart.

Decision priorities (apply in order)

#LayerWhat to extract
1Chipset + environment + modem healthThe first check; gate everything on it
2Protocol cause codesNAS EMM/ESM/5GMM/5GSM, RRC reject/release, SIP 4xx/5xx/6xx, RIL errors, DataFailCause, timestamp-aligned to the symptom
3Framework stack evidenceServiceStateTracker, DataNetworkController, ImsPhoneCallTracker, UiccController logs around the window
4Modem / RF evidenceServing cell, RSRP/RSRQ trend, PLMN, NAS timers (T3346/T3396/T3417), handover and reselection
5ANR / tombstone / watchdogCorrelate process death or hangs with the radio event
6Historical similarityPrior 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.

HypothesisSupporting evidenceContradicting evidence
Modem fault / SSRmd1 exception or SSR near the window, serviceDied, phone restartNo reset markers; modem answered requests normally throughout
Network rejectEMM/ESM/5GMM/SIP cause at the exact timestampSuccessful attach/registration at the same time
UE / framework bugClear exception or wrong state in phone, IMS or carrier appNo app exception; radio shows a network reject
SIM / provisioningABSENT, UICC reset, IMSI read failure, wrong carrier IDCard LOADED, IMSI present, correct carrier config
RF / coverageRSRP below about -115 dBm sustained, repeated searching, RLFStrong 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

MarkerMeaning
RILJ: [nnnn]> without [nnnn]<Request never answered: vendor daemon or modem is stuck
serviceDied, RADIO_NOT_AVAILABLEHAL process died or radio unavailable
subsystem restart / remoteproc crash / ramdumpQualcomm modem SSR
md1 exception, MD_EE, ccci resetMediaTek modem exception
SST: pollStateDone, REG_DENIED, reject causeRegistration outcome in the framework
DataNetwork: ... setup failed cause=, DataRetryManagerData call failure and retry decision
ImsPhoneCallTracker: onCallTerminated reason=IMS call end reason (maps SIP code)
GsmCdmaCallTracker: onDisconnect cause=CS call disconnect cause
AT> / AT<, MipcVsClientMediaTek modem command traffic
QCRIL_*, QMI_* result/indicationQualcomm 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(...)
StepFinding
Real ownerThe shared com.android.phone process, not the IWLAN package the label named.
Root causeA 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 outModem SSR: the modem answered the previous activity-info request seconds earlier, and there were no SSR or md1 markers.
FixIn 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.
LessonThe 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.

StepFinding
Real causeBroken 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 causeThe repeated null-proxy logs are a symptom; "modem disabled" is the IMS adapter giving up on the null proxy, not a baseband crash.
Ruled outModem reset: no md1 exception, no SSR, no serviceDied; the other HAL services were present and working.
Scale lessonA 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.
Common pitfall Confirmation bias: seeing a modem reset somewhere in the log and declaring it the root cause without checking that its timestamp precedes the symptom. Always align timestamps across logcat, kernel log and modem logs (they may use different clocks; find a common event to sync them).
Interview angle Log-reading rounds hand you a snippet and ask "what happened?". Interviewers look for structure: state the first check, find the cause code at the timestamp, name the layer, list alternatives and why you ruled them out, and say what extra log you would collect. They also value knowing which tool answers which question (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.

Analogy

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

#MeaningTypical interpretation
3Illegal UEAuthentication failed / SIM not accepted; USIM treated as invalid until power cycle
6Illegal MEDevice (IMEI) blocked, for example blacklisted
7EPS services not allowedSubscription has no LTE service
8EPS and non-EPS services not allowedNo service at all for this subscription
9UE identity cannot be derived by the networkNetwork lost the UE context; UE re-attaches with IMSI
10Implicitly detachedNetwork detached the UE (for example missed periodic TAU)
11PLMN not allowedNo agreement with this network; PLMN added to EF_FPLMN
12Tracking area not allowedTA stored on the forbidden-TA list for regional provision of service; same PLMN still usable in other TAs
13Roaming not allowed in this tracking areaTA stored on the forbidden-TA list for roaming; not added to EF_FPLMN
14EPS services not allowed in this PLMNLTE not allowed on this network (2G/3G may be); added to the "forbidden PLMNs for GPRS service" list, not EF_FPLMN
15No suitable cells in tracking areaTA stored on the forbidden-TA list for regional provision of service; try another TA of the same PLMN
18CS domain not availableCombined attach: no CS; device must rely on IMS for voice
22CongestionUsually with T3346 back-off
25Not authorized for this CSGClosed subscriber group (femtocell) restriction
40No EPS bearer context activatedNetwork has no default bearer for the UE; re-attach

NAS ESM (LTE session / PDN) causes

#MeaningTypical interpretation
8Operator determined barringSubscriber barred from this service by the operator
26Insufficient resourcesNetwork overload; often comes with T3396 back-off
27Missing or unknown APNWrong APN name in the profile; fix APN configuration
28Unknown PDN typeRequested IP type not recognized
29User authentication failedAPN username/password (PAP/CHAP) rejected
30Request rejected by serving/PDN gatewayGateway refused the connection
31Request rejected, unspecifiedGeneric; needs network-side logs
32Service option not supportedNetwork does not support the request
33Requested service option not subscribedSubscription lacks this APN (for example tethering APN)
36Regular deactivationNormal teardown
38Network failureCore-network problem
50PDN type IPv4 only allowedRetry as IPv4
51PDN type IPv6 only allowedRetry as IPv6 (464XLAT for IPv4 apps)
54PDN connection does not existState mismatch between UE and network
55Multiple PDN connections for a given APN not allowedDuplicate connection to the same APN
65Maximum number of EPS bearers reachedToo 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
3Illegal UE
6Illegal ME
75GS services not allowed
11PLMN not allowed
12Tracking area not allowed
13Roaming not allowed in this tracking area
15No suitable cells in tracking area
22Congestion
27N1 mode not allowed (5G NAS not allowed; use LTE)
62No network slices available
111Protocol error, unspecified

SIP response codes (IMS)

CodeMeaning / typical cause
100 / 180 / 183Trying / Ringing / Session Progress (provisional, normal)
401 / 407Unauthorized / proxy auth required: AKA challenge (a normal registration step)
403Forbidden: provisioning, subscription or registration not allowed
404Not found: bad URI or number
408Request timeout: no answer from the network
480Temporarily unavailable (callee not registered or not reachable)
486Busy here
487Request terminated (caller cancelled)
488Not acceptable here: codec/SDP mismatch
500Server internal error
503Service unavailable: congestion or overload (may include Retry-After)
504Server timeout
603Decline

RIL errors and NAS timers

TokenMeaning
NONESuccess
RADIO_NOT_AVAILABLEHAL/modem down or restarting; request cannot be served
REQUEST_NOT_SUPPORTEDHAL version or vendor does not implement the method
GENERIC_FAILURECatch-all modem failure
INVALID_ARGUMENTSBad parameters from the framework
INVALID_STATERequest not valid in the current modem state
SIM_ABSENT, SIM_PIN2, SIM_PUK2, PASSWORD_INCORRECTSIM-related failures
MODEM_ERR, INTERNAL_ERR, SYSTEM_ERR, NO_MEMORYModem or vendor-daemon internal problems
OEM_ERROR_*Vendor-specific
T3346NAS mobility back-off (congestion) before retrying attach/registration; value assigned by the network
T3396Per-APN back-off after an ESM reject; value assigned by the network
T3402Long back-off after five failed attach/TAU attempts (typical 3GPP default 12 minutes)
T3410Attach supervision: wait for Attach Accept (typical 3GPP default 15 s)
T3411Short retry after a failed attach/TAU (typical 3GPP default 10 s)
T3412Periodic TAU (typical 3GPP default 54 min if the network does not assign another value)
T3417Service Request supervision (typical 3GPP default 5 s)
T3430TAU supervision: wait for TAU Accept (typical 3GPP default 15 s)
T3512Periodic 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
1Unassigned (unallocated) number
16Normal call clearing
17User busy
18No user responding
19No answer from user (alerted)
21Call rejected
31Normal, unspecified
34No circuit/channel available
38Network out of order
41Temporary failure
47Resources unavailable, unspecified
68ACM equal to or greater than ACMmax (credit limit)
Tip Always read a cause together with its timestamp and procedure. EMM #11 on attach means something different from a SIP 403 on REGISTER, and the same ESM #26 is harmless once but a real problem when repeated with T3396 back-off across a fleet.
Interview angle Interviewers throw a number at you ("device gets ESM 27", "EMM 11 while roaming", "SIP 488", "RADIO_NOT_AVAILABLE on every request") and expect the meaning plus the next debugging step: fix the APN, check roaming agreement and forbidden PLMN list, check codecs/SDP, check HAL/modem health. Knowing the handful of common codes cold is expected at senior level.

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 as TelephonyConnectionService.
  • PhoneFactory creates one RIL and one GsmCdmaPhone per slot; ImsPhone handles IMS calls when registered.
  • ServiceStateTracker reacts to networkStateChanged by polling operator, voice reg, data reg and selection mode, then notifies via TelephonyRegistry.
  • DataNetworkController (Android 13+) replaced DcTracker/DataConnection/ApnContext; DataNetwork = one connection, DataProfile = APN.
  • SubscriptionManagerService (Android 14+) replaced SubscriptionController and owns DDS and default voice/SMS subscriptions.
  • UICC tree: UiccController → UiccSlot → UiccCard/UiccPort → UiccProfile → applications (USIM, ISIM) → records.
  • CarrierConfigLoader merges platform defaults, carrier-config app values by carrier ID and carrier-app overrides; broadcasts ACTION_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 / md1 exception (baseband crashed); timestamps decide cause and effect.
  • Radio HAL: HIDL radio@1.0–1.6 monolithic IRadio → stable AIDL (Android 13) split into Network, Data, Voice, Sim, Modem, Messaging, Ims, Config.
  • Each HAL domain has request, Response and Indication interfaces; setResponseFunctions hands callback binders to the vendor.
  • HAL discovery: VINTF declaration → init starts daemon → registers with servicemanager → RIL waitForDeclaredService; 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 are md1 exceptions.
  • 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 + setPreferredDataModem implement 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 ServiceState domains 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; also telephony.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 radio for RIL and telephony logs.
  • dumpsys telephony.registry, dumpsys isub, dumpsys carrier_config and the TelephonyDebugService dump for state.
  • dumpsys connectivity, ip addr, ip route for 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 bugreport for 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.
  1. A framework component calls a CommandsInterface method with a result Message.
  2. RIL.obtainRequest() takes a pooled RILRequest, assigns a serial, acquires the RIL wakelock reference and adds it to mRequestList.
  3. RIL logs [serial]> REQUEST and calls the HAL proxy method, which returns immediately.
  4. Later the vendor calls the matching *Response method with RadioResponseInfo.
  5. processResponse finds and removes the request by serial; processResponseDone sends the result or a CommandException to 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?
  1. The modem detects the card and sends simStatusChanged.
  2. UiccController calls getIccCardStatus and builds the card tree.
  3. PIN state is checked; if needed the user enters the PIN.
  4. Records load: ICCID, IMSI, EF_AD (MNC length), SPN, PLMN lists; state becomes LOADED.
  5. The subscription is created or updated, the carrier ID is resolved and carrier config is loaded.
  6. 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_AVAILABLE so 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.
  1. DataNetwork calls RIL.setupDataCall → IRadioData.setupDataCall(serial, ...).
  2. 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.
  3. The modem's WDS service returns an immediate response (accepted, with a packet data handle) and triggers NAS PDN/PDU signalling.
  4. 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).
  5. The daemon maps the connection to a QMAP mux ID and an rmnet_data interface and calls setupDataCallResponse(info{serial}, result).
  6. 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:

  1. Is the IMS PDN up with IP addresses?
  2. Were P-CSCF addresses received (PCO or DHCP)?
  3. Did AKA with ISIM/USIM succeed (the 401 step)?
  4. Are IMPI/IMPU correct (from ISIM or derived from IMSI)?
  5. Is VoLTE enabled and provisioned in carrier config and modem configuration for this carrier and region?
  6. 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?
  1. Check radio power and airplane mode, SIM state (LOADED?) and subscription.
  2. Look at SST logs: registration state, especially REG_DENIED with a reject cause. Also compare voice vs data ServiceState (they can disagree).
  3. 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).
  4. If searching, check allowed network types, band configuration and manual selection mode.
  5. Pull modem logs for cell search, RRC setup failures and NAS messages.
  6. 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?
  1. Check DDS and preferred data modem before, during and after the call in dumpsys isub and the telephony dump.
  2. Check PhoneSwitcher logs: was a temporary switch made, and was it reverted correctly?
  3. Check setPreferredDataModem requests and responses in the radio log.
  4. Check the data network list per phone and whether internet was set up on the intended SIM.
  5. Verify initial attach APN and data profiles on the right subscription.
  6. If voice was IMS, check the IMS PDN state on both SIMs.
  7. 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.