Skip to content

About

Native AOD and FOD compatibility for Rodin / POCO X7 Pro ColorOS ports with NEES4 shared authorization

Resources

Security policy

Stars

14 stars

Watchers

0 watching

Forks

Repository files navigation

NEESS COS AOD + FOD FIX (POCO X7 Pro / Rodin)

Platform Device SELinux Touch FOD License

Native under-display fingerprint (FOD) and Always-On Display (AOD) hardware compatibility layer for POCO X7 Pro (Rodin) running ColorOS ports.

The Rodin sensor wrapper also supports Rise to wake on ColorOS using Xiaomi pickup events while retaining the screen-off fingerprint hint. See sensor/README.md for the tested build and behavior.

Achieves full OEM-grade FOD unlock, instant optical highlight turn-off, zero lockscreen dimming, seamless animations, and AOD modes without patching ColorOS SystemUI bytecode and without requiring root / Magisk / KernelSU.


Recent FOD/AOD changes

  • A real screen-off single tap restores the AOD clock and fingerprint hint when AOD is enabled and its schedule permits it. With AOD disabled, it shows the hint only; pickup does not force the clock on. See the single-tap integration guide.

  • Hardware FOD events are drained without blocking the sysfs fallback. Drivers without reliable notifications use an 8 ms fallback during active biometric sessions and a slower idle check. Authentication and the vendor's LHBM-ready synchronization remain unchanged.

  • The AOD daemon accepts ColorOS named and numeric wakefulness states, avoids panel overrides while interactive, and refreshes hint mode on native wake events after AOD settings change.

  • /system/bin/nees_aodd has an explicit shell_exec file-context entry for its existing shell service domain. Keep SELinux Enforcing.

  • Double-tap to wake follows the ColorOS Settings toggle through Xiaomi's touch HAL. See the DT2W framework guide; Settings.apk remains unchanged.

  • Call proximity is a separate oplus-services.jar fix. Use the proximity source patcher and guide; do not replace the sensor HAL to apply it.

See updating an existing ROM for builds, permanent installation, rollback and the test matrix. Other touchscreen/fingerprint pairings require their own hardware verification; the shared path does not establish equal speed on every sensor.

Working fixes

Feature Result
FOD Under-display fingerprint unlock, including Goodix and Jiiov FOD sensors.
SOFOD Fingerprint unlock while the display is off.
SOFOD hint Fingerprint icon appears on the screen-off display when needed.
Rise to wake A gentle lift wakes the lock screen and keeps the SOFOD hint working.
Front ALS & Auto-Brightness Stream Bridges Xiaomi als_raw photodiode events to android.sensor.light and subtracts OLED panel optical leakage.
Jiiov idle FOD touch After unlock, Jiiov FOD touch is disarmed on the screen-on launcher so stray presses do not illuminate LHBM; screen-off and new biometric sessions re-arm it. Goodix FOD behavior is unchanged.
AOD All three ColorOS AOD modes work, including All day and Power saving; the vendor Doze overlay supplies the framework Doze service and light sensor resources.

Companion Compatibility Repositories

  • ColorOS Display & Brightness Mapping (Coloros-display-autobrightness-fix-Rodin): Provides the physical DisplayDeviceConfig XML (display_id_4627039422300187648.xml), 2.0-nit night brightness floor adjustment (display_brightness_config_default.xml), and ColorOS lux-to-nit spline curves. Pairs with this repository's sensor HAL (sensors.mt6899.so) to deliver calibrated, instant auto-brightness without binary overwrite conflicts.

The Rise to wake fix is on current main; the earlier v4.0-working-final tag does not include it.

The Rodin AOD Doze overlay source and the installed APK are included for ROM baking. The current framework maps its two string resources; its config_dozeAfterScreenOff boolean is absent from this framework and has no effect.


Architecture Overview

                  ColorOS SystemUI / Keyguard / PowerManager
                                      |
                     +----------------+----------------+
                     |                                 |
                     v                                 v
        [librodin_fp_compat.so]                  [nees_aodd]
    (Bionic DT_NEEDED in mfp-daemon)      (Native Rust AOD Daemon)
                     |                                 |
   +-----------------+-----------------+               |
   |                                   |               |
   v                                   v               v
ColorOS AIDL Interfaces        Xiaomi Hardware Path   Display & Panel
* IBiometricsFingerprint       * Goodix / FocalTech   * Backlight control
* IDisplayPanelFeature           TouchFeature HAL     * Sysfs disp_feature
  - Feature 211 (LHBM = 410)   * /dev/disp_feature    * SOFOD hint state
  - Feature 217 (Smooth AOD)   * /dev/input (FOD)     * Zero-fork stream
  - Feature 22 (HBM off)       * Instant LHBM off

Key Features & Fixes

1. Instant LHBM Off on Authentication (OEM Match)

  • The Bug: On stock ColorOS ports, when the user unlocked the phone and kept their thumb resting on the screen, the optical LHBM spotlight remained brightly lit until the finger was physically removed.
  • The Root Cause: ColorOS requests HBM shutoff via OPLUS_FEATURE_HBM_CONTROL (feature 22, value == 0). If the shim fails to reset Xiaomi touch mode 10 to 0, the touchscreen firmware keeps the hardware LHBM spotlight active as long as physical touch is present.
  • The Solution:
    1. The millisecond authentication succeeds in rodinBpOnAuthSucceeded, setTouchFeature(0, 10, 0) and conditionUpdate(4, 0) / (1, 0) are dispatched immediately.
    2. In OPLUS_FEATURE_HBM_CONTROL when value == 0, touch mode 10 is shut off instantly.
    3. persist.vendor.sys.fp.fod.lhbmoffafterresult=1 is baked in so Xiaomi's mfp-daemon itself terminates LHBM immediately upon auth result.
    4. The highlight extinguishes in 0 ms, identical to OEM HyperOS behavior.

2. Lockscreen Dimming & Black Box Permanently Eliminated

  • Root Cause: SystemUI checks KeyguardFeatureOption.isLocalHBM() by querying vendor.oplus.hardware.displaypanelfeature.IDisplayPanelFeature/default. If this service is null, SystemUI assumes the panel does not support Local-HBM, turns on OnScreenFingerprintDimLayer (dimming the entire lockscreen), and falls back to an opaque black square behind the fingerprint icon.
  • The Solution:
    1. librodin_fp_compat.so registers the AIDL service vendor.oplus.hardware.displaypanelfeature.IDisplayPanelFeature/default in ServiceManager.
    2. Responds to Feature 211 (OPLUS_FEATURE_UDFPS_TYPE) with 0x410 (OPLUS_UDFPS_LOCAL_HBM | OPLUS_UDFPS_LOCAL_HBM_ACCEL).
    3. SystemUI receives isLocalHBM = 410 (true), completely destroying OnScreenFingerprintDimLayer. The lockscreen remains at 100% full brightness and vibrant, with zero black box.

3. Touch Controller and Fingerprint Sensor Variants

Rodin uses separate components for the touchscreen and optical fingerprint sensor. Goodix can name either component, so each unit should be described by its touch controller + FOD sensor pairing. Examples of Rodin hardware pairings are:

Touch controller FOD sensor
FocalTech Goodix
FocalTech Jiiov
Goodix Goodix
Goodix Jiiov
  • Dynamic Hardware Routing: Rather than writing to fixed sysfs nodes, librodin_fp_compat.so binds to Xiaomi's hardware abstraction layer vendor.xiaomi.hw.touchfeature.ITouchFeature/default (Transaction 9, mode 10, value 1). Xiaomi's HAL automatically routes the FOD touch enable command to whichever touch IC is active.
  • Adaptive Edge Polling: Drivers like FocalTech do not always emit standard Linux input key events (KEY_FOD_GESTURE_DOWN) or sysfs notifications. The compatibility worker polls both input device events and /sys/class/touch/touch_dev/fod_press_status with an adaptive 15–25ms active window to ensure instantaneous touch down/up detection on both Goodix and FocalTech hardware.
  • Jiiov FOD: A Rodin unit with Jiiov FOD confirmed the screen-on idle-touch fix. The compatibility layer checks persist.vendor.sys.fp.vendor, disarms touch after Jiiov authentication while the display is on, and re-arms for screen-off or a new fingerprint operation. Goodix FOD follows the existing path; the touch controller can be Goodix or FocalTech.

4. Seamless & Classic AOD Fix (Panel Feature 217)

  • ColorOS SmoothTransitionController queries and sets panel feature 217 (OPLUS_FEATURE_AOD_SMOOTH).
  • librodin_fp_compat.so intercepts SET_FEATURE for feature 217 and returns STATUS_OK (0). Seamless AOD, Classic AOD, and lockscreen fade-in animations render smoothly and stay lit indefinitely without the previous 2-second premature cutoff.

5. Screen-Off Fingerprint (SOFOD) Hint Integration

  • When AOD is disabled or enters energy-saving hide (DOZE->OFF), nees_aodd toggles Setting_AodSwitchEnable to 0. This informs ColorOS OnScreenFingerprintUiMech that AOD is inactive, enabling the screen-off fingerprint icon to appear on pickup or screen tap (notifyWakeUpCallback type 1).
  • On touch or pickup callback, nees_aodd immediately ramps panel brightness to 100 for clear FOD icon visibility, dropping to 0 when the icon hides, and restoring Setting_AodSwitchEnable = 1 when the screen wakes to ON.
  • Rise to wake on ColorOS: The sensor wrapper maps Xiaomi pickup events to the tilt value expected by ColorOS's gesture service. It batches Xiaomi pickup before activation and leaves native FOD and AOD events untouched. No ColorOS app patch is required. The installed build passed three gentle lock-and-lift cycles with the SOFOD hint working.

