Skip to content

Android: fall back to VisiblyInitializedCallback hooks on Android 16#388

Draft
mrmees wants to merge 1 commit intofrida:mainfrom
mrmees:fix/android16-art-compat
Draft

Android: fall back to VisiblyInitializedCallback hooks on Android 16#388
mrmees wants to merge 1 commit intofrida:mainfrom
mrmees:fix/android16-art-compat

Conversation

@mrmees
Copy link
Copy Markdown

@mrmees mrmees commented Mar 29, 2026

Full Disclosure - This is 100% AI. I have no understanding of the underlying code changes, but my Frida setup wasn't working before, and now it is, so I figured I would put it up for review.

Summary

Fix Java .implementation hooking on Android 16 by adding a fallback path for static-trampoline resynchronization when the existing VisiblyInitializedCallback byte signatures no longer match.

On Android 16 / ART APEX 361154300, the existing instrumentArtFixupStaticTrampolines() patterns stop matching, and one of the previously targeted symbols, AdjustThreadVisibilityCounter, is no longer present. This leaves replacement-method bookkeeping stale during ART's visibility / trampoline fixup flow, which appears to be enough to destabilize Java method replacement.

This patch keeps the existing pattern-based behavior for older ART builds, but on Android 16 falls back to attaching directly to the VisiblyInitializedCallback methods that are still present:

  • MarkVisiblyInitialized
  • MakeVisible
  • Run

Each fallback hook triggers the same replacement-method synchronization already used by the existing path.

Why

On a Pixel 8 running Android 16 with ART APEX 361154300, local testing showed:

  • interpreter::DoCall hooks are still found
  • inline GetOatQuickMethodHeader scanning still matches
  • the static-trampoline fixup path is the stale part:
    • MarkVisiblyInitialized still exists, but the old byte pattern no longer matches
    • AdjustThreadVisibilityCounter is gone
    • MakeVisible and Run are present in ClassLinker::VisiblyInitializedCallback

With this fallback in place, Java .implementation stopped crashing immediately in the tested app process and was able to hook and invoke Java methods again.

Implementation

instrumentArtFixupStaticTrampolines() now:

  1. Reuses a local synchronizeReplacements() helper for the existing resync logic.
  2. Keeps the old pattern-based scan/attach behavior unchanged for matching builds.
  3. If no known pattern matches and apiLevel >= 36, falls back to attaching to:
    • _ZN3art11ClassLinker26VisiblyInitializedCallback11MakeVisibleEPNS_6ThreadE
    • _ZN3art11ClassLinker26VisiblyInitializedCallback3RunEPNS_6ThreadE
    • _ZN3art11ClassLinker26VisiblyInitializedCallback22MarkVisiblyInitializedEPNS_6ThreadE

Validation

Validated locally on:

  • Device: Pixel 8
  • Android: 16
  • ART APEX: 361154300

Observed before this patch:

  • Java .implementation crashed or destabilized the session on Android 16

Observed after this patch:

  • hook installation succeeded
  • hooked Java methods could be invoked successfully
  • relocated protobuf runtimes in the target process could also be hooked without immediate process crash

Notes

This is intentionally a narrow compatibility fix. It does not change the existing pattern-based path for older ART builds, and it does not alter GetOatQuickMethodHeader handling or the interpreter hook path.

Copy link
Copy Markdown
Member

@oleavr oleavr left a comment

Choose a reason for hiding this comment

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

Nice catch! Thank you 🙏🏻


// Android 16 ART refactored this callback flow and older byte signatures no longer
// match reliably. Fall back to the callback methods that are still present.
if (getAndroidApiLevel() >= 36) {
Copy link
Copy Markdown
Member

@oleavr oleavr Mar 31, 2026

Choose a reason for hiding this comment

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

I would be good to base this on getArtApexVersion() instead, so new ART on older Android OSes also benefit from this.

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