Repository navigation
feat(assets): openFd opens a bundled APK asset as a file descriptor - #38
Merged
Merged
Conversation
labelle-bgfx#168 plays a bundled music file on Android by decoding it with video.decodeTrack, which reads an fd. To get one, bgfx declared the AAsset* externs itself and read ANativeActivity.assetManager by a hand-counted field index (fields[8]). Android code belongs here, not in the backends, and the struct layout belongs to the NDK header. assets.openFd(activity, name) returns the APK fd plus the asset's byte range; jni/asset_fd.c reads activity->assetManager by name through <android/native_activity.h>. The name checks are split from the JNI half so host tests drive them, and a test takes openFd's address so the Android compile-check type-checks the JNI branch.
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Advanced Run ID:
Comment |
apotema
approved these changes
Oct 1, 2026
apotema
left a comment
Contributor
There was a problem hiding this comment.
Approved. This is exactly the seam the #168 review asked for (reviewed at ff6f338; Claude, on Alexandre's behalf).
jni/asset_fd.c: readsassetManagerthrough<android/native_activity.h>, so there's no more hand-countedfields[8]. The AAsset is closed afterAAsset_openFileDescriptor64, so the caller owns only the dup'd fd. A compressed entry gives -1, as documented.assets.zig: the name checks are split from the JNI half, so host tests cover NUL-termination, the 255-byte boundary, and null/empty/over-long names never reaching JNI._ = &openFdmakes the Android compile-check analyse the JNI branch. The thread-safety note is right:AAssetManageris thread-safe, and the asset is opened and closed in one call.- CI: all 9 checks green.
Before merging:
- Merge
main: the branch is 1 behind;mainhas since released 0.5.0, the Vulkanautodefault. - Release as v0.6.0, not v0.4.1: 0.5.0 already shipped, and this adds public API. Bump
build.zig.zonto0.6.0in this PR or a release PR, then tag v0.6.0. - Add a labelle-registry entry for 0.6.0 (commit + sha256 of the commit tarball, as in #12/#13), or FP's provider lock can't resolve it.
Alexandre's approval on #38 asked for v0.6.0, not v0.4.1: 0.5.0 (the Vulkan `auto` default) shipped meanwhile, and `assets.openFd` is new public API. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
labelle-bgfx#168 plays a bundled music file on Android: it decodes the APK asset with
video.decodeTrack, which reads a file descriptor. To get that fd, the PR declared theAAsset*externs in bgfx and readANativeActivity.assetManagerby a hand-counted index (fields[8]). @apotema's review asked for that to live here instead: Android code goes in labelle-android, bgfx only gets generic seams (the rule from labelle-bgfx#172).What
assets.openFd(activity, name) ?AssetFd: opensname(relative to the APK'sassets/) and returns{ fd, start, len }for the fd decoders here (video.decodeTrack,video.VideoDecoder).AssetFd.close()closes the descriptor; the caller owns it.AAssetManageris thread-safe and theAAssetlives only inside the call.src/jni/asset_fd.c: readsactivity->assetManagerby name through<android/native_activity.h>, then doesAAssetManager_open→AAsset_openFileDescriptor64→AAsset_close(the fd is dup'd, so it outlives the AAsset). Same shape as the otherjni/*.cfiles.root.zigexportsassets;build.zigcompiles the C file.The asset must be stored uncompressed in the APK, which the android provider already does.
Tests
zig build test: host 133/133. The 5 new tests:openFd analyses on every target: takesopenFd's address so the Android compile-check type-checks the JNI branch. That branch was only reached lazily before, which let a calling-convention mismatch through that the first device build caught. I checked that the check fails if the mismatch comes back.ANDROID_NDK_HOME=… zig build test -Dtarget=aarch64-linux-android: compiles.local:pin) and the reworked labelle-bgfx#168. The in-game theme MP3 opens throughopenFdand decodes to exactly 5,375,040 frames (the same as the old path), gameplay runs at 52 FPS, and the theme plays.Next
Release (v0.4.1) → labelle-bgfx#168 bumps its labelle-android pin to it (the same line #186 moves to 0.4.0) → bgfx release → FP #976's pin.
Not in scope: labelle-bgfx's
src/video/backend.zighas the same hand-rolled asset open; moving it ontoopenFdis the follow-up @apotema mentioned.Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.