6. Zero-Fork AOD Keepalive (Watchdog Crash Prevention)

  • nees_aodd operates on pure in-memory string matching on the logcat stream with zero subprocess forks. Panel backlight is held at 28 during DOZE_SUSPEND and performAodUpdate without system overhead, preventing Android process watchdogs (MBrainServer) from killing the daemon.

7. Permanent Boot Loading via ELF DT_NEEDED (Zero Root Requirement)

  • Using patchelf --add-needed librodin_fp_compat.so /vendor/bin/hw/mfp-daemon, the shim is permanently baked into the mfp-daemon binary.
  • The Android bionic dynamic linker loads librodin_fp_compat.so automatically into mfp-daemon upon boot. No LD_PRELOAD, Magisk, or root environment is needed. Clean-flashed devices boot with fully functional FOD out-of-the-box.

8. 100% Pure Strict Enforcing SELinux

  • Zero Permissive Domains: All (typepermissive ...) directives are completely removed.
  • The entire ROM runs under global SELinux Enforcing (getenforce returns Enforcing).
  • Full compliance with SafetyNet, Google Play Integrity, Google Wallet, and banking applications.

How to Inspect SELinux Denials & Add Validated Strict CIL Rules

When porting or modifying system components, never switch to permissive mode. Follow this exact workflow to identify denials and add clean, versioned CIL rules:

Step 1: Capture Audit Denials

Run via ADB:

# Check kernel audit buffer
adb shell "dmesg | grep avc"

# Check logcat audit events
adb shell "logcat -b all -d | grep -iE 'avc:  denied'"

Step 2: Decode the Audit Denial

Example denial message:

type=1400 audit(1790426908.016:38): avc:  denied  { read open getattr } for  comm="mfp-daemon" path="/sys/devices/virtual/touch/touch_dev/fod_enable" dev="sysfs" ino=1234 scontext=u:r:hal_fingerprint_default:s0 tcontext=u:object_r:sysfs:s0 tclass=file permissive=0

Break down the components:

  • scontext: Calling domain (hal_fingerprint_default)
  • tcontext: Target object/domain (sysfs)
  • tclass: Object class (file, dir, binder, service_manager, chr_file, property_service)
  • { ... }: The denied action(s) (read, open, getattr, call, transfer, add, find, set)

Step 3: Translate to Treble CIL Format

In Treble-compliant vendor images (e.g. Android 14/15), system types referenced by vendor CIL files are versioned (e.g. _202404).

Check existing versioned symbols in your vendor image:

grep -E "\(type (sysfs_|system_server_|default_prop_)" /vendor/etc/selinux/vendor_sepolicy.cil

Construct the CIL allow rule:

(allow <scontext> <tcontext> (<tclass> (<actions...>)))

Examples of verified strict rules:

; File and directory access
(allow hal_fingerprint_default sysfs_202404 (file (read open getattr)))
(allow hal_fingerprint_default sysfs_202404 (dir (search read open)))

; Binder IPC between HAL and system server
(allow hal_fingerprint_default system_server_202404 (binder (call transfer)))
(allow system_server_202404 hal_fingerprint_default (binder (call transfer)))

; Property reading
(allow hal_fingerprint_default default_prop_202404 (file (read open getattr map)))
(allow hal_fingerprint_default system_prop_202404 (file (read open getattr map)))

Step 4: Handle AIDL Services in ServiceManager

When an AIDL service is added, servicemanager checks service_contexts.

  • If you assign the service to an existing authorized type: In /vendor/etc/selinux/vendor_service_contexts:
    vendor.oplus.hardware.displaypanelfeature.IDisplayPanelFeature/default u:object_r:vendor_hal_fingerprint_service_xiaomi:s0
    
    Because vendor_hal_fingerprint_service_xiaomi is already allowed to be added by hal_fingerprint_default and found by platform_app_202404 (SystemUI) and system_server_202404, registration succeeds with zero denials and zero extra CIL rules required.

Step 5: Critical Treble Step — Neutralize the 3 precompiled_sepolicy Files in /odm/etc/selinux & /vendor/etc/selinux

On modern Android Treble devices with dedicated vendor/odm partitions (like POCO X7 Pro / Rodin running ColorOS ports), Android ships up to 3 precompiled SELinux policy artifacts:

  1. precompiled_sepolicy
  2. precompiled_sepolicy.plat_sepolicy_and_mapping.sha256
  3. precompiled_sepolicy.*_sepolicy_and_mapping.sha256 (e.g. system_ext or product)

