## File: README.md

---

### Introduction

Vector is a Zygisk module providing an ART hooking framework that maintains API consistency with the original Xposed. It is engineered on top of [LSPlant](https://github.com/JingMatrix/LSPlant) to deliver a stable, native-level instrumentation environment.

The framework allows modules to modify system and application behavior in-memory. Because no APK files are modified, changes are non-destructive, easily reversible via reboot, and compatible across various ROMs and Android versions.

---

### Compatibility

Vector supports devices running **Android 8.1 through Android 17 Beta**.

> [!TIP]
> This framework requires a recent installation of Magisk or KernelSU with Zygisk enabled.

---

### Installation

1. Download the latest release as a system module.
2. Install the module via your root manager (Magisk/KernelSU).
3. Ensure a Zygisk environment (e.g., [NeoZygisk](https://github.com/JingMatrix/NeoZygisk)).
4. Reboot the device.
5. Access management settings via the system notification.

---

### Downloads

| Channel | Source |
| :--- | :--- |
| **Stable Releases** | [GitHub Releases](https://github.com/JingMatrix/Vector/releases) |
| **Canary (CI) Builds** | [GitHub Actions](https://github.com/JingMatrix/Vector/actions/workflows/core.yml?query=branch%3Amaster) |

> [!NOTE]
> Debug builds are recommended for users encountering issues or performing troubleshooting.
> We encourage users to test CI builds to help us identify bugs and accelerate development.

> [!CAUTION]
> GitHub requires users to be **logged in** to download CI artifacts.
>
> The link above is filtered to show only `master` branch builds.
> Please note that builds from Pull Requests (PRs) are often unstable and potentially unsafe (depending on the authors); we recommend staying on the `master` branch for verified builds, unless you are asked to help our debugging sessions.

---

### Support and Contribution

If you encounter issues or wish to help improve the project, please refer to the resources below.

*   **Troubleshooting:** Consult the [guide](https://github.com/JingMatrix/Vector/issues/123) before reporting bugs.
*   **Discussions:** Join our community on [GitHub Discussions](https://github.com/JingMatrix/Vector/discussions).
*   **Localization:** Help translate the project via [Crowdin](https://crowdin.com/project/lsposed_jingmatrix).

> [!IMPORTANT]
> Bug reports are only accepted if they are based on the **latest debug build**.
>
> *Notice for Chinese speakers:*
>
> 为了提高沟通效率，本项目仅接受英文 Issue。请使用 [DeepL](https://www.deepl.com/zh/translator) 或其他翻译工具提交您的反馈。

---

### Developer Resources

Vector supports both legacy and modern hooking standards to ensure broad module compatibility.

*   [Legacy Xposed API](https://api.xposed.info/)
*   [Modern libxposed API](https://libxposed.github.io/api/)
*   [Xposed Module Repository](https://github.com/Xposed-Modules-Repo)

> [!NOTE]
> Vector supports the `libxposed` API via two git submodules: the [module API](./xposed/) and the [service API](./services/).
>
> A successful GitHub Actions build of the [master](https://github.com/JingMatrix/Vector/tree/master) branch indicates that Vector fully supports these APIs at those specific commits.
> Developers are suggested to check out the same commits as Vector.

---

### Credits

This project is made possible by the following open-source contributions:

*   [Magisk](https://github.com/topjohnwu/Magisk/): The foundation of Android customization.
*   [LSPlant](https://github.com/JingMatrix/LSPlant): The core ART hooking engine.
*   [XposedBridge](https://github.com/rovo89/XposedBridge): The standard Xposed APIs.
*   [Dobby](https://github.com/JingMatrix/Dobby): Inline hooking implementation.
*   [LSPosed](https://github.com/LSPosed/LSPosed): Upstream source.
*   [EdXposed](https://github.com/ElderDrivers/EdXposed): Upstream source, before LSPosed.
*   [xz-embedded](https://github.com/tukaani-project/xz-embedded): Library decompression utilities.


Legacy and Historical Dependencies

- ~~[Riru](https://github.com/RikkaApps/Riru)~~
- ~~[SandHook](https://github.com/ganyao114/SandHook/)~~
- ~~[YAHFA](https://github.com/rk700/YAHFA)~~
- ~~[dexmaker](https://github.com/linkedin/dexmaker)~~
- ~~[DexBuilder](https://github.com/LSPosed/DexBuilder)~~


---

### License

Vector is licensed under the [GNU General Public License v3](http://www.gnu.org/copyleft/gpl.html).

---

## File: daemon/README.md

# Vector Daemon Subsystem

The Vector daemon is a standalone, root-privileged Dalvik executable bootstrapped via `app_process`. Operating entirely outside the standard Android application sandbox, it serves as the central coordinator, state manager, and inter-process communication (IPC) asset server for the Vector framework. 

Target processes operating under strict Android sandbox and SELinux constraints cannot safely access external configuration files or SQLite databases. The daemon offloads these operations, providing an IPC backend that serves memory-mapped resources, configuration states, and native file descriptors to target applications securely and efficiently.

## Directory Structure

The daemon is organized into discrete packages handling IPC, state management, OS interfacing, and native environments.

```text
src/main/
├── jni/                      # Native C++ implementations (dex2oat wrapper, logcat parser)
└── kotlin/org/matrix/vector/daemon/
    ├── data/                 # SQLite schema, immutable state cache, and file operations
    ├── env/                  # UNIX domain socket servers and native process monitors
    ├── ipc/                  # AIDL endpoints (Framework, Manager, ModuleApp, InjectedModule, SystemServer)
    ├── system/               # System binder delegates and Notification UI
    ├── utils/                # Context forgery, signature verification, and JNI bridges
    ├── Cli.kt                # Command-line interface definitions
    ├── VectorDaemon.kt       # Main entry point and looper initialization
    └── VectorService.kt      # Primary IVectorDaemon implementation
```

## Concurrency and State Management

To handle concurrent IPC requests without starving Android Binder thread pools, the daemon separates background I/O operations from state reads.

* Immutable State Container: The `DaemonState` data class holds a frozen snapshot of all enabled modules and process scopes. IPC threads read from this object without acquiring locks.
* Atomic Swaps: When the underlying SQLite database changes, the daemon triggers a conflated channel request. A background coroutine queries the database, computes the new module topology, instantiates a new `DaemonState`, and atomically swaps the reference in `ConfigCache`.
* Preference Isolation: High-frequency module preference reads and writes are decoupled from the core state. Managed by `PreferenceStore`, preferences are serialized as binary blobs and pushed as differential updates to modules, preventing unnecessary cache rebuilds.

## IPC Architecture

The daemon implements a multi-layered IPC design utilizing Android's Binder mechanism and UNIX domain sockets. It avoids registering standard AIDL services with `ServiceManager`, relying instead on intercepting Binder transactions via the Zygisk module and actively pushing Binder references to target processes.

### 1. System Server Bootstrapping
During device boot, the daemon establishes a communication channel with the native Vector Zygisk module residing in `system_server`.

* The daemon registers an `IServiceCallback` to listen for the registration of a hardware proxy service (typically the `serial` service). Once intercepted, the daemon replaces the proxy service with its own binder.
* The Zygisk module queries this proxy service to retrieve the framework loader DEX via `SharedMemory` and the class obfuscation map.
* Concurrently, the daemon sends a raw `ACTION_SEND_BINDER` transaction to the `activity` service. The Zygisk module's JNI hook intercepts this transaction before it reaches the Activity Manager, extracting and storing the daemon's primary `VectorService` binder for future use.

### 2. Target Application Rendezvous
When a standard user application spawns, it requests framework access from the daemon.

* The target application queries the `activity` service. The Zygisk module inside `system_server` intercepts this query.
* The `system_server` forwards the application's UID, PID, process name, and a newly created heartbeat `BBinder` to the daemon using the previously stored `VectorService` reference.
* The daemon verifies the request against its `ConfigCache` to determine if the application is within the scope of any enabled modules.
* If approved, the daemon returns an `FrameworkService` binder, which the `system_server` passes back to the target application.
* The daemon links a `DeathRecipient` to the heartbeat binder to automatically clean up internal tracking maps when the application process dies.
* The target application uses the `FrameworkService` binder to fetch its specific module list, framework DEX, and obfuscation map.

### 3. Libxposed Module Injection
Unlike target applications which request access, the daemon actively pushes its API binder to module processes. This mechanism is strictly limited to modules utilizing the modern libxposed API.

* The daemon registers an `IUidObserver` with the Activity Manager to monitor process lifecycles.
* When a UID becomes active, `ModuleAppService` checks if the UID belongs to an enabled libxposed module.
* The daemon retrieves an `IXposedService` binder. To deliver it, the daemon calls `IActivityManager.getContentProviderExternal`, targeting a synthetic authority constructed from the module's package name.
* The daemon executes `IContentProvider.call` with the action `SEND_BINDER` and a `Bundle` containing the binder. This injects the binder into the module's process space before `Application.onCreate` executes, providing access to API verification, scope requests, and remote preferences.

### 4. Native Socket IPC
For native components that operate outside the Java Binder context, the daemon provisions two distinct types of UNIX domain sockets.

* Command-Line Interface: The `CliSocketServer` exposes a filesystem-based socket at `/data/adb/lspd/.cli_sock`. The CLI client authenticates using a compiled-in UUID token and communicates using structured JSON. For live log streaming, the daemon attaches the log file's raw `FileDescriptor` to the socket reply payload, allowing the client to read directly from the OS-level stream buffer.
* Dex2Oat Wrapper: The `Dex2OatServer` listens on an abstract UNIX domain socket. To prevent conflicts and detection, the exact name of this abstract socket is randomized during module installation. The C++ `dex2oat` wrapper connects to this socket to receive necessary file descriptors via `SCM_RIGHTS`.

## Native Environment Subsystems

The daemon relies on native C++ subsystems to intercept Android's compilation pipeline and parse system log buffers directly, avoiding the overhead and limitations of standard shell utilities.

### AOT Compilation Hijacking

Android's ART compiler aggressively inlines methods, which permanently prevents those methods from being hooked at runtime. To enforce the `--inline-max-code-units=0` flag system-wide, Vector utilizes a C++ binary wrapper mounted over the system's `dex2oat` and `dex2oat64` binaries. 

The daemon manages this interception entirely through its native JNI layer. To ensure the replaced compiler binaries are globally visible to all newly spawned application processes, the daemon forks a privileged child process and uses `setns` with `CLONE_NEWNS` to enter the `init` (`PID 1`) mount namespace via `/proc/1/ns/mnt`. It then performs read-only bind mounts (`MS_BIND | MS_REMOUNT | MS_RDONLY`) over the target compiler binaries located in the `/apex` mount points.

When the wrapper executes, it connects to the daemon's abstract UNIX domain socket to retrieve the original compiler binary and the hooking library (`liboat_hook.so`) via `SCM_RIGHTS`. To guarantee the wrapper can connect without SELinux denials, the daemon dynamically writes to `/proc/self/task/[tid]/attr/sockcreate` before binding the socket. This instructs the kernel to label the abstract socket with a specific context, such as `u:r:dex2oat:s0` or `u:r:installd:s0`, matching the strict domains under which the compiler operates.

If the wrapper is disabled or incompatible, the daemon unmounts the binaries and utilizes `resetprop` to inject the inline flag directly into the `dalvik.vm.dex2oat-flags` system property as a fallback. The Kotlin daemon continuously monitors SELinux states via a `FileObserver` on `/sys/fs/selinux/enforce` and its policy files. It dynamically remounts the wrappers if the system drops to permissive mode or alters policy, ensuring the interception persists across state changes.

### Native Logcat Monitoring
Instead of relying on standard logcat shell execution, the daemon runs a native C++ process that interfaces directly with Android's `liblog` buffers (`LOG_ID_MAIN` and `LOG_ID_CRASH`). 

The native parser performs zero-copy processing of log events, strictly filtering output by predefined exact tags (e.g., Magisk, KernelSU) and prefix tags (e.g., dex2oat, Vector, LSPosed). It writes the filtered output into two rotating log files: one for module frameworks and one for verbose system debugging, rotating them automatically when they reach 4MB.

To control this isolated native loop, the Kotlin daemon injects specific string triggers (such as `!!refresh_modules!!` or `!!start_verbose!!`) directly into the Android log stream. The C++ parser intercepts these specific messages originating from its own parent PID and dynamically rotates its file descriptors or alters its verbosity state without requiring additional IPC overhead.

---

## File: dex2oat/README.md

# VectorDex2Oat

VectorDex2Oat is a specialized wrapper and instrumentation suite for the Android `dex2oat` (Ahead-of-Time compiler) binary. It is designed to intercept the compilation process, force specific compiler behaviors (specifically disabling method inlining), and transparently spoof the resulting OAT metadata to hide the presence of the wrapper.

## Overview

In the Android Runtime (ART), `dex2oat` compiles DEX files into OAT files. Modern ART optimizations often inline methods, making it difficult for instrumentation tools to hook specific function calls. 

This project consists of two primary components:
1.  **dex2oat (Wrapper):** A replacement binary that intercepts the execution, communicates via Unix Domain Sockets to obtain the original compiler binary, and executes it with forced flags.
2.  **liboat_hook.so (Hooker):** A shared library injected into the `dex2oat` process via `LD_PRELOAD` that utilizes PLT hooking to sanitize the OAT header's command-line metadata.

## Key Features

*   **Inlining Suppression:** Appends `--inline-max-code-units=0` to the compiler arguments, ensuring all methods remain discrete and hookable.
*   **FD-Based Execution:** Executes the original `dex2oat` via the system linker using `/proc/self/fd/` paths, avoiding direct execution of files on the disk.
*   **Metadata Spoofing:** Intercepts `art::OatHeader::ComputeChecksum` or `art::OatHeader::GetKeyValueStore` to remove traces of the wrapper and its injected flags from the final `.oat` file.
*   **Abstract Socket Communication:** Uses the Linux Abstract Namespace for Unix sockets to coordinate file descriptor passing between the controller and the wrapper.

## Architecture

### The Wrapper [dex2oat.cpp](src/main/cpp/dex2oat.cpp)
The wrapper acts as a "man-in-the-middle" for the compiler. When called by the system, it
1.  connects to a predefined Unix socket (the stub name `5291374ceda0...` will be replaced during installation of `Vector`);
2.  identifies the target architecture (32-bit vs 64-bit) and debug status;
3.  receives File Descriptors (FDs) for both the original `dex2oat` binary and the `oat_hook` library;
4.  reconstructs the command line, replacing the wrapper path with the original binary path and appending the "no-inline" flags;
5.  clears `LD_LIBRARY_PATH` and sets `LD_PRELOAD` to the hooker library's FD;
6.  invokes the dynamic linker (`linker64`) to execute the compiler.

### The Hooker [oat_hook.cpp](src/main/cpp/oat_hook.cpp)
The hooker library is preloaded into the compiler's address space. It uses the [LSPlt](https://github.com/JingMatrix/LSPlt) library to:
1.  Scan the memory map to find the `dex2oat` binary.
2.  Locate and hook internal ART functions:
    *   [art::OatHeader::GetKeyValueStore](https://cs.android.com/android/platform/superproject/+/android-latest-release:art/runtime/oat/oat.cc;l=366)
    *   [art::OatHeader::ComputeChecksum](https://cs.android.com/android/platform/superproject/+/android-latest-release:art/runtime/oat/oat.cc;l=366)
3.  When the compiler attempts to write the "dex2oat-cmdline" key into the OAT header, the hooker intercepts the call, parses the key-value store, and removes the wrapper-specific flags and paths.

---

## File: external/README.md

# External Dependencies

This directory contains all the external dependencies required to build the Vector framework.
They are included as git submodules to ensure version consistency and timely updating.

## Native dependencies

-   [Dobby](https://github.com/JingMatrix/Dobby): 
    A lightweight, multi-platform inline hooking framework. It serves as the backend for all native function hooking (`HookInline`).

-   [fmt](https://github.com/fmtlib/fmt):
    A modern formatting library used for high-performance, type-safe logging throughout the native code.

-   [LSPlant](https://github.com/JingMatrix/LSPlant):
    A hooking framework for the Android Runtime (ART). It provides the core functionality for intercepting and modifying Java methods.

-   [xz-embedded](https://github.com/tukaani-project/xz-embedded):
    A lightweight data compression library with a small footprint. It is used by the ELF parser to decompress the `.gnu_debugdata` section of stripped native libraries.

-   [LSPlt](https://github.com/JingMatrix/LSPlt):
    A library for PLT (Procedure Linkage Table) hooking. It is used in the `dex2oat` sub-project to bypass a detection point. **Note:** This is included as a submodule for project convenience but is not compiled into the `external` C++ library itself.

## Java libraries

-   [apache/commons-lang](https://github.com/apache/commons-lang):
    A package of Java utility classes for the classes that are in java.lang's hierarchy. Some classes are renamed and then used to implement the `XposedHelpers` API.

-   [axml/manifest-editor](https://github.com/JingMatrix/ManifestEditor):
    A a tool used to modify Android Manifest binary file. It is to parse manifestation files of Xposed modules.

---

## File: legacy/README.md

# Legacy Xposed API Implementation

This document details the architecture and implementation of the `legacy` module within the Vector framework. The `legacy` subsystem provides a backward-compatibility layer, implementing the classic `de.robv.android.xposed` API namespace while routing execution to the modern native ART hooking engine.

## Module Topology and Boundaries

The legacy compatibility subsystem spans multiple compilation boundaries to enforce strict separation between the API surface, the Dalvik/ART runtime, and the native execution environment.

- [legacy](.): Contains the Java API surface (`de.robv.android.xposed.*`), state translation handlers (`LegacyDelegateImpl`), reflection caching mechanisms, and resource/shared preference overrides.
- [xposed](../xposed): Manages the isolated classloaders (`VectorModuleClassLoader`), the Ahead-Of-Time (AOT) compiler deoptimizer (`VectorDeopter`), and the Dependency Injection (DI) framework.
- [native](../native): Houses the JNI bridges (`hook_bridge.cpp`, `resources_hook.cpp`), concurrent hook registries, stack-allocated invocation logic, in-memory DEX generation, and binary XML mutation routines.
- [daemon](../daemon): Operates out-of-process with elevated privileges to provision SELinux-permissive directories and manage filesystem contexts for cross-process file sharing.

### Dependency Injection and Bootstrap

During process startup, `Startup.initXposed` is invoked in the `zygisk` module. This routine establishes the DI (Dependency Injection) contract by instantiating `LegacyDelegateImpl` and injecting it into the `xposed` module via `VectorBootstrap.INSTANCE.init()`.

The `LegacyDelegateImpl` satisfies the `LegacyFrameworkDelegate` interface, acting as the sole translation boundary for:

- Application package load events (`onPackageLoaded`).
- System server initialization (`onSystemServerLoaded`).
- Native hook execution routing (`processLegacyHook`).
- Resource directory tracking (`setPackageNameForResDir`).

## Module Initialization

Legacy modules are loaded during the initialization phase via `XposedInit.loadLegacyModules()`. The framework queries the daemon (`VectorServiceClient.INSTANCE.getLegacyModules()`) to retrieve the list of enabled APK paths.

Modules are not loaded using standard Android mechanism. To prevent detection via `ClassLoader.getParent()` chain-walking and to eliminate residual file descriptors, `XposedInit.loadModule` utilizes `VectorModuleClassLoader`. This classloader loads the module APK directly into memory, isolating the module's execution environment from the host application's classpath.

Once mapped into memory, the framework parses two specific manifest files within the APK to initialize Java and native execution hooks:

1. `assets/xposed_init`: Defines the Java entrypoint class, which is loaded via `VectorModuleClassLoader` and inspected for `IXposedMod` implementations to be registered with the internal callback arrays:
    - `IXposedHookZygoteInit`: Invoked immediately with a `StartupParam` structure containing the module path and system server status.
    - `IXposedHookLoadPackage`: Wrapped in `IXposedHookLoadPackage.Wrapper` and appended to the `XposedBridge.sLoadedPackageCallbacks` array.
    - `IXposedHookInitPackageResources`: Appended to `XposedBridge.sInitPackageResourcesCallbacks` array, which subsequently triggers the native resource hooking subsystem via `XposedInit.hookResources()`.

2. `assets/native_init`: Defines native library filenames that are treated as [native hooking modules](https://github.com/LSPosed/LSPosed/wiki/Native-Hook). These names are registered via` NativeAPI::recordNativeEntrypoint` to be intercepted during the dynamic linking process. The `native` module provides an infrastructure for native modules to perform inline hooking via [native_api.cpp](../native/src/jni/native_api_bridge.cpp) without direct access to the framework's core symbols.

### Lifecycle Event Translation

The `xposed` module manages Android lifecycle events (e.g., `LoadedApk.createOrUpdateClassLoaderLocked`), and dispatches a `LegacyPackageInfo` payload to `LegacyDelegateImpl`.

`LegacyDelegateImpl.onPackageLoaded` translates the modern payload into the classic Xposed format. It constructs an `XC_LoadPackage.LoadPackageParam` object, mapping the following fields: `packageName`, `processName`, `classLoader`, `appInfo`, and `isFirstApplication`. The populated parameter object is then passed to `XC_LoadPackage.callAll`, which iterates over the `sLoadedPackageCallbacks` array and executes the registered module callbacks.

The system server represents a unique lifecycle edge case. `LegacyDelegateImpl.onSystemServerLoaded` manually registers `android` into the `loadedPackagesInProcess` set and constructs a hardcoded `LoadPackageParam` with the process name `system_server`.

## Execution Routing and Method Hooking

The method hooking lifecycle involves identifying target executables via reflection, ensuring ART compliance by deoptimizing compiled code, registering JNI trampolines, and managing the execution state during invocation.

### Structural Reflection Caching

Legacy modules rely heavily on reflection to locate target methods and fields (e.g., via `XposedHelpers.findAndHookMethod`). The `legacy` module implements a structural caching mechanism within `XposedHelpers`. Queries are encapsulated into `MemberCacheKey` subclasses (`Method`, `Constructor`, `Field`). These keys compute their hashes based on object identity and structural properties (class references, parameter array contents, and exactness flags) rather than strings. The keys are stored in `ConcurrentHashMap` instances (`fieldCache`, `methodCache`, `constructorCache`), enabling zero-allocation cache hits for repeated reflective lookups.

### AOT Deoptimization

Modern Android Runtime (ART) environments utilize Ahead-Of-Time (AOT) compilation, which frequently inlines short methods into their callers. If an inlined method is hooked, the JNI trampoline will be bypassed because the caller executes the inlined machine code directly.

To mitigate this, the `xposed` module implements `VectorDeopter`. During initialization or application load, `VectorDeopter.deoptMethods()` queries a registry of known inlined methods [VectorInlinedCallers](../xposed/src/main/kotlin/org/matrix/vector/impl/core/VectorInlinedCallers.kt). It iterates through these targets and issues a native command (`HookBridge.deoptimizeMethod`) to force ART to discard the compiled machine code for the target. This forces the method execution back into the ART interpreter (via `ClassLinker::SetEntryPointsToInterpreter` in `lsplant`), which strictly respects method boundaries and guarantees execution of the installed JNI trampolines.

### Native Hook Registry and Execution State Translation

Hook registration is routed from `XposedBridge` to the native layer in [hook_bridge.cpp](../native/src/jni/hook_bridge.cpp). The native environment manages a concurrent global registry to track hooked executables and their associated callbacks.
When a hooked method executes, the native engine pauses standard execution and routes control back to `xposed`, which invokes the `LegacyFrameworkDelegate.processLegacyHook` interface.

The `LegacyDelegateImpl` translates the modern execution state (`OriginalInvoker`) into the legacy specification. It wraps the invocation state within `LegacyApiSupport` and performs the following execution loop:

1.  Iterates forward through all registered `XC_MethodHook` instances, invoking `beforeHookedMethod`.
2.  Checks if any module invoked `setResult()` or `setThrowable()`. If the execution was not skipped, it commands the `OriginalInvoker` to proceed with the native method execution.
3.  Iterates backward through the callbacks, invoking `afterHookedMethod`. If a downstream module threw an exception during execution, `LegacyApiSupport` catches the exception and restores the original cached result or throwable. This protects the host process from unhandled module exceptions.

## Resource Hooking Subsystem

The resource hooking implementation allows legacy modules to replace application assets, layout definitions, and string values at runtime. Because Android optimizes resource retrieval and XML parsing heavily in native C++ code, this subsystem requires a combination of framework-level injection, dynamic class generation, and direct memory manipulation of binary XML structures.

To intercept resource queries, the system replaces the default OS-provided `Resources` instance with a custom `XResources` subclass. During framework startup, `XposedInit.hookResources()` intercepts the Android `android.app.ResourcesManager` component, by applying hooks to the resource factory methods (`createResources`, `createResourcesForActivity` on Android 12+, and `getOrCreateResources` on older versions). When an application requests a new resource object, the hook callback executes `cloneToXResources()`. This method instantiates a new `XResources` object and copies the underlying OS implementation by extracting `mResourcesImpl` via `HiddenApiBridge.Resources_setImpl`. The newly constructed `XResources` instance is then injected back into the operating system's internal tracking arrays (e.g., `mResourceReferences` or the `ActivityResource` struct), encapsulated within a `WeakReference` to prevent memory leaks.

### Dynamic Class Hierarchy Generation

To intercept resource queries effectively, the framework must replace the OS-provided resource instances with `XResources` and `XTypedArray`. However, hardcoding `XResources` to inherit directly from the base AOSP `Resources` class would result in fatal `ClassCastException` aborts when the heavily modified OEM framework attempts to cast the injected object back to its expected proprietary type. To resolve this runtime polymorphism requirement without triggering `ClassNotFoundException` during initial loading, the framework dynamically generates an intermediate class hierarchy.

During initialization, `XposedBridge.initXResources` within the `legacy` module inspects the exact runtime class of the system resources and typed arrays. It then invokes the `native` bridge `ResourcesHook.makeInheritable` to strip the final modifier from these OEM classes at the ART level, ensuring they can be subclassed. Subsequently, it invokes `ResourcesHook.buildDummyClassLoader`. The `native` implementation utilizes the `dex_builder` library to construct a DEX file directly within a memory buffer. It generates dummy classes named `xposed.dummy.XResourcesSuperClass` and `xposed.dummy.XTypedArraySuperClass`, dynamically setting their superclasses to the exact OEM classes detected earlier. This memory buffer is then loaded into the runtime via `dalvik.system.InMemoryDexClassLoader`. Finally, the `legacy` module manipulates the parent chain of its own classloader by overriding the parent field to point to the in-memory dummy classloader. At compile time, `XResources` is declared as extending the `XResourcesSuperClass` stub. At runtime, when Dalvik/ART resolves `XResources`, the manipulated classloader chain provides the dynamically generated dummy class. This mechanism guarantees that `XResources` safely inherits all OEM-specific methods and fields, successfully passing any internal type checks performed by the vendor framework.

On Lenovo ZUI devices, the OEM modified the `obtainTypedArray` implementation to query the device configuration from `android.app.ActivityThread.sCurrentActivityThread`. Accessing this field during Zygote startup returns null, resulting in a fatal `NullPointerException` that crashes the boot process. The legacy module circumvents this by reflecting an empty, uninitialized `ActivityThread` object, injecting it into the static `sCurrentActivityThread` field, invoking `obtainTypedArray`, and immediately nullifying the field in a finally block.

### Replacement Caching and Native Binary XML Mutation

Intercepting high-frequency rendering paths (such as `getDrawable` or `getColor`) and querying a standard hash map for module replacements causes severe lock contention and degrades UI thread performance. To prevent this, `XResources` utilizes a lock-free bitmask cache to validate the existence of a replacement in O(1) time before querying the main `sReplacements` hash map.
- `sSystemReplacementsCache`: A static 256-byte array tracking framework resource IDs (values below `0x7f000000`).
- `mReplacementsCache`: A 128-byte array tracking application-specific resource IDs (values greater than or equal to `0x7f000000`).

The bitmask acts as a high-performance fast-path rejection filter to prevent synchronized map lookups for unmodified resources. During registration, the framework maps the resource ID to an index in a byte array—harvesting entropy from the Type and Entry Index fields—and sets a specific bit using the ID's lowest three bits. Upon resource retrieval, `getReplacement` performs a bitwise check; if the bit is zero, the framework immediately returns `null` without acquiring a monitor. This O(1) check ensures that the majority of resource requests bypass the global `sReplacements` lock, maintaining UI thread performance.

When an application inflates a layout via `LayoutInflater`, the Android OS parses compiled AAPT binary XML files utilizing the native `android::ResXMLParser` C++ class. Standard Java hooks cannot intercept the internal ID resolution performed by this parser. To inject custom module layouts, the framework mutates the binary XML tree in memory.

1. In [resources_hook.cpp](../native/src/jni/resources_hook.cpp), the `PrepareSymbols` function utilizes the `ElfImage` utility to parse `libandroidfw.so` in memory. It resolves unexported, mangled C++ symbols for `android::ResXMLParser::next`, `restart`, and `getAttributeNameID`, caching their memory addresses in global function pointers.

2. If a requested layout is not already cached, `XResources` extracts the native pointer (`mParseState`) and passes it to the JNI bridge `rewriteXmlReferencesNative`. The native code casts the `jlong` back to an `android::ResXMLParser*` and executes a loop, manually invoking `ResXMLParser_next`.

3. When the parser encounters an `android::ResXMLParser::START_TAG` token, it extracts the attribute count and iterates over the tag's attributes. For each attribute, it resolves the `attrNameID` via the cached `getAttributeNameID` pointer. If the ID belongs to the application package namespace (`0x7f000000`), it queries the Java layer via JNI (`XResources.translateAttrId`) to check if a module provided a replacement. If a replacement ID is returned, the native code performs an in-place mutation of the binary XML tree by directly overwriting the integer in the parser's memory allocation (`mResIds[attrNameID] = attrResID`). It repeats this evaluation and mutation logic for the attribute's value reference via `XResources.translateResId`.

4. Upon reaching the `END_DOCUMENT` token, the native loop exits and invokes `ResXMLParser_restart`. When the native bridge returns and the Android framework resumes the inflation process, it unknowingly parses the mutated binary XML tree, correctly resolving the module-provided layout IDs.

## SharedPreferences and SELinux Boundaries

The classic Xposed API relied on the `Context.MODE_WORLD_READABLE` flag, allowing target applications to read configuration files directly from the module's `/data/data//shared_prefs/` directory. Starting with Android 7.0, the operating system throws a `SecurityException` when this flag is used. Furthermore, modern SELinux policies enforce strict application data isolation, preventing cross-process directory traversal regardless of Unix file permissions.

To restore `XSharedPreferences` functionality without compromising system stability, the framework implements a coordinated bypass utilizing the out-of-process daemon and runtime path redirection.

The `daemon` module operates with elevated privileges and provisions a specialized safe-zone directory for module configuration sharing. When resolving the module directory, the daemon executes `setSelinuxContextRecursive` to apply the [u:object_r:xposed_data:s0](../zygisk/module/sepolicy.rule) SELinux context. This specific context is universally readable across standard application domains. The daemon subsequently invokes `Os.chmod` to enforce `755` Unix permissions and adjusts directory ownership. This creates a filesystem bridge that both the module and target applications can legally access without violating SELinux isolation.

### Interception and Redirection

To utilize the safe-zone transparently, the `legacy` module intercepts the configuration saving mechanics within the module's own user interface process. During application load, `LegacyDelegateImpl` parses the module's APK metadata using `VectorMetaDataReader`. If the module declares an `xposedminversion` greater than 92 or contains the `xposedsharedprefs` flag, the framework triggers `hookNewXSP`. This routine applies two critical hooks to `android.app.ContextImpl`:

1.  Flag Stripping: It hooks `checkMode` to intercept the mode integer. If the `MODE_WORLD_READABLE` bit is present, it suppresses the resulting `SecurityException` by setting the hook throwable to null.
2.  Path Redirection: It hooks `getPreferencesDir` using an `XC_MethodReplacement`. Instead of returning the standard isolated data directory, it returns the daemon-provisioned safe-zone path obtained via `VectorServiceClient.INSTANCE.getPrefsPath`.

When the module attempts to save its standard `SharedPreferences`, the Android framework transparently writes the XML file into the SELinux-permissive bridge.

### File I/O and IPC Bypass

When a target application is hooked and instantiates `XSharedPreferences`, the framework determines the path based on the target API level. For modern modules, it bypasses the legacy `/data/data` path entirely and maps directly to the safe-zone.

In the original [Xposed framework](https://github.com/rovo89/XposedBridge), circumventing SELinux at read-time required synchronous IPC via BinderService or native root access via ZygoteService. In the Vector framework, these IPC mechanisms have been removed. Because the daemon pre-emptively assigns a permissive SELinux context to the safe-zone, the target application process possesses the necessary permissions to read the file directly. The SELinuxHelper component unconditionally returns DirectAccessService, an implementation of BaseService. This service acts purely as a structural API shim to maintain compatibility with the internal caching logic of XSharedPreferences, performing raw reads utilizing standard `FileInputStream` and `BufferedInputStream` operations without IPC overhead.

Since standard Android inter-process communication mechanisms (such as broadcast intents or content providers) are overly visible for cross-process preference tracking, `XSharedPreferences` implements an in-process filesystem watcher to handle live updates. When an `OnSharedPreferenceChangeListener` is registered, the framework spawns an internal daemon thread (`sWatcherDaemon`). This thread utilizes `java.nio.file.WatchService` (an abstraction over the Linux `inotify` subsystem) to monitor the safe-zone directory. The thread blocks on `sWatcher.take()`, and upon receiving an `ENTRY_MODIFY` or `ENTRY_DELETE` event for the target XML file, it validates the file hash and natively dispatches the legacy preference change callbacks to the registered listeners.

## Developer References

For module developers building against or debugging the legacy Xposed API, the following external documentation provides historical context and usage guidelines:

- [Xposed Development Tutorial (rovo89)](https://github.com/rovo89/XposedBridge/wiki/Development-tutorial)
- [LSPosed New XSharedPreferences Mechanism](https://github.com/LSPosed/LSPosed/wiki/New-XSharedPreferences)

---

## File: manager/README.md

# Vector Manager

The manager app: Jetpack Compose, one activity, configuring the root daemon over Binder. It holds
no privilege of its own — everything it does to the device, it asks the daemon to do. It replaces
`:app`, which is deleted.

This file covers what the code cannot tell you on its own: the constraints it is built around, and
the places where a mistake fails silently rather than loudly. The rest is in the code.

## The parasitic model

The manager normally runs injected into `com.android.shell` rather than installed. Its
`AndroidManifest.xml` is never registered, so nothing declared there exists at runtime: no
`ContentProvider`, and therefore no `androidx.startup` and nothing that self-registers through
`InitializationProvider`; no `FileProvider`; and no per-app language API, since
`setApplicationLocales` is keyed on an installed package. The language override is applied in
composition instead, which is why it takes effect without a restart.

Everything is therefore initialised explicitly, from the activity. The same APK also installs as an
ordinary app for development, and both modes have to work — so anything that assumes one of them is
a bug waiting for the other.

Its memory is `com.android.shell`'s memory. That is the reason behind decisions that would look
paranoid in a normal app: the log reader indexes byte offsets and pages a window rather than
holding a file, and the module scan is cached rather than repeated.

## How the binder arrives

The framework loads `<managerPackage>.Constants` out of the injected dex by reflection and calls the
static `setBinder(IBinder)`. Nothing in this APK calls it, so R8 is told to keep it in
`proguard-rules.pro`. Rename that class or method and the handshake breaks at runtime with no
compile error anywhere — the app simply comes up reporting no framework.

Order is not fixed. The binder can arrive before the activity exists, or the activity can start
before any binder does. `ServiceLocator.attach()` is idempotent and `bind()` is a plain assignment
to a `StateFlow`, so either order is safe, and repositories collect that flow rather than being
handed a binder — a late arrival, or a reconnection, makes them re-read instead of leaving them
with whatever they managed to fetch before there was a daemon.

## Talking to the daemon

`ipc/DaemonClient` wraps every AIDL call in `runIpc`, which moves it to `Dispatchers.IO` and returns
a `Result`. The interface is
`services/manager-service/src/main/aidl/org/matrix/vector/ipc/IManagerService.aidl`, and it is the
source of truth for what each call means: read the method's documentation there before calling it.

Two properties of Binder shape most of the mistakes made here, and the AIDL spells out what each
method does about them. A proxy returns a *default* for a transaction the daemon does not implement
rather than throwing, so `0`, `null` and empty are indistinguishable from real answers — see
`getProtocolVersion` and `ROOT_UNKNOWN` there. And a call that succeeded is not a call that did
anything: several of these return a `boolean` the daemon uses to refuse, and dropping it turns a
refusal into a silent success.

The daemon owns the truth. When a write and a read disagree, the read is usually coming from the
daemon's asynchronous cache while the write went to its database.

## Logging

Log under `Constants.TAG`, and only under it. `daemon/src/main/jni/logcat.cpp` routes any tag
beginning `Vector` into the daemon's verbose stream, so those lines reach the Logs screen and travel
in the zip export a user attaches to a report. A file-local tag is ordinary Android practice and
would land nowhere. The conventions — prefixes, levels, what never belongs in a message — are on
`Constants.TAG` itself.

Crashes are written to `cacheDir/crash` because that is where `FileSystem.getLogs` already collects
them from, in both of the manager's homes.

## Strings

`res/values/strings.xml`, `strings_logs.xml` and `strings_store.xml`, translated into 18 locales.
`crowdin.yml` points at this module and at the daemon's, and `manager/build.gradle.kts` merges
`../daemon/src/main/res`, so a name collision between the two is a build error.

Nothing user-visible is hard-coded in a composable, and identifiers that must not be translated
carry `translatable="false"`. The build scans `values-*` folders containing a `strings.xml` to
produce `BuildConfig.TRANSLATIONS`, so a locale Crowdin adds needs no code change.

Changing what a string *means* needs a new key. Reword it in place and eighteen translations go on
asserting the old meaning until someone notices, which can be a long time.

## Building and running

```sh
./gradlew :manager:assembleDebug   # the APK
./gradlew :zygisk:zipDebug         # the module zip, which contains it
./gradlew ktfmtFormat              # formatting is ktfmt; CI does not check it
```

The version code is `git rev-list --count refs/remotes/origin/master`, so a branch build and a
master build can share one; `module.prop` and the status page carry a build stamp, which is often
the only way to tell two builds apart on a device. It names where the build came from as well as
what it was built from. The commit leads and what follows says where: `93d66473-JingMatrix-Vector`
for a CI build, the bare `93d66473` for a local one, and `93d66473+thinkpad` — the machine that made
it — when the tree was not clean.

Debug builds add a second launcher activity — a demo mode with scripted device states, in
`src/debug` and absent from release builds, so it cannot be used to make a release report a healthy
framework. It does mean `monkey -c LAUNCHER` picks one of the two at random:

```sh
adb shell am start -n org.matrix.vector.manager/.ui.MainActivity
```

There is no test source set anywhere in this repository, and CI runs `zipAll` and nothing else. A
green tick means it compiles and packages. Everything else is verified by running it against a real
daemon on a device.

---

## File: native/README.md

# Vector Native Library (`native`)

## Purpose and Design Philosophy

This library provides low-level hooking and modification capabilities for the Android OS.
It is not a standalone application but a collection of components designed to be integrated into a larger loading mechanism, such as a Zygisk module.

## Architectural Breakdown

The library is organized into distinct modules, each with a clear responsibility.

### `core` - The Abstract Engine

This module defines the central abstractions and manages the runtime state. It's the conceptual heart of the library.

-   **`Context`**: An abstract base class that defines the injection lifecycle. It contains pure virtual methods like `LoadDex` and `SetupEntryClass`. The consumer of this library (e.g., the Zygisk module) must inherit from `Context` and provide the concrete implementations for these steps.
-   **`ConfigBridge`**: A simple, native-side singleton that acts as a cache for configuration data (specifically, the obfuscation map) that is fetched and provided by the consumer.
-   **`native_api`**: Implements the native module support system. It works by hooking the system's `do_dlopen` function. When it detects a registered module library being loaded, it calls that library's `native_init` entry point, providing it with a set of [API](include/core/native_api.h)s for creating its own native hooks.

### `elf` - Symbol Resolution

This module is responsible for runtime symbol lookups in shared libraries, a critical function for native hooking.

-   **`ElfImage`**: A parser for ELF files mapped into the current process's memory. It can resolve symbols in stripped binaries by locating, decompressing (using `xz-embedded`), and parsing the `.gnu_debugdata` section. It applies a cascading lookup strategy: GNU hash -> ELF hash -> linear scan of the symbol table.
-   **`ElfSymbolCache`**: A thread-safe, lazy-initialized cache for `ElfImage` instances, providing a safe way to access common libraries like `libart.so` and the `linker`.

### `jni` - The Business Logic Interface

This is the most significant module and represents the library's primary service layer. It contains a set of JNI bridges that expose the core features to the injected Java framework code. The functionality here is the main product of the native library.

-   **`jni_bridge.h`**: Provides a set of helper macros (`VECTOR_NATIVE_METHOD`, `REGISTER_VECTOR_NATIVE_METHODS`, etc.) to standardize and simplify the tedious process of writing JNI boilerplate.
-   **`HookBridge`**: The engine for ART method hooking. It maintains a thread-safe map of all active hooks. It also includes some stability controls, such as using atomic operations to set the backup method trampoline and throwing a Java exception instead of causing a native crash if a user tries to invoke the original method of a failed hook.
-   **`ResourcesHook`**: Provides the functionality to intercept and rewrite Android's binary XML resources on the fly. It relies on non-public structures from `libandroidfw.so` and uses the `elf` module to find the necessary function symbols at runtime.
-   **`NativeApiBridge`**: The JNI counterpart to the `core/native_api`. It exposes a method for the Java framework to register the filenames of third-party native modules.

### `common` & `framework`

-   **`common`**: A collection of basic utilities, including a `fmt`-based logging system, global constants, and helper functions.
-   **`framework`**: Contains minimal C++ structure definitions that mirror those inside Android's internal `libandroidfw.so`. These are necessary to correctly interpret resource data pointers.

## 3. Build System

The library is configured with CMake to be built as a **static library (`libnative.a`)**. All external dependencies are also linked statically for maximum portability.

---

## File: xposed/README.md

# Xposed API implementation of the Vector framework

This module implements the [libxposed](https://github.com/libxposed/api) API for the Vector framework. It serves as the primary bridge between the native ART hooking engine (`lsplant`) and module developers, providing a type-safe, OkHttp-style interceptor chain architecture.

## Architectural Overview

The `xposed` module is designed with strict boundaries to ensure stability during the Android boot process and application lifecycles. It is written entirely in Kotlin and operates independently of the legacy Xposed API (`de.robv.android.xposed`). 
It defines a Dependency Injection (DI) contract (`LegacyFrameworkDelegate`) which the `legacy` module must implement and inject during startup.

## Core Components

### 1. The Hooking Engine

*   **`VectorHookBuilder`**: Implements the `HookBuilder` API. It validates the target `Executable`, bundles the module's `Hooker`, `priority`, and `ExceptionMode` into a `VectorHookRecord`, and registers it natively via JNI.
*   **`VectorNativeHooker`**: The JNI trampoline target. When a hooked method is executed, the C++ layer invokes `callback(Array<Any?>)` on this class. It fetches the active hooks (both modern and legacy) from the native registry as global `jobject` references, constructs the root `VectorChain`, and initiates execution.
*   **`VectorChain`**: Implements the recursive `proceed()` state machine.
    *   **Exception Handling**: It implements the logic for `ExceptionMode`. In `PROTECTIVE` mode, if an interceptor throws an exception *before* calling `proceed()`, the chain skips the interceptor. If it throws *after* calling `proceed()`, the chain catches the exception and restores the cached downstream result/throwable to protect the host process.

### 2. The Invocation System

The `Invoker` system allows modules to execute methods while bypassing standard JVM access checks, with granular control over hook execution.

*   **`Type.Origin`**: Dispatches directly to JNI (`HookBridge.invokeOriginalMethod`), bypassing all active hooks.
*   **`Type.Chain`**: Constructs a localized `VectorChain` containing only hooks with a priority less than or equal to the requested `maxPriority`, allowing modules to execute partial hook chains.
*   **`VectorCtorInvoker`**: Handles constructor invocation. It separates memory allocation (`HookBridge.allocateObject`) from initialization (`invokeOriginalMethod` / `invokeSpecialMethod`) to support safe `newInstanceSpecial` logic.

### 3. Dependency Injection Contract

To maintain the separation of concerns, the `xposed` module communicates with the legacy Xposed ecosystem via `VectorBootstrap` and `LegacyFrameworkDelegate`.

When `xposed` intercepts an Android lifecycle event (e.g., `LoadedApk.createClassLoader`), it dispatches the event internally via `VectorLifecycleManager` and then delegates the raw parameters to `LegacyFrameworkDelegate` so the `legacy` module can construct and dispatch the legacy `XC_LoadPackage` callbacks.

### 4. In-Memory ClassLoading & Isolation

Modules are executed strictly from memory using an isolated ClassLoader, ensuring zero disk footprint and maximum stealth against anti-cheat mechanisms.
* The module APK is loaded into `SharedMemory` (ashmem) to bypass Java heap limitations. Once the Android Runtime (ART) ingests the DEX buffers, the ashmem is instantly unmapped, preventing memory leaks and leaving no residual file descriptors.
* The `VectorModuleClassLoader` is attached exclusively to the Xposed Framework's classloader branch, preventing the target app from discovering the module via reflection or `ClassLoader.getParent()` chain-walking.
* `VectorURLStreamHandler` intercepts standard `jar:` requests, reading assets and resources natively from the module path without triggering Android's global `JarFile` cache, preventing OS-level file locks.

---

## File: zygisk/README.md

# Vector Zygisk Module and Framework Loader

## Overview

This subsystem constitutes the injection engine of the Vector framework. It acts as the bridge between the Android Zygote process and the high-level Java/Kotlin Xposed API. The architecture is designed to avoid standard Android service registration and disk-based class loading, operating entirely through in-memory execution, JNI-level Binder interception, and process identity transplantation.

The subsystem is divided into two discrete layers:
1. _Native Zygisk Layer_ (C++): Hooks process creation via Zygisk, filters target processes, establishes the initial IPC bridge, and bootstraps the Dalvik environment from memory.
2. _Framework Loader_ (Kotlin): The Java-world payload. It handles high-level Android framework manipulation, manages the custom Binder routing service, and orchestrates the Parasitic Manager execution.

## IPC Architecture and Binder Relay

Vector utilizes a two-phase IPC routing mechanism to establish communication between injected applications and the root daemon. Instead of registering standard AIDL endpoints with ServiceManager, it intercepts the lowest level of Java Binder communication within the Dalvik VM.

### The JNI Binder Trap
In `ipc_bridge.cpp`, the module uses the ART internal function `SetTableOverride` to replace the JNI function `CallBooleanMethodV`. This override intercepts all native calls to `android.os.Binder.execTransact` system-wide. 

When a transaction occurs, the hook inspects the transaction code. If it matches the constant kBridgeTransactionCode (`_VEC`), the transaction is diverted to the static Kotlin method `BridgeService.execTransact`. All other transactions pass through to the original Android framework unmodified.

### Phase 1: System Server Initialization
The `system_server` acts as the primary proxy router for the framework. During the `postServerSpecialize` callback, the following sequence occurs:
1. The native module queries `ServiceManager` for the `serial` service (or `serial_vector` for late-inject scenarios). This service acts as a temporary rendezvous point.
2. The module sends a `_VEC` transaction to retrieve a temporary binder, which it uses to fetch the framework DEX file descriptor and the obfuscation map.
3. The module installs the JNI Binder Trap (`HookBridge`) and bootstraps the Kotlin layer via `Main.forkCommon`.
4. Concurrently, the root daemon initiates a Binder transaction directly to the `system_server`. The JNI trap intercepts this, and BridgeService processes the `SEND_BINDER` action, storing the daemon's primary `IVectorDaemon` binder, sending back `system_server` context and linking a `DeathRecipient`.

### Phase 2: User Application Rendezvous
Standard applications initialize their IPC connection by routing requests through the `system_server`.
1. In `postAppSpecialize`, the application queries `ServiceManager` for the `activity` service (which resides in `system_server`).
2. The application sends a `_VEC` transaction containing the `GET_BINDER` action, its process name, and a newly allocated heartbeat `BBinder`.
3. The JNI trap inside `system_server` intercepts this transaction before the Activity Manager processes it.
4. The `system_server`'s BridgeService forwards the application's UID, PID, and heartbeat binder to the root daemon via the `IVectorDaemon` binder acquired in Phase 1.
5. The daemon evaluates the request against its internal scope state. If approved, it generates an `IFrameworkService` binder and returns it to the `system_server`, which writes it back to the waiting application's reply parcel.
6. The application uses this dedicated binder to fetch its specific framework DEX and obfuscation map.

### The Heartbeat Mechanism
To manage process lifecycles without polling, the native module generates a dummy Binder object (`heartbeat_binder`) during both initialization phases. This object is passed to the daemon and kept alive in the application process via a JNI Global Reference (`env->NewGlobalRef`). If the application or `system_server` terminates normally or is killed by the kernel, the global reference is destroyed, the binder node is released, and the daemon's `DeathRecipient` triggers immediate resource cleanup.

## Memory Execution and Obfuscation Synchronization

Vector does not write framework code to the /data partition.

1. Asset Delivery: The root daemon provides the framework DEX via a `SharedMemory` file descriptor, using `kDexTransactionCode`. The C++ layer wraps this file descriptor in a `java.nio.DirectByteBuffer` and initializes a `dalvik.system.InMemoryDexClassLoader`.
2. Dynamic Relinking: The daemon randomizes framework class names on each boot. The native module fetches a serialized dictionary over IPC, using `kObfuscationMapTransactionCode`. `SetupEntryClass` uses this map to locate the randomized entry point (`org.matrix.vector.core.Main`) and BridgeService, enabling the framework to link correctly at runtime.

## Parasitic Manager and Identity Transplantation

The Vector Manager application is not installed as a standard package. It runs by hollowing out a host process (e.g., `com.android.shell`) using a parasitic execution model.

### System Server Intent Redirection
Within the `system_server`, `ParasiticManagerSystemHooker` intercepts `ActivityTaskSupervisor.resolveActivity`. When it detects an Intent tagged with the `LAUNCH_MANAGER` category, it dynamically modifies the returned ActivityInfo. It forces the system to launch the host package while setting the processName to the Manager's package name and adjusting theme and recents flags to mimic a standalone application.

### Application Host Hijacking
When the native module detects the host package UID and the Manager process name during `preAppSpecialize`, it injects `GID_INET` (3003) into the process's GID array to ensure network access. Control is then passed to `ParasiticManagerHooker.kt`, which performs the identity transplantation:
1. Code Injection: It intercepts `LoadedApk.getClassLoader` and `ActivityThread.handleBindApplication`, swapping the host's ApplicationInfo with a hybrid object constructed from the manager's APK (provided via file descriptor). The manager's DEX is injected into the host's `PathClassLoader`.
2. State Forgery: The system ActivityManager is unaware of the spoofed Manager activities. To prevent data loss during lifecycle transitions (e.g., screen rotation), the hooker intercepts `performStopActivityInner` to manually capture Bundle and PersistableBundle states into static concurrent maps. These states are reinjected during `scheduleLaunchActivity`.
3. Context Spoofing: It intercepts `ActivityThread.installProvider` and `WebViewFactory.getProvider` to construct forged `ContextImpl` instances, bypassing internal Android and Chromium package-name validation checks.