488df98996
Silences browser accessibility warnings on the HA token, MQTT username, and MQTT password fields. Uses new-password for the secret inputs to discourage Chrome's site-password autofill from leaking into broker / HA-token configuration.
90 lines
6.0 KiB
Markdown
90 lines
6.0 KiB
Markdown
# LedGrab TODO
|
|
|
|
## Android — Restore Multi-ABI Wheels
|
|
|
|
During emulator testing, we switched the build to **x86 only** (see `android/app/build.gradle.kts` `abiFilters`) to avoid having to keep the arm64-v8a / x86_64 pydantic-core wheels current. Before shipping, restore all three ABIs:
|
|
|
|
- [x] Rebuild `pydantic-core` wheels for all three ABIs with the current SOABI + libpython linking settings (`android/build-scripts/build-pydantic-core.sh` — now supports `arm64`, `x86_64`, `x86` args; defaults to all three).
|
|
- [x] Verify wheels: all three now list `libpython3.11.so` in `NEEDED` (`llvm-readelf -d`), automated in the build script.
|
|
- [x] Restored `abiFilters += listOf("arm64-v8a", "x86_64", "x86")` in `build.gradle.kts`. Multi-ABI debug APK builds cleanly (~99 MB).
|
|
- [ ] Re-test on real ARM64 Android TV hardware (still pending — only emulator-verified build).
|
|
|
|
Build cache + scripts live in `android/build-scripts/` and `android/.build-cache/` (junction host + sysconfigdata for each ABI).
|
|
|
|
## Android CI Pipeline
|
|
|
|
Build the Android APK automatically on push/tag.
|
|
|
|
- [x] Generate Gradle wrapper (`gradlew`) and commit it
|
|
- [x] Create CI workflow (`.gitea/workflows/build-android.yml`)
|
|
- JDK 17 + Android SDK + NDK setup
|
|
- Python 3.11 for Chaquopy build
|
|
- Recreate the directory junction via `ln -s` on Linux CI
|
|
- `./gradlew assembleDebug` on master push, `assembleRelease` on `v*` tags (if signing secrets set)
|
|
- Uploads APK as CI artifact; attaches to Gitea release on tag push
|
|
- [x] Commit pre-built pydantic-core wheels to `android/wheels/` (arm64, x86, x86_64)
|
|
- [x] APK signing for release builds — conditional signing config reads keystore from env vars (`ANDROID_KEYSTORE_PATH/_PASSWORD/_ALIAS/_KEY_PASSWORD`), falls back to debug signing locally
|
|
- [ ] Provision a real keystore and add the four CI secrets:
|
|
- `ANDROID_KEYSTORE_BASE64` (base64-encoded .jks)
|
|
- `ANDROID_KEYSTORE_PASSWORD`
|
|
- `ANDROID_KEY_ALIAS`
|
|
- `ANDROID_KEY_PASSWORD`
|
|
- [ ] Add `LedGrab-{tag}-android-release.apk` row to the release description table in `.gitea/workflows/release.yml` → `create-release` job
|
|
- [ ] Verify the CI workflow passes end-to-end with the now-restored multi-ABI build (larger APK, longer Android build step)
|
|
|
|
## Android Root Capture (No Permission Dialog, No System Indicator)
|
|
|
|
MediaProjection shows a mandatory system overlay/indicator while capturing — unavoidable on stock Android. Many cheap Android TV boxes ship pre-rooted, so an alternative root-only path would give much better UX.
|
|
|
|
- [ ] Detect root at runtime: check for `su` binary, `Superuser.apk`, etc.
|
|
- [ ] Implement `SurfaceControlCaptureEngine` (new capture engine) using hidden `SurfaceControl.screenshot()` API via reflection
|
|
- No permission dialog
|
|
- No system capture indicator
|
|
- Direct bitmap output (no encoder/decoder roundtrip)
|
|
- [ ] Engine priority: higher than MediaProjection when root detected
|
|
- [ ] Fallback chain: `SurfaceControl` (root) → `MediaProjection` (stock) → `adb screencap` (last resort)
|
|
- [ ] Handle Android version differences in `SurfaceControl` API surface (renamed/moved across API 29, 30, 33)
|
|
- [ ] Alternative: shell out to `screenrecord --output-format=h264 -` as root (same H.264 decode as scrcpy_client_engine, but local instead of remote ADB)
|
|
|
|
Known projects using this approach for reference: scrcpy-hidden-api, shizuku, commercial scrcpy-derived apps.
|
|
|
|
## Android USB Serial Support
|
|
|
|
Drive USB LED controllers (APA102, WS2812) connected directly to the Android TV box via USB-to-serial adapters.
|
|
|
|
- [ ] Add [usb-serial-for-android](https://github.com/mik3y/usb-serial-for-android) dependency to `android/app/build.gradle.kts`
|
|
- [ ] Create Kotlin `UsbSerialBridge` class that:
|
|
- Enumerates USB serial devices via Android USB Host API
|
|
- Requests user permission for USB device access
|
|
- Opens a serial connection (baud rate configurable)
|
|
- Exposes a write method callable from Python via Chaquopy
|
|
- [ ] Create Python `AndroidSerialProvider` in `server/src/ledgrab/core/devices/` that:
|
|
- Replaces `pyserial` on Android (which can't access USB ports)
|
|
- Calls `UsbSerialBridge` via Chaquopy to send LED data
|
|
- Registers as an alternative serial transport when `is_android()` is True
|
|
- [ ] Add USB device permission dialog to `MainActivity` (auto-triggered on device connect)
|
|
- [ ] Test with common USB-to-serial chips: CH340, CP2102, FTDI
|
|
- [ ] Document supported USB LED controllers in README
|
|
|
|
## Performance Metrics Abstraction
|
|
|
|
The codebase has direct `psutil.*` calls scattered across `api/routes/system.py` and `core/processing/metrics_history.py`, with ad-hoc `if psutil is not None` guards sprinkled in to support Android. This couples Android platform handling to every call site.
|
|
|
|
- [ ] Refactor: introduce `MetricsProvider` protocol in `utils/metrics.py` with methods like `cpu_percent()`, `memory_info()`, `process_info()`
|
|
- [ ] Implement `PsutilMetricsProvider` (desktop) and `NullMetricsProvider` (fallback when psutil missing)
|
|
- [ ] Later: `AndroidMetricsProvider` reading from `/proc` (see section below)
|
|
- [ ] Replace all direct `psutil.*` calls with the provider; only one factory location knows about psutil availability
|
|
|
|
## Android Performance Metrics
|
|
|
|
Currently `psutil` (used for CPU/RAM monitoring in the web UI) is not available on Android via Chaquopy. Metrics calls are guarded with `if psutil is not None` so they return no data on Android.
|
|
|
|
- [ ] Implement Android-native metrics collection:
|
|
- CPU usage via `/proc/self/stat` + `/proc/stat` parsing (no psutil needed)
|
|
- RAM usage via `/proc/meminfo` or `ActivityManager.getMemoryInfo()` through Chaquopy bridge
|
|
- App-specific memory via `Debug.getMemoryInfo()` (Kotlin → Python)
|
|
- [ ] Create `AndroidMetricsProvider` in `server/src/ledgrab/utils/` that implements the same interface as the psutil-based provider
|
|
- [ ] Wire into existing metrics endpoints (`/api/v1/system/metrics`) with platform detection
|
|
- [ ] Consider: device battery/temperature readings for TV boxes (some have thermal throttling)
|
|
- [ ] Optional: GPU usage via `/sys/class/kgsl/kgsl-3d0/gpubusy` on Adreno, Mali-specific paths for Mali GPUs
|