From 590d50e52d799e8d45932005c5d0a4f418e38eb5 Mon Sep 17 00:00:00 2001 From: Hansong Zhang Date: Wed, 14 Jan 2026 17:12:53 -0800 Subject: [PATCH 01/23] Add LlamaDemo Android instrumentation test workflow Run emulator-based instrumentation tests on Ubuntu 24.04 runner with: - KVM hardware acceleration - X11/graphics library dependencies for headless emulator - Android SDK setup via android-actions/setup-android - AVD caching for faster subsequent runs --- .github/workflows/llm-android.yml | 139 ++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 .github/workflows/llm-android.yml diff --git a/.github/workflows/llm-android.yml b/.github/workflows/llm-android.yml new file mode 100644 index 0000000000..529f021c60 --- /dev/null +++ b/.github/workflows/llm-android.yml @@ -0,0 +1,139 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. +# All rights reserved. +# +# This source code is licensed under the BSD-style license found in the +# LICENSE file in the root directory of this source tree. + +name: LlamaDemo Android + +on: + pull_request: + branches: [main] + paths: + - 'llm/android/**' + - '.github/workflows/llm-android.yml' + workflow_dispatch: + inputs: + pte_url: + description: 'URL to download model .pte file' + required: false + type: string + default: 'https://ossci-android.s3.amazonaws.com/executorch/stories/snapshot-20260114/stories110M.pte' + tokenizer_url: + description: 'URL to download tokenizer file' + required: false + type: string + default: 'https://ossci-android.s3.amazonaws.com/executorch/stories/snapshot-20260114/tokenizer.model' + +permissions: + contents: read + +env: + # Default URLs for pull_request trigger (workflow_dispatch inputs override these) + DEFAULT_PTE_URL: 'https://ossci-android.s3.amazonaws.com/executorch/stories/snapshot-20260114/stories110M.pte' + DEFAULT_TOKENIZER_URL: 'https://ossci-android.s3.amazonaws.com/executorch/stories/snapshot-20260114/tokenizer.model' + +jobs: + instrumentation-test: + runs-on: linux.24_04.4x + env: + API_LEVEL: 34 + ARCH: x86_64 + EMULATOR_OPTIONS: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none + + name: Instrumentation Test LlamaDemo + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Enable KVM group perms + run: | + echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules + sudo udevadm control --reload-rules + sudo udevadm trigger --name-match=kvm + + - name: Install Android Emulator dependencies + run: | + cat /etc/os-release + sudo apt-get update + sudo apt-get install -y \ + libx11-xcb1 \ + libxcb1 \ + libxcb-glx0 \ + libxcb-shm0 \ + libpulse0 \ + libnss3 \ + libxcomposite1 \ + libxcursor1 \ + libxi6 \ + libxtst6 \ + libasound2t64 \ + libgl1-mesa-glx \ + libgl1-mesa-dri + + - name: Set up Android SDK + uses: android-actions/setup-android@v3 + + - name: Install Android Emulator and system image + run: | + sdkmanager --install "emulator" "platform-tools" "platforms;android-${{ env.API_LEVEL }}" "system-images;android-${{ env.API_LEVEL }};default;${{ env.ARCH }}" + + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'temurin' + + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + + - name: Download model files + run: | + PTE_URL="${{ inputs.pte_url || env.DEFAULT_PTE_URL }}" + TOKENIZER_URL="${{ inputs.tokenizer_url || env.DEFAULT_TOKENIZER_URL }}" + + mkdir -p /tmp/llama-models + echo "Downloading model from $PTE_URL" + curl -fL -o /tmp/llama-models/model.pte "$PTE_URL" + echo "Downloading tokenizer from $TOKENIZER_URL" + curl -fL -o /tmp/llama-models/tokenizer.model "$TOKENIZER_URL" + + ls -la /tmp/llama-models/ + + - name: AVD cache + uses: actions/cache@v4 + id: avd-cache + with: + path: | + ~/.android/avd/* + ~/.android/adb* + key: avd-${{ env.API_LEVEL }}-${{ env.ARCH }} + + - name: Create AVD and generate snapshot for caching + if: steps.avd-cache.outputs.cache-hit != 'true' + uses: reactivecircus/android-emulator-runner@v2 + with: + api-level: ${{ env.API_LEVEL }} + arch: ${{ env.ARCH }} + force-avd-creation: false + ram-size: 6144M + emulator-options: ${{ env.EMULATOR_OPTIONS }} + disable-animations: false + working-directory: llm/android/LlamaDemo + script: echo "Generated AVD snapshot for caching." + + - name: Run instrumentation tests + uses: reactivecircus/android-emulator-runner@v2 + with: + api-level: ${{ env.API_LEVEL }} + arch: ${{ env.ARCH }} + force-avd-creation: false + ram-size: 6144M + emulator-options: -no-snapshot-save ${{ env.EMULATOR_OPTIONS }} + disable-animations: true + working-directory: llm/android/LlamaDemo + script: | + adb shell mkdir -p /data/local/tmp/llama/ + adb push /tmp/llama-models/model.pte /data/local/tmp/llama/ + adb push /tmp/llama-models/tokenizer.model /data/local/tmp/llama/ + ./gradlew connectedCheck -PskipModelDownload=true From 4f80ca7006000bb4e5861c5a2c3a8d9c14d94cf9 Mon Sep 17 00:00:00 2001 From: Hansong Zhang Date: Wed, 14 Jan 2026 17:15:40 -0800 Subject: [PATCH 02/23] fix --- .github/workflows/llm-android.yml | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/.github/workflows/llm-android.yml b/.github/workflows/llm-android.yml index 529f021c60..cf48823bd2 100644 --- a/.github/workflows/llm-android.yml +++ b/.github/workflows/llm-android.yml @@ -52,25 +52,6 @@ jobs: sudo udevadm control --reload-rules sudo udevadm trigger --name-match=kvm - - name: Install Android Emulator dependencies - run: | - cat /etc/os-release - sudo apt-get update - sudo apt-get install -y \ - libx11-xcb1 \ - libxcb1 \ - libxcb-glx0 \ - libxcb-shm0 \ - libpulse0 \ - libnss3 \ - libxcomposite1 \ - libxcursor1 \ - libxi6 \ - libxtst6 \ - libasound2t64 \ - libgl1-mesa-glx \ - libgl1-mesa-dri - - name: Set up Android SDK uses: android-actions/setup-android@v3 From 8eaa2444c8df7c444bd3a2bf35f93c2165970c05 Mon Sep 17 00:00:00 2001 From: Hansong Zhang Date: Wed, 14 Jan 2026 17:21:19 -0800 Subject: [PATCH 03/23] Try --- .github/workflows/llm-android.yml | 7 ------- 1 file changed, 7 deletions(-) diff --git a/.github/workflows/llm-android.yml b/.github/workflows/llm-android.yml index cf48823bd2..4e2daf5df3 100644 --- a/.github/workflows/llm-android.yml +++ b/.github/workflows/llm-android.yml @@ -52,13 +52,6 @@ jobs: sudo udevadm control --reload-rules sudo udevadm trigger --name-match=kvm - - name: Set up Android SDK - uses: android-actions/setup-android@v3 - - - name: Install Android Emulator and system image - run: | - sdkmanager --install "emulator" "platform-tools" "platforms;android-${{ env.API_LEVEL }}" "system-images;android-${{ env.API_LEVEL }};default;${{ env.ARCH }}" - - name: Set up JDK 17 uses: actions/setup-java@v4 with: From 3d071729330b81034f5670b41ae662cfd815b208 Mon Sep 17 00:00:00 2001 From: Hansong Zhang Date: Wed, 14 Jan 2026 17:24:33 -0800 Subject: [PATCH 04/23] Fix --- .github/workflows/llm-android.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/llm-android.yml b/.github/workflows/llm-android.yml index 4e2daf5df3..1e35623869 100644 --- a/.github/workflows/llm-android.yml +++ b/.github/workflows/llm-android.yml @@ -90,7 +90,7 @@ jobs: api-level: ${{ env.API_LEVEL }} arch: ${{ env.ARCH }} force-avd-creation: false - ram-size: 6144M + ram-size: 16384M emulator-options: ${{ env.EMULATOR_OPTIONS }} disable-animations: false working-directory: llm/android/LlamaDemo @@ -102,7 +102,7 @@ jobs: api-level: ${{ env.API_LEVEL }} arch: ${{ env.ARCH }} force-avd-creation: false - ram-size: 6144M + ram-size: 16384M emulator-options: -no-snapshot-save ${{ env.EMULATOR_OPTIONS }} disable-animations: true working-directory: llm/android/LlamaDemo From c47ae33abd7683c8815e5999347f113b718f0f8b Mon Sep 17 00:00:00 2001 From: Hansong Zhang <107070759+kirklandsign@users.noreply.github.com> Date: Wed, 14 Jan 2026 17:31:59 -0800 Subject: [PATCH 05/23] Update llm-android.yml --- .github/workflows/llm-android.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/llm-android.yml b/.github/workflows/llm-android.yml index 1e35623869..5b0e050067 100644 --- a/.github/workflows/llm-android.yml +++ b/.github/workflows/llm-android.yml @@ -35,7 +35,7 @@ env: jobs: instrumentation-test: - runs-on: linux.24_04.4x + runs-on: 8-core-ubuntu env: API_LEVEL: 34 ARCH: x86_64 From 4a4bd4b78880aaa61644218e4bdcc00fbbad3f54 Mon Sep 17 00:00:00 2001 From: Hansong Zhang <107070759+kirklandsign@users.noreply.github.com> Date: Wed, 14 Jan 2026 17:44:03 -0800 Subject: [PATCH 06/23] Change runner from 8-core to 16-core Ubuntu --- .github/workflows/llm-android.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/llm-android.yml b/.github/workflows/llm-android.yml index 5b0e050067..e20ee2d839 100644 --- a/.github/workflows/llm-android.yml +++ b/.github/workflows/llm-android.yml @@ -35,7 +35,7 @@ env: jobs: instrumentation-test: - runs-on: 8-core-ubuntu + runs-on: 16-core-ubuntu env: API_LEVEL: 34 ARCH: x86_64 From 076565d8c7ceab20a1a09323a5a1e013c448f042 Mon Sep 17 00:00:00 2001 From: Hansong Zhang <107070759+kirklandsign@users.noreply.github.com> Date: Wed, 14 Jan 2026 22:17:34 -0800 Subject: [PATCH 07/23] Change runner from 16-core to 8-core Ubuntu --- .github/workflows/llm-android.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/llm-android.yml b/.github/workflows/llm-android.yml index e20ee2d839..5b0e050067 100644 --- a/.github/workflows/llm-android.yml +++ b/.github/workflows/llm-android.yml @@ -35,7 +35,7 @@ env: jobs: instrumentation-test: - runs-on: 16-core-ubuntu + runs-on: 8-core-ubuntu env: API_LEVEL: 34 ARCH: x86_64 From aaa99d958650c904716d82365dec609552510753 Mon Sep 17 00:00:00 2001 From: Hansong Zhang Date: Wed, 14 Jan 2026 22:29:31 -0800 Subject: [PATCH 08/23] logcat --- .github/workflows/llm-android.yml | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/.github/workflows/llm-android.yml b/.github/workflows/llm-android.yml index 1e35623869..5bb05138a1 100644 --- a/.github/workflows/llm-android.yml +++ b/.github/workflows/llm-android.yml @@ -110,4 +110,25 @@ jobs: adb shell mkdir -p /data/local/tmp/llama/ adb push /tmp/llama-models/model.pte /data/local/tmp/llama/ adb push /tmp/llama-models/tokenizer.model /data/local/tmp/llama/ - ./gradlew connectedCheck -PskipModelDownload=true + + # Start logcat in background and save to file + adb logcat -c + adb logcat > /tmp/logcat.txt & + LOGCAT_PID=$! + + # Run tests + ./gradlew connectedCheck -PskipModelDownload=true || TEST_EXIT_CODE=$? + + # Stop logcat + kill $LOGCAT_PID || true + + # Exit with the test exit code + exit ${TEST_EXIT_CODE:-0} + + - name: Upload logcat + if: always() + uses: actions/upload-artifact@v4 + with: + name: logcat + path: /tmp/logcat.txt + retention-days: 7 From b8824b4d08b98e0a850c2469b0625526af3e8fa7 Mon Sep 17 00:00:00 2001 From: Hansong Zhang Date: Wed, 14 Jan 2026 22:40:36 -0800 Subject: [PATCH 09/23] Update gradle --- .github/workflows/llm-android.yml | 54 +++++----- llm/android/LlamaDemo/app/build.gradle.kts | 113 ++++++++++++++------- 2 files changed, 103 insertions(+), 64 deletions(-) diff --git a/.github/workflows/llm-android.yml b/.github/workflows/llm-android.yml index 5a940ff88e..e4b905cfd7 100644 --- a/.github/workflows/llm-android.yml +++ b/.github/workflows/llm-android.yml @@ -14,25 +14,27 @@ on: - '.github/workflows/llm-android.yml' workflow_dispatch: inputs: - pte_url: - description: 'URL to download model .pte file' + model_preset: + description: 'Model preset to use' + required: true + type: choice + options: + - stories + - llama + - custom + default: 'stories' + custom_pte_url: + description: 'Custom URL for model .pte file (only used when model_preset is custom)' required: false type: string - default: 'https://ossci-android.s3.amazonaws.com/executorch/stories/snapshot-20260114/stories110M.pte' - tokenizer_url: - description: 'URL to download tokenizer file' + custom_tokenizer_url: + description: 'Custom URL for tokenizer file (only used when model_preset is custom)' required: false type: string - default: 'https://ossci-android.s3.amazonaws.com/executorch/stories/snapshot-20260114/tokenizer.model' permissions: contents: read -env: - # Default URLs for pull_request trigger (workflow_dispatch inputs override these) - DEFAULT_PTE_URL: 'https://ossci-android.s3.amazonaws.com/executorch/stories/snapshot-20260114/stories110M.pte' - DEFAULT_TOKENIZER_URL: 'https://ossci-android.s3.amazonaws.com/executorch/stories/snapshot-20260114/tokenizer.model' - jobs: instrumentation-test: runs-on: 8-core-ubuntu @@ -61,19 +63,6 @@ jobs: - name: Setup Gradle uses: gradle/actions/setup-gradle@v4 - - name: Download model files - run: | - PTE_URL="${{ inputs.pte_url || env.DEFAULT_PTE_URL }}" - TOKENIZER_URL="${{ inputs.tokenizer_url || env.DEFAULT_TOKENIZER_URL }}" - - mkdir -p /tmp/llama-models - echo "Downloading model from $PTE_URL" - curl -fL -o /tmp/llama-models/model.pte "$PTE_URL" - echo "Downloading tokenizer from $TOKENIZER_URL" - curl -fL -o /tmp/llama-models/tokenizer.model "$TOKENIZER_URL" - - ls -la /tmp/llama-models/ - - name: AVD cache uses: actions/cache@v4 id: avd-cache @@ -107,17 +96,22 @@ jobs: disable-animations: true working-directory: llm/android/LlamaDemo script: | - adb shell mkdir -p /data/local/tmp/llama/ - adb push /tmp/llama-models/model.pte /data/local/tmp/llama/ - adb push /tmp/llama-models/tokenizer.model /data/local/tmp/llama/ - # Start logcat in background and save to file adb logcat -c adb logcat > /tmp/logcat.txt & LOGCAT_PID=$! - # Run tests - ./gradlew connectedCheck -PskipModelDownload=true || TEST_EXIT_CODE=$? + # Build Gradle command with model preset + MODEL_PRESET="${{ inputs.model_preset || 'stories' }}" + GRADLE_ARGS="-PmodelPreset=$MODEL_PRESET" + + # Add custom URLs if using custom preset + if [ "$MODEL_PRESET" = "custom" ]; then + GRADLE_ARGS="$GRADLE_ARGS -PcustomPteUrl=${{ inputs.custom_pte_url }} -PcustomTokenizerUrl=${{ inputs.custom_tokenizer_url }}" + fi + + # Run tests (Gradle will download and push model files) + ./gradlew connectedCheck $GRADLE_ARGS || TEST_EXIT_CODE=$? # Stop logcat kill $LOGCAT_PID || true diff --git a/llm/android/LlamaDemo/app/build.gradle.kts b/llm/android/LlamaDemo/app/build.gradle.kts index ed5c06d95c..f80fe6acd5 100644 --- a/llm/android/LlamaDemo/app/build.gradle.kts +++ b/llm/android/LlamaDemo/app/build.gradle.kts @@ -12,12 +12,30 @@ plugins { } // Model files configuration for instrumentation tests -val modelFilesBaseUrl = "https://ossci-android.s3.amazonaws.com/executorch/stories/snapshot-20260114" -val deviceModelDir = "/data/local/tmp/llama" -val modelFiles = mapOf( - "stories110M.pte" to "model.pte", - "tokenizer.model" to "tokenizer.model" +// Supported presets: stories, llama, custom +val modelPreset: String = (project.findProperty("modelPreset") as? String) ?: "stories" + +// Preset configurations +val modelPresets = mapOf( + "stories" to mapOf( + "baseUrl" to "https://ossci-android.s3.amazonaws.com/executorch/stories/snapshot-20260114", + "pteFile" to "stories110M.pte", + "tokenizerFile" to "tokenizer.model", + "verifyChecksum" to true + ), + "llama" to mapOf( + "baseUrl" to "https://huggingface.co/executorch-community/Llama-3.2-1B-ET/resolve/main", + "pteFile" to "llama3_2-1B.pte", + "tokenizerFile" to "tokenizer.model", + "verifyChecksum" to false + ) ) + +// Custom URLs (used when modelPreset is "custom") +val customPteUrl: String? = project.findProperty("customPteUrl") as? String +val customTokenizerUrl: String? = project.findProperty("customTokenizerUrl") as? String + +val deviceModelDir = "/data/local/tmp/llama" val skipModelDownload: Boolean = (project.findProperty("skipModelDownload") as? String)?.toBoolean() ?: false fun execCmd(vararg args: String): String { @@ -39,7 +57,7 @@ fun execCmdWithExitCode(vararg args: String): Pair { } tasks.register("pushModelFiles") { - description = "Download model files from S3 and push to connected Android device if not present" + description = "Download model files and push to connected Android device if not present" group = "verification" doLast { @@ -48,6 +66,31 @@ tasks.register("pushModelFiles") { return@doLast } + logger.lifecycle("Using model preset: $modelPreset") + + // Determine URLs based on preset + val pteUrl: String + val tokenizerUrl: String + val verifyChecksum: Boolean + + if (modelPreset == "custom") { + pteUrl = customPteUrl ?: throw GradleException("customPteUrl is required when modelPreset is 'custom'") + tokenizerUrl = customTokenizerUrl ?: throw GradleException("customTokenizerUrl is required when modelPreset is 'custom'") + verifyChecksum = false + } else { + val preset = modelPresets[modelPreset] ?: throw GradleException("Unknown model preset: $modelPreset. Valid options: stories, llama, custom") + val baseUrl = preset["baseUrl"] as String + pteUrl = "$baseUrl/${preset["pteFile"]}" + tokenizerUrl = "$baseUrl/${preset["tokenizerFile"]}" + verifyChecksum = preset["verifyChecksum"] as Boolean + } + + // Files to download: source URL -> target name on device + val filesToDownload = mapOf( + pteUrl to "model.pte", + tokenizerUrl to "tokenizer.model" + ) + // Check if adb is available val adbPath = android.adbExecutable.absolutePath val (adbCheckCode, _) = execCmdWithExitCode(adbPath, "devices") @@ -56,7 +99,7 @@ tasks.register("pushModelFiles") { } // Check which files need to be pushed - val filesToPush = modelFiles.filter { (_, targetName) -> + val filesToPush = filesToDownload.filter { (_, targetName) -> val devicePath = "$deviceModelDir/$targetName" val (exitCode, _) = execCmdWithExitCode(adbPath, "shell", "test -f $devicePath && echo exists") exitCode != 0 @@ -77,43 +120,45 @@ tasks.register("pushModelFiles") { // Create device directory execCmd(adbPath, "shell", "mkdir -p $deviceModelDir") - for ((sourceName, targetName) in filesToPush) { + for ((sourceUrl, targetName) in filesToPush) { val localPath = "$tempDir/$targetName" - val checksumPath = "$tempDir/$sourceName.sha256sums" val devicePath = "$deviceModelDir/$targetName" - // Download file (with original name for checksum verification, then rename) - val downloadPath = "$tempDir/$sourceName" - logger.lifecycle("Downloading $sourceName...") + // Download file + logger.lifecycle("Downloading from $sourceUrl...") val (dlCode, dlOutput) = execCmdWithExitCode( - "curl", "-fL", "-o", downloadPath, "$modelFilesBaseUrl/$sourceName" + "curl", "-fL", "-o", localPath, sourceUrl ) if (dlCode != 0) { - throw GradleException("Failed to download $sourceName: $dlOutput") + throw GradleException("Failed to download from $sourceUrl: $dlOutput") } - // Download and verify checksum - logger.lifecycle("Verifying checksum for $sourceName...") - val (csDownloadCode, csDownloadOutput) = execCmdWithExitCode( - "curl", "-fL", "-o", checksumPath, "$modelFilesBaseUrl/$sourceName.sha256sums" - ) - if (csDownloadCode != 0) { - throw GradleException("Failed to download checksum for $sourceName: $csDownloadOutput") - } + // Verify checksum if enabled and available (only for stories preset) + if (verifyChecksum && modelPreset == "stories") { + val sourceName = sourceUrl.substringAfterLast("/") + val checksumPath = "$tempDir/$sourceName.sha256sums" + val checksumUrl = "$sourceUrl.sha256sums" - // Verify checksum (run sha256sum in the temp directory) - val (verifyCode, verifyOutput) = execCmdWithExitCode( - "bash", "-c", "cd $tempDir && sha256sum -c $sourceName.sha256sums" - ) - if (verifyCode != 0) { - throw GradleException("Checksum verification failed for $sourceName: $verifyOutput") - } - logger.lifecycle("Checksum verified for $sourceName") + logger.lifecycle("Verifying checksum for $sourceName...") + val (csDownloadCode, csDownloadOutput) = execCmdWithExitCode( + "curl", "-fL", "-o", checksumPath, checksumUrl + ) + if (csDownloadCode == 0) { + // Rename file temporarily for checksum verification + val tempForChecksum = "$tempDir/$sourceName" + execCmd("cp", localPath, tempForChecksum) - // Rename file if needed - if (sourceName != targetName) { - execCmd("mv", downloadPath, localPath) - logger.lifecycle("Renamed $sourceName to $targetName") + val (verifyCode, verifyOutput) = execCmdWithExitCode( + "bash", "-c", "cd $tempDir && sha256sum -c $sourceName.sha256sums" + ) + if (verifyCode != 0) { + throw GradleException("Checksum verification failed for $sourceName: $verifyOutput") + } + logger.lifecycle("Checksum verified for $sourceName") + execCmd("rm", "-f", tempForChecksum) + } else { + logger.lifecycle("Checksum file not available, skipping verification") + } } // Push to device From 550859c2b5fa5a3e25a840b415cbfa6d31e4891f Mon Sep 17 00:00:00 2001 From: Hansong Zhang Date: Wed, 14 Jan 2026 22:41:32 -0800 Subject: [PATCH 10/23] use llama as default --- llm/android/LlamaDemo/app/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llm/android/LlamaDemo/app/build.gradle.kts b/llm/android/LlamaDemo/app/build.gradle.kts index f80fe6acd5..b1d385a3b9 100644 --- a/llm/android/LlamaDemo/app/build.gradle.kts +++ b/llm/android/LlamaDemo/app/build.gradle.kts @@ -13,7 +13,7 @@ plugins { // Model files configuration for instrumentation tests // Supported presets: stories, llama, custom -val modelPreset: String = (project.findProperty("modelPreset") as? String) ?: "stories" +val modelPreset: String = (project.findProperty("modelPreset") as? String) ?: "llama" // Preset configurations val modelPresets = mapOf( From 472e9c08463b256a4f1afa62da23e462a782112d Mon Sep 17 00:00:00 2001 From: Hansong Zhang Date: Wed, 14 Jan 2026 22:43:17 -0800 Subject: [PATCH 11/23] Update --- .github/workflows/llm-android.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/llm-android.yml b/.github/workflows/llm-android.yml index e4b905cfd7..f6bb4214f9 100644 --- a/.github/workflows/llm-android.yml +++ b/.github/workflows/llm-android.yml @@ -42,6 +42,7 @@ jobs: API_LEVEL: 34 ARCH: x86_64 EMULATOR_OPTIONS: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none + RAM_SIZE: 16384M name: Instrumentation Test LlamaDemo steps: @@ -70,7 +71,7 @@ jobs: path: | ~/.android/avd/* ~/.android/adb* - key: avd-${{ env.API_LEVEL }}-${{ env.ARCH }} + key: avd-${{ env.API_LEVEL }}-${{ env.ARCH }}-ram${{ env.RAM_SIZE }} - name: Create AVD and generate snapshot for caching if: steps.avd-cache.outputs.cache-hit != 'true' @@ -79,7 +80,7 @@ jobs: api-level: ${{ env.API_LEVEL }} arch: ${{ env.ARCH }} force-avd-creation: false - ram-size: 16384M + ram-size: ${{ env.RAM_SIZE }} emulator-options: ${{ env.EMULATOR_OPTIONS }} disable-animations: false working-directory: llm/android/LlamaDemo @@ -91,7 +92,7 @@ jobs: api-level: ${{ env.API_LEVEL }} arch: ${{ env.ARCH }} force-avd-creation: false - ram-size: 16384M + ram-size: ${{ env.RAM_SIZE }} emulator-options: -no-snapshot-save ${{ env.EMULATOR_OPTIONS }} disable-animations: true working-directory: llm/android/LlamaDemo From 0637ccc5e87a5141fa3a12359d187c86e47d89d4 Mon Sep 17 00:00:00 2001 From: Hansong Zhang Date: Wed, 14 Jan 2026 22:46:36 -0800 Subject: [PATCH 12/23] Fix --- .github/workflows/llm-android.yml | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/.github/workflows/llm-android.yml b/.github/workflows/llm-android.yml index f6bb4214f9..0fd22df69a 100644 --- a/.github/workflows/llm-android.yml +++ b/.github/workflows/llm-android.yml @@ -88,6 +88,10 @@ jobs: - name: Run instrumentation tests uses: reactivecircus/android-emulator-runner@v2 + env: + MODEL_PRESET: ${{ inputs.model_preset || 'stories' }} + CUSTOM_PTE_URL: ${{ inputs.custom_pte_url }} + CUSTOM_TOKENIZER_URL: ${{ inputs.custom_tokenizer_url }} with: api-level: ${{ env.API_LEVEL }} arch: ${{ env.ARCH }} @@ -97,27 +101,12 @@ jobs: disable-animations: true working-directory: llm/android/LlamaDemo script: | - # Start logcat in background and save to file - adb logcat -c - adb logcat > /tmp/logcat.txt & + adb logcat -c && adb logcat > /tmp/logcat.txt & LOGCAT_PID=$! - - # Build Gradle command with model preset - MODEL_PRESET="${{ inputs.model_preset || 'stories' }}" GRADLE_ARGS="-PmodelPreset=$MODEL_PRESET" - - # Add custom URLs if using custom preset - if [ "$MODEL_PRESET" = "custom" ]; then - GRADLE_ARGS="$GRADLE_ARGS -PcustomPteUrl=${{ inputs.custom_pte_url }} -PcustomTokenizerUrl=${{ inputs.custom_tokenizer_url }}" - fi - - # Run tests (Gradle will download and push model files) + [ "$MODEL_PRESET" = "custom" ] && GRADLE_ARGS="$GRADLE_ARGS -PcustomPteUrl=$CUSTOM_PTE_URL -PcustomTokenizerUrl=$CUSTOM_TOKENIZER_URL" ./gradlew connectedCheck $GRADLE_ARGS || TEST_EXIT_CODE=$? - - # Stop logcat kill $LOGCAT_PID || true - - # Exit with the test exit code exit ${TEST_EXIT_CODE:-0} - name: Upload logcat From 618e6bc78591bf2fc8197c9026c10eb118d0f2a6 Mon Sep 17 00:00:00 2001 From: Hansong Zhang Date: Wed, 14 Jan 2026 22:52:26 -0800 Subject: [PATCH 13/23] Fix --- .github/workflows/llm-android.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/llm-android.yml b/.github/workflows/llm-android.yml index 0fd22df69a..d8727ba925 100644 --- a/.github/workflows/llm-android.yml +++ b/.github/workflows/llm-android.yml @@ -103,8 +103,7 @@ jobs: script: | adb logcat -c && adb logcat > /tmp/logcat.txt & LOGCAT_PID=$! - GRADLE_ARGS="-PmodelPreset=$MODEL_PRESET" - [ "$MODEL_PRESET" = "custom" ] && GRADLE_ARGS="$GRADLE_ARGS -PcustomPteUrl=$CUSTOM_PTE_URL -PcustomTokenizerUrl=$CUSTOM_TOKENIZER_URL" + if [ "$MODEL_PRESET" = "custom" ]; then GRADLE_ARGS="-PmodelPreset=$MODEL_PRESET -PcustomPteUrl=$CUSTOM_PTE_URL -PcustomTokenizerUrl=$CUSTOM_TOKENIZER_URL"; else GRADLE_ARGS="-PmodelPreset=$MODEL_PRESET"; fi ./gradlew connectedCheck $GRADLE_ARGS || TEST_EXIT_CODE=$? kill $LOGCAT_PID || true exit ${TEST_EXIT_CODE:-0} From 2babdbb67662a92cd109ff0a541839c1e61beede Mon Sep 17 00:00:00 2001 From: Hansong Zhang Date: Wed, 14 Jan 2026 22:57:26 -0800 Subject: [PATCH 14/23] Fix --- .github/workflows/llm-android.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/llm-android.yml b/.github/workflows/llm-android.yml index d8727ba925..0e720bc415 100644 --- a/.github/workflows/llm-android.yml +++ b/.github/workflows/llm-android.yml @@ -101,6 +101,7 @@ jobs: disable-animations: true working-directory: llm/android/LlamaDemo script: | + adb shell cat /proc/meminfo | head -5 adb logcat -c && adb logcat > /tmp/logcat.txt & LOGCAT_PID=$! if [ "$MODEL_PRESET" = "custom" ]; then GRADLE_ARGS="-PmodelPreset=$MODEL_PRESET -PcustomPteUrl=$CUSTOM_PTE_URL -PcustomTokenizerUrl=$CUSTOM_TOKENIZER_URL"; else GRADLE_ARGS="-PmodelPreset=$MODEL_PRESET"; fi From 9e8045ae22d6fd2924e2696a3d09949add9e9677 Mon Sep 17 00:00:00 2001 From: Hansong Zhang Date: Wed, 14 Jan 2026 23:00:05 -0800 Subject: [PATCH 15/23] Fix --- .github/workflows/llm-android.yml | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/.github/workflows/llm-android.yml b/.github/workflows/llm-android.yml index 0e720bc415..81fce1154f 100644 --- a/.github/workflows/llm-android.yml +++ b/.github/workflows/llm-android.yml @@ -79,13 +79,26 @@ jobs: with: api-level: ${{ env.API_LEVEL }} arch: ${{ env.ARCH }} - force-avd-creation: false + force-avd-creation: true ram-size: ${{ env.RAM_SIZE }} emulator-options: ${{ env.EMULATOR_OPTIONS }} disable-animations: false working-directory: llm/android/LlamaDemo script: echo "Generated AVD snapshot for caching." + - name: Configure AVD RAM + run: | + # Find and update AVD config to set RAM + AVD_DIR="$HOME/.android/avd" + for config in "$AVD_DIR"/*.avd/config.ini; do + if [ -f "$config" ]; then + echo "Updating RAM in $config" + sed -i 's/hw.ramSize=.*/hw.ramSize=16384/' "$config" || true + grep -q "hw.ramSize" "$config" || echo "hw.ramSize=16384" >> "$config" + cat "$config" | grep -E "hw.ramSize|AvdId" + fi + done + - name: Run instrumentation tests uses: reactivecircus/android-emulator-runner@v2 env: @@ -97,7 +110,7 @@ jobs: arch: ${{ env.ARCH }} force-avd-creation: false ram-size: ${{ env.RAM_SIZE }} - emulator-options: -no-snapshot-save ${{ env.EMULATOR_OPTIONS }} + emulator-options: -no-snapshot-save -memory 16384 ${{ env.EMULATOR_OPTIONS }} disable-animations: true working-directory: llm/android/LlamaDemo script: | @@ -105,9 +118,7 @@ jobs: adb logcat -c && adb logcat > /tmp/logcat.txt & LOGCAT_PID=$! if [ "$MODEL_PRESET" = "custom" ]; then GRADLE_ARGS="-PmodelPreset=$MODEL_PRESET -PcustomPteUrl=$CUSTOM_PTE_URL -PcustomTokenizerUrl=$CUSTOM_TOKENIZER_URL"; else GRADLE_ARGS="-PmodelPreset=$MODEL_PRESET"; fi - ./gradlew connectedCheck $GRADLE_ARGS || TEST_EXIT_CODE=$? - kill $LOGCAT_PID || true - exit ${TEST_EXIT_CODE:-0} + ./gradlew connectedCheck $GRADLE_ARGS; TEST_EXIT_CODE=$?; kill $LOGCAT_PID || true; exit $TEST_EXIT_CODE - name: Upload logcat if: always() From f63ee53c15f7a751c436a9dd65615935e836bc52 Mon Sep 17 00:00:00 2001 From: Hansong Zhang Date: Wed, 14 Jan 2026 23:20:14 -0800 Subject: [PATCH 16/23] Fix --- .github/workflows/llm-android.yml | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/.github/workflows/llm-android.yml b/.github/workflows/llm-android.yml index 81fce1154f..00c0d90d8d 100644 --- a/.github/workflows/llm-android.yml +++ b/.github/workflows/llm-android.yml @@ -42,7 +42,7 @@ jobs: API_LEVEL: 34 ARCH: x86_64 EMULATOR_OPTIONS: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none - RAM_SIZE: 16384M + RAM_SIZE: 16384 name: Instrumentation Test LlamaDemo steps: @@ -80,7 +80,6 @@ jobs: api-level: ${{ env.API_LEVEL }} arch: ${{ env.ARCH }} force-avd-creation: true - ram-size: ${{ env.RAM_SIZE }} emulator-options: ${{ env.EMULATOR_OPTIONS }} disable-animations: false working-directory: llm/android/LlamaDemo @@ -88,14 +87,12 @@ jobs: - name: Configure AVD RAM run: | - # Find and update AVD config to set RAM AVD_DIR="$HOME/.android/avd" for config in "$AVD_DIR"/*.avd/config.ini; do if [ -f "$config" ]; then echo "Updating RAM in $config" - sed -i 's/hw.ramSize=.*/hw.ramSize=16384/' "$config" || true - grep -q "hw.ramSize" "$config" || echo "hw.ramSize=16384" >> "$config" - cat "$config" | grep -E "hw.ramSize|AvdId" + sed -i 's/hw.ramSize=.*/hw.ramSize=${{ env.RAM_SIZE }}/' "$config" || true + grep -q "hw.ramSize" "$config" || echo "hw.ramSize=${{ env.RAM_SIZE }}" >> "$config" fi done @@ -109,12 +106,10 @@ jobs: api-level: ${{ env.API_LEVEL }} arch: ${{ env.ARCH }} force-avd-creation: false - ram-size: ${{ env.RAM_SIZE }} - emulator-options: -no-snapshot-save -memory 16384 ${{ env.EMULATOR_OPTIONS }} + emulator-options: -no-snapshot-save ${{ env.EMULATOR_OPTIONS }} disable-animations: true working-directory: llm/android/LlamaDemo script: | - adb shell cat /proc/meminfo | head -5 adb logcat -c && adb logcat > /tmp/logcat.txt & LOGCAT_PID=$! if [ "$MODEL_PRESET" = "custom" ]; then GRADLE_ARGS="-PmodelPreset=$MODEL_PRESET -PcustomPteUrl=$CUSTOM_PTE_URL -PcustomTokenizerUrl=$CUSTOM_TOKENIZER_URL"; else GRADLE_ARGS="-PmodelPreset=$MODEL_PRESET"; fi From 6ce6d09f3581d8920fab0a11660571e60e9e67e3 Mon Sep 17 00:00:00 2001 From: Hansong Zhang Date: Wed, 14 Jan 2026 23:22:58 -0800 Subject: [PATCH 17/23] Add qwen --- .github/workflows/llm-android.yml | 1 + llm/android/LlamaDemo/app/build.gradle.kts | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/.github/workflows/llm-android.yml b/.github/workflows/llm-android.yml index 00c0d90d8d..620d848db1 100644 --- a/.github/workflows/llm-android.yml +++ b/.github/workflows/llm-android.yml @@ -21,6 +21,7 @@ on: options: - stories - llama + - qwen3 - custom default: 'stories' custom_pte_url: diff --git a/llm/android/LlamaDemo/app/build.gradle.kts b/llm/android/LlamaDemo/app/build.gradle.kts index b1d385a3b9..ad8ef449cc 100644 --- a/llm/android/LlamaDemo/app/build.gradle.kts +++ b/llm/android/LlamaDemo/app/build.gradle.kts @@ -13,7 +13,7 @@ plugins { // Model files configuration for instrumentation tests // Supported presets: stories, llama, custom -val modelPreset: String = (project.findProperty("modelPreset") as? String) ?: "llama" +val modelPreset: String = (project.findProperty("modelPreset") as? String) ?: "stories" // Preset configurations val modelPresets = mapOf( @@ -28,6 +28,12 @@ val modelPresets = mapOf( "pteFile" to "llama3_2-1B.pte", "tokenizerFile" to "tokenizer.model", "verifyChecksum" to false + ), + "qwen3" to mapOf( + "baseUrl" to "https://huggingface.co/pytorch/Qwen3-4B-INT8-INT4/resolve/main", + "pteFile" to "model.pte", + "tokenizerFile" to "tokenizer.json", + "verifyChecksum" to false ) ) From 29560f0f647afa7a3e9239fb913f042dadbfa7a9 Mon Sep 17 00:00:00 2001 From: Hansong Zhang Date: Wed, 14 Jan 2026 23:27:44 -0800 Subject: [PATCH 18/23] Revert "Fix" This reverts commit f63ee53c15f7a751c436a9dd65615935e836bc52. --- .github/workflows/llm-android.yml | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/.github/workflows/llm-android.yml b/.github/workflows/llm-android.yml index 620d848db1..d215809d67 100644 --- a/.github/workflows/llm-android.yml +++ b/.github/workflows/llm-android.yml @@ -43,7 +43,7 @@ jobs: API_LEVEL: 34 ARCH: x86_64 EMULATOR_OPTIONS: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none - RAM_SIZE: 16384 + RAM_SIZE: 16384M name: Instrumentation Test LlamaDemo steps: @@ -81,6 +81,7 @@ jobs: api-level: ${{ env.API_LEVEL }} arch: ${{ env.ARCH }} force-avd-creation: true + ram-size: ${{ env.RAM_SIZE }} emulator-options: ${{ env.EMULATOR_OPTIONS }} disable-animations: false working-directory: llm/android/LlamaDemo @@ -88,12 +89,14 @@ jobs: - name: Configure AVD RAM run: | + # Find and update AVD config to set RAM AVD_DIR="$HOME/.android/avd" for config in "$AVD_DIR"/*.avd/config.ini; do if [ -f "$config" ]; then echo "Updating RAM in $config" - sed -i 's/hw.ramSize=.*/hw.ramSize=${{ env.RAM_SIZE }}/' "$config" || true - grep -q "hw.ramSize" "$config" || echo "hw.ramSize=${{ env.RAM_SIZE }}" >> "$config" + sed -i 's/hw.ramSize=.*/hw.ramSize=16384/' "$config" || true + grep -q "hw.ramSize" "$config" || echo "hw.ramSize=16384" >> "$config" + cat "$config" | grep -E "hw.ramSize|AvdId" fi done @@ -107,10 +110,12 @@ jobs: api-level: ${{ env.API_LEVEL }} arch: ${{ env.ARCH }} force-avd-creation: false - emulator-options: -no-snapshot-save ${{ env.EMULATOR_OPTIONS }} + ram-size: ${{ env.RAM_SIZE }} + emulator-options: -no-snapshot-save -memory 16384 ${{ env.EMULATOR_OPTIONS }} disable-animations: true working-directory: llm/android/LlamaDemo script: | + adb shell cat /proc/meminfo | head -5 adb logcat -c && adb logcat > /tmp/logcat.txt & LOGCAT_PID=$! if [ "$MODEL_PRESET" = "custom" ]; then GRADLE_ARGS="-PmodelPreset=$MODEL_PRESET -PcustomPteUrl=$CUSTOM_PTE_URL -PcustomTokenizerUrl=$CUSTOM_TOKENIZER_URL"; else GRADLE_ARGS="-PmodelPreset=$MODEL_PRESET"; fi From 0b147e67b798a3bc057224fe7eb8a2e2392aaa1b Mon Sep 17 00:00:00 2001 From: Hansong Zhang Date: Wed, 14 Jan 2026 23:36:55 -0800 Subject: [PATCH 19/23] Clr dir --- .github/workflows/llm-android.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/llm-android.yml b/.github/workflows/llm-android.yml index d215809d67..2198b892fc 100644 --- a/.github/workflows/llm-android.yml +++ b/.github/workflows/llm-android.yml @@ -116,6 +116,8 @@ jobs: working-directory: llm/android/LlamaDemo script: | adb shell cat /proc/meminfo | head -5 + adb shell rm -rf /data/local/tmp/llama + adb shell mkdir -p /data/local/tmp/llama adb logcat -c && adb logcat > /tmp/logcat.txt & LOGCAT_PID=$! if [ "$MODEL_PRESET" = "custom" ]; then GRADLE_ARGS="-PmodelPreset=$MODEL_PRESET -PcustomPteUrl=$CUSTOM_PTE_URL -PcustomTokenizerUrl=$CUSTOM_TOKENIZER_URL"; else GRADLE_ARGS="-PmodelPreset=$MODEL_PRESET"; fi From e00a68c95e51568e4366664492d51d6805566f24 Mon Sep 17 00:00:00 2001 From: Hansong Zhang Date: Wed, 14 Jan 2026 23:42:13 -0800 Subject: [PATCH 20/23] Fix tokenizer.model being deleted before push When targetName equals sourceName (e.g., both are tokenizer.model), localPath and tempForChecksum point to the same file. The checksum verification was deleting this file, causing the subsequent push to fail with "No such file or directory". Now we check if a copy is needed and only delete if we made a copy. --- llm/android/LlamaDemo/app/build.gradle.kts | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/llm/android/LlamaDemo/app/build.gradle.kts b/llm/android/LlamaDemo/app/build.gradle.kts index ad8ef449cc..1ed751653a 100644 --- a/llm/android/LlamaDemo/app/build.gradle.kts +++ b/llm/android/LlamaDemo/app/build.gradle.kts @@ -146,13 +146,16 @@ tasks.register("pushModelFiles") { val checksumUrl = "$sourceUrl.sha256sums" logger.lifecycle("Verifying checksum for $sourceName...") - val (csDownloadCode, csDownloadOutput) = execCmdWithExitCode( + val (csDownloadCode, _) = execCmdWithExitCode( "curl", "-fL", "-o", checksumPath, checksumUrl ) if (csDownloadCode == 0) { - // Rename file temporarily for checksum verification + // Copy file to original name for checksum verification if needed val tempForChecksum = "$tempDir/$sourceName" - execCmd("cp", localPath, tempForChecksum) + val needsCopy = localPath != tempForChecksum + if (needsCopy) { + execCmd("cp", localPath, tempForChecksum) + } val (verifyCode, verifyOutput) = execCmdWithExitCode( "bash", "-c", "cd $tempDir && sha256sum -c $sourceName.sha256sums" @@ -161,7 +164,10 @@ tasks.register("pushModelFiles") { throw GradleException("Checksum verification failed for $sourceName: $verifyOutput") } logger.lifecycle("Checksum verified for $sourceName") - execCmd("rm", "-f", tempForChecksum) + // Only delete the temp copy if we made one + if (needsCopy) { + execCmd("rm", "-f", tempForChecksum) + } } else { logger.lifecycle("Checksum file not available, skipping verification") } From 82ee80eb54c2228604b4602a0af66f25f0940441 Mon Sep 17 00:00:00 2001 From: Hansong Zhang Date: Wed, 14 Jan 2026 23:46:31 -0800 Subject: [PATCH 21/23] Fix ConcurrentModificationException when saving logs The saveLogs() method was directly iterating over the logs ArrayList with Gson while another thread could be adding logs via ETLogging.log(). This caused a ConcurrentModificationException during activity destroy. Fix by creating a defensive copy of the list before serialization. --- .../example/executorchllamademo/DemoSharedPreferences.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/llm/android/LlamaDemo/app/src/main/java/com/example/executorchllamademo/DemoSharedPreferences.java b/llm/android/LlamaDemo/app/src/main/java/com/example/executorchllamademo/DemoSharedPreferences.java index 99a94c00eb..4b8a1fefb7 100644 --- a/llm/android/LlamaDemo/app/src/main/java/com/example/executorchllamademo/DemoSharedPreferences.java +++ b/llm/android/LlamaDemo/app/src/main/java/com/example/executorchllamademo/DemoSharedPreferences.java @@ -62,7 +62,9 @@ public String getSettings() { public void saveLogs() { SharedPreferences.Editor editor = sharedPreferences.edit(); Gson gson = new Gson(); - String msgJSON = gson.toJson(ETLogging.getInstance().getLogs()); + // Create a copy to avoid ConcurrentModificationException if logs are added during serialization + ArrayList logsCopy = new ArrayList<>(ETLogging.getInstance().getLogs()); + String msgJSON = gson.toJson(logsCopy); editor.putString(context.getString(R.string.logs_json_key), msgJSON); editor.apply(); } From b45d7dbaa4974d395145a2f0b6682358ce769687 Mon Sep 17 00:00:00 2001 From: Hansong Zhang Date: Wed, 14 Jan 2026 23:48:16 -0800 Subject: [PATCH 22/23] Clean up workflow: use env var for RAM, remove redundant options - Use RAM_SIZE env var in Configure AVD RAM step - Remove redundant ram-size and -memory emulator options - Remove meminfo debug output - Keep directory clearing for fresh model files each run --- .github/workflows/llm-android.yml | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/.github/workflows/llm-android.yml b/.github/workflows/llm-android.yml index 2198b892fc..bd5740e0af 100644 --- a/.github/workflows/llm-android.yml +++ b/.github/workflows/llm-android.yml @@ -43,7 +43,7 @@ jobs: API_LEVEL: 34 ARCH: x86_64 EMULATOR_OPTIONS: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none - RAM_SIZE: 16384M + RAM_SIZE: 16384 name: Instrumentation Test LlamaDemo steps: @@ -81,7 +81,6 @@ jobs: api-level: ${{ env.API_LEVEL }} arch: ${{ env.ARCH }} force-avd-creation: true - ram-size: ${{ env.RAM_SIZE }} emulator-options: ${{ env.EMULATOR_OPTIONS }} disable-animations: false working-directory: llm/android/LlamaDemo @@ -89,14 +88,12 @@ jobs: - name: Configure AVD RAM run: | - # Find and update AVD config to set RAM AVD_DIR="$HOME/.android/avd" for config in "$AVD_DIR"/*.avd/config.ini; do if [ -f "$config" ]; then echo "Updating RAM in $config" - sed -i 's/hw.ramSize=.*/hw.ramSize=16384/' "$config" || true - grep -q "hw.ramSize" "$config" || echo "hw.ramSize=16384" >> "$config" - cat "$config" | grep -E "hw.ramSize|AvdId" + sed -i 's/hw.ramSize=.*/hw.ramSize=${{ env.RAM_SIZE }}/' "$config" || true + grep -q "hw.ramSize" "$config" || echo "hw.ramSize=${{ env.RAM_SIZE }}" >> "$config" fi done @@ -110,12 +107,10 @@ jobs: api-level: ${{ env.API_LEVEL }} arch: ${{ env.ARCH }} force-avd-creation: false - ram-size: ${{ env.RAM_SIZE }} - emulator-options: -no-snapshot-save -memory 16384 ${{ env.EMULATOR_OPTIONS }} + emulator-options: -no-snapshot-save ${{ env.EMULATOR_OPTIONS }} disable-animations: true working-directory: llm/android/LlamaDemo script: | - adb shell cat /proc/meminfo | head -5 adb shell rm -rf /data/local/tmp/llama adb shell mkdir -p /data/local/tmp/llama adb logcat -c && adb logcat > /tmp/logcat.txt & From af89b33c5f0a785684710561ffdcac2d2d8fb4b4 Mon Sep 17 00:00:00 2001 From: Hansong Zhang Date: Wed, 14 Jan 2026 23:56:16 -0800 Subject: [PATCH 23/23] Add job summary with test configuration parameters --- .github/workflows/llm-android.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.github/workflows/llm-android.yml b/.github/workflows/llm-android.yml index bd5740e0af..ae00ae353e 100644 --- a/.github/workflows/llm-android.yml +++ b/.github/workflows/llm-android.yml @@ -50,6 +50,17 @@ jobs: - name: Checkout repository uses: actions/checkout@v4 + - name: Write job summary + run: | + echo "## Test Configuration" >> $GITHUB_STEP_SUMMARY + echo "| Parameter | Value |" >> $GITHUB_STEP_SUMMARY + echo "|-----------|-------|" >> $GITHUB_STEP_SUMMARY + echo "| Model Preset | \`${{ inputs.model_preset || 'stories' }}\` |" >> $GITHUB_STEP_SUMMARY + if [ "${{ inputs.model_preset }}" = "custom" ]; then + echo "| Custom PTE URL | \`${{ inputs.custom_pte_url }}\` |" >> $GITHUB_STEP_SUMMARY + echo "| Custom Tokenizer URL | \`${{ inputs.custom_tokenizer_url }}\` |" >> $GITHUB_STEP_SUMMARY + fi + - name: Enable KVM group perms run: | echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules