Skip to content

9/N Add Android demo app with JNI bridge and Kotlin SDK#17942

Closed
lucylq wants to merge 1 commit intopytorch:mainfrom
lucylq:export-D94806717
Closed

9/N Add Android demo app with JNI bridge and Kotlin SDK#17942
lucylq wants to merge 1 commit intopytorch:mainfrom
lucylq:export-D94806717

Conversation

@lucylq
Copy link
Contributor

@lucylq lucylq commented Mar 5, 2026

Summary:
sync oss and internal

Reviewed By: julianchan-meta

Differential Revision: D94806717

Summary:
Add a Jetpack Compose Android demo app for Gemma 3N speech transcription and translation on-device via ExecuTorch. All new files are placed under `fb/` directories to keep them internal-only (excluded from GitHub export via ShipIt).

bypass-github-export-checks Contains internal-only changes (all new files under fb/ paths, modifications marked oss-disable)

**Kotlin SDK** (extension/android/.../extension/fb/gemma3n/):
- `Gemma3nModule.kt` — main API: `load()`, `transcribe(wavPath, prompt)`, `generateText(prompt)`, `reset()`, `close()`. Uses `AtomicLong` native handle + `Closeable` pattern (follows AsrModule).
- `Gemma3nCallback.kt` — streaming interface: `onToken(String)` + `onStats(String)`
- `Gemma3nConfig.kt` — generation config: `maxNewTokens`, `temperature`

**JNI bridge** (extension/android/jni/fb/jni_layer_gemma3n.cpp):
- 7 native methods wrapping `Gemma3nRunner`: create, destroy, load (+ prefill_template), isLoaded, transcribe, generateText, reset
- WAV loading via `load_wav_audio_data`, zero-padding to 480k samples
- UTF-8 safe token streaming via `GetJavaVM`/`AttachCurrentThread` callback pattern
- Stats JSON forwarded via `onStats` callback after generation completes

**Android demo app** (examples/demo-apps/android/fb/Gemma3nDemo/):
- Single-activity Compose app with setup/loading/main screens
- Audio recording via `AudioRecord` (16kHz mono PCM, max 30s) with WAV file writing
- WAV file picker via `ACTION_GET_CONTENT`
- Prompt dropdown: Transcribe / Translate to Spanish / Translate to Chinese / custom
- Text-only generation mode
- Streaming token output + performance stats display (speech encoder, prefill, tok/s, TTFT, total)
- `build_and_deploy.sh` script for end-to-end AAR build + APK deploy

**CMake build** (examples/models/fb/gemma3n/CMakeLists.txt):
- `gemma3n_runner` static library for Android, shared for desktop
- `gemma3n_main` CLI binary (desktop only)
- CMakePresets for `gemma3n-cpu` and `gemma3n-android` (arm64-v8a)

**Build integration:**
- `extension/android/CMakeLists.txt`: added `EXECUTORCH_BUILD_GEMMA3N_JNI` flag to compile Gemma3N runner sources + JNI into `libexecutorch.so` (lines marked `oss-disable`)
- `scripts/build_android_library.sh`: added `-DEXECUTORCH_BUILD_GEMMA3N_JNI` passthrough (default OFF, marked `oss-disable`)

Reviewed By: julianchan-meta

Differential Revision: D94806717
@lucylq lucylq requested a review from larryliu0820 as a code owner March 5, 2026 19:18
Copilot AI review requested due to automatic review settings March 5, 2026 19:18
@pytorch-bot
Copy link

pytorch-bot bot commented Mar 5, 2026

🔗 Helpful Links

🧪 See artifacts and rendered test results at hud.pytorch.org/pr/pytorch/executorch/17942

Note: Links to docs will display an error until the docs builds have been completed.

❌ 30 New Failures, 1 Cancelled Job, 3 Unrelated Failures

As of commit 46516e7 with merge base 2cb1ef5 (image):

NEW FAILURES - The following jobs have failed:

CANCELLED JOB - The following job was cancelled. Please retry:

FLAKY - The following jobs failed but were likely due to flakiness present on trunk:

This comment was automatically generated by Dr. CI and updates every 15 minutes.

@meta-cla meta-cla bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Mar 5, 2026
@meta-codesync
Copy link
Contributor

meta-codesync bot commented Mar 5, 2026

@lucylq has exported this pull request. If you are a Meta employee, you can view the originating Diff in D94806717.

@github-actions
Copy link

github-actions bot commented Mar 5, 2026

This PR needs a release notes: label

If your change should be included in the release notes (i.e. would users of this library care about this change?), please use a label starting with release notes:. This helps us keep track and include your important work in the next release notes.

To add a label, you can comment to pytorchbot, for example
@pytorchbot label "release notes: none"

For more information, see
https://github.com/pytorch/pytorch/wiki/PyTorch-AutoLabel-Bot#why-categorize-for-release-notes-and-how-does-it-work.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

@lucylq lucylq closed this Mar 6, 2026
psiddh added a commit that referenced this pull request Mar 6, 2026
## Summary

Add a generic hook in `extension/android/CMakeLists.txt` that
conditionally includes `fb/extended_targets/CMakeLists.txt` if it
exists. This allows internal or partner-specific JNI extensions (e.g.,
Gemma3N) to plug into the Android JNI build **without modifying OSS
files**.

When `fb/extended_targets/CMakeLists.txt` does not exist (as in OSS
builds), the hook is a complete no-op.

## Motivation

PR #17942 added Gemma3N Android demo app support, but required modifying
two OSS files (`extension/android/CMakeLists.txt` and
`scripts/build_android_library.sh`) with `@oss-disable` lines. This
creates ongoing merge friction and scales poorly as more internal models
are added.

This PR introduces a one-time, stable hook so that:

| Build System | How it Works | Result |
| :--- | :--- | :--- |
| **Internal Buck CI** | Uses TARGETS files directly | No change needed
|
| **Internal CMake/Gradle** | Hook includes
`fb/extended_targets/CMakeLists.txt` which sets internal flags | Works |
| **OSS CMake/Gradle** | Hook is a no-op (`fb/extended_targets/` does
not exist) | Works |


## Test plan

- OSS builds: No behavior change. The `fb/extended_targets/` directory
does not exist, so the `if(EXISTS ...)` evaluates to false and is a
no-op.
- Internal builds: Place a `CMakeLists.txt` in
`extension/android/fb/extended_targets/` to verify it gets included.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. fb-exported meta-exported

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants