# frankbarretta/lsfg-android-application architecture

> Architecture diagram of the GitHub repository frankbarretta/lsfg-android-application, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-08-01). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/frankbarretta/lsfg-android-application
- Repository: https://github.com/frankbarretta/lsfg-android-application

## Overview

#### Purpose and Entry Points
LSFG is a sideloaded Android frame-generation overlay for games. It captures display frames, runs a patched external `lsfg-vk-android` framegen library, and presents generated frames above the target app. Main UI/navigation begins at `app/src/main/java/com/lsfg/android/ui/MainActivity.kt`; runtime orchestration is the foreground service in `app/src/main/java/com/lsfg/android/session/LsfgForegroundService.kt`.

#### UI, Configuration, and Session Launch
Compose screens collect DLL, target-app, projection, pacing, and framegen settings, persisted through preferences. A projection request yields the per-session MediaProjection token; the service must post its foreground notification before capture work. Relevant paths: `app/src/main/java/com/lsfg/android/ui/ProjectionRequestActivity.kt`, `app/src/main/java/com/lsfg/android/prefs/LsfgPreferences.kt`, `app/src/main/java/com/lsfg/android/session/LsfgForegroundService.kt`.

#### Overlay Host and Input Boundary
`OverlayManager` owns the system overlay and its surface lifecycle. It can use application-overlay windows or an accessibility-overlay host; the latter is mediated by the accessibility service. The service waits for a valid output surface before starting capture, and surface recreation drives resize/retarget handling. Touch passthrough is implemented through touchable-inset management rather than non-touchable window flags. Paths: `app/src/main/java/com/lsfg/android/session/OverlayManager.kt`, `app/src/main/java/com/lsfg/android/session/LsfgAccessibilityService.kt`, `app/src/main/java/com/lsfg/android/session/FrameGraphView.kt`.

#### Capture and Privileged Timing
The visible video path is MediaProjection → VirtualDisplay → ImageReader → `AHardwareBuffer`; `CaptureEngine` supplies these frames to JNI/native rendering. Root and Shizuku code provide alternative/privileged integration, but Shizuku is timing-only and does not supply visible overlay buffers. Its AIDL boundary separates the app from the Shizuku user service. Paths: `app/src/main/java/com/lsfg/android/session/CaptureEngine.kt`, `app/src/main/java/com/lsfg/android/session/ShizukuCaptureEngine.kt`, `app/src/main/aidl/com/lsfg/android/shizuku/IShizukuCaptureService.aidl`.

#### Native Render and Framegen Pipeline
Kotlin calls one JNI boundary; native code owns a worker-thread render loop, persistent Vulkan session, AHardwareBuffer import, framegen context lifecycle, pacing, and presentation to the overlay `ANativeWindow`. Imported buffers are shared with framegen through Android Vulkan external-memory/AHB mechanisms; device synchronization is a critical boundary because framegen has its own Vulkan device. Paths: `app/src/main/java/com/lsfg/android/session/NativeBridge.kt`, `app/src/main/cpp/lsfg_jni.cpp`, `app/src/main/cpp/lsfg_render_loop.cpp`, `app/src/main/cpp/android_vk_session.cpp`, `app/src/main/cpp/ahb_image_bridge.cpp`.

#### Shader Asset Pipeline and Capability Gate
A user-selected proprietary `Lossless.dll` is processed on-device: native extraction translates DXBC resources to SPIR-V, writes shader assets under app storage, then probes each module on a headless Vulkan device before full initialization. The DLL is deleted afterward. Devices lacking required Vulkan capabilities—especially robustness2—fall back to capture-only mirror output. Paths: `app/src/main/java/com/lsfg/android/session/ShaderExtractor.kt`, `app/src/main/cpp/android_shader_loader.cpp`, `app/src/main/cpp/android_vk_probe.cpp`.

#### Runtime Coordination and Infrastructure
Parameter changes requiring allocation/context changes are serialized by the foreground service; hot-applicable controls use dedicated JNI calls. Native crash handlers and Kotlin crash reporting preserve failures for next-launch reporting. The app targets Android 10+ and uses Kotlin/Compose plus C++20/NDK/CMake, Vulkan 1.2+, MediaProjection, WindowManager overlays, optional AccessibilityService, and optional Shizuku. Planned CPU/GPU/NNAPI postprocessing scaffolding exists but is not end-to-end wired. Paths: `app/src/main/java/com/lsfg/android/session/CrashReporter.kt`, `app/src/main/cpp/crash_reporter.cpp`, `app/src/main/cpp/nnapi_postprocess.cpp`.

Main entry points: [`app/src/main/java/com/lsfg/android/session/LsfgForegroundService.kt`](https://github.com/frankbarretta/lsfg-android-application/blob/main/app/src/main/java/com/lsfg/android/session/LsfgForegroundService.kt) (Foreground session service), [`app/src/main/cpp/lsfg_render_loop.cpp`](https://github.com/frankbarretta/lsfg-android-application/blob/main/app/src/main/cpp/lsfg_render_loop.cpp) (Vulkan render loop), [`app/src/main/java/com/lsfg/android/ui/MainActivity.kt`](https://github.com/frankbarretta/lsfg-android-application/blob/main/app/src/main/java/com/lsfg/android/ui/MainActivity.kt) (Compose UI), [`app/src/main/cpp/android_vk_probe.cpp`](https://github.com/frankbarretta/lsfg-android-application/blob/main/app/src/main/cpp/android_vk_probe.cpp) (Vulkan capability probe)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_android["Android control"]
  node_ui["Compose UI<br/>Android UI<br/>[MainActivity.kt]"]
  node_projection_request["Projection request<br/>permission activity"]
  node_preferences[("Preferences<br/>settings store<br/>[LsfgPreferences.kt]")]
  node_service["Foreground session service<br/>runtime orchestrator"]
  node_crash_reporter["Crash reporting<br/>failure persistence<br/>[CrashReporter.kt]"]
end

subgraph group_capture["Capture and overlay"]
  node_target_display["Target app display<br/>Android display content"]
  node_overlay_manager["Overlay manager<br/>surface host<br/>[OverlayManager.kt]"]
  node_accessibility["Accessibility overlay host<br/>accessibility service"]
  node_frame_graph_view["Overlay view<br/>surface view<br/>[FrameGraphView.kt]"]
  node_capture_engine["MediaProjection capture<br/>capture engine<br/>[CaptureEngine.kt]"]
  node_shizuku_engine["Shizuku timing integration<br/>privileged timing"]
  node_shizuku_aidl["Shizuku AIDL boundary<br/>IPC contract"]
end

subgraph group_native["Native frame pipeline"]
  node_native_bridge{{"JNI bridge<br/>Kotlin-native API<br/>[NativeBridge.kt]"}}
  node_jni["JNI entrypoint<br/>JNI implementation<br/>[lsfg_jni.cpp]"]
  node_render_loop["Vulkan render loop<br/>worker renderer"]
  node_vulkan_session["Vulkan session<br/>persistent Vulkan state"]
  node_ahb_bridge["AHardwareBuffer bridge<br/>external-memory import"]
  node_native_crash["Native crash handler<br/>failure capture<br/>[crash_reporter.cpp]"]
end

subgraph group_assets["Shader capability gate"]
  node_shader_extractor["DLL shader extraction<br/>asset preparation<br/>[ShaderExtractor.kt]"]
  node_shader_loader["DXBC to SPIR-V loader<br/>native shader extraction"]
  node_vulkan_probe["Vulkan capability probe<br/>capability gate"]
end

node_ui -->|"reads and saves settings"| node_preferences
node_ui -->|"requests consent"| node_projection_request
node_ui -->|"launches session"| node_service
node_preferences -->|"session configuration"| node_service
node_projection_request -->|"MediaProjection token"| node_service
node_service -->|"creates overlay"| node_overlay_manager
node_accessibility -.->|"optional overlay host"| node_overlay_manager
node_overlay_manager -->|"owns surface"| node_frame_graph_view
node_frame_graph_view -->|"surface lifecycle"| node_service
node_service -->|"starts after surface ready"| node_capture_engine
node_target_display -->|"MediaProjection capture"| node_capture_engine
node_capture_engine -->|"AHardwareBuffer frames"| node_native_bridge
node_service -.->|"optional timing mode"| node_shizuku_engine
node_shizuku_engine -->|"IPC"| node_shizuku_aidl
node_service -->|"lifecycle and controls"| node_native_bridge
node_native_bridge -->|"JNI calls"| node_jni
node_jni -->|"commands and frames"| node_render_loop
node_render_loop -->|"uses renderer device"| node_vulkan_session
node_render_loop -->|"imports input"| node_ahb_bridge
node_render_loop -->|"presents to ANativeWindow"| node_frame_graph_view
node_shader_extractor -->|"selected DLL"| node_shader_loader
node_shader_loader -->|"SPIR-V assets"| node_vulkan_probe
node_vulkan_probe -->|"framegen or mirror-only gate"| node_service
node_vulkan_probe -->|"validated assets"| node_render_loop
node_native_crash -->|"native failures"| node_crash_reporter

click node_ui "https://github.com/frankbarretta/lsfg-android-application/blob/main/app/src/main/java/com/lsfg/android/ui/MainActivity.kt"
click node_projection_request "https://github.com/frankbarretta/lsfg-android-application/blob/main/app/src/main/java/com/lsfg/android/ui/ProjectionRequestActivity.kt"
click node_preferences "https://github.com/frankbarretta/lsfg-android-application/blob/main/app/src/main/java/com/lsfg/android/prefs/LsfgPreferences.kt"
click node_service "https://github.com/frankbarretta/lsfg-android-application/blob/main/app/src/main/java/com/lsfg/android/session/LsfgForegroundService.kt"
click node_crash_reporter "https://github.com/frankbarretta/lsfg-android-application/blob/main/app/src/main/java/com/lsfg/android/session/CrashReporter.kt"
click node_overlay_manager "https://github.com/frankbarretta/lsfg-android-application/blob/main/app/src/main/java/com/lsfg/android/session/OverlayManager.kt"
click node_accessibility "https://github.com/frankbarretta/lsfg-android-application/blob/main/app/src/main/java/com/lsfg/android/session/LsfgAccessibilityService.kt"
click node_frame_graph_view "https://github.com/frankbarretta/lsfg-android-application/blob/main/app/src/main/java/com/lsfg/android/session/FrameGraphView.kt"
click node_capture_engine "https://github.com/frankbarretta/lsfg-android-application/blob/main/app/src/main/java/com/lsfg/android/session/CaptureEngine.kt"
click node_shizuku_engine "https://github.com/frankbarretta/lsfg-android-application/blob/main/app/src/main/java/com/lsfg/android/session/ShizukuCaptureEngine.kt"
click node_shizuku_aidl "https://github.com/frankbarretta/lsfg-android-application/blob/main/app/src/main/aidl/com/lsfg/android/shizuku/IShizukuCaptureService.aidl"
click node_native_bridge "https://github.com/frankbarretta/lsfg-android-application/blob/main/app/src/main/java/com/lsfg/android/session/NativeBridge.kt"
click node_jni "https://github.com/frankbarretta/lsfg-android-application/blob/main/app/src/main/cpp/lsfg_jni.cpp"
click node_render_loop "https://github.com/frankbarretta/lsfg-android-application/blob/main/app/src/main/cpp/lsfg_render_loop.cpp"
click node_vulkan_session "https://github.com/frankbarretta/lsfg-android-application/blob/main/app/src/main/cpp/android_vk_session.cpp"
click node_ahb_bridge "https://github.com/frankbarretta/lsfg-android-application/blob/main/app/src/main/cpp/ahb_image_bridge.cpp"
click node_shader_extractor "https://github.com/frankbarretta/lsfg-android-application/blob/main/app/src/main/java/com/lsfg/android/session/ShaderExtractor.kt"
click node_shader_loader "https://github.com/frankbarretta/lsfg-android-application/blob/main/app/src/main/cpp/android_shader_loader.cpp"
click node_vulkan_probe "https://github.com/frankbarretta/lsfg-android-application/blob/main/app/src/main/cpp/android_vk_probe.cpp"
click node_native_crash "https://github.com/frankbarretta/lsfg-android-application/blob/main/app/src/main/cpp/crash_reporter.cpp"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_ui,node_projection_request,node_preferences,node_service,node_crash_reporter toneBlue
class node_target_display,node_overlay_manager,node_accessibility,node_frame_graph_view,node_capture_engine,node_shizuku_engine,node_shizuku_aidl toneAmber
class node_native_bridge,node_jni,node_render_loop,node_vulkan_session,node_ahb_bridge,node_native_crash toneMint
class node_shader_extractor,node_shader_loader,node_vulkan_probe toneRose
```

## Components

### Android control

- [Compose UI](https://github.com/frankbarretta/lsfg-android-application/blob/main/app/src/main/java/com/lsfg/android/ui/MainActivity.kt): Android UI · Collects session, pacing, and framegen settings. · `app/src/main/java/com/lsfg/android/ui/MainActivity.kt`
- [Projection request](https://github.com/frankbarretta/lsfg-android-application/blob/main/app/src/main/java/com/lsfg/android/ui/ProjectionRequestActivity.kt): permission activity · Obtains the per-session MediaProjection token. · `app/src/main/java/com/lsfg/android/ui/ProjectionRequestActivity.kt`
- [Preferences](https://github.com/frankbarretta/lsfg-android-application/blob/main/app/src/main/java/com/lsfg/android/prefs/LsfgPreferences.kt): settings store · `app/src/main/java/com/lsfg/android/prefs/LsfgPreferences.kt`
- [Foreground session service](https://github.com/frankbarretta/lsfg-android-application/blob/main/app/src/main/java/com/lsfg/android/session/LsfgForegroundService.kt): runtime orchestrator · Serializes session changes and starts capture only after notification and output surface readiness. · `app/src/main/java/com/lsfg/android/session/LsfgForegroundService.kt`
- [Crash reporting](https://github.com/frankbarretta/lsfg-android-application/blob/main/app/src/main/java/com/lsfg/android/session/CrashReporter.kt): failure persistence · Preserves native and Kotlin failures for the next launch. · `app/src/main/java/com/lsfg/android/session/CrashReporter.kt`

### Capture and overlay

- **Target app display**: Android display content
- [Overlay manager](https://github.com/frankbarretta/lsfg-android-application/blob/main/app/src/main/java/com/lsfg/android/session/OverlayManager.kt): surface host · Owns overlay windows, touchable insets, and output surface lifecycle. · `app/src/main/java/com/lsfg/android/session/OverlayManager.kt`
- [Accessibility overlay host](https://github.com/frankbarretta/lsfg-android-application/blob/main/app/src/main/java/com/lsfg/android/session/LsfgAccessibilityService.kt): accessibility service · Optional host for accessibility-overlay windows. · `app/src/main/java/com/lsfg/android/session/LsfgAccessibilityService.kt`
- [Overlay view](https://github.com/frankbarretta/lsfg-android-application/blob/main/app/src/main/java/com/lsfg/android/session/FrameGraphView.kt): surface view · Provides the presentation surface to the overlay host. · `app/src/main/java/com/lsfg/android/session/FrameGraphView.kt`
- [MediaProjection capture](https://github.com/frankbarretta/lsfg-android-application/blob/main/app/src/main/java/com/lsfg/android/session/CaptureEngine.kt): capture engine · Creates VirtualDisplay and ImageReader frames backed by AHardwareBuffer. · `app/src/main/java/com/lsfg/android/session/CaptureEngine.kt`
- [Shizuku timing integration](https://github.com/frankbarretta/lsfg-android-application/blob/main/app/src/main/java/com/lsfg/android/session/ShizukuCaptureEngine.kt): privileged timing · Provides timing integration only, not visible overlay buffers. · `app/src/main/java/com/lsfg/android/session/ShizukuCaptureEngine.kt`
- [Shizuku AIDL boundary](https://github.com/frankbarretta/lsfg-android-application/blob/main/app/src/main/aidl/com/lsfg/android/shizuku/IShizukuCaptureService.aidl): IPC contract · Separates the app from the Shizuku user service. · `app/src/main/aidl/com/lsfg/android/shizuku/IShizukuCaptureService.aidl`

### Native frame pipeline

- [JNI bridge](https://github.com/frankbarretta/lsfg-android-application/blob/main/app/src/main/java/com/lsfg/android/session/NativeBridge.kt): Kotlin-native API · Single boundary for lifecycle, frames, and hot controls. · `app/src/main/java/com/lsfg/android/session/NativeBridge.kt`
- [JNI entrypoint](https://github.com/frankbarretta/lsfg-android-application/blob/main/app/src/main/cpp/lsfg_jni.cpp): JNI implementation · `app/src/main/cpp/lsfg_jni.cpp`
- [Vulkan render loop](https://github.com/frankbarretta/lsfg-android-application/blob/main/app/src/main/cpp/lsfg_render_loop.cpp): worker renderer · Owns frame pacing, framegen lifecycle, and overlay presentation. · `app/src/main/cpp/lsfg_render_loop.cpp`
- [Vulkan session](https://github.com/frankbarretta/lsfg-android-application/blob/main/app/src/main/cpp/android_vk_session.cpp): persistent Vulkan state · Maintains the renderer device and presentation state. · `app/src/main/cpp/android_vk_session.cpp`
- [AHardwareBuffer bridge](https://github.com/frankbarretta/lsfg-android-application/blob/main/app/src/main/cpp/ahb_image_bridge.cpp): external-memory import · Imports capture buffers across the framegen device boundary. · `app/src/main/cpp/ahb_image_bridge.cpp`
- [Native crash handler](https://github.com/frankbarretta/lsfg-android-application/blob/main/app/src/main/cpp/crash_reporter.cpp): failure capture · `app/src/main/cpp/crash_reporter.cpp`

### Shader capability gate

- [DLL shader extraction](https://github.com/frankbarretta/lsfg-android-application/blob/main/app/src/main/java/com/lsfg/android/session/ShaderExtractor.kt): asset preparation · Processes selected Lossless.dll and deletes it after asset generation. · `app/src/main/java/com/lsfg/android/session/ShaderExtractor.kt`
- [DXBC to SPIR-V loader](https://github.com/frankbarretta/lsfg-android-application/blob/main/app/src/main/cpp/android_shader_loader.cpp): native shader extraction · Translates DLL resources and writes app-storage shader assets. · `app/src/main/cpp/android_shader_loader.cpp`
- [Vulkan capability probe](https://github.com/frankbarretta/lsfg-android-application/blob/main/app/src/main/cpp/android_vk_probe.cpp): capability gate · Headlessly validates shader modules and required capabilities such as robustness2. · `app/src/main/cpp/android_vk_probe.cpp`

## Connections

- Compose UI → Preferences: reads and saves settings
- Compose UI → Projection request: requests consent
- Compose UI → Foreground session service: launches session
- Preferences → Foreground session service: session configuration
- Projection request → Foreground session service: MediaProjection token
- Foreground session service → Overlay manager: creates overlay
- Accessibility overlay host → Overlay manager: optional overlay host
- Overlay manager → Overlay view: owns surface
- Overlay view → Foreground session service: surface lifecycle
- Foreground session service → MediaProjection capture: starts after surface ready
- Target app display → MediaProjection capture: MediaProjection capture
- MediaProjection capture → JNI bridge: AHardwareBuffer frames
- Foreground session service → Shizuku timing integration: optional timing mode
- Shizuku timing integration → Shizuku AIDL boundary: IPC
- Foreground session service → JNI bridge: lifecycle and controls
- JNI bridge → JNI entrypoint: JNI calls
- JNI entrypoint → Vulkan render loop: commands and frames
- Vulkan render loop → Vulkan session: uses renderer device
- Vulkan render loop → AHardwareBuffer bridge: imports input
- Vulkan render loop → Overlay view: presents to ANativeWindow
- DLL shader extraction → DXBC to SPIR-V loader: selected DLL
- DXBC to SPIR-V loader → Vulkan capability probe: SPIR-V assets
- Vulkan capability probe → Foreground session service: framegen or mirror-only gate
- Vulkan capability probe → Vulkan render loop: validated assets
- Native crash handler → Crash reporting: native failures
