"""Embedded loader redirection, independent of any game or device.""" import json import shutil import struct import subprocess import zipfile import pytest from test_agent import load_agent from test_patches import _analysis from frameport.analysis import detect from frameport.analysis import static_openxr as sx from frameport.apk.workspace import ApkWorkspace from frameport.core.events import Reporter from frameport.patches import base from frameport.patches.frame import static_openxr_loader as patch @pytest.fixture def embedded(tmp_path): # A real ELF layout with synthetic strings; change only e_machine to model an arm64 game. compiler = shutil.which("cc") if not compiler: pytest.skip("needs host C compiler") strings = [f"/{p}/etc/openxr/1/active_runtime{abi}.json" for p in ("product", "odm", "oem", "vendor", "system") for abi in ("", ".aarch64", ".arm64-v8a")] strings += list(sx.BROKERS) + ["RuntimeManifestFile", "xrNegotiateLoaderRuntimeInterface", "unrelated"] src = tmp_path / "embedded.c" src.write_text("const char *strings[] = {" + ",".join(json.dumps(s) for s in strings) + "};") out = tmp_path / "embedded.so" subprocess.run([compiler, "-shared", "-fPIC", str(src), "-o", str(out)], check=True) data = bytearray(out.read_bytes()) struct.pack_into("= 23 def test_patch_and_adapter_without_overport(tmp_path, monkeypatch, embedded): inner = tmp_path / "inner.so" inner.write_bytes(b"unmodified Khronos loader") monkeypatch.setattr(patch.overport, "ensure_runtime_lib", lambda *args: inner) apk = tmp_path / "in.apk" with zipfile.ZipFile(apk, "w") as z: z.writestr("lib/arm64-v8a/libengine.so", embedded) a = _analysis(extra={"static_openxr_loader": ["libengine.so"]}) selection = {patch.StaticOpenXRLoader.id: {}, "frame.adapter": {}} p = patch.StaticOpenXRLoader() assert p.detect(a).recommended assert not p.applies(_analysis()) with ApkWorkspace(apk) as ws: ctx = base.ApkContext(ws, a, {}, Reporter(), selection) assert p.apply(ctx) assert base.get("frame.adapter").apply(ctx) assert ws.read_lib("libopenxr_loader_original.so") == inner.read_bytes() assert ws.has(ws.lib("libframe_settings.so")) assert all(ok for _, ok, _ in p.validate(ctx)) assert all(ok for _, ok, _ in base.get("frame.adapter").validate(ctx)) assert not p.apply(ctx) assert not base.get("frame.adapter").apply(ctx) out = ws.write(tmp_path / "out.apk") with ApkWorkspace(out) as ws: ctx.ws = ws assert not p.apply(ctx) ws.put(ws.lib("libengine.so"), embedded) assert not p.validate(ctx)[0][1] def test_manifest_repair_and_launcher_upgrade(tmp_path, monkeypatch): a = load_agent(monkeypatch, tmp_path) root = tmp_path / "game" a.write_openxr_runtime_manifest(str(root), False) assert not root.exists() a.write_openxr_runtime_manifest(str(root), True) target = root / "lepton-data/external/fp_openxr_runtime.json" manifest = json.loads(target.read_text()) assert manifest["runtime"]["library_path"] == patch.SHIM victim = tmp_path / "victim" victim.write_text("untouched") target.unlink() target.symlink_to(victim) a.write_openxr_runtime_manifest(str(root), True) assert victim.read_text() == "untouched" assert not target.is_symlink() anchor = tmp_path / "anchors/com.example.game" anchor.mkdir(parents=True) a.write_launcher(str(anchor), str(root), "com.example.game", "Test", 123, "/lepton", {}, static_openxr=True) text = (anchor / "launch.sh").read_text() assert " _openxr_manifest com.example.game\n" in text assert a.set_openxr_manifest_line(text, "com.example.game", True) == text assert "_openxr_manifest" not in a.set_openxr_manifest_line(text, "com.example.game", False) subprocess.run(["bash", "-n", str(anchor / "launch.sh")], check=True) def test_runtime_shim_host(tmp_path): import os from pathlib import Path root = Path(__file__).resolve().parents[1] headers = next((root / "native/.cache").glob("openxr-*/openxr/openxr.h"), None) cc = shutil.which("cc") if not headers or not cc: pytest.skip("needs cached OpenXR headers and host C compiler") src = root / "native/xrruntime" inc = str(headers.parent.parent) subprocess.run([cc, "-shared", "-fPIC", "-I", inc, str(src / "test_bridge.c"), "-o", str(tmp_path / "libopenxr_loader_generic.so")], check=True) exe = tmp_path / "shim_test" subprocess.run([cc, "-Wall", "-Wextra", "-Werror", "-Wno-missing-field-initializers", "-I", inc, str(src / "xrruntime.c"), str(src / "test.c"), "-ldl", "-lpthread", "-o", str(exe)], check=True) env = dict(os.environ, LD_LIBRARY_PATH=str(tmp_path)) subprocess.run([str(exe)], env=env, check=True) (tmp_path / "libopenxr_loader_generic.so").unlink() subprocess.run([str(exe), "missing"], env=env, check=True) def test_composed_khronos_paths(tmp_path, embedded): # Rebuild the fixture with Khronos platform_utils.hpp's actual fragment table. # This is also the layout in OVRPort's unmodified Khronos loader. from frameport.analysis import elf cc = shutil.which("cc") src = tmp_path / "composed.c" strings = list(sx.PARTITIONS) + [sx.SUBDIR, "/active_runtime.json", "/active_runtime.aarch64.json"] strings += list(sx.BROKERS) + ["RuntimeManifestFile", "xrNegotiateLoaderRuntimeInterface"] src.write_text("const char *strings[] = {" + ",".join(json.dumps(s) for s in strings) + "};") out = tmp_path / "composed.so" subprocess.run([cc, "-shared", "-fPIC", str(src), "-o", str(out)], check=True) buf = bytearray(out.read_bytes()) struct.pack_into("= 2 def test_analysis_records_embedded_loader(tmp_path, embedded, quest_manifest): apk = tmp_path / "analyze.apk" with zipfile.ZipFile(apk, "w") as z: z.writestr("AndroidManifest.xml", quest_manifest) z.writestr("lib/arm64-v8a/libengine.so", embedded) assert detect.analyze(apk).extra["static_openxr_loader"] == ["libengine.so"] def test_triage_only_when_chain_absent(): from frameport.validate.triage import triage line = "RuntimeManifestFile::FindManifestFiles - using global runtime file /vendor/etc/openxr/1/active_runtime.json" assert "static-openxr-loader-bypass" in {f.id for f in triage(line, "RUNNING").findings} for chain in ("FrameBridge: settings read", "fp_xrruntime: negotiated"): assert "static-openxr-loader-bypass" not in {f.id for f in triage(line + "\n" + chain, "RUNNING").findings} def test_heuristic_selects_chain_without_game_specific_rules(): from frameport.recommend.engine import suggest a = _analysis(package="com.example.othergame", engine="Other", libs=["libengine.so"], extra={"static_openxr_loader": ["libengine.so"], "vr_kind": "openxr"}) r = suggest(a, use_catalog=False) assert {"frame.static_openxr_loader", "frame.adapter"} <= r.patches.keys() assert not r.as_is