init commитььиьа

This commit is contained in:
huker committed 2026-10-07 00:46:54 +03:00
commit ede7d165a4
12 files changed
+541

No files matched your search

+16
View File
@@ -0,0 +1,16 @@
# Build artifacts / release archives
*.zip
*.apk
!module/**/*.apk
# OS / editor junk
.DS_Store
Thumbs.db
*~
.idea/
.vscode/
*.swp
# Logs / temp
*.log
*.tmp
+114
View File
@@ -0,0 +1,114 @@
# eSIM Slots Fix — OnePlus 15R (macan)
Сделано с ебучим квеном 3.8 максим.
Полноценная поддержка eSIM для **OnePlus 15R (macan / CPH2767)** на портах LineageOS (Android 16).
---
## Проблема
Порты AOSP для OnePlus 15R поставляются с неработающей eSIM, хотя железо (чип eUICC) и вендорные HAL Oplus полностью присутствуют:
1. **В настройках нет страницы eSIM.** AOSP `EuiccManager` включает интерфейс встроенной SIM, только если слот объявлен как несъёмный eUICC. Стоковая прошивка Oplus передаёт это в рантайме; порты AOSP — нет.
2. **Чип eUICC не получает питание при загрузке.** На ColorOS/OxygenOS проприетарные сервисы Oplus выполняют последовательность включения (`setUimPower` / `setEsimStatus` / `setEsimGpio`) через вендорный HAL eSIM. В портах AOSP этих сервисов нет, и чип остаётся выключенным.
3. **RIL не считает слот 1 eUICC-слотом.** Qualcomm RIL ждёт специфичную для Oplus конфигурацию `SET_SIM_TYPE` после загрузки; без неё модем игнорирует встроенный слот.
## Что делает модуль
| Компонент | Файл | Назначение |
|---|---|---|
| RRO-оверлей | `product/overlay/EuiccSlotsFix.apk` | Переопределяет `config_non_removable_euicc_slots` в `[1]`, чтобы Настройки и EuiccManager показали eSIM |
| Демон активации | `esimd.sh` | Питает eUICC во время бутанимации и ведёт всю последовательность активации RIL |
| Ручной цикл | `esimd-manual.sh` | Одноразовая активация с живым прогрессом |
| Кнопка в KSU | `action.sh` | Кнопка действия модуля в KernelSU Manager: статус + ручная активация |
| Watchdog | `service.sh` | Перезапускает демон, если он умер |
| Хук загрузки | `post-fs-data.sh` | Монтирует RRO-оверлей (tmpfs) и рано запускает демон |
### Фазы демона
- **Фаза A (бутанимация):** ждёт появления `vendor.oplus.hardware.esim.IOplusEsim/default`, затем подаёт питание на eUICC через HAL Oplus. Чип жив ещё до окончания загрузки Android — тот же тайминг, что на стоке.
- **Фаза B (радио поднялось):** ждёт сервис `phone`, даёт RIL до 60 с самостоятельно обнаружить eUICC. Если не обнаружен — до 6 попыток активации: `SET_SIM_TYPE [1,1]` → рестарт qcrild → ожидание ресинка RIL (`Received GET_SIM_TYPE_INFO`) → `SET_SIM_TYPE [1,2]` → ожидание определения карты.
- **Фаза C (постоянный монитор):** каждые 30 с проверяет наличие eSIM. Два подряд сбоя — автоматическая реактивация. eSIM восстанавливается без участия пользователя.
## Технические детали
### Последовательность питания eUICC (вендорные HAL Oplus)
```
vendor.oplus.hardware.esim.IOplusEsim/default
tx 1 = getEsimGpio
tx 3 = setEsimGpio(1)
tx 5 = setUimPower(0|1)
vendor.oplus.hardware.subsys_interface.subsys_radio.ISubsysRadio/slot1
tx 289 = setEsimStatus(91, 1)
Порядок: setUimPower(0) -> setEsimStatus(91,1) -> setEsimGpio(1) -> setUimPower(1)
Контрольное чтение GPIO должно вернуть 00000001
```
### SET_SIM_TYPE (транзакция 175 ITelephony)
```
service call phone 175 \
i32 2 i32 1 i32 0 i32 0 i32 0 i32 1 i32 1 i32 0 i32 1 i32 1 i32 <T>
T = 1 только физические слоты (сбрасывает RIL)
T = 2 физический + eUICC (финальная конфигурация)
```
Порядок `[1,1] → рестарт qcrild → [1,2]` обязателен: модем применяет тип
eUICC-слота только после чистой реинициализации RIL.
### Маркеры успеха
- radio logcat: `Received GET_SIM_TYPE_INFO` (RIL ресинкнулся)
- radio logcat: `[1] recv card status:3` (карта eUICC отвечает)
- `dumpsys isub`: активная подписка с `simSlotIndex=1 portIndex=0 isEmbedded=1`
## Требования
- OnePlus 15R (macan, CPH2767), порт LineageOS на Android 16
- KernelSU (проверено на KSU 3.3.0 с SUSfs)
- Вендорный образ Oplus с рабочими HAL `esim` и `subsys_radio`
- Хотя бы один eSIM-профиль, загруженный в eUICC (проверено с MTS BY; переключение профилей MTS BY ⇄ Roamless работает)
> Примечание: в KernelSU 3.x нет magic mount, поэтому RRO разворачивается
> tmpfs-биндом поверх `/product/overlay` в `post-fs-data.sh`, а не папкой `system/`.
## Использование
- **Автоматически:** делать ничего не нужно. eUICC запитывается во время бутанимации, eSIM регистрируется через ~20–30 с после загрузки.
- **Вручную:** KernelSU → Модули → *eSIM Slots Fix* → кнопка действия. Показывает текущий статус, выполняет полный цикл активации с живым прогрессом, выводит результат и последние строки лога.
## Логи
- `/data/adb/euicc_daemon.log` — активность демона, ручные циклы, события монитора (автообрезка на 256 КБ)
- `/data/adb/esimd.pid` — PID демона
## Ограничения
- В устройстве **один чип eUICC**: одновременно активен только один eSIM-профиль. Одновременные два eSIM (MEP) не поддерживаются конфигурацией модема — поведение такое же, как на стоковой прошивке.
- Физическая nano-SIM + eSIM работают одновременно (DSDS, 2 активные подписки).
- Дополнительные bundled-правки, не связанные с eSIM: флаг поддержки спутниковой телефонии и override idle-таймера SurfaceFlinger (анти-мерцание для LTPO-панелей).
## Структура проекта
```
EuiccSlotsFix/
├── README.md английский readme
├── README-RU.md этот файл
└── module/
├── module.prop
├── customize.sh
├── post-fs-data.sh
├── service.sh
├── action.sh
├── esimd.sh
├── esimd-manual.sh
└── product/
├── overlay/EuiccSlotsFix.apk
└── etc/permissions/android.hardware.telephony.satellite.xml
```
+113
View File
@@ -0,0 +1,113 @@
# eSIM Slots Fix — OnePlus 15R (macan)
Built with Qwen3.8 Max!1!1!1!11
Full eSIM support for **OnePlus 15R (macan / CPH2767)** running LineageOS-based Android 16 ports.
---
## The Problem
AOSP-based ports for OnePlus 15R ship without working eSIM, even though the hardware (eUICC chip) and Oplus vendor HALs are fully present:
1. **Settings does not show the eSIM page.** AOSP `EuiccManager` only enables the embedded SIM UI when a slot is reported as a non-removable eUICC. The Oplus stock framework injects this at runtime; AOSP ports do not.
2. **The eUICC chip is never powered on at boot.** On ColorOS/OxygenOS, proprietary Oplus framework services run the power-up sequence (`setUimPower` / `setEsimStatus` / `setEsimGpio`) through the vendor eSIM HAL. Those services do not exist on AOSP ports, so the chip stays dead.
3. **The RIL does not treat slot 1 as an eUICC.** Qualcomm RIL expects an Oplus-specific `SET_SIM_TYPE` configuration push after boot; without it the modem ignores the embedded slot.
## What This Module Does
| Component | File | Purpose |
|---|---|---|
| RRO overlay | `product/overlay/EuiccSlotsFix.apk` | Overrides `config_non_removable_euicc_slots` to `[1]` so Settings and EuiccManager expose the eSIM UI |
| Activation daemon | `esimd.sh` | Powers the eUICC during boot animation and drives the full RIL activation sequence |
| Manual cycle | `esimd-manual.sh` | One-shot activation with live progress output |
| KSU action button | `action.sh` | Module action in KernelSU Manager: status + manual activation |
| Watchdog | `service.sh` | Respawns the daemon if it dies |
| Boot hook | `post-fs-data.sh` | Mounts the RRO overlay (tmpfs) and starts the daemon early |
### Daemon phases
- **Phase A (boot animation):** waits for `vendor.oplus.hardware.esim.IOplusEsim/default`, then powers the eUICC via the Oplus HAL power sequence. The chip is alive before Android finishes booting — the same timing as stock firmware.
- **Phase B (radio up):** waits for the `phone` service, gives the RIL up to 60 s to detect the eUICC on its own. If not detected, runs up to 6 activation attempts: `SET_SIM_TYPE [1,1]` → qcrild restart → wait for RIL re-sync (`Received GET_SIM_TYPE_INFO`) → `SET_SIM_TYPE [1,2]` → wait for card detection.
- **Phase C (runtime monitor):** checks eSIM presence every 30 s forever. Two consecutive failures trigger automatic re-activation. The eSIM comes back without user interaction.
## Technical Details
### eUICC power sequence (Oplus vendor HALs)
```
vendor.oplus.hardware.esim.IOplusEsim/default
tx 1 = getEsimGpio
tx 3 = setEsimGpio(1)
tx 5 = setUimPower(0|1)
vendor.oplus.hardware.subsys_interface.subsys_radio.ISubsysRadio/slot1
tx 289 = setEsimStatus(91, 1)
Order: setUimPower(0) -> setEsimStatus(91,1) -> setEsimGpio(1) -> setUimPower(1)
GPIO readback must return 00000001
```
### SET_SIM_TYPE (ITelephony transaction 175)
```
service call phone 175 \
i32 2 i32 1 i32 0 i32 0 i32 0 i32 1 i32 1 i32 0 i32 1 i32 1 i32 <T>
T = 1 physical-only slot map (forces RIL reset)
T = 2 physical + eUICC (final configuration)
```
The `[1,1] → qcrild restart → [1,2]` order is required: the modem applies the
eUICC slot type only after a clean RIL re-initialization.
### Success markers
- radio logcat: `Received GET_SIM_TYPE_INFO` (RIL re-synced)
- radio logcat: `[1] recv card status:3` (eUICC card responding)
- `dumpsys isub`: active subscription with `simSlotIndex=1 portIndex=0 isEmbedded=1`
## Requirements
- OnePlus 15R (macan, CPH2767), LineageOS-based Android 16 port
- KernelSU (tested on KSU 3.3.0 with SUSfs)
- Oplus vendor image with working `esim` and `subsys_radio` HALs
- At least one eSIM profile downloaded to the eUICC (tested with MTS BY; profile switching MTS BY ⇄ Roamless works)
> Note: KernelSU 3.x has no magic mount, so the RRO is deployed with a tmpfs
> bind over `/product/overlay` in `post-fs-data.sh` instead of a `system/` dir.
## Usage
- **Automatic:** nothing to do. eUICC powers during boot animation, eSIM registers ~20–30 s after boot.
- **Manual:** KernelSU → Modules → *eSIM Slots Fix* → action button. Shows current status, runs the full activation cycle with live progress, prints the result and recent log lines.
## Logs
- `/data/adb/euicc_daemon.log` — daemon activity, manual cycles, monitor events (auto-truncated at 256 KB)
- `/data/adb/esimd.pid` — daemon PID
## Limitations
- The device has a **single eUICC chip**: only one eSIM profile can be active at a time. Simultaneous dual-eSIM (MEP) is not supported by the modem configuration — same behavior as stock firmware.
- Physical nano-SIM + eSIM work simultaneously (DSDS, 2 active subscriptions).
- Bundled extras unrelated to eSIM: satellite telephony feature flag and a SurfaceFlinger idle-timer override (anti-flicker for LTPO panels).
## Project Layout
```
EuiccSlotsFix/
├── README.md this file
├── README-RU.md Russian readme
└── module/
├── module.prop
├── customize.sh
├── post-fs-data.sh
├── service.sh
├── action.sh
├── esimd.sh
├── esimd-manual.sh
└── product/
├── overlay/EuiccSlotsFix.apk
└── etc/permissions/android.hardware.telephony.satellite.xml
```
+40
View File
@@ -0,0 +1,40 @@
#!/system/bin/sh
LOG=/data/adb/euicc_daemon.log
ESIM_SVC="vendor.oplus.hardware.esim.IOplusEsim/default"
gpio_st() {
service call "$ESIM_SVC" 1 2>/dev/null | grep -oE '[0-9a-f]{8} [0-9a-f]{8}' | head -1 | awk '{print $2}'
}
status() {
G=$(gpio_st)
D=$(dumpsys isub 2>/dev/null | grep -c 'simSlotIndex=1 portIndex=0 isEmbedded=1')
N=$(dumpsys isub 2>/dev/null | grep 'simSlotIndex=1 ' | grep -oE 'displayName=[^ ]+' | head -1)
if [ "$G" = "00000001" ]; then
echo "eUICC power : ON"
else
echo "eUICC power : OFF ($G)"
fi
if [ "${D:-0}" -ge 1 ]; then
echo "eSIM in slot: YES $N"
else
echo "eSIM in slot: NO"
fi
}
echo "=== eSIM Fix ==="
status
echo
echo "Running activation cycle (~1-2 min)..."
echo
sh /data/adb/modules/euicc_slots_fix/esimd-manual.sh
echo
echo "=== Result ==="
status
echo
echo "Log:"
tail -8 "$LOG" 2>/dev/null
if [[ -z "$MMRL" ]] && ([[ -n "$KSU" ]] || [[ -n "$APATCH" ]]); then
sleep 10
fi
+12
View File
@@ -0,0 +1,12 @@
ui_print "- eSIM Slots Fix v1.1"
ui_print "- by huker667"
ui_print "- OnePlus 15R (macan), LineageOS-based Android 16"
set_perm_recursive "$MODPATH" 0 0 0755 0644
set_perm "$MODPATH/post-fs-data.sh" 0 0 0755
set_perm "$MODPATH/service.sh" 0 0 0755
set_perm "$MODPATH/action.sh" 0 0 0755
set_perm "$MODPATH/esimd.sh" 0 0 0755
set_perm "$MODPATH/esimd-manual.sh" 0 0 0755
ui_print "- Done. Reboot to activate."
+57
View File
@@ -0,0 +1,57 @@
#!/system/bin/sh
ESIM_SVC="vendor.oplus.hardware.esim.IOplusEsim/default"
SUB_SVC="vendor.oplus.hardware.subsys_interface.subsys_radio.ISubsysRadio/slot1"
LOG=/data/adb/euicc_daemon.log
M1="i32 2 i32 1 i32 0 i32 0 i32 0 i32 1 i32 1 i32 0 i32 1 i32 1 i32 1"
M2="i32 2 i32 1 i32 0 i32 0 i32 0 i32 1 i32 1 i32 0 i32 1 i32 1 i32 2"
log() {
echo "$(date '+%F %T') [manual] $*" >> "$LOG"
echo "$*"
}
gpio_state() {
service call "$ESIM_SVC" 1 2>/dev/null | grep -oE '[0-9a-f]{8} [0-9a-f]{8}' | head -1 | awk '{print $2}'
}
detected() {
dumpsys isub 2>/dev/null | grep -c 'simSlotIndex=1 portIndex=0 isEmbedded=1'
}
log "=== manual cycle start ==="
service call "$ESIM_SVC" 5 i32 0 >/dev/null 2>&1
service call "$SUB_SVC" 289 i32 91 i32 1 >/dev/null 2>&1
service call "$ESIM_SVC" 3 i32 1 >/dev/null 2>&1
service call "$ESIM_SVC" 5 i32 1 >/dev/null 2>&1
sleep 1
log "gpio=$(gpio_state)"
logcat -c -b radio 2>/dev/null
service call phone 175 $M1 >/dev/null 2>&1
sleep 2
log "SET_SIM_TYPE[1,1] sent, restarting qcrild..."
setprop ctl.restart vendor.qcrild
setprop ctl.restart vendor.qcrild2
t=0
while [ $t -lt 40 ]; do
n=$(logcat -d -b radio 2>/dev/null | grep -c "Received GET_SIM_TYPE_INFO")
[ "${n:-0}" -ge 1 ] 2>/dev/null && break
sleep 1
t=$((t+1))
done
log "ril sync after ${t}s"
service call phone 175 $M2 >/dev/null 2>&1
log "SET_SIM_TYPE[1,2] sent, waiting for eSIM detection..."
p=0
while [ $p -lt 15 ]; do
sleep 3
p=$((p+1))
d=$(detected)
[ "${d:-0}" -ge 1 ] 2>/dev/null && break
done
log "=== manual cycle done: detect=$(detected) ($((p * 3))s) ==="
pgrep -f esimd.sh >/dev/null 2>&1 || setsid /system/bin/sh /data/adb/modules/euicc_slots_fix/esimd.sh >/dev/null 2>&1 </dev/null &
exit 0
+132
View File
@@ -0,0 +1,132 @@
#!/system/bin/sh
ESIM_SVC="vendor.oplus.hardware.esim.IOplusEsim/default"
SUB_SVC="vendor.oplus.hardware.subsys_interface.subsys_radio.ISubsysRadio/slot1"
LOG=/data/adb/euicc_daemon.log
M1="i32 2 i32 1 i32 0 i32 0 i32 0 i32 1 i32 1 i32 0 i32 1 i32 1 i32 1"
M2="i32 2 i32 1 i32 0 i32 0 i32 0 i32 1 i32 1 i32 0 i32 1 i32 1 i32 2"
log() { echo "$(date '+%F %T') $*" >> "$LOG"; }
if [ -f "$LOG" ] && [ "$(wc -c < "$LOG" 2>/dev/null)" -gt 262144 ]; then
tail -c 65536 "$LOG" > "$LOG.tmp" && mv "$LOG.tmp" "$LOG"
fi
gpio_state() {
service call "$ESIM_SVC" 1 2>/dev/null | grep -oE '[0-9a-f]{8} [0-9a-f]{8}' | head -1 | awk '{print $2}'
}
gpio_on() {
service call "$ESIM_SVC" 5 i32 0 >/dev/null 2>&1
service call "$SUB_SVC" 289 i32 91 i32 1 >/dev/null 2>&1
service call "$ESIM_SVC" 3 i32 1 >/dev/null 2>&1
service call "$ESIM_SVC" 5 i32 1 >/dev/null 2>&1
}
esim_detected() {
dumpsys isub 2>/dev/null | grep -c 'simSlotIndex=1 portIndex=0 isEmbedded=1'
}
card_up() {
logcat -d -b radio 2>/dev/null | grep -cF "[1] recv card status:3"
}
echo $$ > /data/adb/esimd.pid
log "=== esimd started pid=$$ ==="
i=0
while [ $i -lt 600 ]; do
service check "$ESIM_SVC" 2>/dev/null | grep -q ': found' && break
sleep 0.5
i=$((i+1))
done
log "phaseA: esim HAL ready after ~$((i/2))s"
G=$(gpio_state)
if [ "$G" != "00000001" ]; then
j=0
while [ $j -lt 10 ]; do
gpio_on
sleep 1
G=$(gpio_state)
[ "$G" = "00000001" ] && break
j=$((j+1))
done
log "phaseA: gpio powered, state=$G tries=$((j+1))"
else
log "phaseA: gpio already ON"
fi
i=0
while [ $i -lt 300 ]; do
service check phone 2>/dev/null | grep -q ': found' && break
sleep 1
i=$((i+1))
done
log "phaseB: phone service after ~${i}s"
w=0
while [ $w -lt 60 ]; do
[ "$(esim_detected)" -ge 1 ] 2>/dev/null && break
sleep 3
w=$((w+3))
done
attempt=0
while [ $attempt -lt 6 ]; do
D=$(esim_detected)
if [ "${D:-0}" -ge 1 ] 2>/dev/null; then
log "phaseB: eSIM UP (attempt $attempt, detect=$D card=$(card_up))"
break
fi
attempt=$((attempt+1))
log "phaseB: attempt $attempt (detect=$D card=$(card_up))"
G=$(gpio_state)
if [ "$G" != "00000001" ]; then
gpio_on
sleep 1
fi
logcat -c -b radio 2>/dev/null
service call phone 175 $M1 >/dev/null 2>&1
sleep 2
setprop ctl.restart vendor.qcrild
setprop ctl.restart vendor.qcrild2
t=0
while [ $t -lt 40 ]; do
n=$(logcat -d -b radio 2>/dev/null | grep -c "Received GET_SIM_TYPE_INFO")
[ "${n:-0}" -ge 1 ] 2>/dev/null && break
sleep 1
t=$((t+1))
done
service call phone 175 $M2 >/dev/null 2>&1
p=0
while [ $p -lt 12 ]; do
sleep 3
p=$((p+1))
[ "$(card_up)" -ge 1 ] 2>/dev/null && break
done
done
log "phaseB: done, detect=$(esim_detected) card=$(card_up)"
fails=0
while true; do
sleep 30
if [ "$(esim_detected)" -ge 1 ] 2>/dev/null; then
fails=0
else
fails=$((fails+1))
log "monitor: eSIM not detected (fails=$fails)"
if [ $fails -ge 2 ]; then
log "monitor: reactivating"
gpio_on
sleep 1
service call phone 175 $M1 >/dev/null 2>&1
sleep 2
setprop ctl.restart vendor.qcrild
sleep 10
service call phone 175 $M2 >/dev/null 2>&1
fails=0
fi
fi
done
+6
View File
@@ -0,0 +1,6 @@
id=euicc_slots_fix
name=eSIM Slots Fix
version=v1.1
versionCode=2
author=huker667
description=Full eSIM support for OnePlus 15R (macan) on LineageOS-based Android 16 ports. RRO for eUICC slot visibility, early boot activation daemon with auto-recovery, manual activation action button.
+37
View File
@@ -0,0 +1,37 @@
#!/system/bin/sh
MODDIR=${0%/*}
TMP=/dev/euicc_overlay_tmp
SRC=/product/overlay
if [ -f "$MODDIR/product/overlay/EuiccSlotsFix.apk" ]; then
rm -rf "$TMP" 2>/dev/null
mkdir -p "$TMP"
cp -a "$SRC/." "$TMP/" 2>/dev/null
cp -a "$MODDIR/product/overlay/EuiccSlotsFix.apk" "$TMP/" 2>/dev/null
mount -t tmpfs -o mode=755 tmpfs "$SRC"
cp -a "$TMP/." "$SRC/" 2>/dev/null
chown -R root:root "$SRC"
chmod 755 "$SRC"
restorecon -R "$SRC" 2>/dev/null
rm -rf "$TMP"
fi
PTMP=/dev/perm_tmp
PERM=/product/etc/permissions
if [ -f "$MODDIR/product/etc/permissions/android.hardware.telephony.satellite.xml" ]; then
rm -rf "$PTMP" 2>/dev/null
mkdir -p "$PTMP"
cp -a "$PERM/." "$PTMP/" 2>/dev/null
cp -a "$MODDIR/product/etc/permissions/android.hardware.telephony.satellite.xml" "$PTMP/" 2>/dev/null
mount -t tmpfs -o mode=755 tmpfs "$PERM"
cp -a "$PTMP/." "$PERM/" 2>/dev/null
chown -R root:root "$PERM"
chmod 755 "$PERM"
chmod 644 "$PERM"/*.xml 2>/dev/null
restorecon -R "$PERM" 2>/dev/null
rm -rf "$PTMP"
fi
/data/adb/ksu/bin/resetprop ro.surface_flinger.set_idle_timer_ms 3000
setsid /system/bin/sh "$MODDIR/esimd.sh" >/dev/null 2>&1 </dev/null &
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<permissions>
<feature name="android.hardware.telephony.satellite" />
</permissions>
Binary file not shown.
+10
View File
@@ -0,0 +1,10 @@
#!/system/bin/sh
until [ "$(getprop sys.boot_completed)" = "1" ]; do sleep 2; done
sleep 5
while true; do
if ! pgrep -f esimd.sh >/dev/null 2>&1; then
echo "$(date) esimd not running, respawning" >> /data/adb/euicc_daemon.log
setsid /system/bin/sh /data/adb/modules/euicc_slots_fix/esimd.sh >/dev/null 2>&1 </dev/null &
fi
sleep 20
done