HyperCore v6.11.0 — Thermal Guard Corrections
A full audit of the daemon, the WebUI and the packaging turned up that the 3-tier thermal guard was not enforcing two of its three tiers. Gaming at 70°C ran uncapped, and the vendor thermal stack was being suppressed on a hot device by the same code path that claims to stand down when it gets warm.
Both are fixed, along with the packaging gaps that let the module run code it had just rejected.
Nothing here is cosmetic. If you play games in a warm room, the behaviour change is real and it is in the direction of not cooking the phone.
Thermal guard
- Tier 1 now actually caps
Gaming— the tier-1 branch was gated on the MOBA profile, so a plain Gaming title at 70°C fell through to the hardware ceiling with no mitigation at all. Both profiles are capped now; MOBA keeps the higher 2.0 GHz Big allowance. - Ceilings are clamped to the hardware maximum — the tier values are constants, so a part reporting a lower ceiling must not be pushed above it.
- The vendor thermal stack is no longer suppressed when hot —
apply_profilewrotesconfig 10(thermal-nolimits) andthrm_enable 0at every tier, immediately undoing the skip thatenforce_gaming_thermal_bypassperforms at tier >= 1. - A dead sensor no longer reads as a cold SoC — a sensor reporting 0 has not produced a sample, but the raw read went into the threshold comparisons directly, pinning the device at Tier 0 with the bypass armed.
- Thermal zones are selected by type, not by index — the scan skipped zones that had not published a reading yet, which on MTK parts is most of them for the first seconds after boot. The hardcoded fallback is now accepted only after its
typeconfirms it is the wanted sensor. - GPU cooling device is matched properly —
thermal-devfreqis the generic cpufreq type and matches the CPU policies too, so gaming could forcecur_state 0onto a CPU cooling device.
CPU
- Governor and rate limits are applied per cluster — the stock baseline captures the Big cluster separately because MTK parts routinely boot the two clusters on different governors, but one value was written to all policies. Interactive was handing the Big cluster the Little cluster's values.
- Devfreq ceiling is raised before the floor is lifted — devfreq returns
-EINVALfor min above max. Latent today, silent failure tomorrow.
Packaging & security
update.jsonis generated at build time — it is whatmodule.proppointsupdateJsonat, and nothing in the repo read it, which is exactly why no build step touched it and the release URL went stale on every version bump.- Install no longer executes a payload that failed verification — the integrity layer asked the daemon to verify itself even after the manifest check had already failed.
status.jsonis created 0600 — it took whatever the inherited umask allowed, leaving the copy in/devworld-readable.- Uninstall preserves user configuration — it removed all of
/data/adb/hypercore, taking charge limits, the hand-built gamelist and the HUD config with it. Settings now go to a timestamped sidecar under/data/adb/hypercore_removed/. - Grants are revoked on uninstall — the
SYSTEM_ALERT_WINDOWappops outlived the module. - Gamelist autodetect no longer appends to shared storage — it wrote as root to a path an app could replace with a symlink.
Notes
- Tier 2 keeps its existing 1.8 GHz ceiling. A never-applied 1.4/1.5 GHz value had been sitting in a comment; adopting it would have stacked a large behaviour change on top of a correctness fix.
- A peer at uid 2000 (
adb shell) is not a read-only client. It is deliberate, since the documentedadb shellworkflow depends on it, but anyone holding an adb pairing token can drive charge mode,PURGE_RAMand profile switching. Worth knowing before leaving wireless debugging enabled.
Verification
- 81,648 tier transitions across every starting tier and a dense CPU/battery grid were replayed against the previous implementation: zero divergence whenever both sensors reported, which is what makes the Tier 1 change safe to land.
- Clean under
-Wall -Wextra -Werrorand the clang static analyzer.