# 画面設計書 11-TFLiteベンチマーク実行画面

## 概要

本ドキュメントは、TFLite Benchmarkツールアプリにおける「TFLiteベンチマーク実行画面」（BenchmarkModelActivity）の画面設計書である。本画面はIntent経由で引数を受け取り、TensorFlow Liteモデルのベンチマーク（推論速度測定）を実行して即座に終了するUIなしのActivityである。

### 本画面の処理概要

**業務上の目的・背景**：TensorFlow Liteモデルの推論性能を定量的に測定するためのベンチマークツールである。モデル開発者やアプリ開発者が、特定のモデルの推論速度をAndroidデバイス上で計測し、デリゲート（GPU、Hexagonなど）の効果を検証する際に使用する。adbコマンドやテスト自動化ツールから起動されることを前提としており、開発・検証フェーズでの性能評価を目的とする。

**画面へのアクセス方法**：本Activityは`android:theme="@android:style/Theme.NoDisplay"`が設定されたUIなしのActivityであり、adbコマンドまたは外部アプリケーションからIntent経由で起動する。起動コマンド例：`adb shell am start -n org.tensorflow.lite.benchmark/.BenchmarkModelActivity --es args "--graph=/path/to/model.tflite --num_threads=4"`

**主要な操作・処理内容**：
1. Intent Bundleから`args`または`--args`キーでベンチマーク引数文字列を取得する
2. 引数に`--use_hexagon=true`または`--use_hexagon=1`が含まれる場合、`--hexagon_lib_path`にネイティブライブラリディレクトリパスを自動付加する
3. `Trace.beginSection("TFLite Benchmark Model")`でシステムトレースを開始する
4. `BenchmarkModel.run(args)`でネイティブベンチマークを実行する
5. `Trace.endSection()`でトレースを終了する
6. `finish()`でActivity自身を終了する

**画面遷移**：外部Intent（adbまたはアプリ）から起動され、ベンチマーク完了後にfinish()で自動終了する。他の画面への遷移は存在しない。

**権限による表示制御**：UIが存在しないため表示制御はない。ただし、`READ_EXTERNAL_STORAGE`権限がモデルファイル読み込みに必要である。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 81 | TFLite推論エンジン | 主機能 | BenchmarkModel.run()を通じてTFLiteモデルのベンチマーク（推論速度測定）を実行 |
| 82 | TFLiteデリゲート | 補助機能 | --use_hexagon引数によるHexagonデリゲートの指定・ネイティブライブラリパスの設定 |

## 画面種別

UIなし（バックグラウンド処理）。Theme.NoDisplayを使用。

## URL/ルーティング

- パッケージ名: `org.tensorflow.lite.benchmark`
- Activity名: `.BenchmarkModelActivity`
- Intent起動: `adb shell am start -n org.tensorflow.lite.benchmark/.BenchmarkModelActivity --es args "<ベンチマーク引数>"`

## 入出力項目

| 項目名 | 型 | I/O | 必須 | 説明 |
|--------|-----|-----|------|------|
| args | String (Bundle Extra) | 入力 | はい（argsまたは--argsのいずれか） | ベンチマーク実行引数（例: `--graph=/path/to/model.tflite --num_threads=4`） |
| --args | String (Bundle Extra) | 入力 | はい（argsまたは--argsのいずれか） | ベンチマーク実行引数（argsキーのフォールバック） |
| ログ出力 | Logcat | 出力 | - | TAG `tflite_BenchmarkModelActivity` でベンチマーク引数と結果をログ出力 |
| システムトレース | Trace | 出力 | - | `TFLite Benchmark Model` セクションとしてシステムトレースに記録 |

## 表示項目

UIなしのため表示項目は存在しない。ベンチマーク結果はLogcatおよびシステムトレースに出力される。

## イベント仕様

### 1-Activity起動（onCreate）

1. `getIntent().getExtras()`でBundleを取得する
2. Bundleから`args`キーで文字列を取得。取得できない場合は`--args`キーにフォールバックする
3. 引数文字列にHexagonデリゲート指定（`--use_hexagon=true`または`--use_hexagon=1`）が含まれている場合、`--hexagon_lib_path=<nativeLibraryDir>`を引数に追加する
4. Logcat（TAG: `tflite_BenchmarkModelActivity`）にベンチマーク引数をINFOレベルで出力する
5. `Trace.beginSection("TFLite Benchmark Model")`でシステムトレースセクションを開始する
6. `BenchmarkModel.run(args)`を呼び出し、ネイティブレイヤーでベンチマークを同期実行する
7. `Trace.endSection()`でシステムトレースセクションを終了する
8. `finish()`でActivityを終了する

## データベース更新仕様

### 操作別データベース影響一覧

本画面はデータベース操作を行わない。

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| - | - | - | データベース操作なし |

## メッセージ仕様

| メッセージID | レベル | メッセージ内容 | 出力条件 |
|-------------|--------|--------------|---------|
| M-01 | INFO | "Running TensorFlow Lite benchmark with args: {args}" | Activity起動時に常時出力 |

## 例外処理

| 例外 | 発生条件 | 処理 |
|------|---------|------|
| NullPointerException | Intentに`args`/`--args`キーが存在しない場合 | BundleからのgetString()でnullが返り、contains()呼び出し時にクラッシュする可能性がある |
| UnsatisfiedLinkError | ネイティブライブラリが見つからない場合 | BenchmarkModelクラスの静的初期化子で`tensorflowlite_benchmark_plus_flex`を先にロードし、失敗時に`tensorflowlite_benchmark`にフォールバックする |

## 備考

- 本Activityは`android:noHistory="true"`が設定されており、タスク履歴に残らない
- `android:theme="@android:style/Theme.NoDisplay"`により画面描画は一切行われない
- minSdkVersion: 23、targetSdkVersion: 31
- OpenCLライブラリ（libOpenCL.so、libOpenCL-pixel.so）をオプションとしてuses-libraryで宣言している
- BenchmarkModelクラスはFlex Delegateサポート版ライブラリ（`tensorflowlite_benchmark_plus_flex`）を優先的にロードし、存在しない場合は標準版（`tensorflowlite_benchmark`）にフォールバックする

---

## コードリーディングガイド

本画面を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

本画面で扱うデータは、Intent Bundleに格納されたベンチマーク引数文字列（String）のみである。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | AndroidManifest.xml | `tensorflow/lite/tools/benchmark/android/AndroidManifest.xml` | Activity宣言、Theme.NoDisplay、noHistory=true、READ_EXTERNAL_STORAGE権限、OpenCLライブラリ宣言を確認（18-45行目） |

**読解のコツ**: AndroidManifest.xmlでActivityのthemeやexported属性を確認することで、本画面がUI非表示・外部起動専用であることが分かる。

#### Step 2: エントリーポイントを理解する

BenchmarkModelActivityのonCreateが唯一のエントリーポイントである。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | BenchmarkModelActivity.java | `tensorflow/lite/tools/benchmark/android/src/org/tensorflow/lite/benchmark/BenchmarkModelActivity.java` | onCreate内でIntent解析→Hexagonパス付加→BenchmarkModel.run()→finish()の一連の処理フローを確認（33-50行目） |

**主要処理フロー**:
1. **36行目**: `Intent intent = getIntent()` でIntentを取得
2. **37行目**: `Bundle bundle = intent.getExtras()` でBundleを取得
3. **38行目**: `args`キー優先、フォールバックで`--args`キーから引数文字列を取得
4. **39-42行目**: Hexagonデリゲート使用時にネイティブライブラリパスを自動付加
5. **45行目**: `Trace.beginSection("TFLite Benchmark Model")` でトレース開始
6. **46行目**: `BenchmarkModel.run(args)` でネイティブベンチマーク実行
7. **47行目**: `Trace.endSection()` でトレース終了
8. **49行目**: `finish()` でActivity終了

#### Step 3: ネイティブブリッジを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | BenchmarkModel.java | `tensorflow/lite/tools/benchmark/android/src/org/tensorflow/lite/benchmark/BenchmarkModel.java` | ネイティブライブラリロード戦略（flex対応版→標準版）とJNI呼び出しの構造を確認（19-37行目） |

**主要処理フロー**:
- **20-27行目**: 静的初期化子でflex対応版ライブラリを先にロード、UnsatisfiedLinkError時に標準版にフォールバック
- **32行目**: `run(String args)` メソッドが `nativeRun(args)` を呼び出し
- **36行目**: `private static native void nativeRun(String args)` でJNIメソッドを宣言

### プログラム呼び出し階層図

```
BenchmarkModelActivity.onCreate()
    |
    +-- getIntent().getExtras()          [Intent引数取得]
    |
    +-- Hexagon判定 & パス付加           [条件付き引数追加]
    |
    +-- Trace.beginSection()             [トレース開始]
    |
    +-- BenchmarkModel.run(args)
    |       |
    |       +-- nativeRun(args)          [JNI: ネイティブベンチマーク実行]
    |
    +-- Trace.endSection()               [トレース終了]
    |
    +-- finish()                         [Activity終了]
```

### データフロー図

```
[入力]                    [処理]                         [出力]

Intent Bundle      -->  BenchmarkModelActivity      -->  Logcat (TAG: tflite_BenchmarkModelActivity)
  args: String           .onCreate()
                             |
                         引数解析 & Hexagonパス付加
                             |
                         BenchmarkModel.run()        -->  System Trace ("TFLite Benchmark Model")
                             |
                         nativeRun() [JNI]           -->  ベンチマーク結果 (ネイティブ側で出力)
                             |
                         finish()                    -->  Activity終了
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| BenchmarkModelActivity.java | `tensorflow/lite/tools/benchmark/android/src/org/tensorflow/lite/benchmark/BenchmarkModelActivity.java` | ソース | メインActivity。Intent引数取得・ベンチマーク実行・終了を担う |
| BenchmarkModel.java | `tensorflow/lite/tools/benchmark/android/src/org/tensorflow/lite/benchmark/BenchmarkModel.java` | ソース | ネイティブベンチマーク実行のJNIブリッジクラス |
| AndroidManifest.xml | `tensorflow/lite/tools/benchmark/android/AndroidManifest.xml` | 設定 | Activity宣言、権限、テーマ、OpenCLライブラリの定義 |
