plugins { id("com.android.application") } // The Rust side (this directory's Cargo.toml) is built separately with // `cargo ndk`, straight into src/main/jniLibs/ -- see the repo-root // AGENTS.md-style comment at the top of Cargo.toml for why this crate // stays outside the main Rust workspace, and RUST.md's I2 for the exact // build command. android { namespace = "dev.iris.android.demo" compileSdk = 37 defaultConfig { applicationId = "dev.iris.android.demo" // 29, not 26: `iris::android::view`'s touch handler dates each // sample with `MotionEvent.getEventTimeNanos` and // `getHistoricalEventTimeNanos`, both API 29, and a missing JNI // method there is a hard crash on the first touch rather than a // degraded fling. Raised deliberately rather than guarded at // runtime: nothing this app is built for runs below 29, and an // untested fallback path is its own defect. `build-apk.sh`'s // `cargo ndk -P` is kept at the same number. minSdk = 29 // 37, matching `compileSdk` and the Compose app in `app/` -- which // is the one part of this that is measured rather than reasoned: // that app targets 37 and its keyboard does push the transcript up // on Iris's phone, and this one targeted 34 and does not // (2026-09-07). The emulator here is API 36 and the push-up works // there at either target, so the target is the only difference the // two devices do not share. // // The mechanism, stated as the reading it is: below targetSdk 35 // a window keeps the legacy behaviour, where `adjustResize` shrinks // the window for the IME and `getInsets(ime()).bottom` therefore // measures the overlap with an already-shrunk window -- zero, with // nothing left to push up. `MainActivity`'s // `setDecorFitsSystemWindows(false)` opts out of that, and on API // 36 it still takes; Android 16 deprecated it and Android 17 is // where it appears not to. At 35+ edge-to-edge is not opt-in, so // the app is handed the real overlap without relying on a // deprecated call. If the phone still reports `ime_bottom=0` with // a nonzero `dispatches` in the Diagnostics pane, this reading was // wrong and the `WindowInsetsAnimation.Callback` in // `MainActivity` is the other half to look at. targetSdk = 37 versionCode = 1 versionName = "1.0" } // A release build must be signed, and the key is per machine rather than per repo -- same // reasoning and the same key as `app/build-apk.sh` (the Compose app): it is what a phone // recognises the app by, and a secret never lives in a checkout (the mount is shared with an // untrusted VM). `build-apk.sh` generates this key once and points at it through the // environment; without it a release build here is unsigned, which is fine for everything // except installing. def keystore = System.getenv("AI_APP_KEYSTORE") signingConfigs { if (keystore != null) { release { storeFile = file(keystore) storePassword = System.getenv("AI_APP_KEYSTORE_PASSWORD") keyAlias = "ai-app" keyPassword = storePassword } } } buildTypes { debug { } // P0's iris half (docs/RUST.md's P0 box): the build a phone actually runs. The `.so` // itself is built separately with `cargo ndk --release --features "transcript-screen // force-gles bench"` straight into src/main/jniLibs/ (this crate's own Cargo.toml) -- // Gradle here only packages and signs whatever is already there, the same division as the // debug/tabs-screen build this project started with. `applicationIdSuffix` keeps it // installable beside a debug build of the tabs demo rather than replacing it. release { applicationIdSuffix ".bench" if (keystore != null) { signingConfig = signingConfigs.release } } } compileOptions { sourceCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_17 } }