Commit Graph
18 Commits
Author SHA1 Message Date
The412Banner ebae834e36 A loading panel that proves the session is moving
Between Play and the client's first frame there was a line of text in a corner
of a black screen, for minutes on a first run. The panel in the middle now
shows the runtime's milestone, the client's own download percentage lifted out
of its log (its bootstrap prints "Downloading update (a of b KB)", which the
milestones never reflected), a clock, and a rotating hint about what is
happening. It reads the log's tail only, twice a second; a session that has
already drawn a frame does not get the panel again.
2026-09-19 14:45:22 -04:00
The412Banner b27a4f5b31 Main screen: scroll, and size from the window rather than the panel
On a landscape phone the install button sat under the navigation bar with no
way to reach it. The screen now scrolls, everything on it is smaller, and the
side gutter grows with the window width (24dp, 96dp from 600dp, 240dp from
960dp) so the buttons stay a sensible width on a wide panel instead of spanning
it. The logo is the icon clipped to a circle; shown raw, an adaptive icon is a
bare square.
2026-09-19 14:32:37 -04:00
The412Banner f86b64b18e Verify the signature from minSdk 21, or apksigner never looks at v1
It only checks the schemes an apk's own minSdk requires, so at 26 it reported
v1 as false while the JAR signature was sitting in META-INF the whole time.
The file check beside it says the same thing a second way.
2026-09-19 14:27:51 -04:00
The412Banner 432e197454 On-screen controls for a device with no pad, gone the moment one is attached
A phone had no way to answer Big Picture: touch moved the pointer and nothing
pressed a button. The on-screen pad writes into the same rings the physical one
does, so the client sees a single Xbox pad whichever is in use and both work at
once. An InputManager listener takes the controls away when a controller
appears and brings them back when it goes; steamdeck-osc in Downloads pins it
either way. Virtual input devices no longer count as controllers — the system's
own synthetic devices would otherwise hide the controls with nothing to
replace them.
2026-09-19 14:27:05 -04:00
The412Banner cc868496d1 Sign the apk with apksigner so v1 is actually there
AGP drops JAR signing at minSdk 24 and above and the DSL flag does not move it,
release build or not. zipalign then apksigner with the three schemes named
explicitly is the only version of this that can be checked.
2026-09-19 14:25:16 -04:00
The412Banner 71f84b93cc Tell lint that targetSdk 28 is the point
A release build fails on ExpiredTargetSdkVersion, which exists because Play
will not take an sdk that old. It is right about the rule and wrong about this
app: 29+ forbids executing a file from the app's own data directory, which is
the one thing this app exists to do.
2026-09-19 14:23:08 -04:00
The412Banner 4b43a617d4 Build the release variant so the apk carries v1 signing too
AGP drops JAR signing from a debug build when minSdk is 24 or higher, whatever
the signing config says, so the check added with the testkey failed on its
first run. Nothing is minified in either variant; this only changes which one
CI hands over.
2026-09-19 14:20:07 -04:00
The412Banner 344e70afc6 Keep the session alive in the background, rename the package, sign with the testkey, and draw the app a logo
The session now belongs to a foreground service rather than the activity.
Android demotes a process as soon as its last visible activity goes and the
low-memory killer reaps the guest, so leaving Big Picture to answer a message
came back to a dead Steam; the service holds the process at perceptible
priority, a partial wake lock keeps the CPU from dropping the guest's threads,
and a high-performance WiFi lock keeps a backgrounded download from being
throttled to nothing. The notification is silent (IMPORTANCE_LOW), carries a
Stop action, and returns to the session when tapped. Back now puts the app away
and leaves Steam running; a swipe out of recents ends the session.

The compositor moved with it: it is process-wide, started once, and merely
swaps the Surface it presents into as the activity comes and goes.

Package is com.steamdeck.launcher, signed with the AOSP testkey (v1+v2+v3) so
every build installs over the last one, and CI asserts all three schemes.

