From cb55d4b6c6d886ce79d84b0f2caa145f07055761 Mon Sep 17 00:00:00 2001 From: Hari Srinivasan Date: Wed, 4 Jun 2025 14:05:44 +0530 Subject: [PATCH 1/2] Add ELF alignment script from google --- .github/check_elf_alignment.sh | 116 +++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 .github/check_elf_alignment.sh diff --git a/.github/check_elf_alignment.sh b/.github/check_elf_alignment.sh new file mode 100644 index 000000000000..a71f5a83aef6 --- /dev/null +++ b/.github/check_elf_alignment.sh @@ -0,0 +1,116 @@ +#!/bin/bash +# File copied from https://cs.android.com/android/platform/superproject/main/+/main:system/extras/tools/check_elf_alignment.sh +# See https://developer.android.com/guide/practices/page-sizes for context + +progname="${0##*/}" +progname="${progname%.sh}" + +# usage: check_elf_alignment.sh [path to *.so files|path to *.apk] + +cleanup_trap() { + if [ -n "${tmp}" -a -d "${tmp}" ]; then + rm -rf ${tmp} + fi + exit $1 +} + +usage() { + echo "Host side script to check the ELF alignment of shared libraries." + echo "Shared libraries are reported ALIGNED when their ELF regions are" + echo "16 KB or 64 KB aligned. Otherwise they are reported as UNALIGNED." + echo + echo "Usage: ${progname} [input-path|input-APK|input-APEX]" +} + +if [ ${#} -ne 1 ]; then + usage + exit +fi + +case ${1} in + --help | -h | -\?) + usage + exit + ;; + + *) + dir="${1}" + ;; +esac + +if ! [ -f "${dir}" -o -d "${dir}" ]; then + echo "Invalid file: ${dir}" >&2 + exit 1 +fi + +if [[ "${dir}" == *.apk ]]; then + trap 'cleanup_trap' EXIT + + echo + echo "Recursively analyzing $dir" + echo + + if { zipalign --help 2>&1 | grep -q "\-P "; }; then + echo "=== APK zip-alignment ===" + zipalign -v -c -P 16 4 "${dir}" | egrep 'lib/arm64-v8a|lib/x86_64|Verification' + echo "=========================" + else + echo "NOTICE: Zip alignment check requires build-tools version 35.0.0-rc3 or higher." + echo " You can install the latest build-tools by running the below command" + echo " and updating your \$PATH:" + echo + echo " sdkmanager \"build-tools;35.0.0-rc3\"" + fi + + dir_filename=$(basename "${dir}") + tmp=$(mktemp -d -t "${dir_filename%.apk}_out_XXXXX") + unzip "${dir}" lib/* -d "${tmp}" >/dev/null 2>&1 + dir="${tmp}" +fi + +if [[ "${dir}" == *.apex ]]; then + trap 'cleanup_trap' EXIT + + echo + echo "Recursively analyzing $dir" + echo + + dir_filename=$(basename "${dir}") + tmp=$(mktemp -d -t "${dir_filename%.apex}_out_XXXXX") + deapexer extract "${dir}" "${tmp}" || { echo "Failed to deapex." && exit 1; } + dir="${tmp}" +fi + +RED="\e[31m" +GREEN="\e[32m" +ENDCOLOR="\e[0m" + +unaligned_libs=() + +echo +echo "=== ELF alignment ===" + +matches="$(find "${dir}" -type f)" +IFS=$'\n' +for match in $matches; do + # We could recursively call this script or rewrite it to though. + [[ "${match}" == *".apk" ]] && echo "WARNING: doesn't recursively inspect .apk file: ${match}" + [[ "${match}" == *".apex" ]] && echo "WARNING: doesn't recursively inspect .apex file: ${match}" + + [[ $(file "${match}") == *"ELF"* ]] || continue + + res="$(objdump -p "${match}" | grep LOAD | awk '{ print $NF }' | head -1)" + if [[ $res =~ 2\*\*(1[4-9]|[2-9][0-9]|[1-9][0-9]{2,}) ]]; then + echo -e "${match}: ${GREEN}ALIGNED${ENDCOLOR} ($res)" + else + echo -e "${match}: ${RED}UNALIGNED${ENDCOLOR} ($res)" + unaligned_libs+=("${match}") + fi +done + +if [ ${#unaligned_libs[@]} -gt 0 ]; then + echo -e "${RED}Found ${#unaligned_libs[@]} unaligned libs (only arm64-v8a/x86_64 libs need to be aligned).${ENDCOLOR}" +elif [ -n "${dir_filename}" ]; then + echo -e "ELF Verification Successful" +fi +echo "=====================" \ No newline at end of file From 9dacc54e4dc6a7c107b842e0ca4e2ddcdd88f721 Mon Sep 17 00:00:00 2001 From: Hari Srinivasan Date: Wed, 4 Jun 2025 14:06:17 +0530 Subject: [PATCH 2/2] CI test for 16kb and non-16kb page alignment --- .github/workflows/tests_emulator.yml | 69 ++++++++++++++++++++++++---- 1 file changed, 60 insertions(+), 9 deletions(-) diff --git a/.github/workflows/tests_emulator.yml b/.github/workflows/tests_emulator.yml index 50f33570c0fe..80e407968650 100644 --- a/.github/workflows/tests_emulator.yml +++ b/.github/workflows/tests_emulator.yml @@ -24,15 +24,18 @@ jobs: strategy: fail-fast: false matrix: - # Refactor to make these dynamic with a low/high bracket only on schedule, not push - # For now this is the latest supported API. Previously API 29 was fastest. - # #13695: This was reverted to API 30, 31 was unstable. This should be fixed - api-level: [30] - arch: [x86_64] - target: [google_apis] - first-boot-delay: [600] - # This is useful for benchmarking, do 0, 1, 2, etc (up to 256 max job-per-matrix limit) for averages - iteration: [0] + # Control which API level + target combinations run + include: + - api-level: 30 + arch: x86_64 + target: google_apis + first-boot-delay: 600 + iteration: 0 + - api-level: 35 + arch: x86_64 + target: google_apis + first-boot-delay: 600 + iteration: 0 steps: - name: Free Disk Space (Ubuntu) uses: insightsengineering/disk-space-reclaimer@v1 @@ -158,6 +161,54 @@ jobs: sleep 5 ./gradlew uninstallAll jacocoAndroidTestReport --daemon + - name: Configure NDK tools PATH for alignment checking + run: | + echo "Using pre-installed NDK tools for alignment checking" + if [ ! -d "$ANDROID_NDK_LATEST_HOME" ]; then + echo "Error: NDK tools not found at $ANDROID_NDK_LATEST_HOME" + echo "The NDK should be pre-installed in the runner image. Failing fast." + exit 1 + fi + + NDK_VERSION=$(basename $ANDROID_NDK_LATEST_HOME) + echo "Using NDK version: $NDK_VERSION" + echo "export PATH=$ANDROID_NDK_LATEST_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin:$PATH" >> $GITHUB_ENV + + - name: Check APK ELF Alignment + run: | + chmod +x .github/check_elf_alignment.sh + APK_PATH="AnkiDroid/build/outputs/apk/play/release/AnkiDroid-play-arm64-v8a-release.apk" + + if [ ! -f "$APK_PATH" ]; then + echo "Error: APK file not found at $APK_PATH" + echo "The APK should have been built in previous steps. Failing fast." + exit 1 + fi + + echo "Using APK: $APK_PATH" + .github/check_elf_alignment.sh $APK_PATH + + - name: Verify zipalign + run: | + APK_PATH="AnkiDroid/build/outputs/apk/play/release/AnkiDroid-play-arm64-v8a-release.apk" + echo "Verifying zipalign with 16KB alignment for $APK_PATH" + + # Find the latest build-tools version dynamically + LATEST_BUILD_TOOLS=$(ls -d $ANDROID_HOME/build-tools/* | sort -V | tail -n 1) + ZIPALIGN_PATH="$LATEST_BUILD_TOOLS/zipalign" + echo "Using zipalign at: $ZIPALIGN_PATH" + + # Verify zipalign exists + if [ ! -f "$ZIPALIGN_PATH" ]; then + echo "Error: zipalign not found at $ZIPALIGN_PATH" + echo "Available build-tools versions:" + ls -la $ANDROID_HOME/build-tools/ + exit 1 + fi + + # Use the zipalign tool + $ZIPALIGN_PATH -c -P 16 -v 4 $APK_PATH + - name: Upload Test Report uses: actions/upload-artifact@v4 if: always()