Why this is critical: During early boot, Android init verifies whether the SHA256 hashes of the system partitions match the stored .sha256 checksum files. If they match, init loads precompiled_sepolicy directly into the kernel and completely ignores your edits to vendor_sepolicy.cil and odm_sepolicy.cil! Any custom allow rules you added will never take effect.

The Professional Solution: Remove or back up all 3 precompiled_sepolicy* files located in:

  • /odm/etc/selinux/
  • /vendor/etc/selinux/

When these 3 files are neutralized, Android init detects that no valid precompiled policy exists and automatically invokes /system/bin/secilc at boot time to compile plat_sepolicy.cil + vendor_sepolicy.cil + odm_sepolicy.cil into a monolithic runtime policy, seamlessly activating all custom strict rules with zero bootloop risk.


Repository Structure

NEESS-COS-AOD-FOD-FIX/
├── bake_into_rom.sh                   # 1-command root ROM bake installer
├── README.md                          # Main documentation & SELinux guide
├── aod/                               # Native Rust AOD helper daemon
│   ├── Cargo.toml
│   ├── Cargo.lock
│   ├── nees_aodd.rc                   # Init service definition (u:r:shell:s0)
│   └── src/main.rs                    # Zero-fork logcat listener & backlight manager
├── fod/                               # Native C++ FOD & panel compatibility shim
│   ├── native/
│   │   ├── CMakeLists.txt
│   │   └── rodin_fp_compat.cpp        # Instant LHBM off, Local-HBM 410, AIDL hooks
│   └── zz_rodin_fp_compat.rc          # Hardware init & Goodix/Focaltech permissions
├── sepolicy/                          # Pure strict Enforcing policies
│   ├── vendor_sepolicy.cil.append     # Verified 100% strict enforcing CIL rules
│   ├── vendor_sepolicy_strict.cil.append # Standalone strict rules reference
│   ├── vendor_file_contexts.append    # Vendor file contexts (erofs/ext4)
│   └── plat_file_contexts.append      # Platform file contexts
├── system/                            # Prepared system partition payloads
│   ├── bin/nees_aodd                  # Compiled native AOD daemon
│   ├── etc/init/nees_aodd.rc          # AOD init script
│   └── build.prop.append              # AOD & FOD system properties
├── vendor/                            # Prepared vendor partition payloads
│   └── lib64/librodin_fp_compat.so    # Compiled native FOD shim
└── scripts/                           # Build & maintenance scripts
    ├── bake_into_rom.sh               # Alternate script location
    ├── build_aod.sh                   # Cargo cross-compiler script
    └── build_fod.sh                   # NDK CMake build script

Integration into Unpacked ROM

Option 1: Automated 1-Command Bake Script (Recommended)

chmod +x bake_into_rom.sh
./bake_into_rom.sh /path/to/unpacked_rom_root

The script automatically:

  1. Copies nees_aodd and its .rc into system/.
  2. Copies librodin_fp_compat.so and zz_rodin_fp_compat.rc into vendor/.
  3. Patches /vendor/bin/hw/mfp-daemon ELF header with DT_NEEDED: librodin_fp_compat.so.
  4. Injects strict CIL rules into vendor_sepolicy.cil.
  5. Maps IDisplayPanelFeature in vendor_service_contexts and odm_service_contexts.
  6. Safely handles precompiled_sepolicy to force fresh compile.
  7. Updates file_contexts for erofs/ext4 image repackers.
  8. Injects properties into build.prop.

Post-Boot Verification

Run these commands in an ADB shell:

# 1. Verify global SELinux is 100% Enforcing
getenforce
# Output: Enforcing

# 2. Verify DisplayPanelFeature AIDL registration
service list | grep -i displaypanel
# Output: 522 vendor.oplus.hardware.displaypanelfeature.IDisplayPanelFeature/default: [...]

# 3. Verify SystemUI Local-HBM evaluation
logcat -d | grep -i "isLocalHBM"
# Output: FeatureOption-->isLocalHBM val=410

# 4. Verify ZERO SELinux denials for fingerprint & AOD
dmesg | grep -iE 'avc.*fingerprint'
# Output: (empty / zero denials)

Credits & Authors

  • NEESCHAL – Lead developer, hardware reverse engineering, protocol shims, and timing state machines.
  • Community testers for feedback and telemetry logs.

License

Licensed under the Apache License, Version 2.0. Copyright (c) 2026 NEESCHAL-3 and NEESS-COS-AOD-FOD-FIX Contributors.

About

Native AOD and FOD compatibility for Rodin / POCO X7 Pro ColorOS ports with NEES4 shared authorization

Resources

Security policy

Stars

14 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages