ReviewOS

craft-native/craft

[S3-012] Resolve Android 35 default software-image external-fence frame stalls

#437
Open chris opened this 13 hours ago ·
13 hours ago

Parent: https://github.com/craft-native/craft/issues/393 Related native extent/lifecycle repair: https://github.com/craft-native/craft/issues/435

Observable failure

The Android 35 default arm64 SDK image, revision 2, advertises the required Vulkan surface/swapchain maintenance support but cannot complete the maintained native fixture's first 61 actual frames within the unchanged 30-second stage deadline. The final controlled run reaches 31 frames, one native session and no input events; public Surface.present takes about 984ms while CPU scene drawing takes 0.306ms and GPU readback 0.010ms. The actual native/window extent is 256x192 throughout.

The same consumed source files and identical decompressed public package archive pass all 370 frames, four native sessions, two real pointer events, five independently anchored actual compositor captures and complete disposal on Android 35 Google APIs arm64 revision 9. The image selection is the only command/candidate difference. Both rows dispose every owned process group, native guest and generated workspace.

Earlier instrumented default-image runs isolate the external presentation-fence path: the guest MESA worker logs completion promptly, while its enclosing vkWaitForFences call often returns near a full second later. One baseline sample has 31 waits, median worker completion 0ms and median return lag 991ms. A per-image presentation-resource prototype did not resolve it. Short-polling controls are diagnostic evidence only and are absent from the source candidate.

The exact installed guest driver source revision and internal notification defect are not yet established. Do not attribute a particular upstream implementation until binary/source provenance or a minimized driver reproduction proves it.

Required work and acceptance

  • Minimize the external-fence completion failure using the real maintained native public interface or a genuine Vulkan/ANativeWindow driver probe, preserving all original failure receipts.
  • Identify the owning guest driver/system-image source and exact affected binary/revision. Link the upstream defect or fix rather than adding a Craft polling/reconnect workaround.
  • Qualify any corrected, normally installed released toolchain against the same actual View extents, 61-frame/30-second stage deadlines, 1000ms native wait budgets, complete scene/input/capture and ownership gates.
  • Rerun both the previously failing image and the maintained passing image with matching consumed-source identities; retain separate truthful outcomes.
  • Keep software-emulator scope separate from physical GPU/device execution and full native game/fidelity claims.

No raised guards, shortened tick/frame scenarios, successful blank/no-op rendering, synthetic lifecycle callbacks, abandoned processes or hidden failed matrix rows.

Initial retained identities

Baseline repository revision: 806d3d5 plus the #435 reviewed source candidate. The compared public archive's decompressed tar SHA256 is ad6fea1c71fbf8ca32702139506418f0d027bb0d67667a1deea730e71f1f6bc0; all 1,066 archive members and every recorded consumed source file match. Original gzip archives are retained separately because their timestamp headers differ.

Android emulator 37.2.13 build 16740729, hardware CPU virtualization, software llvmpipe LLVM 21.1.4, NDK 27.2.12479018, Gradle 8.11.1, pinned Zig 0.18.0-dev.146+35accc0.

Default image original installed-byte SHA256 values:

  • system.img: 794b4c44ed71c18399fdc20027212e2cdbb2cb9c8616daf2996983d79bccf1ff
  • vendor.img: 43a41517c15237e7cefc58ec02012d531feb9aa825c731bcb23ed915485daeb8
  • kernel-ranchu: a9dda2ae115395ea352bca2201294b4df0020a7f425cbfae879ee66a03a8f19f

Local original receipts: /tmp/craft-vulkan-android-acceptance/run-Wk0UjT (passing Google APIs row), run-diL5If (failed default row), and /tmp/craft-vulkan-final-image-matrix.json. Canonical source/CI receipt links will be appended during delivery; this open issue does not claim the default row is qualified.

9 hours ago

The installed guest module and a matching upstream deadline defect are now identified. This issue remains open for corrected released-toolchain qualification.

A bounded read-only run booted the same default API35 arm64 revision2 image and launched the original retained Vulkan APK. The app process maps identified /vendor/lib64/hw/vulkan.ranchu.so: 1,637,816 bytes, SHA256 f152208e8ac1d3bdbfed4b379f2926860b3ff81b7d0fb05e89b885e92f9b7765, ELF build ID 97175a87159c1611c26e784dab8676ef. All six installed image files still match the original failing row. Build metadata is AE3A.240806.019/12368160, dated September13,2024. All33 diagnostic commands succeeded and owned app/emulator/process groups were disposed.

The module's exported gfxstream::guest::WorkPool::waitAll at 0x160c14 calls the timeout body at 0x1613b0. Instructions 0x161440..0x161468 contain the old deadline calculation: add relative microseconds to tv_usec, multiply by1000, carry seconds only on integer wrap, then call pthread_cond_timedwait. They omit seconds/remainder normalization. The owning guest source is Google's gfxstream; the emulator host's separate Mesa/lavapipe revision does not identify this guest implementation.

Google already repaired that calculation in upstream commit2c1b3c4, July12,2024, referencing Bug347288539 and external-fence worker starvation. The exact old file blob is dafb6ea4f908c5a83ad5e257fc8ea11c3c40218a; fixed blob 0eba3d168bf8d41d61ab5cbee8f746f3bf8a1f0b. Both public source blobs and all24 retained research artifacts were independently verified.

This strongly supports the cause of our delay: with1,000,000us remaining and tv_usec235,000, the installed calculation gives invalid tv_nsec1,235,000,000. Immediate timed-wait rejection can keep the owner holding the mutex until wall-time rollover permits a valid deadline. Actual new logs show worker PID1890/TID1960 finishing fd121 at01:13:21.235, while owner TID1935 returns success at01:13:22.001. The upstream explanation and installed instructions match this pattern; a causal fixed-image A/B has not been performed.

Retained collection receipt SHA256 b7c343944662506f5362dbbfc817d0ec1dc9f293e99adca3cce26cd32b0f7ab3, audit /tmp/craft-437-source-provenance/guest-provenance-audit.json; sealed research receipt /tmp/craft-437-guest-research-a3728r36/verification.json, SHA256 b959032d50f6adeead6599ced0d9ddf19f1af23fbf51a2c31697ea16d8ef8ab3.

The complete installed repository revision/build manifest remains unproved: the matching artifact API returned501 UNIMPLEMENTED. The public Android15_r1 file matches the old helper, which does not establish that entire tag as the installed revision. No Craft polling workaround, source duplication, ABI shim, binary replacement or raised deadline was introduced. The Google APIs revision9 pass remains a separate image outcome. A normally released corrected default toolchain must still pass the original complete scene/input/capture/lifecycle/cleanup and frame/time budgets before this issue can close.

Sign in to comment on this issue.