open-standards/wai/wai-sink-android/sink/build.gradle.kts
Transaction Science d61d8691a3
All checks were successful
WAI operation catalogue / does this change touch it (push) Successful in 12s
wai-sink-android native sink library / does this change touch it (push) Successful in 13s
wai-sink-swift native sink package / does this change touch it (push) Successful in 27s
WAI breaking changes and the conformance runner / WAI breaking · does this change touch WAI (push) Successful in 14s
WAI examples / WAI examples · does this change touch them (push) Successful in 16s
WAI breaking changes and the conformance runner / WAI breaking · wire, record and API against main · linux (push) Successful in 33s
WAI operation catalogue / the catalogue and every door · linux (push) Successful in 13m46s
WAI breaking changes and the conformance runner / WAI breaking and conform · their tests, and the independent verifiers through wai conform · linux (push) Successful in 9m59s
WAI examples / WAI examples · portable · linux (push) Successful in 12m29s
wai-sink-android native sink library / every ABI, the AAR, and the instrumented tests in a headless emulator · macos (push) Successful in 7m25s
wai-sink-android native sink library / the JNI layer and the platform-free half on the host JVM · linux-arm64 (push) Successful in 7m30s
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (push) Successful in 11m13s
wai-sink-swift native sink package / libwai slices, desktop tests, simulator tests · macos (push) Successful in 16m30s
WAI examples / WAI examples · the archive, the readiness check, the browser and Apple · macos (push) Successful in 34m15s
WAI examples / WAI examples · android-app · linux-arm64 (push) Successful in 21m46s
wai-sink-android: WaiIntDecoder, native-sink §13's integer decode through JNI, libwai built with sink_decode
The Kotlin library carries the decoder the Swift package carries. jni/wai_sink_jni.c gains the
thirteen wai_int_* calls (decoder open, free and info; a parameter set's new, add, listing and
free; a payload's decode and an envelope's, answering { bytes, answer }; a frame stream's open,
reset and free and its next object's decode); WaiIntDecoder and WaiIntFrameStream wrap them as
the Swift package does, and WaiSinkException.INT_INPUT carries WAI_ERR_INT_INPUT.
scripts/build-native.sh builds libwai with sink_decode for every ABI (wgpu's Vulkan backend,
loaded at run time; nothing new beyond the crates wai-rs's Cargo.lock holds) and checks the new
exports; its macOS host build now reads a Mach-O library's exports with nm -g (-D read none).

core/src/testkit/int-cases.json names a committed vector of each of the eight integer
capabilities with its set and the output its corpus commits (a SHA-256 of the whole output or of
each frame, or photo's ref_rgb.bin), and a stream of each of the three frame forms from the
corpus's own index. IntDecodeTest (host JVM) and IntDecodeDeviceTest (instrumented;
test-emulator.sh stages the files into the test APK) decode every case and every frame with the
GPU offered and on the CPU alone, requiring the same bytes and the committed output; a float
capability is refused on both integer paths; an unreadable configuration is INT_INPUT.

Run on 2026-11-11: on an arm64 laptop (Metal), the host JVM tests, 20 of 20: 8 of 9 cases on the
GPU (wai.video.int_motion on the CPU) and 7 of 16 frames, every output the CPU's and the committed
one; the three ABIs built and linked (16 KiB pages, exports checked); in the arm64 emulator (API
36), 16 of 16 instrumented tests. The emulator's own Vulkan driver (gfxstream over the host's
software renderer) crashed the test process with a SIGSEGV inside its vkQueueSubmit at the
decoder's first submission, so test-emulator.sh runs it with the guest's Vulkan off
(WAI_SINK_EMULATOR_VULKAN=on keeps it); the decoder there states the GPU absent and decodes every
case on the CPU. No run on a device's Vulkan GPU was possible here: the README and native-sink
§13 say so.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-11 17:31:26 -05:00

136 lines
4.8 KiB
Kotlin

// The Android library (AAR): the platform-free half (../core/src/main), the player and attention
// integration (src/main), and the JNI layer's libraries for each ABI, built out of band by
// scripts/build-native.sh android with the NDK pinned below.
//
// Published with maven-publish as science.transaction.wai:wai-sink:<version>, the version of
// wai/wai-rs/Cargo.toml (the toolchain's) unless -Pwai.version gives it: to the repository
// `staging` (build/staging-repo, which scripts/check-publication.sh reads), and, with
// -Pwai.maven.url, to the repository `forge` there, its token from the environment variable
// WAI_PACKAGES_TOKEN.
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
plugins {
id("com.android.library")
id("org.jetbrains.kotlin.android")
id("maven-publish")
}
val waiVersion: String = providers.gradleProperty("wai.version").orNull
?: Regex("""(?m)^version = "([^"]+)"$""").find(file("../../wai-rs/Cargo.toml").readText())?.groupValues?.get(1)
?: error("no version in wai/wai-rs/Cargo.toml")
android {
// The package of the library's manifest: the publication's group and the library's name.
// The Kotlin classes keep their package, wai.sink, which the JNI layer's symbols name.
namespace = "science.transaction.wai.sink"
compileSdk = 36
ndkVersion = "29.0.14206865"
defaultConfig {
minSdk = 24
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles("consumer-rules.pro")
}
sourceSets {
getByName("main") {
kotlin.srcDir("../core/src/main/kotlin")
jniLibs.srcDir(layout.buildDirectory.dir("jniLibs"))
}
getByName("androidTest") {
kotlin.srcDir("../core/src/testkit/kotlin")
assets.srcDir("../../live-conformance/native-sink")
// The integer decode's cases and the files they name, under wai/, staged by
// scripts/test-emulator.sh (core/src/testkit/int-cases.json).
assets.srcDir(layout.buildDirectory.dir("int-assets"))
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
packaging {
jniLibs {
useLegacyPackaging = false
}
}
buildFeatures {
buildConfig = false
}
publishing {
singleVariant("release") {
withSourcesJar()
}
}
}
kotlin {
compilerOptions {
jvmTarget.set(JvmTarget.JVM_17)
allWarningsAsErrors.set(true)
}
}
dependencies {
// The platform's media player library, and its HTTP presentations module.
api("androidx.media3:media3-exoplayer:1.11.1")
api("androidx.media3:media3-exoplayer-hls:1.11.1")
androidTestImplementation("androidx.test:runner:1.7.0")
androidTestImplementation("androidx.test:core:1.7.0")
androidTestImplementation("androidx.test.ext:junit:1.3.0")
androidTestImplementation("junit:junit:4.13.2")
}
publishing {
publications {
register<MavenPublication>("release") {
groupId = "science.transaction.wai"
artifactId = "wai-sink"
version = waiVersion
afterEvaluate {
from(components["release"])
}
pom {
name.set("wai-sink")
description.set("The WAI native sink for the platform player: libwai's C interface through JNI, the loopback relay, and the player and attention integration (extensions/native-sink.md).")
url.set("https://wai.transaction.science")
licenses {
license {
name.set("Apache-2.0")
url.set("https://www.apache.org/licenses/LICENSE-2.0")
}
}
scm {
url.set("https://git.transaction.science/Transaction-Science/open-standards")
}
}
}
}
repositories {
maven {
name = "staging"
url = uri(layout.buildDirectory.dir("staging-repo"))
}
providers.gradleProperty("wai.maven.url").orNull?.let { target ->
maven {
name = "forge"
url = uri(target)
// The forge's own address on the private network, which has no TLS.
isAllowInsecureProtocol = target.startsWith("http://")
credentials(HttpHeaderCredentials::class) {
name = "Authorization"
value = "token " + (providers.environmentVariable("WAI_PACKAGES_TOKEN").orNull
?: error("publishing to $target needs the environment variable WAI_PACKAGES_TOKEN"))
}
authentication {
create<HttpHeaderAuthentication>("header")
}
}
}
}
}