Skip to content

feat: Support HyperOS 4 (Android 17) - #183

Open
liuran001 wants to merge 6 commits into
parallelcc:mainfrom
liuran001:main
Open

feat: Support HyperOS 4 (Android 17)#183
liuran001 wants to merge 6 commits into
parallelcc:mainfrom
liuran001:main

Conversation

@liuran001

Copy link
Copy Markdown

支持 HyperOS 4 (Android 17)
已在 Xiaomi 17 Pro OS 4.0.0.27 Beta A17 测试可用
Native 代码来源于 https://github.com/wxxsfxyzm/MiuiBackGestureHook

Copilot AI lite review requested due to automatic review settings August 30, 2026 01:13
@qodo-code-review

qodo-code-review Bot commented Aug 30, 2026

Copy link
Copy Markdown

PR Summary by Qodo

Support HyperOS 4 and Android 17 launcher gestures

✨ Enhancement 🐞 Bug fix 📝 Documentation ⚙️ Configuration changes 🕐 40+ Minutes

Grey Divider

AI Description

• Restores Xiaomi launcher long-press gestures on HyperOS 4 through an arm64 LSPosed payload.
• Routes native requests to configured Circle to Search or VIS services safely.
• Extends Android 17 compatibility across home-button hooks, builds, and documentation.
Diagram

sequenceDiagram
    actor User
    participant Native as Native Payload
    participant Launcher as Launcher Invoke
    participant Bridge as System Server
    participant Router as Trigger Router
    participant Service as Search Service
    User->>Native: Long press
    Native->>Launcher: Invoke search
    Launcher->>Bridge: Contextual request
    Bridge->>Router: Apply settings
    alt CSService selected
        Router->>Service: Bypassed contextual search
    else VIS or CSHelper
        Router->>Service: Voice interaction trigger
    end
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Version-pinned launcher offsets
  • ➕ Much smaller resolver implementation
  • ➕ Faster matching during launcher startup
  • ➖ Breaks on launcher updates
  • ➖ Requires maintaining offsets per Xiaomi build
  • ➖ Raises crash risk when binaries drift
2. Java-only system-server routing
  • ➕ Avoids native build and hook maintenance
  • ➕ Keeps implementation within existing Kotlin hooks
  • ➖ Cannot observe the gesture because HyperOS 4 moved the launcher pipeline outside ART
  • ➖ Would require a separate gesture source or user workflow

Recommendation: Keep the structural native resolver and system-server bridge. HyperOS 4's pure-native launcher makes Java-only interception insufficient, while runtime-validated fingerprints and fail-closed behavior are safer and more maintainable than fixed binary offsets. Review should focus on resolver assumptions, hook rollback/idempotency, and behavior across launcher builds.

Files changed (29) +2711 / -37

Enhancement (5) +1591 / -0
ModuleMain.ktEnable HyperOS 4 native trigger routing +24/-0

Enable HyperOS 4 native trigger routing

• Detects Xiaomi Android 17 devices and installs the native launcher bridge for both MiCTS and VISTrigger. VISTrigger also bootstraps contextual search without enabling MiCTS-specific provider bypasses.

app/src/main/java/com/parallelc/micts/ModuleMain.kt

NativeLauncherTriggerHooker.ktBridge native launcher requests through system server +195/-0

Bridge native launcher requests through system server

• Adds an Android 17 system-server hook that authenticates Xiaomi launcher callers, applies gesture and vibration preferences, and routes requests to CSService or voice interaction. It passes unrelated and self-generated requests through and resolves launcher identity retryably.

app/src/main/java/com/parallelc/micts/hooker/NativeLauncherTriggerHooker.kt

launcher_cs_resolver.cppResolve launcher search handlers structurally +726/-0

Resolve launcher search handlers structurally

• Parses mapped ARM64 ELF images and identifies contextual-search support, invocation, and long-press functions through validated imports and instruction fingerprints. Supports legacy and modern HyperOS 4 launcher shapes and fails closed on ambiguous matches.

native/launcher_cs_resolver.cpp

launcher_cs_resolver.hDefine contextual-search resolver contracts +47/-0

