Skip to content

CI test for 16kb and non-16kb page alignment #18248

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 116 additions & 0 deletions .github/check_elf_alignment.sh
Original file line number Diff line number Diff line change
@@ -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 <pagesize_kb>"; }; 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 "====================="
69 changes: 60 additions & 9 deletions .github/workflows/tests_emulator.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fantastic - approved, pending upstream PR merge+release and this change here

Suggested change
target: google_apis
target: google_apis_ps16k

Copy link
Contributor Author

@Haz3-jolt Haz3-jolt Jun 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep I have amended the commit already, waiting for the release to do a force push!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

had a review comment on that PR I just had time to address now, hopefully will release soon - maintainer there is collaborating fine and that change is needed of course

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hasn't been released yet, but temporarily depending on this commit hash for the android-emulator-runner package should work, the PR is merged now ReactiveCircus/android-emulator-runner@66283c0

first-boot-delay: 600
iteration: 0
steps:
- name: Free Disk Space (Ubuntu)
uses: insightsengineering/disk-space-reclaimer@v1
Expand Down Expand Up @@ -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()
Expand Down