Panel Calibrator is a rooted display calibration utility for devices that expose panel compensation nodes through privileged system interfaces.
The project focuses on auditability first:
- read-only backup before any write-capable workflow
- explicit command preview for privileged operations
- model-prefix based profile selection
- vector-size checks before writing panel data
- no bundled private checksum implementation
This app is intended for lab, repair, and research environments where the operator already understands the target display stack and has authorization to use root access. It is not a consumer repair wizard.
The app can inspect or prepare shell commands for these interfaces:
/sys/class/lcd/panel/poc/sys/class/lcd/panel/poc_onoff/sys/class/lcd/panel/poc_mca/dev/poc/efs/afc/rewrited/efs/afc/apply_count/efs/afc/diff_data
Read-only scans and backups run directly through su -c. Any command that changes panel state, writes /dev/poc, or writes /efs/afc opens a confirmation dialog that shows the exact shell command and requires typing the current device model.
The vector write path is restricted to /sdcard/ and /storage/emulated/0/, and the app checks the byte size before writing to /dev/poc.
The app does not read raw /dev/poc content by default. That node is treated as a driver interface, not a normal file.
The backup action writes a timestamped directory under:
/sdcard/PanelCalibratorBackup/YYYYMMDD_HHMMSS/
Backup contents:
| Path | Contents |
|---|---|
meta/identity.txt |
root identity, model, device, build fingerprint, kernel, date |
meta/sysfs_poc_listing.txt |
ls -l /sys/class/lcd/panel/poc* |
sysfs/*.txt |
bounded text snapshots from /sys/class/lcd/panel/poc* |
dev/poc.metadata.txt |
/dev/poc ls/stat metadata only |
efs/afc/ |
recursive copy of /efs/afc |
efs/afc.find.txt |
source tree inventory |
efs/afc.ls-lR.txt |
source tree long listing |
The profile table is keyed by model prefix. Each profile defines vector size, grid size, resolution, and whether the legacy one-byte warm-up write is required before vector transfer.
| Profile group | Model prefixes | Vector size | Grid | Resolution | Warm-up write |
|---|---|---|---|---|---|
| Group A | SM-N950, SC-01K, SCV37 |
546008 |
80 x 80 |
1440 x 2960 |
SM-N950F/N |
| Group A | SM-G950, SC-02J, SCV36 |
532816 |
120 x 148 |
1440 x 2960 |
SM-G950F/N |
| Group A | SM-G955, SC-03J, SCV35 |
532816 |
120 x 148 |
1440 x 2960 |
SM-G955F/N |
| Group B | SM-G960, SC-02K, SCV38 |
536706 |
120 x 148 |
1440 x 2960 |
no |
| Group B | SM-G965, SC-03K, SCV39 |
536706 |
120 x 148 |
1440 x 2960 |
no |
| Group B | SM-N960, SC-01L, SCV40 |
536706 |
80 x 80 |
1440 x 2960 |
no |
| Group C | SM-G970 |
310846 |
120 x 120 |
1080 x 2280 |
no |
| Group D | SM-G973, SC-03L, SCV41 |
551186 |
160 x 160 |
1440 x 3040 |
no |
| Group D | SM-G975, SC-04L, SC-05L, SCV42 |
551186 |
160 x 160 |
1440 x 3040 |
no |
| Group D | SM-G977 |
551186 |
160 x 160 |
1440 x 3040 |
no |
| Group E | SM-A605 |
302686 |
60 x 60 |
1080 x 2220 |
no |
| Group E | SM-A750 |
302686 |
60 x 60 |
1080 x 2220 |
no |
| Group E | SM-G885 |
302686 |
60 x 60 |
1080 x 2220 |
no |
./gradlew :app:testDebugUnitTest :app:assembleDebug --no-daemonDebug APK:
app/build/outputs/apk/debug/app-debug.apk
| Component | Version |
|---|---|
| AGP | 9.2.1 |
| Gradle wrapper | 9.4.1 |
| Kotlin / Compose compiler plugin | 2.4.0 |
| Compose UI | 1.10.0 |
| Material icons extended | 1.7.8 |
| Material3 | 1.4.0 |
| Activity Compose | 1.13.0 |
| compileSdk | 36 |
| targetSdk | 36 |
The workflow in .github/workflows/build.yml runs unit tests and builds the debug APK on pushes and pull requests. It uploads the APK as a workflow artifact for inspection.
MIT. See LICENSE.