Define contextual-search resolver contracts

• Introduces resolved offset structures, diagnostic stages, candidate counts, and the public launcher-profile resolution API.

native/launcher_cs_resolver.h

micts_native_hook.cppRestore HyperOS 4 launcher long-press gestures +599/-0

Restore HyperOS 4 launcher long-press gestures

• Initializes only in the HyperOS spawner family, resolves launcher handlers, tracks motion intent, overrides contextual-search feature probes, and redirects valid long presses. Installation is retryable, rolls back partial feature overrides, protects hook pages, and falls back to stock handling when routing is unavailable.

native/micts_native_hook.cpp

Bug fix (2) +108 / -23
CSMSHooker.ktScope contextual-search bypasses and support Android 17 APIs +52/-12

Scope contextual-search bypasses and support Android 17 APIs

• Separates service bootstrapping from provider bypass hooks and limits bypass behavior to module-owned calls using thread-local state. Supports both contextual-search method signatures and prevents bridged self-invocations from being intercepted recursively.

app/src/main/java/com/parallelc/micts/hooker/CSMSHooker.kt

LongPressHomeHooker.ktAdapt home-button hooks to HyperOS 4 classes +56/-11

Adapt home-button hooks to HyperOS 4 classes

• Finds HyperOS 4's dedicated Home key rule before falling back to older MIUI classes. Searches inherited fields and callback variants so long-press handling remains compatible across releases.

app/src/main/java/com/parallelc/micts/hooker/LongPressHomeHooker.kt

Documentation (14) +254 / -13
README.mdDocument Android 17 support in Chinese +2/-2

Document Android 17 support in Chinese

• Extends the advertised device and VIS compatibility range through Android 17.

README.md

README_en.mdDocument Android 17 support in English +1/-1

Document Android 17 support in English

• Updates the English compatibility statement from Android 9–16 to Android 9–17.

README_en.md

README_ru.mdDocument Android 17 support in Russian +1/-1

Document Android 17 support in Russian

• Updates the Russian compatibility statement to include Android 17.

README_ru.md

strings.xmlExtend Greek compatibility text to Android 17 +1/-1

Extend Greek compatibility text to Android 17

• Updates the localized Xposed description to advertise Android 9–17 support.

app/src/main/res/values-el/strings.xml

strings.xmlExtend Spanish compatibility text to Android 17 +1/-1

Extend Spanish compatibility text to Android 17

• Updates the localized Xposed description to advertise Android 9–17 support.

app/src/main/res/values-es/strings.xml

strings.xmlExtend Japanese compatibility text to Android 17 +1/-1

Extend Japanese compatibility text to Android 17

• Updates the localized Xposed description to advertise Android 9–17 support.

app/src/main/res/values-ja/strings.xml

strings.xmlExtend Russian compatibility text to Android 17 +1/-1

Extend Russian compatibility text to Android 17

• Updates the localized Xposed description to advertise Android 9–17 support.

app/src/main/res/values-ru/strings.xml

strings.xmlExtend Turkish compatibility text to Android 17 +1/-1

Extend Turkish compatibility text to Android 17

• Updates the localized Xposed description to advertise Android 9–17 support.

app/src/main/res/values-tr/strings.xml

strings.xmlExtend Vietnamese compatibility text to Android 17 +1/-1

Extend Vietnamese compatibility text to Android 17

• Updates the localized Xposed description to advertise Android 9–17 support.

app/src/main/res/values-vi/strings.xml

strings.xmlExtend Traditional Chinese compatibility text +1/-1

Extend Traditional Chinese compatibility text

• Updates the localized Xposed description to advertise Android 9–17 support.

app/src/main/res/values-zh-rTW/strings.xml

strings.xmlExtend Simplified Chinese compatibility text +1/-1

Extend Simplified Chinese compatibility text

• Updates the localized Xposed description to advertise Android 9–17 support.

app/src/main/res/values-zh/strings.xml

strings.xmlExtend default compatibility text to Android 17 +1/-1

Extend default compatibility text to Android 17

• Updates the default Xposed description to advertise Android 9–17 support.

