Add build-car: unstable APK signed with the AOSP platform key
The MG4 head unit's platform certificate (c8a2e9bc…192ab8, per tools/README.md) is the public AOSP test key. build-car fetches that key into the gitignored tools/ directory from a pinned android-9.0.0_r1 tag, builds assembleUnstableDebug, zipaligns and signs it, and refuses to finish unless both the key's certificate and the resulting signer match the expected SHA-256. Output lands in build/car/ with a .sha256 sidecar. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -33,30 +33,99 @@
|
|||||||
sdk = "${android.androidsdk}/libexec/android-sdk";
|
sdk = "${android.androidsdk}/libexec/android-sdk";
|
||||||
# gradle/gradle-daemon-jvm.properties pins the daemon to JDK 21.
|
# gradle/gradle-daemon-jvm.properties pins the daemon to JDK 21.
|
||||||
jdk = pkgs.jdk21;
|
jdk = pkgs.jdk21;
|
||||||
|
buildTools = "${sdk}/build-tools/${buildToolsVersion}";
|
||||||
|
|
||||||
|
# AGP otherwise downloads an aapt2 binary from Maven, which is dynamically linked
|
||||||
|
# against a generic FHS and does not run on NixOS. Use the SDK's patched one.
|
||||||
|
# Gradle is also pointed at the Nix JDK so the daemon toolchain criteria are met
|
||||||
|
# locally instead of downloading a (non-NixOS) JDK through foojay.
|
||||||
|
gradleOpts = builtins.concatStringsSep " " [
|
||||||
|
"-Dorg.gradle.project.android.aapt2FromMavenOverride=${buildTools}/aapt2"
|
||||||
|
"-Dorg.gradle.java.installations.paths=${jdk.home}"
|
||||||
|
"-Dorg.gradle.java.installations.auto-download=false"
|
||||||
|
];
|
||||||
|
|
||||||
|
# The MG4 head unit is signed with the public AOSP test platform key, so that is
|
||||||
|
# the key a system-UID (unstable) build must carry. See tools/README.md and OTA.md.
|
||||||
|
aospKeys = "https://raw.githubusercontent.com/aosp-mirror/platform_build/android-9.0.0_r1/target/product/security";
|
||||||
|
platformCertSha256 = "c8a2e9bccf597c2fb6dc66bee293fc13f2fc47ec77bc6b2b0d52c11f51192ab8";
|
||||||
|
|
||||||
|
buildCar = pkgs.writeShellApplication {
|
||||||
|
name = "build-car";
|
||||||
|
runtimeInputs = [ jdk pkgs.curl pkgs.openssl pkgs.coreutils pkgs.gnugrep pkgs.gawk ];
|
||||||
|
text = ''
|
||||||
|
root=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
|
||||||
|
cd "$root"
|
||||||
|
if [ ! -f app/build.gradle ]; then
|
||||||
|
echo "build-car: run this from the FatihsMG4 checkout" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
export ANDROID_HOME=${sdk} ANDROID_SDK_ROOT=${sdk} JAVA_HOME=${jdk.home}
|
||||||
|
export GRADLE_OPTS="${gradleOpts}"
|
||||||
|
echo "sdk.dir=$ANDROID_HOME" > local.properties
|
||||||
|
|
||||||
|
# Keys live in tools/, which .gitignore keeps out of the repository.
|
||||||
|
for f in platform.pk8 platform.x509.pem; do
|
||||||
|
if [ ! -f "tools/$f" ]; then
|
||||||
|
echo "Fetching AOSP test key tools/$f"
|
||||||
|
curl -sSfL -o "tools/$f" "${aospKeys}/$f"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
cert=$(openssl x509 -in tools/platform.x509.pem -outform der | sha256sum | cut -d' ' -f1)
|
||||||
|
if [ "$cert" != "${platformCertSha256}" ]; then
|
||||||
|
echo "build-car: tools/platform.x509.pem has SHA-256 $cert, expected ${platformCertSha256}" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
./gradlew assembleUnstableDebug "$@"
|
||||||
|
version=$(./gradlew -q printUnstableVersion "$@" | tail -1)
|
||||||
|
|
||||||
|
in=app/build/outputs/apk/unstable/debug/app-unstable-debug.apk
|
||||||
|
mkdir -p build/car
|
||||||
|
aligned=build/car/aligned.apk
|
||||||
|
out="build/car/FatihsMG4-unstable-$version.apk"
|
||||||
|
|
||||||
|
"${buildTools}/zipalign" -f -p 4 "$in" "$aligned"
|
||||||
|
# Options come before the input APK; apksigner rejects the other order.
|
||||||
|
"${buildTools}/apksigner" sign \
|
||||||
|
--key tools/platform.pk8 --cert tools/platform.x509.pem \
|
||||||
|
--out "$out" "$aligned"
|
||||||
|
rm -f "$aligned" "$out.idsig"
|
||||||
|
|
||||||
|
signer=$("${buildTools}/apksigner" verify --print-certs "$out" \
|
||||||
|
| awk -F': ' '/Signer #1 certificate SHA-256 digest/ { print $2 }')
|
||||||
|
if [ "$signer" != "${platformCertSha256}" ]; then
|
||||||
|
echo "build-car: $out is signed with $signer, expected ${platformCertSha256}" >&2
|
||||||
|
rm -f "$out"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
sha256sum "$out" | cut -d' ' -f1 > "$out.sha256"
|
||||||
|
|
||||||
|
echo
|
||||||
|
echo "Signed with the AOSP platform key: $out"
|
||||||
|
echo "Install on the head unit:"
|
||||||
|
echo " adb push $out /data/local/tmp/update.apk"
|
||||||
|
echo " adb shell \"pm install -r -f -d -t /data/local/tmp/update.apk\""
|
||||||
|
'';
|
||||||
|
};
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
default = pkgs.mkShell {
|
default = pkgs.mkShell {
|
||||||
packages = [ jdk android.androidsdk ];
|
packages = [ jdk android.androidsdk buildCar ];
|
||||||
|
|
||||||
ANDROID_HOME = sdk;
|
ANDROID_HOME = sdk;
|
||||||
ANDROID_SDK_ROOT = sdk;
|
ANDROID_SDK_ROOT = sdk;
|
||||||
JAVA_HOME = jdk.home;
|
JAVA_HOME = jdk.home;
|
||||||
|
|
||||||
# AGP otherwise downloads an aapt2 binary from Maven, which is dynamically linked
|
GRADLE_OPTS = gradleOpts;
|
||||||
# against a generic FHS and does not run on NixOS. Use the SDK's patched one.
|
|
||||||
# Gradle is also pointed at the Nix JDK so the daemon toolchain criteria are met
|
|
||||||
# locally instead of downloading a (non-NixOS) JDK through foojay.
|
|
||||||
GRADLE_OPTS = builtins.concatStringsSep " " [
|
|
||||||
"-Dorg.gradle.project.android.aapt2FromMavenOverride=${sdk}/build-tools/${buildToolsVersion}/aapt2"
|
|
||||||
"-Dorg.gradle.java.installations.paths=${jdk.home}"
|
|
||||||
"-Dorg.gradle.java.installations.auto-download=false"
|
|
||||||
];
|
|
||||||
|
|
||||||
shellHook = ''
|
shellHook = ''
|
||||||
echo "sdk.dir=$ANDROID_HOME" > local.properties
|
echo "sdk.dir=$ANDROID_HOME" > local.properties
|
||||||
echo "FatihsMG4 dev shell — JDK $(java -version 2>&1 | head -1 | cut -d'"' -f2), SDK at $ANDROID_HOME"
|
echo "FatihsMG4 dev shell — JDK $(java -version 2>&1 | head -1 | cut -d'"' -f2), SDK at $ANDROID_HOME"
|
||||||
echo " ./gradlew assembleStableDebug # debug APK"
|
echo " ./gradlew assembleStableDebug # debug APK"
|
||||||
echo " ./gradlew assembleUnstableDebug # build that can update itself (OTA)"
|
echo " ./gradlew assembleUnstableDebug # build that can update itself (OTA)"
|
||||||
|
echo " build-car # unstable build signed for the car"
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user