Skip to content

Upstream#17

Merged
superturtlee merged 7 commits into
masterfrom
upstream
Jul 24, 2026
Merged

Upstream#17
superturtlee merged 7 commits into
masterfrom
upstream

Conversation

@superturtlee

Copy link
Copy Markdown
Owner

No description provided.

Leaf-lsgtky and others added 7 commits July 13, 2026 21:46
Android 17 (API 36) replaced the old 3-argument
IServiceConnection.connected(ComponentName, IBinder, boolean) with a
new 4-argument overload that adds an IBinderSession parameter, and
removed the old overload entirely from the framework interface.

Vector's IServiceConnection stub and the ManagerService connection
implementation only declared/overrode the old 3-argument signature.
When system_server dispatched the new 4-argument connected() to the
parasitic manager process on Android 17, the Stub lacked the new
abstract method and threw AbstractMethodError, killing the manager
process. system_server then hit DeadObjectException while dispatching
a broadcast to the dead process, triggering a framework restart
(SYSTEM_RESTART) every time the manager was opened.

Fix:
- Add an IBinderSession stub (android.app.IBinderSession extends
  IInterface) with binderTransactionCompleted(long) and
  binderTransactionStarting(String):long, matching the Android 17
  framework interface.
- Declare both connected() overloads in the IServiceConnection stub so
  it compiles against Android 8.1~17 (the old overload is simply never
  invoked on Android 17+).
- Override the new 4-argument connected() in ManagerService's
  connection Stub (no-op, same as the existing 3-argument override).
The build system passed string macros to the C/C++ compiler wrapped in
single quotes, e.g.  -DVERSION_NAME='2.0'  and
-DINJECTED_PACKAGE_NAME='com.android.shell'. On Linux/macOS the shell
strips the single quotes and the compiler sees a quoted string literal,
but on Windows single quotes are not shell quoting characters, so the
compiler receives -DVERSION_NAME='2.0' (a multi-character constant) or
-DINJECTED_PACKAGE_NAME='com.android.shell', causing compilation
failures:
  - narrowing conversion from 'int' to 'const char*'
  - expected unqualified-id / multi-character constant

Fix by passing the values as bare tokens
(-DVERSION_NAME=2.0, -DINJECTED_PACKAGE_NAME=com.android.shell) and
stringizing them at the C++ side via a STRINGIZE macro, which is robust
across Windows and Unix toolchains. Also move the stringize helper
macros out of a namespace (macros are not namespace members and cannot
be invoked with a qualified name).
Symptoms: the module list came up empty and detail pages showed nothing.
There were two independent causes.

1. DNS. With the "doh" setting on, CloudflareDNS resolved every host only
   through cloudflare-dns.com (bootstrapped on 1.1.1.1) with no fallback.
   Where Cloudflare is blocked, every lookup fails immediately, so the
   list, per-module detail and GitHub all fail at once and the app is
   unusable until DoH is turned off by hand. DoH is now best-effort: on
   failure it falls back to the system resolver, remembers the failure for
   the session, and uses a short DoH timeout so the first fallback is
   quick. This is the fix for the reported empty list.

2. Endpoints. The old mirror chain no longer serves the list:
   modules.lsposed.org returns 403 for modules.json, modules-blogcdn
   returns 418, and modules-cloudflare has no DNS record. Only
   backup.modules.lsposed.org still serves modules.json; per-module detail
   (module/<pkg>.json) is served by both backup and modules.lsposed.org.
   The single mirror list is split accordingly (list -> backup only;
   detail -> backup then modules.lsposed.org) and the dead mirrors dropped.

Alongside those:

- Treat non-2xx and empty/blank/invalid responses as load failures rather
  than silent successes, and restore the loaded state after a failed
  refresh so the UI never hangs refreshing. Keep cached data when a remote
  refresh fails.
- README: the list payload no longer reliably carries README/releases, so
  detail is fetched per module on demand. When detail lacks a README, or
  all detail mirrors are down, fall back to the module's GitHub repo
  (github.com/Xposed-Modules-Repo/<pkg>) for the rendered README. The
  README tab shows a loading state while detail downloads instead of the
  empty placeholder, and keeps the already-loaded richer module rather
  than flickering back to the leaner list summary on a repo refresh.
- Rendering: GitHub now emits the heading permalink anchor as a sibling
  after the heading, so markdown.css's old heading-descendant hide rule
  missed it and the floated link icon leaked into the left gutter; hide
  .anchor outright.
- "Open in browser" stays on modules.lsposed.org, whose per-module web
  page (unlike the JSON API host) returns HTML and has no .json suffix.
- Added logging (tag LSPosedManager, captured by the daemon verbose log)
  across list and detail loading so future empty-list/empty-detail reports
  are diagnosable.

Endpoint reference for maintainers:
  backup.modules.lsposed.org  modules.json 200,  module/<pkg>.json 200
  modules.lsposed.org         modules.json 403,  module/<pkg>.json 200,  /module/<pkg> HTML 200
  modules-blogcdn             418
  modules-cloudflare          no DNS record
Each module mirrors a GitHub repo at github.com/Xposed-Modules-Repo/<pkg>
(README + releases), the ultimate source behind the GitHub fallbacks.

---------

Co-authored-by: Qing <44231502+byemaxx@users.noreply.github.com>
Co-authored-by: JingMatrix <jingmatrix@gmail.com>
The daemon re-declared the DEX2OAT_* state values as literals that had
drifted out of sync with the ILSPManagerService AIDL contract the Manager
decodes with: MOUNT_FAILED, SEPOLICY_INCORRECT and CRASHED were effectively
swapped. Since the daemon returns `compatibility` verbatim over the binder,
a mount failure was surfaced in the UI as "Crashed", a sepolicy error as
"Mount failed", etc.

Derive the constants from ILSPManagerService instead of re-declaring them so
the AIDL is the single source of truth for both ends and they cannot drift
again.
…rix#787)

The manager's "Re-optimize" action cleared an app's profile and recompiled it
through two hidden IPackageManager binder calls, clearApplicationProfileData()
and performDexOptMode(). Android 17 removes both from framework.jar, so the
daemon crashed with NoSuchMethodError.

Dexopt and profiles have been owned by the ART Service since Android 14, which
exposes the same operations through the package shell (cmd package art
clear-app-profiles / cmd package compile). Route through the shell on Android
14+ and keep the binder calls for older releases; when a shell command fails,
fall back to the binder call, which is still available on Android 14 through 16.

Both steps now live in a single PackageOptimizer.optimize() that clears the
profile before the speed-profile recompile, since a stale profile would
otherwise constrain what the profile-guided compile rebuilds. The two service
methods collapse into one AIDL entry point, optimizePackage(), so the manager
triggers the whole operation in a single IPC.
@superturtlee
superturtlee merged commit 79e431e into master Jul 24, 2026
1 check passed
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.

4 participants