Sky-Kim's picture
Initial commit
2e7837a
|
Raw
History Blame Contribute Delete
3.16 kB

Android LLM bridge (AndroidBridge~)

A thin Kotlin/JNI bridge that runs an on-device LLM on Android via the LiteRT-LM runtime, exposed to Unity as an AAR. A Unity C# layer calls it through AndroidJavaObject; this folder is the native (Kotlin) side, shipped inside the com.sky.ondeviceagent package.

This folder (AndroidBridge~) holds the source, hidden from Unity's importer by the trailing ~. Unity consumes the prebuilt AAR (not this source) from the same package at Runtime/Plugins/Android/llm-release.aar — rebuild from here only when the bridge changes.

Build

Standard Android Gradle build (build it with a JDK 17, e.g. Unity's bundled OpenJDK):

./gradlew assembleRelease
# output: build/outputs/aar/llm-release.aar

Replace this package's prebuilt AAR with the output — from this folder that is ../Runtime/Plugins/Android/llm-release.aar — then run Assets ▸ External Dependency Manager ▸ Android Resolver ▸ Resolve so the transitive Maven deps (declared in LiteRtDependencies.xml) are fetched.

Unity Player Settings for the consumer: IL2CPP, ARM64, minSdk 31.

JNI contract

The AAR exposes exactly this (the Unity C# side depends on the names):

initialize(String modelPath, String backend, InitCallback)
generate(String prompt, byte[] jpeg /* nullable */, StreamCallback)                          // text/multimodal, no tools
generate(String systemPrompt, String prompt, byte[] jpeg, String toolsJson, StreamCallback)  // tool-aware overload
provideToolResult(String callId, String result)
interface InitCallback   { onReady(); onError(String) }
interface StreamCallback { onChunk(String); onToolCall(String callId, String name, String argsJson); onComplete(String); onError(String) }

Backends

initialize takes a backend string mapped to LiteRT-LM backends:

Backend Notes
GPU OpenCL; falls back to CPU where unavailable. Most portable.
CPU Always available, slowest.
NPU Qualcomm Hexagon via QNN. Needs an NPU-exported model and a supported SoC/HTP (verified on SM8750 / Hexagon v79). Falls back to CPU if init fails.

The QNN runtime version must match the NPU model's QNN context binary and libLiteRtDispatch_Qualcomm.so (known-good pairing: QNN 2.44.0).

Third-party / bundled components

Component Source License (verify before redistribution)
LiteRT-LM (com.google.ai.edge.litertlm) Google AI Edge Verify upstream terms
kotlinx-coroutines JetBrains Apache-2.0
libLiteRtDispatch_Qualcomm.so (bundled in jniLibs/) LiteRT / Qualcomm QNN dispatch ⚠️ Verify redistribution terms (Qualcomm QNN components are proprietary)
QNN runtime + LiteRT QNN delegate (com.qualcomm.qti:qnn-*) Qualcomm ⚠️ Proprietary; fetched at build via Maven, not committed

The bridge's own Kotlin source is Apache-2.0. The bundled .so and the Maven-fetched QNN artifacts carry their own terms — confirm redistribution rights before publishing this repo publicly.