From 4d9250fc2e282c17726c7b193837e64f467c0935 Mon Sep 17 00:00:00 2001 From: Laiteux Date: Tue, 3 Feb 2026 12:55:59 +0400 Subject: [PATCH] Add README --- README.md | 237 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 237 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..dd5fec6 --- /dev/null +++ b/README.md @@ -0,0 +1,237 @@ +# openeuicc-bridge + +An Android ContentProvider that exposes [OpenEUICC/EasyEUICC](https://gitea.angry.im/PeterCxy/OpenEUICC) LPA functionality via ADB, enabling programmatic eSIM profile management. + +## Build & Install + +```bash +./build+install.sh +``` + +The script: +1. Compiles [`LpaProvider.java`](https://github.com/Laiteux/openeuicc-bridge/blob/main/src/im/angry/openeuicc/bridge/LpaProvider.java) to `.class` files +2. Converts to `.dex` using d8, then disassembles to smali +3. Injects smali into the decompiled EasyEUICC APK +4. Rebuilds and signs the APK with [9eSIM Community Key](https://github.com/9esim/9eSIMCommunityKey) +5. Installs via `adb install` + +**Requirements:** apktool, adb, java, javac + +**Included:** Build tools in `tools/`, Java dependencies in `deps/` + +## Content Authority + +``` +content://lpa/ +``` + +## Endpoints + +| Endpoint | Description | Input | Output | +|----------|-------------|-------|--------| +| `cards` | List eSIM cards | — | `slot`, `port`, `eid` | +| `profiles` | Get profiles on a card | `slot`, `port` | `iccid`, `enabled`, `provider`, `nickname` | +| `downloadProfile` | Download a profile | `slot`, `port`, `activationCode`¹, `address`¹, `matchingId`?, `confirmationCode`?, `imei`?, `callbackUrl`? | `iccid`, `enabled`, `provider`, `nickname` | +| `deleteProfile` | Delete a profile | `slot`, `port`, `iccid` | `success` | +| `enableProfile` | Enable a profile | `slot`, `port`, `iccid`, `refresh`?=true | `success` | +| `setProfileNickname` | Set/clear profile nickname | `slot`, `port`, `iccid`, `nickname`?="" | `success` | +| `preferences` | Get all preferences | — | `name`, `enabled` | +| `setPreference` | Set a preference | `name`, `enabled` | `success` | + +¹ Provide either `activationCode` OR `address` +? = optional + +## Usage Examples + +#### List cards + +```bash +adb shell content query --uri 'content://lpa/cards' +``` +``` +Row: 0 slot=0, port=0, eid=89049032123456789012345678901234 +Row: 1 slot=1, port=0, eid=89044012345678901234567890123456 +``` + +#### List profiles + +```bash +adb shell content query --uri 'content://lpa/profiles?slot=0&port=0' +``` +``` +Row: 0 iccid=8901234567890123456, enabled=true, provider=Example Carrier, nickname=Work +Row: 1 iccid=8909876543210987654, enabled=false, provider=Another Carrier, nickname=NULL +``` + +#### Download profile + +With activation code: +```bash +adb shell content query --uri 'content://lpa/downloadProfile?slot=0&port=0&activationCode=LPA:1$smdp.example.com$ABC123' +``` + +With address and matching ID: +```bash +adb shell content query --uri 'content://lpa/downloadProfile?slot=0&port=0&address=smdp.example.com&matchingId=ABC123' +``` + +With confirmation code: +```bash +adb shell content query --uri 'content://lpa/downloadProfile?slot=0&port=0&activationCode=LPA:1$smdp.example.com$ABC123&confirmationCode=1234' +``` + +With callback URL: +```bash +adb shell content query --uri 'content://lpa/downloadProfile?slot=0&port=0&activationCode=LPA:1$smdp.example.com$ABC123&callbackUrl=https://example.com/callback' +``` +``` +Row: 0 iccid=8901234567890123456, enabled=true, provider=Example Carrier, nickname=NULL +``` + +#### Delete profile + +```bash +adb shell content query --uri 'content://lpa/deleteProfile?slot=0&port=0&iccid=8901234567890123456' +``` +``` +Row: 0 success=true +``` + +#### Enable profile + +```bash +adb shell content query --uri 'content://lpa/enableProfile?slot=0&port=0&iccid=8901234567890123456' +``` +``` +Row: 0 success=true +``` + +#### Set profile nickname + +```bash +adb shell content query --uri 'content://lpa/setProfileNickname?slot=0&port=0&iccid=8901234567890123456&nickname=Work' +``` + +Clear profile nickname: +```bash +adb shell content query --uri 'content://lpa/setProfileNickname?slot=0&port=0&iccid=8901234567890123456' +``` +``` +Row: 0 success=true +``` + +#### Get preferences + +```bash +adb shell content query --uri 'content://lpa/preferences' +``` +``` +Row: 0 name=verboseLogging, enabled=false +Row: 1 name=safeguardActiveProfile, enabled=true +Row: 2 name=filterProfileList, enabled=true +Row: 3 name=ignoreTlsCertificate, enabled=true +Row: 4 name=notificationsDownload, enabled=false +Row: 5 name=notificationsDelete, enabled=false +Row: 6 name=notificationsEnableDisable, enabled=false +``` + +#### Set preference + +```bash +adb shell content query --uri 'content://lpa/setPreference?name=ignoreTlsCertificate&enabled=true' +``` +``` +Row: 0 success=true +``` + +#### Error example + +```bash +adb shell content query --uri 'content://lpa/profiles' +``` +``` +Row: 0 error=missing_arg_slot +``` + +### JSON Output + +Add the `json` parameter to any endpoint to receive results as JSON in a single `rows` column. + +```bash +adb shell content query --uri 'content://lpa/profiles?slot=0&port=0&json' +``` + +Example outputs: + +```json +// cards +[ + {"slot":0,"port":0,"eid":"89049032123456789012345678901234"}, + {"slot":1,"port":0,"eid":"89044012345678901234567890123456"} +] + +// profiles +[ + {"iccid":"8901234567890123456","enabled":true,"provider":"Example Carrier","nickname":"Work"}, + {"iccid":"8909876543210987654","enabled":false,"provider":"Another Carrier","nickname":null} +] + +// preferences +[ + {"name":"verboseLogging","enabled":false}, + {"name":"safeguardActiveProfile","enabled":true}, + {"name":"filterProfileList","enabled":true}, + {"name":"ignoreTlsCertificate","enabled":true}, + {"name":"notificationsDownload","enabled":false}, + {"name":"notificationsDelete","enabled":false}, + {"name":"notificationsEnableDisable","enabled":false} +] + +// success response (enableProfile, deleteProfile, setProfileNickname, setPreference) +[ + {"success":true} +] + +// error response +[ + {"error":"missing_arg_slot"} +] +``` + +## Errors + +Errors are returned in an `error` column: +- `no_endpoint` - No endpoint specified +- `unknown_endpoint` - Endpoint not found +- `missing_arg_` - Required argument missing +- `unknown_preference_name` - Invalid preference name +- `safeguard_active_profile` - Operation blocked by safeguard + +## Preferences + +| Name | Description | +|------|-------------| +| `verboseLogging` | Enable verbose logging | +| `forceUseTelephonyManager` | Force use TelephonyManager API (privileged only) | +| `safeguardActiveProfile` | Prevent operations on active profile | +| `filterProfileList` | Filter to show only operational profiles | +| `ignoreTlsCertificate` | Ignore TLS certificate errors | +| `notificationsDownload` | Process download notifications | +| `notificationsDelete` | Process delete notifications | +| `notificationsEnableDisable` | Process enable/disable notifications | + +## Download profile callback URL + +When `callbackUrl` is provided for `downloadProfile`, progress updates are POSTed as JSON: + +```json +{ + "timestamp": 1770108790, + "state": "Authenticating", + "progress": 40, + "address": "smdp.example.com", + "matchingId": "ABC123", + "confirmationCode": null, + "imei": null +} +```