Skip to content

docs: add Claiming an issue section to CONTRIBUTING.md #24

docs: add Claiming an issue section to CONTRIBUTING.md

docs: add Claiming an issue section to CONTRIBUTING.md #24

Workflow file for this run

name: BAOSP Full Build
on:
workflow_dispatch:
inputs:
build_target:
description: 'AOSP build target (lunch target)'
required: false
default: 'aosp_x86_64-userdebug'
aosp_branch:
description: 'AOSP branch to build'
required: false
default: 'android-14.0.0_r1'
jobs:
# ──────────────────────────────────────────────
# Job 1: Build andrdscren Screen Reader APK
# Always pulls the latest commit from main.
# ──────────────────────────────────────────────
build-screenreader:
name: Build Screen Reader (andrdscren)
runs-on: ubuntu-22.04
steps:
- name: Checkout andrdscren — latest main
uses: actions/checkout@v4
with:
repository: tech-master33/andrdscren
ref: main
fetch-depth: 0
path: andrdscren
- name: Print latest commit being built
run: |
cd andrdscren
echo "Building andrdscren commit:"
git log -1 --format="%H %s (%ci)"
- name: Set up Java 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
- name: Set up Android SDK
uses: android-actions/setup-android@v3
- name: Grant Gradle execute permission
run: chmod +x andrdscren/gradlew
- name: Build screen reader APK
working-directory: andrdscren
run: |
./gradlew clean assembleDebug assembleRelease \
--no-daemon \
--stacktrace || ./gradlew clean assembleDebug --no-daemon --stacktrace
- name: Collect screen reader APK
run: |
mkdir -p /tmp/screenreader-output
RELEASE=$(find andrdscren/app/build/outputs/apk/release -name "*.apk" 2>/dev/null | head -1)
DEBUG=$(find andrdscren/app/build/outputs/apk/debug -name "*.apk" 2>/dev/null | head -1)
if [ -n "$RELEASE" ]; then
cp "$RELEASE" /tmp/screenreader-output/andrdscren.apk
echo "Using release APK: $RELEASE"
elif [ -n "$DEBUG" ]; then
cp "$DEBUG" /tmp/screenreader-output/andrdscren.apk
echo "Using debug APK: $DEBUG"
else
echo "ERROR: No APK found"
exit 1
fi
ls -lh /tmp/screenreader-output/
- name: Upload screen reader APK
uses: actions/upload-artifact@v4
with:
name: andrdscren-apk
path: /tmp/screenreader-output/andrdscren.apk
retention-days: 30
if-no-files-found: error
# ──────────────────────────────────────────────
# Job 2: Build AOTTS TTS Engine APK
# Always pulls the latest commit from main.
# ──────────────────────────────────────────────
build-aotts:
name: Build AOTTS TTS Engine
runs-on: ubuntu-22.04
steps:
- name: Checkout AOTTS — latest main
uses: actions/checkout@v4
with:
repository: tech-master33/aotts
ref: main
fetch-depth: 0
path: aotts
- name: Print latest commit being built
run: |
cd aotts
echo "Building aotts commit:"
git log -1 --format="%H %s (%ci)"
- name: Set up Java 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
- name: Set up Android SDK
uses: android-actions/setup-android@v3
- name: Install Android NDK
run: |
echo "y" | sdkmanager "ndk;23.1.7779620" "cmake;3.22.1"
echo "NDK_HOME=$ANDROID_SDK_ROOT/ndk/23.1.7779620" >> $GITHUB_ENV
- name: Clone SVOX Pico native source
run: |
mkdir -p aotts/src/main/cpp/pico
git clone --depth=1 \
https://android.googlesource.com/platform/external/svox \
aotts/src/main/cpp/pico_src || true
if [ -d aotts/src/main/cpp/pico_src/pico ]; then
cp -r aotts/src/main/cpp/pico_src/pico/* aotts/src/main/cpp/pico/
fi
rm -rf aotts/src/main/cpp/pico_src
- name: Download SVOX Pico language data files
run: |
mkdir -p aotts/src/main/assets/lang
SVOX_RAW="https://android.googlesource.com/platform/external/svox/+archive/refs/heads/master/pico/lang.tar.gz"
echo "Fetching SVOX Pico language data from AOSP..."
curl -L "$SVOX_RAW" -o /tmp/pico_lang.tar.gz 2>/dev/null || true
if [ -f /tmp/pico_lang.tar.gz ] && [ -s /tmp/pico_lang.tar.gz ]; then
tar -xzf /tmp/pico_lang.tar.gz -C aotts/src/main/assets/lang/ 2>/dev/null || true
echo "Extracted language data from AOSP tarball"
fi
# Fallback: sparse clone just the lang folder
if [ -z "$(ls -A aotts/src/main/assets/lang/*.bin 2>/dev/null)" ]; then
echo "Tarball failed, trying sparse clone..."
git clone --depth=1 --filter=blob:none --sparse \
https://android.googlesource.com/platform/external/svox \
/tmp/svox_clone || true
if [ -d /tmp/svox_clone ]; then
git -C /tmp/svox_clone sparse-checkout set pico/lang
git -C /tmp/svox_clone checkout || true
find /tmp/svox_clone/pico/lang -name "*.bin" \
-exec cp {} aotts/src/main/assets/lang/ \; 2>/dev/null || true
fi
fi
echo "Language files:"
ls -lh aotts/src/main/assets/lang/ || echo "(none — build continues without them)"
- name: Grant Gradle execute permission
run: chmod +x aotts/gradlew
- name: Build AOTTS APK
working-directory: aotts
run: |
./gradlew clean assembleDebug assembleRelease \
-Pandroid.ndkVersion=23.1.7779620 \
--no-daemon \
--stacktrace || \
./gradlew clean assembleDebug \
-Pandroid.ndkVersion=23.1.7779620 \
--no-daemon \
--stacktrace
- name: Collect AOTTS APK
run: |
mkdir -p /tmp/aotts-output
RELEASE=$(find aotts/build/outputs/apk/release -name "*.apk" 2>/dev/null | head -1)
DEBUG=$(find aotts/build/outputs/apk/debug -name "*.apk" 2>/dev/null | head -1)
if [ -n "$RELEASE" ]; then
cp "$RELEASE" /tmp/aotts-output/aotts.apk
echo "Using release APK"
elif [ -n "$DEBUG" ]; then
cp "$DEBUG" /tmp/aotts-output/aotts.apk
echo "Using debug APK"
else
echo "ERROR: No APK found"
exit 1
fi
ls -lh /tmp/aotts-output/
- name: Upload AOTTS APK
uses: actions/upload-artifact@v4
with:
name: aotts-apk
path: /tmp/aotts-output/aotts.apk
retention-days: 30
if-no-files-found: error
# ──────────────────────────────────────────────
# Job 3: Build full AOSP system image
# Waits for both APKs, re-signs them with the
# AOSP platform key, drops them in as privileged
# system apps, and builds the system image.
# ──────────────────────────────────────────────
build-aosp:
name: Build AOSP System Image
runs-on: ubuntu-22.04
needs: [build-screenreader, build-aotts]
steps:
- name: Checkout BAOSP repo
uses: actions/checkout@v4
with:
path: baosp
- name: Free up disk space
run: |
sudo apt-get remove -y '^dotnet-.*' '^llvm-.*' 'php.*' \
azure-cli google-cloud-sdk google-chrome-stable firefox \
powershell mono-devel snapd || true
sudo apt-get autoremove -y
sudo apt-get clean
sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc \
/usr/local/share/boost /opt/hostedtoolcache/CodeQL
df -h
- name: Install AOSP build dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
openjdk-11-jdk \
git-core gnupg flex bison \
build-essential zip curl zlib1g-dev \
gcc-multilib g++-multilib libc6-dev-i386 \
lib32ncurses5-dev x11proto-core-dev libx11-dev \
lib32z1-dev libgl1-mesa-dev libxml2-utils xsltproc unzip \
libncurses5 libncurses5-dev bc rsync wget python3 \
python3-pip repo
- name: Install repo tool (if not from apt)
run: |
if ! command -v repo &>/dev/null; then
mkdir -p ~/.bin
curl https://storage.googleapis.com/git-repo-downloads/repo > ~/.bin/repo
chmod a+x ~/.bin/repo
echo "$HOME/.bin" >> $GITHUB_PATH
fi
repo version
- name: Configure Git for repo
run: |
git config --global user.email "baosp-builder@github-actions.local"
git config --global user.name "BAOSP Builder"
git config --global color.ui false
- name: Cache AOSP source
id: aosp-cache
uses: actions/cache@v4
with:
path: aosp-source
key: aosp-source-${{ github.event.inputs.aosp_branch || 'android-14.0.0_r1' }}
restore-keys: |
aosp-source-
- name: Initialize AOSP repo
if: steps.aosp-cache.outputs.cache-hit != 'true'
run: |
mkdir -p aosp-source
cd aosp-source
BRANCH="${{ github.event.inputs.aosp_branch || 'android-14.0.0_r1' }}"
repo init \
-u https://android.googlesource.com/platform/manifest \
-b "$BRANCH" \
--depth=1 \
--no-clone-bundle
echo "Initialized AOSP repo for branch: $BRANCH"
- name: Sync AOSP source
run: |
cd aosp-source
repo sync \
-c \
-j$(nproc) \
--no-tags \
--no-clone-bundle \
--fail-fast \
--force-sync
echo "AOSP sync complete"
df -h
- name: Download screen reader APK
uses: actions/download-artifact@v4
with:
name: andrdscren-apk
path: /tmp/screenreader-output
- name: Download AOTTS APK
uses: actions/download-artifact@v4
with:
name: aotts-apk
path: /tmp/aotts-output
- name: Re-sign APKs with AOSP platform key
run: |
# The AOSP platform key lives in build/target/product/security/
# We use signapk.jar (built as part of AOSP host tools) to strip
# the existing debug/dev signature and replace it with the platform
# key so both apps run as system-signed privileged applications.
PLATFORM_PK8="aosp-source/build/target/product/security/platform.pk8"
PLATFORM_CERT="aosp-source/build/target/product/security/platform.x509.pem"
if [ ! -f "$PLATFORM_PK8" ] || [ ! -f "$PLATFORM_CERT" ]; then
echo "Platform keys not found — building signapk host tool first..."
cd aosp-source
source build/envsetup.sh
TARGET="${{ github.event.inputs.build_target || 'aosp_x86_64-userdebug' }}"
lunch "$TARGET"
make -j$(nproc) signapk 2>&1 | tail -20
cd ..
fi
SIGNAPK_JAR=$(find aosp-source/out/host -name "signapk.jar" 2>/dev/null | head -1)
if [ -z "$SIGNAPK_JAR" ]; then
echo "WARNING: signapk.jar not found — falling back to zipalign+apksigner"
# Use Android build tools apksigner as fallback
APKSIGNER=$(find $ANDROID_SDK_ROOT/build-tools -name "apksigner" 2>/dev/null | sort -V | tail -1)
if [ -n "$APKSIGNER" ]; then
echo "Using apksigner at: $APKSIGNER"
# Convert PK8 to PKCS12 for apksigner
openssl pkcs8 -in "$PLATFORM_PK8" -inform DER -nocrypt \
-out /tmp/platform.pem 2>/dev/null || true
if [ -f /tmp/platform.pem ]; then
for APK in /tmp/screenreader-output/andrdscren.apk /tmp/aotts-output/aotts.apk; do
[ -f "$APK" ] || continue
echo "Signing $APK with platform key..."
"$APKSIGNER" sign \
--key /tmp/platform.pem \
--cert "$PLATFORM_CERT" \
"$APK" && echo "Signed: $APK" || echo "WARNING: Could not sign $APK"
done
fi
else
echo "WARNING: No signing tool available — APKs will be re-signed by Soong via Android.bp certificate field"
fi
else
echo "Using signapk at: $SIGNAPK_JAR"
for APK in /tmp/screenreader-output/andrdscren.apk /tmp/aotts-output/aotts.apk; do
[ -f "$APK" ] || continue
SIGNED="${APK%.apk}-platform-signed.apk"
echo "Signing $APK with AOSP platform key..."
java -jar "$SIGNAPK_JAR" \
"$PLATFORM_CERT" "$PLATFORM_PK8" \
"$APK" "$SIGNED" && \
mv "$SIGNED" "$APK" && \
echo "Platform-signed: $APK" || \
echo "WARNING: signapk failed for $APK — Soong will re-sign via Android.bp"
done
fi
- name: Place screen reader into AOSP tree (privileged)
run: |
APK="/tmp/screenreader-output/andrdscren.apk"
if [ ! -f "$APK" ]; then
echo "WARNING: Screen reader APK not found — skipping"
else
DEST="aosp-source/packages/apps/Andrdscren"
mkdir -p "$DEST"
cp "$APK" "$DEST/Andrdscren.apk"
# certificate: "platform" → Soong re-signs with platform key if not already done
# privileged: true → installs to /system/priv-app for elevated permissions
# (required for AccessibilityService to work reliably)
cat > "$DEST/Android.bp" << 'EOF'
android_app_import {

Check failure on line 376 in .github/workflows/baosp-build.yml

View workflow run for this annotation

GitHub Actions / .github/workflows/baosp-build.yml

Invalid workflow file

You have an error in your yaml syntax on line 376
name: "Andrdscren",
apk: "Andrdscren.apk",
certificate: "platform",
privileged: true,
dex_preopt: {
enabled: false,
},
}
EOF
echo "Screen reader placed at $DEST (privileged, platform-signed)"
ls -lh "$DEST"
fi
- name: Place AOTTS into AOSP tree (privileged)
run: |
APK="/tmp/aotts-output/aotts.apk"
if [ ! -f "$APK" ]; then
echo "WARNING: AOTTS APK not found — skipping"
else
DEST="aosp-source/packages/apps/AoTTS"
mkdir -p "$DEST"
cp "$APK" "$DEST/AoTTS.apk"
# TTS engines also benefit from platform signing to register
# as a trusted system TTS provider without user confirmation.
cat > "$DEST/Android.bp" << 'EOF'
android_app_import {
name: "AoTTS",
apk: "AoTTS.apk",
certificate: "platform",
privileged: true,
dex_preopt: {
enabled: false,
},
}
EOF
echo "AOTTS placed at $DEST (privileged, platform-signed)"
ls -lh "$DEST"
fi
- name: Apply BAOSP accessibility patches
run: |
cd aosp-source
PATCH_DIR="../baosp/patches"
if [ -d "$PATCH_DIR" ] && ls "$PATCH_DIR"/*.patch &>/dev/null; then
for patch in "$PATCH_DIR"/*.patch; do
echo "Applying patch: $patch"
patch -p1 < "$patch" || echo "WARNING: $patch failed to apply — skipping"
done
else
echo "No patches found — skipping"
fi
- name: Copy BAOSP device overlays
run: |
if [ -d baosp/device ]; then
cp -r baosp/device/* aosp-source/device/
echo "Copied BAOSP device overlays"
else
echo "No device overlays — skipping"
fi
- name: Enable screen reader and TTS as system defaults
run: |
# Patches SettingsProvider's default values so that on first boot
# the screen reader is already on and AOTTS is the default TTS
# engine — no manual setup needed after flashing.
OVERLAY_DIR="aosp-source/frameworks/base/packages/SettingsProvider/res/values"
mkdir -p "$OVERLAY_DIR"
cat > "$OVERLAY_DIR/baosp_accessibility_defaults.xml" << 'EOF'
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Enable Android accessibility framework on first boot -->
<integer name="def_accessibility_enabled">1</integer>
<!-- Enable the BAOSP screen reader service by default -->
<string name="def_enabled_accessibility_services" translatable="false"
>com.example.andrd/com.example.andrd.ScreenReaderService</string>
<!-- Set AOTTS (SVOX Pico) as the default TTS engine -->
<string name="def_tts_default_synth" translatable="false"
>com.example.picottsengine</string>
<!-- Default TTS speech rate and pitch (100 = normal) -->
<integer name="def_tts_default_rate">100</integer>
<integer name="def_tts_default_pitch">100</integer>
<!-- Enable touch exploration (required for screen reader gestures) -->
<integer name="def_touch_exploration_enabled">1</integer>
</resources>
EOF
echo "Accessibility defaults written"
# Belt-and-suspenders: also set via build.prop fragment
cat > "aosp-source/device/baosp_accessibility.prop" << 'EOF'
# BAOSP: accessibility defaults
ro.product.accessibility.screenreader=com.example.andrd/com.example.andrd.ScreenReaderService
ro.product.tts.default_engine=com.example.picottsengine
EOF
echo "Build prop fragment written"
- name: Build AOSP system image
run: |
cd aosp-source
TARGET="${{ github.event.inputs.build_target || 'aosp_x86_64-userdebug' }}"
source build/envsetup.sh
lunch "$TARGET"
echo "Building target: $TARGET with $(($(nproc) - 1)) jobs"
df -h
m -j$(($(nproc) - 1)) systemimage 2>&1 | tee build.log
echo "Build complete"
df -h
- name: Collect build artifacts
if: always()
run: |
DEVICE=$(cd aosp-source && source build/envsetup.sh 2>/dev/null && \
get_build_var TARGET_DEVICE 2>/dev/null || echo "generic_x86_64")
OUT="aosp-source/out/target/product/$DEVICE"
mkdir -p /tmp/baosp-images
for img in system.img boot.img recovery.img userdata.img ramdisk.img; do
if [ -f "$OUT/$img" ]; then
cp "$OUT/$img" /tmp/baosp-images/
echo "Collected $img ($(du -sh "$OUT/$img" | cut -f1))"
fi
done
[ -f aosp-source/build.log ] && cp aosp-source/build.log /tmp/baosp-images/
ls -lh /tmp/baosp-images/
- name: Upload BAOSP system images
if: always()
uses: actions/upload-artifact@v4
with:
name: baosp-system-images
path: /tmp/baosp-images/
retention-days: 30
if-no-files-found: warn
- name: Upload build log on failure
if: failure()
uses: actions/upload-artifact@v4
with:
name: build-log
path: aosp-source/build.log
retention-days: 7
if-no-files-found: ignore