diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 6948f9fd1a0..fa5cd854cc0 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -10,7 +10,8 @@ on: - .ci/docker/** - .github/workflows/android.yml - install_requirements.sh - - examples/demo-apps/** + - examples/demo-apps/android/** + - extension/android/** - extension/module/** workflow_dispatch: @@ -101,7 +102,7 @@ jobs: android-app-archive: https://gha-artifacts.s3.amazonaws.com/${{ github.repository }}/${{ github.run_id }}/artifact/app-debug.apk android-test-archive: https://gha-artifacts.s3.amazonaws.com/${{ github.repository }}/${{ github.run_id }}/artifact/app-debug-androidTest.apk # The test spec can be downloaded from https://ossci-assets.s3.amazonaws.com/android-llama2-device-farm-test-spec.yml - test-spec: arn:aws:devicefarm:us-west-2:308535385114:upload:02a2cf0f-6d9b-45ee-ba1a-a086587469e6/414cb54d-4d83-4576-8317-93244e4dc50e + test-spec: arn:aws:devicefarm:us-west-2:308535385114:upload:02a2cf0f-6d9b-45ee-ba1a-a086587469e6/abd86868-fa63-467e-a5c7-218194665a77 # The exported llama2 model and its tokenizer, can be downloaded from https://ossci-assets.s3.amazonaws.com/executorch-android-llama2-7b.zip. # Among the input, this is the biggest file and uploading it to AWS beforehand makes the test run much faster extra-data: arn:aws:devicefarm:us-west-2:308535385114:upload:02a2cf0f-6d9b-45ee-ba1a-a086587469e6/bd15825b-ddab-4e47-9fef-a9c8935778dd diff --git a/examples/demo-apps/android/LlamaDemo/android-llama2-device-farm-test-spec.yml b/examples/demo-apps/android/LlamaDemo/android-llama2-device-farm-test-spec.yml new file mode 100644 index 00000000000..4df9f18cc5f --- /dev/null +++ b/examples/demo-apps/android/LlamaDemo/android-llama2-device-farm-test-spec.yml @@ -0,0 +1,76 @@ +version: 0.1 + +android_test_host: amazon_linux_2 + +phases: + install: + commands: + + pre_test: + commands: + # Prepare the model and the tokenizer + - adb -s $DEVICEFARM_DEVICE_UDID shell "ls -la /sdcard/" + - adb -s $DEVICEFARM_DEVICE_UDID shell "mkdir -p /data/local/tmp/llama/" + - adb -s $DEVICEFARM_DEVICE_UDID shell "mv /sdcard/tokenizer.bin /data/local/tmp/llama/tokenizer.bin" + - adb -s $DEVICEFARM_DEVICE_UDID shell "mv /sdcard/xnnpack_llama2.pte /data/local/tmp/llama/xnnpack_llama2.pte" + - adb -s $DEVICEFARM_DEVICE_UDID shell "chmod 664 /data/local/tmp/llama/tokenizer.bin" + - adb -s $DEVICEFARM_DEVICE_UDID shell "chmod 664 /data/local/tmp/llama/xnnpack_llama2.pte" + - adb -s $DEVICEFARM_DEVICE_UDID shell "ls -la /data/local/tmp/llama/" + + test: + commands: + # By default, the following ADB command is used by Device Farm to run your Instrumentation test. + # Please refer to Android's documentation for more options on running instrumentation tests with adb: + # https://developer.android.com/studio/test/command-line#run-tests-with-adb + - echo "Starting the Instrumentation test" + - | + adb -s $DEVICEFARM_DEVICE_UDID shell "am instrument -r -w --no-window-animation \ + $DEVICEFARM_TEST_PACKAGE_NAME/$DEVICEFARM_TEST_PACKAGE_RUNNER 2>&1 || echo \": -1\"" | + tee $DEVICEFARM_LOG_DIR/instrument.log + + # Parse the results + - |- + INSTRUMENT_LOG="$DEVICEFARM_LOG_DIR/instrument.log" + + DID_ANY_TESTS_START=$(grep "INSTRUMENTATION_STATUS_CODE: 1" $INSTRUMENT_LOG | wc -l); + TESTS_PASSED=$(grep "INSTRUMENTATION_STATUS_CODE: 0" $INSTRUMENT_LOG | wc -l); + TESTS_ERRORED=$(grep "INSTRUMENTATION_STATUS_CODE: -1" $INSTRUMENT_LOG | wc -l); + TESTS_FAILED=$(grep "INSTRUMENTATION_STATUS_CODE: -2" $INSTRUMENT_LOG | wc -l); + TESTS_IGNORED=$(grep "INSTRUMENTATION_STATUS_CODE: -3" $INSTRUMENT_LOG | wc -l); + TESTS_ASSUMPTION_FAILED=$(grep "INSTRUMENTATION_STATUS_CODE: -4" $INSTRUMENT_LOG | wc -l); + TESTS_PROCESSES_CRASHED=$(grep "INSTRUMENTATION_RESULT: shortMsg=Process crashed." $INSTRUMENT_LOG | wc -l); + + # And print the results so that the CI job can show them later + - | + INSTRUMENT_LOG="$DEVICEFARM_LOG_DIR/instrument.log" + + if [ $DID_ANY_TESTS_START -eq 0 ]; + then + echo "[PyTorch] Marking the test suite as failed because no tests started!"; + false; + elif [ $TESTS_FAILED -ne 0 ]; + then + OBSERVED_TPS=$(grep "The observed TPS " $INSTRUMENT_LOG | tail -n 1) + + if [ -n "${OBSERVED_TPS}" ]; + then + echo "[PyTorch] ${OBSERVED_TPS}"; + else + echo "[PyTorch] Marking the test suite as failed because it failed to load the model"; + fi + elif [ $TESTS_ERRORED -ne 0 ]; + then + echo "[PyTorch] Marking the test suite as failed because $TESTS_ERRORED tests errored!"; + false; + elif [ $TESTS_PROCESSES_CRASHED -ne 0 ]; + then + echo "[PyTorch] Marking the test suite as failed because the app crashed due to OOM!"; + false; + fi; + + post_test: + commands: + +artifacts: + # By default, Device Farm will collect your artifacts from the $DEVICEFARM_LOG_DIR directory. + - $DEVICEFARM_LOG_DIR diff --git a/extension/android/CMakeLists.txt b/extension/android/CMakeLists.txt index 4d4460203c0..cc7afc0c80f 100644 --- a/extension/android/CMakeLists.txt +++ b/extension/android/CMakeLists.txt @@ -61,6 +61,7 @@ if(EXECUTORCH_BUILD_LLAMA_JNI) set(CUSTOM_OPS_PATH ${CMAKE_CURRENT_BINARY_DIR}/../../examples/models/llama2/custom_ops/libcustom_ops.a) add_library(custom_ops STATIC IMPORTED) set_property(TARGET custom_ops PROPERTY IMPORTED_LOCATION ${CUSTOM_OPS_PATH}) + target_link_options_shared_lib(custom_ops) if(TARGET pthreadpool) set(LLAMA_JNI_SRCS jni/jni_layer_llama.cpp ../../backends/xnnpack/threadpool/cpuinfo_utils.cpp)