app/src/main/res/values/strings.xml

LICENSE-Apache-2.0Bundle the native source license +161/-0

Bundle the native source license

• Includes the complete Apache License 2.0 text required by the attributed upstream-derived native code.

native/LICENSE-Apache-2.0

README.mdExplain the HyperOS 4 native hook architecture +80/-0

Explain the HyperOS 4 native hook architecture

• Documents why Java hooks no longer work, how native launcher requests reach system-server routing, and the arm64 process scope. Records upstream attribution, licensing, and deviations from MiuiBackGestureHook.

native/README.md

Other (8) +758 / -1
.gitignoreIgnore CMake native build artifacts +1/-0

Ignore CMake native build artifacts

• Adds the '.cxx' directory generated by Android external native builds to ignored files.

.gitignore

build.gradle.ktsConfigure the arm64 LSPosed native payload +25/-1

Configure the arm64 LSPosed native payload

• Pins released NDK and CMake versions, builds only the arm64 native target, and packages the library uncompressed with Xposed metadata. It also extends VISTrigger's description through Android 17 without excluding 32-bit Java-only installations.

app/build.gradle.kts

native_init.listRegister the LSPosed native entry library +1/-0

Register the LSPosed native entry library

• Declares 'libmicts_hyos_lsp.so' as the module's LSPosed native initialization payload.

app/src/main/resources/META-INF/xposed/native_init.list

CMakeLists.txtBuild and harden the HyperOS native library +56/-0

Build and harden the HyperOS native library

• Defines the arm64 C++17 shared library and links its resolver, hook backend, and launcher payload. Enables strict warnings, symbol hiding, section garbage collection, relocation hardening, and 16 KB page alignment.

native/CMakeLists.txt

exports-lsposed.mapExport only the LSPosed native entry +6/-0

Export only the LSPosed native entry

• Defines a linker version script that exposes 'native_init' while hiding all other native symbols.

native/exports-lsposed.map

lsposed_hook_backend.cppProvide resilient PLT and inline hook infrastructure +638/-0

Provide resilient PLT and inline hook infrastructure

• Implements ELF image discovery, relocation patching, LSPosed inline hooks, and per-image 'madvise' guards that preserve patched pages. Guards all matching runtime images and supports retryable, idempotent launcher installation with rollback helpers.

native/lsposed_hook_backend.cpp

lsposed_hook_backend.hExpose native hook backend operations +17/-0

Expose native hook backend operations

• Declares backend initialization, runtime page guarding, and PLT and inline hook installation APIs.

native/lsposed_hook_backend.h

native_api.hDefine the LSPosed native API surface +14/-0

Define the LSPosed native API surface

• Adds the hook and unhook function table plus the native library-load callback type used by the payload.

native/native_api.h

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

There are confirmed functional and compliance issues in the new native path (madvise guard idempotency and invoke failure handling) plus missing bundled Apache-2.0 license text referenced by the new native README.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR adds Android 17 / HyperOS 4 support by introducing an LSPosed native payload to hook the HyperOS 4 launcher’s native gesture pipeline, and updates the system-server side hooks and user-facing docs/strings to reflect Android 9–17 support.

Changes:

  • Add a new native/ CMake-built LSPosed entry (native_init) that inline/PLT hooks HyperOS 4 launcher native code paths to restore gesture-handle long press triggering.
  • Update system-server hook logic to safely gate/bypass ContextualSearch permission/provider checks only for MiCTS-managed invocations (and add a native-launcher trigger bridge).
  • Bump documentation and localized strings from “Android 9–16” to “Android 9–17”, plus Gradle/packaging changes to build and ship the native library.
File summaries
File Description
README.md Updates Chinese README support range to Android 9–17 and VIS notes.
README_en.md Updates English README support range to Android 9–17.
README_ru.md Updates Russian README support range to Android 9–17.
native/README.md Documents the new HyperOS 4 native payload design and attribution.
native/native_api.h Declares the native LSPosed API entry structure/types.
native/micts_native_hook.cpp Implements launcher/runtime detection + inline hook routing to contextual search.
native/lsposed_hook_backend.h Declares LSPosed hook backend helpers (PLT/inline + madvise guard).
native/lsposed_hook_backend.cpp Implements PLT hooking, inline hooking wrapper, and MADV_DONTNEED guard logic.
native/launcher_cs_resolver.h Declares resolver API + diagnostics for locating contextual-search functions.
native/launcher_cs_resolver.cpp Implements ELF parsing + structural fingerprint resolver for target offsets.
native/exports-lsposed.map Exports native_init symbol for LSPosed loading.
native/CMakeLists.txt Adds arm64-only native build with hardening/linker flags and version script.
app/src/MiCTS/resources/META-INF/xposed/native_init.list Registers the native entry library for LSPosed.
app/src/main/res/values/strings.xml Updates module description to Android 9–17.
app/src/main/res/values-zh/strings.xml Updates Chinese module description to Android 9–17.
app/src/main/res/values-zh-rTW/strings.xml Updates zh-rTW module description to Android 9–17.
app/src/main/res/values-vi/strings.xml Updates Vietnamese module description to Android 9–17.
app/src/main/res/values-tr/strings.xml Updates Turkish module description to Android 9–17.
app/src/main/res/values-ru/strings.xml Updates Russian module description to Android 9–17.
app/src/main/res/values-ja/strings.xml Updates Japanese module description to Android 9–17.
app/src/main/res/values-es/strings.xml Updates Spanish module description to Android 9–17.
app/src/main/res/values-el/strings.xml Updates Greek module description to Android 9–17.
app/src/main/java/com/parallelc/micts/ModuleMain.kt Wires in the new native launcher trigger hooker for Xiaomi on Android 17+.
app/src/main/java/com/parallelc/micts/hooker/NativeLauncherTriggerHooker.kt Adds system-server hook to gate/bridge native launcher contextual-search requests.
app/src/main/java/com/parallelc/micts/hooker/LongPressHomeHooker.kt Updates MIUI/HyperOS key-rule hooking to handle class split/overrides on HyperOS 4.
app/src/main/java/com/parallelc/micts/hooker/CSMSHooker.kt Makes permission/provider bypass conditional via ThreadLocal and supports new overload.
app/build.gradle.kts Adds NDK/CMake native build configuration and packaging adjustments.
.gitignore Ignores .cxx build outputs.
Review details
  • Files reviewed: 26/28 changed files
  • Comments generated: 3
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread native/README.md
Comment thread native/lsposed_hook_backend.cpp
Comment thread native/micts_native_hook.cpp
- Bundle the Apache-2.0 licence text that native/README.md links to
- Guard every image matching the runtime name instead of requiring a unique
  match, so an ambiguous basename no longer blocks hook installation
- Fall back to the stock handler when the contextual-search invoke helper is
  unavailable, rather than consuming the gesture for nothing
- Use a released NDK and CMake so CI can resolve them
@liuran001
liuran001 requested a lite review from Copilot August 30, 2026 01:29
@qodo-code-review

qodo-code-review Bot commented Aug 30, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Failed installs cannot recover ✓ Resolved 🐞 Bug ☼ Reliability
Description
InstallLauncherHook leaves previously installed motion-event and feature-probe PLT hooks active
when a later feature or inline hook fails, with inline failure clearing only the long-press handler
and invoke pointer. This partial state can falsely report contextual-search support without
replacement routing and makes retries fail because PltHookRaw rejects slots already pointing to
the replacement, preventing feature activation until process restart.
Code

native/micts_native_hook.cpp[R485-490]

+                       &g_original_has_system_feature) != kHookSuccess ||
+            AtomicLoad(&g_original_has_system_feature) == nullptr) {
+        Log(ANDROID_LOG_ERROR,
+            "contextual-search feature probe hook unavailable; leaving the "
+            "launcher stock rather than swallowing an unusable long press");
+        return;
Evidence
The installation sequence commits the motion-event PLT hook before the feature-probe and inline
hooks, and HookPackageManagerHasSystemFeature changes false contextual-search feature results to
true once installed. Later failure paths return without restoring earlier PLT slots; specifically,
the inline-hook failure branch only clears the long-press and invoke globals, so the feature
override remains active even though routing installation failed. Because the install guard remains
unset, later callbacks retry, but the PLT backend rejects a slot whose current value already equals
the replacement, demonstrating why the partial installation cannot recover.

native/micts_native_hook.cpp[423-424]
native/micts_native_hook.cpp[471-505]
native/lsposed_hook_backend.cpp[523-547]
native/micts_native_hook.cpp[301-319]
native/micts_native_hook.cpp[482-505]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Make launcher hook installation atomic or safely resumable after any intermediate failure. Ensure that failed setup does not leave the motion-event or contextual-search feature-probe hooks active without the long-press inline routing, and that subsequent retries can complete rather than failing on already-replaced PLT slots.

## Issue Context
The motion-event PLT hook is installed before the feature-probe and inline hooks, and the contextual-search feature-probe hook changes false feature results to true. Current failure paths do not restore earlier PLT slots; in particular, inline-hook failure clears only the long-press handler and invoke pointer, leaving the feature override active. The install guard remains unset and later callbacks retry, but the PLT backend rejects slots that already point to the replacement.

## Fix Focus Areas
- native/micts_native_hook.cpp[301-319]
- native/micts_native_hook.cpp[423-505]
- native/lsposed_hook_backend.cpp[500-547]
- native/lsposed_hook_backend.h[13-17]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Duplicate runtimes block installation ✓ Resolved 🐞 Bug ≡ Correctness
Description
install_madvise_hook(nullptr) resolves libhyper_os_flutter.so by basename but requires exactly
one match, so when the documented system and APK copies are both mapped,
EnsureLsposedMadviseGuard() fails and OnLibraryLoaded rejects the launcher hook. This disables
the new HyperOS 4 gesture support on that valid runtime layout even if both copies were already
guarded individually.
Code

native/lsposed_hook_backend.cpp[R290-292]

+    if (!FindImage(requested, 0u, &image) &&
+            (runtime_name == nullptr ||
+             !FindImage(kHyperRuntimeName, 0u, &image))) {
Evidence
The backend counts basename matches and FindImage rejects any count other than one; the
no-argument guard path uses that basename lookup. The PR's own native documentation states that two
copies of this library are mapped, while launcher setup aborts whenever this guard call fails.

native/lsposed_hook_backend.cpp[184-235]
native/lsposed_hook_backend.cpp[286-297]
native/README.md[46-53]
native/micts_native_hook.cpp[520-529]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Do not fail launcher-hook setup when multiple `libhyper_os_flutter.so` images are mapped.

## Issue Context
The module explicitly supports a system runtime copy and an APK-mapped copy, but basename lookup treats multiple matches as failure. Track and validate guards per image, and make the no-argument readiness check succeed only after all relevant loaded runtime images have been handled without relying on a unique basename.

## Fix Focus Areas
- native/lsposed_hook_backend.cpp[227-297]
- native/micts_native_hook.cpp[520-529]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

3. Rejected invocation consumes gesture 🐞 Bug ≡ Correctness ⭐ New
Description
The new preflight only checks that g_contextual_search_invoke is non-null, but the invocation can
return false; the handler has already marked the gesture complete and does not run the stock
handler in that case. A launcher-side rejection therefore swallows the long press without opening
contextual search or preserving stock behavior.
Code

native/micts_native_hook.cpp[R412-415]

+    if (AtomicLoad(&g_contextual_search_invoke) == nullptr) {
+        Log(ANDROID_LOG_WARN,
+            "contextual-search invoke unavailable; keeping the stock route");
+        if (original != nullptr) original(closure, trigger_mode);
Evidence
InvokeContextualSearch explicitly returns false when the launcher returns zero, while the
long-press handler's new check only handles a null function pointer. After that check, the handler
sets the completion marker, ignores the invocation result, and falls back to the original only for
cleanup failure.

native/micts_native_hook.cpp[322-339]
native/micts_native_hook.cpp[410-429]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A non-null invoke function is not sufficient to guarantee routing: `InvokeContextualSearch` reports launcher rejection with `false`, but `HookLongPressHandler` ignores that result after consuming the detector state.

## Issue Context
Preserve or invoke the original stock route when contextual-search invocation returns false, while keeping closure completion and cleanup ownership consistent.

## Fix Focus Areas
- native/micts_native_hook.cpp[410-429]
- native/micts_native_hook.cpp[322-339]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context sources
Review mode: 🧠 Deep: This is a large, high-density runtime change spanning Java hooks, native ELF resolution, inline/PLT patching, concurrency, and system-server/launcher integration, with many independent failure modes that benefit from redundant review passes.

Grey Divider

Tip of the day
💡 Did you know, you can enable the Remediation agent and Qodo fixes findings in a dedicated fix PR

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Previous reviews

Review updated until commit 0524859

Results up to commit 27a94e7 🧠 Deep


🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)


Action required
1. Failed installs cannot recover ✓ Resolved 🐞 Bug ☼ Reliability
Description
InstallLauncherHook leaves previously installed motion-event and feature-probe PLT hooks active
when a later feature or inline hook fails, with inline failure clearing only the long-press handler
and invoke pointer. This partial state can falsely report contextual-search support without
replacement routing and makes retries fail because PltHookRaw rejects slots already pointing to
the replacement, preventing feature activation until process restart.
Code

native/micts_native_hook.cpp[R485-490]

+                       &g_original_has_system_feature) != kHookSuccess ||
+            AtomicLoad(&g_original_has_system_feature) == nullptr) {
+        Log(ANDROID_LOG_ERROR,
+            "contextual-search feature probe hook unavailable; leaving the "
+            "launcher stock rather than swallowing an unusable long press");
+        return;
Evidence
The installation sequence commits the motion-event PLT hook before the feature-probe and inline
hooks, and HookPackageManagerHasSystemFeature changes false contextual-search feature results to
true once installed. Later failure paths return without restoring earlier PLT slots; specifically,
the inline-hook failure branch only clears the long-press and invoke globals, so the feature
override remains active even though routing installation failed. Because the install guard remains
unset, later callbacks retry, but the PLT backend rejects a slot whose current value already equals
the replacement, demonstrating why the partial installation cannot recover.

native/micts_native_hook.cpp[423-424]
native/micts_native_hook.cpp[471-505]
native/lsposed_hook_backend.cpp[523-547]
native/micts_native_hook.cpp[301-319]
native/micts_native_hook.cpp[482-505]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Make launcher hook installation atomic or safely resumable after any intermediate failure. Ensure that failed setup does not leave the motion-event or contextual-search feature-probe hooks active without the long-press inline routing, and that subsequent retries can complete rather than failing on already-replaced PLT slots.

## Issue Context
The motion-event PLT hook is installed before the feature-probe and inline hooks, and the contextual-search feature-probe hook changes false feature results to true. Current failure paths do not restore earlier PLT slots; in particular, inline-hook failure clears only the long-press handler and invoke pointer, leaving the feature override active. The install guard remains unset and later callbacks retry, but the PLT backend rejects slots that already point to the replacement.

## Fix Focus Areas
- native/micts_native_hook.cpp[301-319]
- native/micts_native_hook.cpp[423-505]
- native/lsposed_hook_backend.cpp[500-547]
- native/lsposed_hook_backend.h[13-17]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Duplicate runtimes block installation ✓ Resolved 🐞 Bug ≡ Correctness
Description
install_madvise_hook(nullptr) resolves libhyper_os_flutter.so by basename but requires exactly
one match, so when the documented system and APK copies are both mapped,
EnsureLsposedMadviseGuard() fails and OnLibraryLoaded rejects the launcher hook. This disables
the new HyperOS 4 gesture support on that valid runtime layout even if both copies were already
guarded individually.
Code

native/lsposed_hook_backend.cpp[R290-292]

+    if (!FindImage(requested, 0u, &image) &&
+            (runtime_name == nullptr ||
+             !FindImage(kHyperRuntimeName, 0u, &image))) {
Evidence
The backend counts basename matches and FindImage rejects any count other than one; the
no-argument guard path uses that basename lookup. The PR's own native documentation states that two
copies of this library are mapped, while launcher setup aborts whenever this guard call fails.

native/lsposed_hook_backend.cpp[184-235]
native/lsposed_hook_backend.cpp[286-297]
native/README.md[46-53]
native/micts_native_hook.cpp[520-529]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Do not fail launcher-hook setup when multiple `libhyper_os_flutter.so` images are mapped.

## Issue Context
The module explicitly supports a system runtime copy and an APK-mapped copy, but basename lookup treats multiple matches as failure. Track and validate guards per image, and make the no-argument readiness check succeed only after all relevant loaded runtime images have been handled without relying on a unique basename.

## Fix Focus Areas
- native/lsposed_hook_backend.cpp[227-297]
- native/micts_native_hook.cpp[520-529]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Qodo Logo

Comment thread native/lsposed_hook_backend.cpp Outdated
Comment thread native/micts_native_hook.cpp Outdated

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

It introduces a substantial native hooking subsystem and build/packaging changes, and there are correctness concerns (e.g., concurrency in launcher-caller gating) that should be resolved and re-validated on target devices.

Review details

Suppressed comments (3)

Previously missed (3) — in code that hasn't changed since the last review.

app/src/main/java/com/parallelc/micts/hooker/NativeLauncherTriggerHooker.kt:89

  • isLauncherCaller reads/writes launcherUidResolved / launcherUid without any synchronization. This can race across binder threads and lead to seeing launcherUidResolved=true with a stale launcherUid, misclassifying callers and incorrectly bridging/consuming requests. Wrap the whole resolution + read path in a single synchronized block (or use atomics) so the state is published consistently.
    private fun isLauncherCaller(uid: Int): Boolean {
        if (launcherUidResolved) return uid == launcherUid
        val context = runCatching {
            Class.forName("android.app.ActivityThread")
                .getDeclaredMethod("currentApplication")

app/src/main/java/com/parallelc/micts/hooker/LongPressHomeHooker.kt:40

  • The thrown NoSuchMethodException message is misleading: the lookup falls back to onLongPress, but the exception always reports only onMiuiLongPress. This makes debugging OS variations harder when neither exists. Include both candidate method names in the error message.
            val longPress = findCallback(rule, "onMiuiLongPress", "onLongPress")
                ?: throw NoSuchMethodException("${rule.name}.onMiuiLongPress")
            module!!.hook(longPress).intercept(OnLongPressHooker())

app/build.gradle.kts:38

  • The native payload build is configured in defaultConfig, so it will be built/packaged for all flavors (including VISTrigger). If VISTrigger doesn't load META-INF/xposed/native_init.list, this adds build time and APK size without functional benefit. Consider scoping the externalNativeBuild.cmake { targets/abiFilters } configuration to the MiCTS flavor (or excluding the .so from other variants).
        externalNativeBuild {
            cmake {
                targets += "micts_hyos_lsp"
                // The payload is arm64 only. Restrict the native build, not
                // the APK — that would strip the dependencies' own libraries
  • Files reviewed: 27/29 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

A PLT slot already pointing at our replacement cannot be hooked again, so a
failure partway through left the earlier hooks in place and made every later
attempt fail on them — the feature probe would keep claiming contextual-search
support with no routing behind it, until the process restarted.

Skip whatever a previous attempt got through, and undo the feature override if
the inline hook still cannot be installed.
@liuran001
liuran001 marked this pull request as draft August 30, 2026 02:21
@liuran001
liuran001 marked this pull request as ready for review August 30, 2026 02:44
Comment thread native/micts_native_hook.cpp
@qodo-code-review

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit a20b236

The launcher's code is mapped straight out of the APK. When those pages are
reclaimed they come back from the file, silently undoing the inline patch while
LSPosed still holds a now-dangling trampoline — the process stays up, the
payload stays loaded, nothing is logged, and the gesture simply stops working
until the spawner is restarted.

PLT hooks survive that because they patch the GOT rather than the code, so the
motion-event hook is used as the checkpoint: it compares the handler against the
prologue captured before patching, and on a match drops LSPosed's stale record
before hooking again.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants