# Architecture — SonoiQ

## 系統形態

SonoiQ 是典型的**醫療超聲嵌入式宿主架構**：超聲探頭（硬體，含 FPGA 波束形成器與前端模擬電路）通過 USB 或 Wi-Fi 連接到 Android 主機。App 分四層：

1. **UI 層**（`com.Com.*` Activities + `handprobe.application.gui.*` Fragments）— 掃描界面、測量、菜單
2. **核心層**（`handprobe.application.*`）— `Ultrasys` 單例統籌影像管線；preset/measurement/patient/cine/network 子系統
3. **JNI 橋**（`jni.*`、`kernel.*`）— `libdoppler` / `libHSocketIf` 的 Java 接口 + C→Java 消息泵
4. **Native 引擎**（28 個 `.so`）— 超聲信號處理（doppler）、影像處理（OpenCV）、AI 推理（PyTorch/TFLite）、語音（Vosk）、視頻（FFmpeg/x264）

數據入口是探頭（RF/影像流經 FPGA 採集），出口是屏幕顯示、DICOM 存儲/打印、PDF 報告與本地檔案。

## Components

- **Probe hardware（FPGA）** — 探頭內固件由 `assets/pid/FPGA_ch16*.rbf`（Intel/Altera bitstream）+ `PID03.zip` 探頭描述庫定義；App 側通過 `HPidIf.setPidFilesPath()` / `InitPidSys()` 初始化
- **UsbProbeManager / WlanProbe** — 傳輸層：USB bulk 讀寫（`UsbWriteDwords`/`UsbReadDwords`/`WUsbReadImg`）或 Wi-Fi 探頭（`handprobe.application.wlan.*`）
- **Ultrasys** — Java 核心單例：`DscCtrl`（數字掃描轉換）、`FeUltrasysCtrl`（前端控制）、`ImagePlayer`、`CinePlayer`、`PresetServer`、MITI 熱指數
- **kernel.MainHandler** — native 消息泵：`jnitojava.JavaGetMessage(long[4])` 輪詢 → 廣播給註冊的 Doppler Handler
- **DICOM services** — `JDicomServer`/`Storage`/`Worklist`/`MPPS`/`Print`（`handprobe.components.dicom.*`）
- **AI engines** — `handprobe.application.ai.*`（診斷算法）+ `handprobe.components.ai.{pytorch,tensorflow}`（推理封裝）
- **Storage** — xUtils SQLite：`UserInfo/sonoiq.db`、`OperatorAuth/sonoiq.db`、`PatientInfo/sonoiq.db` + 外部存儲檔案系統（`PodFilesSys`）

## System Diagram

```mermaid
flowchart TD
    Probe[["Ultrasound Probe<br>FPGA beamformer"]] -->|"USB bulk / WiFi"| Xport[UsbProbeManager / WlanProbe]
    Xport -->|jnitojava| Native[["Native engines<br>libdoppler · libHSocketIf<br>OpenCV · PyTorch · TFLite<br>Vosk · FFmpeg"]]
    Native -->|"JavaGetMessage(what,arg1,arg2)"| Pump[kernel.MainHandler]
    Pump -->|broadcast| Core[Ultrasys singleton]
    Core --> DSC[DscCtrl]
    Core --> Img[ImagePlayer / DispSurface]
    Core --> Cine[CinePlayer / CinePartitionBuffer]
    Core --> MITI[MITIData]
    Img --> UI[Activities / Fragments<br>com.Com.handprobe · gui.*]
    UI --> Dicom[DICOM Server/Storage/Worklist/MPPS/Print]
    Dicom --> Net{{"PACS / Printer<br>(external)"}}
    UI --> AI[ai.* diagnosis]
    AI --> Native
    UI --> DB[("SQLite ×3<br>xUtils")]
    Core --> Preset[PresetServer / ExamMode]
    Preset --> Assets[["assets/<br>PID03.zip · presetPara · BodyMark"]]
```

## Data Flow

1. **採集** — 探頭 FPGA 採集 RF/影像，App 經 `UsbProbeManager.Read()` / `ReadEncImg()` 拉取（`jnitojava.WUsbReadImg`）
2. **處理** — native 完成波束形成/掃描轉換/多普勒處理；結果經 `JavaGetMessage` 上拋
3. **顯示** — `Ultrasys` 分發 → `ImagePlayer`/`DispSurface`（OpenGL，`HGLImageJNIViewLib`）渲染到 UI
4. **AI** — 用戶觸發測量 → `ai.*` 調用 PyTorch/TFLite 模型 → 結果疊加顯示
5. **存儲/輸出** — 圖像/報告寫本地（`PodFilesSys`）、經 DICOM 上傳 PACS、打印或輸出 PDF

## Key Design Decisions

- **單一 arm64-v8a ABI** — 現代設備專用，壓縮體積（探頭 App 一般跑在專用平板）
- **探頭即數據庫** — 探頭參數（元素數、半徑、頻率）由 `PID03.zip` 描述，native 側查詢（`GetProbeElementNumber()` 等），App 換探頭即可切換參數
- **7 種連接類型共存** — `ConnectType`（SIMU/WLAN/WUSB/USB/UWLAN/RGBIF/BROADCAST）由 `HSysctrlIf.SetProbeConnType()` 同步到 native
- **OEM 由常數+資源派生** — 同一 dex 經 `MyApplication.OEM_*_ID` 與 `def_vet` 等資源開關切換品牌/人獸醫模式，無需分叉代碼
- **C→Java 採用輪詢而非直接 JNIEnv 回調** — `JavaGetMessage` 阻塞輪詢 + 主線程 Handler 廣播，避免 JNI 跨線程回調複雜性
- **資源全面混淆** — `res/` 檔名短隨機化（如 `xY.png`、`9_.jpg`），但 `assets/` 保持明文目錄結構
