docs: describe the JNI architecture the app actually uses

The root README still documented the abandoned approach: iperf3 3.21 binaries
bundled in assets and run through a Process runner, and a lib/ layout that no
longer matched. It now covers the JNI design, the current feature set and how
to test against a local iperf3 server, and says plainly that the binaries
still sitting in assets/iperf3/ are undeclared in pubspec.yaml and therefore
never reach the APK.

docs/README.md gains the threading, pipe-shutdown and stop-handling
constraints that the fixes on this branch depend on, so the next change does
not have to rediscover why the join order and the worker thread matter.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-26 19:03:59 +09:00
parent 6f809913bd
commit 0dc747edef
2 changed files with 76 additions and 22 deletions
+45 -13
View File
@@ -1,13 +1,16 @@
# iperf3-gui
A Flutter-based Android GUI wrapper for iperf3, the popular network performance measurement tool.
A Flutter-based Android GUI wrapper for iperf3, the popular network performance
measurement tool.
## Features
- Client-mode network throughput testing
- Simple UI: enter server address, port, and press GO
- Raw iperf3 output display
- Bundled iperf3 v3.21 binaries for arm64-v8a and armeabi-v7a
- Configurable server, port, duration and parallel streams
- Live iperf3 output, streamed line by line while the test runs
- Stop a running test early
- Copy the transcript to the clipboard
- iperf3 3.19 compiled into the app as a native library — no external binary
## Architecture
@@ -15,33 +18,62 @@ A Flutter-based Android GUI wrapper for iperf3, the popular network performance
lib/
├── domain/
│ ├── models/ # TestConfiguration, Iperf3Result
│ └── services/ # Iperf3Service (Process runner)
├── data/
│ └── services/ # Iperf3Service (MethodChannel → JNI)
├── ui/
│ └── features/
│ └── test_run/ # TestRunScreen, TestRunViewModel
├── main.dart # App entry point
└── pubspec.yaml # Dependencies: provider, path_provider
└── main.dart # App entry point
android/app/src/main/
├── kotlin/…/IperfRunner.kt # MethodChannel handler, runs tests off the platform thread
└── cpp/iperf_jni.c # JNI bridge into the iperf3 API
```
See [docs/README.md](docs/README.md) for the data flow, the native API surface
and the design decisions behind them.
## Why JNI instead of executing a binary
Android SELinux in Enforcing mode blocks `execve()` from the `untrusted_app`
domain, so shipping an iperf3 ELF in assets and running it via `Process.start()`
fails with "Permission denied". iperf3 is therefore compiled as a shared library
(`libiperf3jni.so`) and called in-process over JNI.
`assets/iperf3/` still holds the pre-compiled binaries from that earlier
approach. They are not declared in `pubspec.yaml`, so they are not packaged into
the APK, and nothing in the app reads them.
## Building
Prerequisites:
- Flutter 3.47+
- Flutter 3.47+
- Android SDK with platform android-36
- JDK 17
- NDK r28+ and CMake 3.22.1 (for the native build)
```bash
flutter create . --org novoyuuparosk --project-name iperf3gui
flutter pub get
flutter analyze
flutter test
flutter build apk --debug
adb install -r build/app/outputs/flutter-apk/app-debug.apk
```
### iperf3 Binaries
## Testing against a local server
Pre-compiled binaries are sourced from [davidBar-On/android-iperf3](https://github.com/davidBar-On/android-iperf3)
and bundled in `assets/iperf3/` (arm64-v8a and armeabi-v7a for Android 28+).
```bash
iperf3 -s -p 5201 # on a machine on the same network
ip -4 addr show # note its address
```
Enter that address in the app, then press GO.
## Dependencies
- Dart: `provider`
- Native: iperf3 3.19 + cJSON, built by CMake for `armeabi-v7a` and `arm64-v8a`
## License
MIT — bundled iperf3 v3.21 is BSD-3-Clause licensed.
MIT — bundled iperf3 3.19 is BSD-3-Clause licensed.