# Android module (Tauri serial plugin)
## Dependency
- [usb-serial-for-android](https://github.com/mik3y/usb-serial-for-android) (`com.github.mik3y:usb-serial-for-android`) — the `UsbSerialPort` interface: `read` / `write` with timeout, `purgeHwBuffers`, `setFlowControl`, RTS/DTR/CTS lines, etc.
## Lifecycle / cleanup
`SerialPlugin` registers `Application.ActivityLifecycleCallbacks` in `load()` and calls `SerialPortManager.cleanup()` when the host `Activity` is destroyed (USB ports closed, broadcast receiver unregistered, IO executor shut down). This complements JS `close` / `closeAll` and reduces leaks or stale native work after the WebView/activity is gone.
## Unit tests (Kotlin)
Tests live under `src/test/kotlin/`. Pure JVM tests (no Robolectric required):
- `SerialModelsTest` — model enums / defaults (`Parity` / `StopBits` round-trip, invalid `fromValue` fallbacks)
- `SerialByteAccumulatorTest` — thread-safe byte coalescing for `BufferedEmitter`
- `SerialDataEmitFieldsTest` — `serialDataPayloadFromChunk` / `flushAccumulatorToEmit` / `applyToJSObject` (binary + UTF-8)
- `SerialPluginConversionTest` — `Map.toJSObject` / `List.toJSArray` helpers from `SerialPlugin.kt`
- `BufferedEmitterTest` — `pendingByteCount()` before flush
JVM unit tests use **`testImplementation("org.json:json:…")`** so `JSONObject.put` is not the Android stub that throws (“Method … not mocked”).
`BufferedEmitter` itself still schedules timers and builds `JSObject` on device; the buffer + flush pipeline is covered by the tests above.
Run from the `android/` directory (Android SDK, **JDK 17+** for Gradle; use **17** if Gradle errors on JDK 25):
```bash
cd android
export JAVA_HOME=$(/usr/libexec/java_home -v 17) # macOS; use JDK 17 on Linux/Windows
./gradlew test
```
This repo includes a Gradle wrapper (`gradlew`, `gradle/wrapper/`). The module depends on `:tauri-android` from `.tauri/tauri-api` (bundled under `android/.tauri/tauri-api` or generated by Tauri).
## Behavior tied to the library
| `setTimeout` | Stored in `SerialPortConfig.timeout` and used for `write()` and as a fallback for `read()` when the call passes `timeout == 0`. |
| `clearBuffer` | `UsbSerialPort.purgeHwBuffers()` (when supported by the driver). |
| `setFlowControl` | `UsbSerialPort.setFlowControl(RTS_CTS / XON_XOFF / NONE)`. |
| `bytesToRead` | With **listening** (`startListening`): bytes in the plugin’s [BufferedEmitter] before the next `serialData` flush (not the kernel queue). Without listening: `0`. |
| `bytesToWrite` | Always `0`: writes are synchronous; usb-serial exposes no TX backlog. |