OMAPI, Telephony API, and Card Readers: How eSIM Adapters Talk to Your Phone

Short answer: an app that manages a removable eUICC has to send raw APDU commands to the card, and Android offers exactly two ways to do that — the Telephony API (iccOpenLogicalChannel, Android 5.1+) and OMAPI (android.se.omapi, Android 9+). Both are gated by access rules stored on the card itself, in an ARA-M applet or ARF. If your phone's manufacturer never exposed the SIM slot as an OMAPI secure element, both paths fail and no app can fix it. The third option sidesteps Android completely: put the card in an external reader and let a computer or a rooted/custom-ROM device act as the LPA.

Disclosure: published by Switch eSIM, which sells removable eUICC cards. Our commercial interest is in you concluding that these cards work on your phone. This article instead explains, in detail, the specific ways they fail to — including a failure mode no app or vendor can work around. Where I could not verify something, including claims about our own products, it is marked.


The three access paths

Path A: Telephony API Path B: OMAPI Path C: External reader
API TelephonyManager.iccOpenLogicalChannel / iccTransmitApduLogicalChannel android.se.omapi.SEServiceReaderSessionChannel PC/SC (CCID) over USB or Bluetooth
Since Android 5.1 (carrier privileges) API 28 (Android 9); getUiccReader(slot) added API 30 (Android 11) N/A — not an Android API
Gated by UICC carrier privileges: app signing cert hash must be on the card GlobalPlatform Access Control Enforcer, reading ARA-M or ARF on the card Nothing on the phone
Who controls access Card issuer Card issuer You
Fails when No matching cert on card; OEM restrictions OEM never implemented the SIM OMAPI reader Reader/driver problems

The critical structural point, and the one that explains most confusion in forum threads: paths A and B are both ultimately authorised by data stored on the card, not by a permission you can grant in Android settings. There is no toggle. Either the card carries the app's certificate hash or the app is refused.


Path A: the Telephony API and carrier privileges

Android 5.1 introduced a mechanism where the platform reads certificates stored on a UICC and grants apps signed by those certificates access to a set of privileged telephony methods. AOSP's documentation is explicit about the mechanics: the rule stores a DeviceAppID-REF-DO containing the SHA-1 (20 byte) or SHA-256 (32 byte) signature of the certificate, optionally concatenated with a PKG-REF-DO holding the full package name as ASCII, max 127 bytes. UiccCarrierPrivilegeRules.java loads and caches those rules, and compares a caller's certificate against them one at a time. When the UICC is removed, the rules are destroyed with it.

For our purposes the relevant methods are iccOpenLogicalChannel and iccTransmitApduLogicalChannel — open a logical channel to an applet by AID, then push APDUs down it. That is precisely what an LPA needs to reach the ISD-R.

Two practical consequences:

Carrier privileges are per-SIM, not per-device. AOSP notes that on multi-SIM devices "carrier #1 only has access privileges for SIM #1 and vice versa," and that the CarrierConfig.xml used is determined by the inserted SIM. Move the card and privileges move with it.

This path has been narrowing. Access to device identifiers via carrier privileges has been progressively tightened across releases, and app-store-delivered carrier apps now need explicit privilege grants. Treat Path A as a legacy fallback, not a design target.


Path B: OMAPI, and what the spec actually requires

OMAPI is the GlobalPlatform/SIMalliance Open Mobile API. Android 9 introduced support for it along with a backend implementation comprising a Secure Element Service and an SE HAL.

The object model is short: SEService connects (asynchronously — you must wait for OnConnectedListener or poll isConnected()), getReaders() enumerates secure elements, openSession() powers and prepares one, and a channel carries APDUs.

The naming convention matters more than it looks. Android's Reader.getName() documentation specifies that a SIM reader must be named SIM[Slot], an SD reader SD[Slot], an embedded SE eSE[Slot], with slot numbering starting at 1 and the "1" optional for the first reader. The Secure Element CTS test enforces this: "All Secure Element Reader names should start with SIM, eSE, or SD."

This is why older adapter apps string-match on "SIM1". getUiccReader(int slotNumber) — which does the job properly — was only added in API level 30, per the AOSP API diff between levels 29 and 30. An app supporting Android 9 and 10 has no clean way to ask for "the UICC in slot 2."

Also worth knowing: the Reader docs state readers "can be physical devices or virtual devices. They can be removable or not. They can contain Secure Element that can or cannot be removed." The API was designed for removable secure elements from the start — the same conclusion the GSMA specs reach from the other direction.

The Access Control Enforcer

OMAPI access is not open. GlobalPlatform's Secure Element Access Control specification (GPD_SPE_013, v1.0 May 2012, v1.1 Oct 2014, v1.2 current) defines an Access Rule Application Master (ARA-M) — "an ordinary SE application which can be selected by a GlobalPlatform-defined AID" — which holds access rules, optionally delegating to ARA-C clients, or falling back to Access Rule Files (ARF). On the device side an Access Control Enforcer requests the relevant rules and "shall permit the access only if the rules indicate that it is acceptable."

Each rule maps a device app (by certificate hash) to an SE applet (by AID) plus an APDU permission. The spec's stated purpose is preventing unauthorised access and denial-of-service attacks such as PIN blocking.

The enforcement is real and it is not optional on major hardware. A developer on Stack Overflow reported OMAPI openLogicalChannel working through Android 12 on a Pixel and breaking on Android 13 — while stating they used no carrier privilege rules. The response is the useful part: "I'm wondering how this was ever working in your case. In all my setups I needed it for accessing the SEService. The Access Control Enforcer was always checking the access properly in my Pixel devices."

Android 13 and the vendor stable interface

Android 13 converted OMAPI into a vendor stable interface so HAL modules could also reach secure elements, under the Android Ready SE programme. Two details are worth flagging. First, AOSP states OEMs integrating a secure element "need to enable this interface, as it's disabled by default." Second, because HAL modules have no package name or signing certificate, SE vendors can define a 16-byte UUID — padded to 20 bytes with FF, matching the DeviceAppID-REF-DO size — mapped to the HAL module's UID in vendor config.

That padding detail is a small confirmation that the 20-byte DeviceAppID-REF-DO field is the universal hinge of this entire access-control system.


Why phones that "support eSIM" still fail

Here is the failure that no app can route around, documented in a LineageOS issue from November 2025 for the OnePlus 7 Pro (guacamole) on lineage-23:

Current Behavior: OMAPI UICC access is absent, causing all UICC operations to fail: No UICC readers appear through OMAPI. TelephonyManager fallback (iccOpenLogicalChannel) is blocked with SecurityException because no UICC SE is exposed.

The attached logcat from eSIM.me shows the fallback chain executing and collapsing:

esim.me.lpa: [SA][getReaders] error: Timed out waiting for 1000 ms
LpaUtils: [SA-OM]: Failed to open channel: eUICC unavailability
          cause: Timed out waiting for 1000 ms
esim.me.lpa: --simAllianceOM2: false
LpaUtils: [TM]: Attempting to open logical channel
esim.me.lpa: [TM][getReaders] TelephonyPermissions:
             reportAccessDeniedToReadIdentifiers:esim.me:...

Read in order: OMAPI times out at 1000 ms, the app records simAllianceOM2: false, falls back to TelephonyManager, and is denied there too. Both paths, one root cause: the device build never exposed the SIM slot as an OMAPI secure element.

That is a device-tree and HAL matter, not an app matter. The issue links to a LineageOS Gerrit change adding the capability for a different OnePlus model — which tells you the fix lives in the ROM's device configuration, and that it is done per device, per OS version, by whoever maintains that build. It is not something a card vendor, an app developer, or you can supply from userspace.

The generic vendor advice for these situations is worse than useless. Xiaomi's official "eSIM card is not working" page suggests checking activation with your carrier, verifying settings, and confirming network coverage — none of which touch APDU access. A separate GitHub issue for XiaomiEsimLPA reports "manage eSIM" simply doing nothing on a Xiaomi 17 Pro regardless of slot. These are symptoms of the access layer, described in the vocabulary of the network layer.

The diagnostic question is therefore never "does my phone support eSIM." It is "does my phone's build expose a SIM OMAPI reader." Those are unrelated properties.


The privileged shortcut, and the hash that matters

There is one way to escape card-stored access rules entirely: be a system app. The OpenEUICC project makes this the explicit basis of its two variants.

OpenEUICC is the privileged build, intended to live in /system/priv-app, signed with the platform certificate, and serve as the system LPA. It "can be used to manage all kinds of eSIM chips, embedded or removable." Its own README carries a caveat worth quoting because it cuts against vendor marketing: "When privileged, OpenEUICC supports any eUICC chip that implements the SGP.22 standard, internal or external. However, there is no guarantee that external (removable) eSIMs actually follow the standard. Please DO NOT submit bug reports for non-functioning removable eSIMs."

EasyEUICC is the unprivileged build, installable as a normal user app. It can only reach cards whose ARF/ARA contains the hash of its signing certificate. The project publishes that hash for card vendors to embed:

For removable eSIM chip vendors: to have your chip supported by official builds of EasyEUICC when inserted, include the ARA-M hash 2A2FA878BC7C3354C2CF82935A5945A3EDAE4AFA

That is the concrete mechanism behind an abstract idea. A removable eUICC vendor decides, at manufacture, which apps may talk to their card, by writing certificate hashes into ARA-M. Whether a given card includes the EasyEUICC hash is a per-product fact you should ask any vendor directly — including us. I was not able to confirm it for our cards before publication.

EasyEUICC also cannot manage your phone's internal eSIM, for the same structural reason in reverse: the built-in chip's ARA-M does not grant it access and never will.

This is the honest summary of the removable eUICC situation on Android. The card body is standards-clean. The access path is a three-way negotiation between your OEM's HAL, the app's signing key, and rules burned into the card — and you control none of the three.


Path C: external readers

Both Android paths disappear if you stop using the phone as the reader. A removable eUICC in a PC/SC (CCID) smart-card reader is reachable by host software acting as the LPA, with no Android secure-element stack, no ARA-M negotiation against a phone app, and no OEM HAL involvement. Download and manage profiles on a computer, then move the card to the phone, which sees an ordinary SIM.

This is why the reader approach is the reliable fallback for exactly the devices in the section above.

Two things in this brief I could not verify and have therefore not written as fact: whether lpac and comparable tools support PC/SC readers in the configurations we'd recommend (I ran out of search budget before confirming), and the iOS Bluetooth-reader workflow the brief refers to as "your iOS story." I have no notes, product, or test data for the latter. A concrete claim that a Bluetooth reader enables removable-eUICC management on iPhone needs a documented test before it appears on our site — it is the most link-worthy claim in the brief and the easiest to be wrong about. Flagged, not drafted.


Troubleshooting matrix

Symptom Likely cause Diagnostic Realistic fix
App reports no eUICC found; log shows getReaders timeout Device exposes no SIM OMAPI reader adb logcat during detection; look for reader enumeration failing ROM/device-tree change, or use an external reader. Not fixable in-app.
OMAPI fails, then Telephony fallback throws SecurityException No UICC SE exposed — both paths blocked by one cause Same log; note the two-stage failure External reader, or a build that exposes OMAPI
Reader found but openLogicalChannel denied Access Control Enforcer refused; app cert hash absent from ARA-M/ARF Confirm which app build you're running; check vendor's supported-app list Use the app the card grants access to
Worked on Android 12, broke on 13 Enforcement or HAL behaviour changed across the release Test the same card and app on another OS version Confirm app support for that Android version
Card works on a custom ROM, not stock Privileged system LPA bypasses card-stored rules Compare app variants — privileged vs unprivileged Unprivileged app requires the card to carry its hash
Second SIM slot fails, first works Slot-2 reader unnamed/unexposed, or app hardcodes SIM1 Try the card in slot 1 Slot 1, or an app using getUiccReader() on Android 11+

adb logcat is the single highest-value diagnostic here and almost no consumer guide mentions it. The failure is legible in the log and invisible in the UI.


Limitations

Everything cited above came from AOSP documentation, Android API references, GlobalPlatform specifications, and public issue trackers retrieved in this session. Specific gaps: I did not confirm the OMAPI feature-flag string (android.hardware.se.omapi.uicc appears in the LineageOS issue text but I did not verify it against AOSP); I did not verify PC/SC support in lpac or any specific host tool; I did not verify the iOS Bluetooth reader workflow at all; I did not verify whether Switch cards carry the EasyEUICC ARA-M hash or any other app's; and the three failure reports cited (OnePlus 7 Pro/LineageOS, Pixel/Android 13, Xiaomi 17 Pro) are individual third-party reports, not a support matrix and not our testing. No device was tested for this article. The GlobalPlatform Access Control quotes are from v1.0/v1.1 PDFs; v1.2 is current and I did not diff them.



Learn more:

  1. Android Developers — android.se.omapi.SEService, added in API level 28
  2. Android API diff 29→30 — getUiccReader(int) added to SEService
  3. Android Developers — android.se.omapi.Reader: SIM[Slot]/SD[Slot]/eSE[Slot] naming, removable secure elements
  4. AOSP — CTS test for Secure Element: Android 9 introduced OMAPI support; reader names must start with SIM, eSE or SD
  5. AOSP — OMAPI vendor stable interface (Android 13): disabled by default, 16-byte UUID padded to 20 bytes with FF
  6. AOSP — UICC carrier privileges: DeviceAppID-REF-DO SHA-1/SHA-256, PKG-REF-DO, UiccCarrierPrivilegeRules.java
  7. AOSP — Carrier configuration: privilege granted only to apps signed with the certificate on the SIM
  8. AOSP — Device identifiers: per-SIM privilege scoping on multi-SIM devices
  9. GlobalPlatform Secure Element Access Control v1.1 (GPD_SPE_013) — ARA-M, ARA-C, ARF, Access Control Enforcer
  10. GlobalPlatform Secure Element Access Control v1.0 — ARA-M selectable by GlobalPlatform-defined AID
  11. GlobalPlatform — Secure Element Access Control v1.2 specification page and version history
  12. LineageOS issue #9577 — "UICC not exposed → Third-party apps cannot access physical SIM," with eSIM.me logcat
  13. Stack Overflow — OMAPI openLogicalChannel failing on Android 13; Access Control Enforcer always checked on Pixel
  14. Stack Overflow — isSecureElementPresent() false for a custom card; missing carrier privileges applet as suspected cause
  15. OpenEUICC README — privileged OpenEUICC vs unprivileged EasyEUICC; ARA-M hash 2A2FA878BC7C3354C2CF82935A5945A3EDAE4AFA
  16. OpenEUICC (mirror) — "An eSIM chip must include the certificate of EasyEUICC in its ARA-M field"
  17. CoIMS_Wiki — practical ARA-M applet installation and --acr-list-aram rule dumps via GlobalPlatformPro
  18. XiaomiEsimLPA issue #24 — "Manage eSIM does nothing on Xiaomi 17 Pro"
  19. Xiaomi support — "The eSIM card is not working" (illustrating network-layer advice for an access-layer fault)

Learn more:

  1.   Android Developers
  2. OMAPI vendor stable interface  
  3. Interface estável do fornecedor OMAPI  
  4. CTS test for Secure Element  
  5.   Android Developers
  6. android.se.omapi.SEService
  7. Secure Element Access Control
  8. Secure Element Access Control v1.1
  9. Secure Element Management Service v1.1.0.9
  10. GlobalPlatform Secure Element Access Control v1.2
  11. Method for allowing an access control enforcer to access to rules of a secure element with a single specific command, and associated device
  12. Secure Element Management Service v1.0
  13. OpenEUICC/README.md at master · AKoskovich/OpenEUICC · GitHub
  14. AXP-OS/packages_apps_OpenEUICC: (WIP) eSIM LPA (Local Profile Assistant) implementation for Android. System privilege required. Forked from https://gitea.angry.im/PeterCxy/OpenEUICC/
  15. WitAqua/packages_apps_OpenEUICC · GitHub
  16. hzy132/OpenEUICC_for_Magisk: OpenEUICC for Magisk. OpenEUICC is an eSIM LPA (Local Profile Assistant) implementation for Android. Also includes EasyEUICC. The release of this repository is automatically generated by GitHub Actions whenever there is a new commit in the original repository. · GitHub
  17. Chromium Docs
  18. AKoskovich/OpenEUICC · GitHub
  19. Privilégios da operadora do UICC  
  20. Privilegios de operador de UICC  
  21.   Android Open Source Project
  22. CoIMS_Wiki/README.md at master · herlesupreeth/CoIMS_Wiki · GitHub
  23.   Android Open Source Project
  24.   Android Open Source Project
  25. UICC not exposed → Third-party apps cannot access physical SIM (#9577) · Issues · LineageOS / issues / android · GitLab
  26. Android phone can not find a custom SIM card using "android.se.omapi.Reader.isSecureElementPresent()"
  27.   Android Developers
  28. OMAPI OpenLogicalChannel failed on Android 13
  29. Manage esim does nothing on Xiaomi 17 Pro · Issue #24 · tehcneko/XiaomiEsimLPA · GitHub
  30. The eSIM card is not working
Back to blog

Get your Switch eSIM Adapter today!

Unlock the World, Anytime Anywhere