The launcher icon is our own controller on a purple glow — the spirit of the
Steam tile the client entry uses, none of its geometry.
2026-09-19 14:17:25 -04:00
The412Banner 4031f512fc Cache everything CI can, and credit both authors
The repo is private, so each run is billed. Three caches now carry a rebuild:
Gradle's own through setup-gradle (dependencies, build cache, configuration
cache), the CMake/ninja tree keyed on the C sources and the NDK, and the two
cross-compiled preloads — the last of which also skips installing the cross
toolchain, since a run that changes only Kotlin has no reason to touch a C
compiler. Superseded pushes are cancelled, documentation pushes do not build,
and the apk is stored rather than recompressed.

The preload assertions moved from the cross binutils to readelf, which reads
any ELF whatever the host, so they keep running on a cache hit.

Credits name The412Banner and maxjivi05: the runtime under all of this is
Max's gamescope work from WinNative.
2026-09-19 14:07:06 -04:00
The412Banner 97ee688eff Size the session from the panel, not the app window
resources.displayMetrics is the window after the system bars and the cutout are
subtracted, so the first session on a 1080p device came up 1920x968 and
gamescope patched its EDID to suit. The panel's own bounds are what a client
should be told the display is.
2026-09-19 14:01:40 -04:00
The412Banner 814ab2cac0 Add to the process environment rather than replacing it
Matches the exec path this was ported from; the guest command already starts
with env -i, so clearing the host side changed nothing except how far the code
sits from a configuration proven on a device.
2026-09-19 14:01:08 -04:00
The412Banner 085f663347 Ship libsndfile.so, which the PulseAudio core links
Caught by the closure check the previous commit added, before a device had to
find it: the daemon would have failed to start and the session would have run
without audio.
2026-09-19 13:57:01 -04:00
The412Banner 20a3b1ad63 Ship libffi.so, and check the whole native dependency closure in CI
libwayland-server.so links libffi, so loading the compositor threw
UnsatisfiedLinkError the moment Play started a session. The library was there,
its dependency was not — which is exactly the kind of gap a build cannot see
and a device finds immediately, so CI now walks every NEEDED of every .so we
package and fails on anything that resolves to neither the apk nor the
platform.
2026-09-19 13:54:41 -04:00
The412Banner 83cc1c4ec8 README: how to skip the 790 MB download on a device that already has the runtime 2026-09-19 13:53:33 -04:00
The412Banner c22cbc9f43 Type into the session: hardware keys to the compositor, and a log path that always exists
The session script redirects its own output into BL_LOG with exec, and a
redirection a non-interactive shell cannot open ends that shell — so a denied
storage permission would have killed the session rather than just losing the
log. Downloads is used once proven writable, files/logs otherwise.

Keyboard events now reach wl_keyboard, which is what the client's first-run
login needs on a device with a keyboard attached.
2026-09-19 13:49:29 -04:00
The412Banner 9b3dd05f4f Ship every shader header the effect chain includes
effects_chain.c runs the X11 renderer's committed SPIR-V; copying only the ones
named in the first screenful left deband_frag.h behind.
2026-09-19 13:45:20 -04:00
The412Banner 9119eb0045 Import the downloader the installer uses, and package libwayland-server.so
The compositor links libwayland-server.so as an imported target, so CMake never
copies it into the apk; it has to travel in jniLibs like the PulseAudio set.
2026-09-19 13:42:45 -04:00
The412Banner 4022351e22 SteamDeck: a standalone launcher for the native ARM64 Linux Steam client
Lifts Bannerlator's Linux/gamescope runtime out into an app of its own: the
Wayland compositor, the proot session, the runtime installer, the fake-evdev
controller path and the PulseAudio server, with none of the Wine, container or
store machinery around them.

One activity installs the runtime from the same winlator-contents catalog and a
second one runs the session: compositor on a SurfaceView, gamescope and Valve's
native arm64 client under proot, a physical pad republished into the fake-input
rings, and the session's milestones on screen until the first frame arrives.
2026-09-19 13:39:17 -04:00